aboutsummaryrefslogtreecommitdiff
path: root/.config/awesome/quarrel/native
diff options
context:
space:
mode:
authordelta <darkussdelta@gmail.com>2025-07-04 00:38:29 +0200
committerdelta <darkussdelta@gmail.com>2025-07-04 00:38:29 +0200
commitb3530d7c4a102935fa26498a160ee1dc6c1e9c03 (patch)
treed7751206a694bc5de2d6b34b0c077cfcd1855798 /.config/awesome/quarrel/native
parentdf75ec5ed5e3848c497f0439acb43ec9246ad3e7 (diff)
:3
Diffstat (limited to '.config/awesome/quarrel/native')
-rw-r--r--.config/awesome/quarrel/native/Cargo.toml19
-rw-r--r--.config/awesome/quarrel/native/init.lua4
-rw-r--r--.config/awesome/quarrel/native/src/http.rs22
-rw-r--r--.config/awesome/quarrel/native/src/lenses/application.rs85
-rw-r--r--.config/awesome/quarrel/native/src/lenses/calculator.rs47
-rw-r--r--.config/awesome/quarrel/native/src/lenses/entry.rs19
-rw-r--r--.config/awesome/quarrel/native/src/lenses/mod.rs78
-rw-r--r--.config/awesome/quarrel/native/src/lib.rs14
-rw-r--r--.config/awesome/quarrel/native/src/moondrop.rs3
-rw-r--r--.config/awesome/quarrel/native/src/mpd.rs142
-rw-r--r--.config/awesome/quarrel/native/src/net/mod.rs4
-rw-r--r--.config/awesome/quarrel/native/src/util.rs3
12 files changed, 199 insertions, 241 deletions
diff --git a/.config/awesome/quarrel/native/Cargo.toml b/.config/awesome/quarrel/native/Cargo.toml
index 8d56c9f..2551507 100644
--- a/.config/awesome/quarrel/native/Cargo.toml
+++ b/.config/awesome/quarrel/native/Cargo.toml
@@ -8,22 +8,21 @@ edition = "2021"
[dependencies]
freedesktop_entry_parser = "1.3.0"
cpc = "1.9.1"
-mlua = { version = "0.8.7", features = [ "module", "lua54", "serialize" ] }
+mlua = { version = "0.10.3", features = [ "module", "lua54", "serialize" ] }
rayon = "1.6.1"
serde = { version = "1.0.152", features = [ "derive" ] }
url = "2.3.1"
-rodio = "0.17.1"
-nix = "0.26.2"
+rodio = "0.20.1"
+nix = { version = "0.29.0", features = [ "ioctl", "socket" ] }
chrono = "0.4.24"
-itertools = "0.10.5"
+itertools = "0.14.0"
html-escape = "0.2.13"
-mpd = { git = "https://github.com/kstep/rust-mpd", features = [ "serde" ], version = "0.1.0" }
-cairo-rs = { git = "https://github.com/gtk-rs/gtk-rs-core.git", version = "0.18.0" }
-gdk-pixbuf = { git = "https://github.com/gtk-rs/gtk-rs-core.git", version = "0.18.0" }
-symphonia = "0.5.3"
-dirs = "5.0.1"
+dirs = "6.0.0"
once_cell = "1.18.0"
-
+ureq = "3.0.9"
+anyhow = { version = "1.0.97", features = ["backtrace"] }
+mdrop = { git = "https://github.com/frahz/mdrop" }
+sysinfo = "0.35.0"
[lib]
crate-type = ["cdylib"]
diff --git a/.config/awesome/quarrel/native/init.lua b/.config/awesome/quarrel/native/init.lua
index e5d5aab..6a823ba 100644
--- a/.config/awesome/quarrel/native/init.lua
+++ b/.config/awesome/quarrel/native/init.lua
@@ -26,16 +26,12 @@ package.cpath = package.cpath .. ";" .. cfg .. "quarrel/native/lib?.so"
---@field decode_html fun(input: string): string
---@field open_file fun(path: string): FileHandle
----@class Mpd
----@field init
-
---@class Net
---@field get_essid fun(): string
---@class QuarrelNative
---@field lenses Lenses
---@field util Util
----@field mpd Mpd
---@field net Net
local qnative = require "qnative"
diff --git a/.config/awesome/quarrel/native/src/http.rs b/.config/awesome/quarrel/native/src/http.rs
new file mode 100644
index 0000000..e995556
--- /dev/null
+++ b/.config/awesome/quarrel/native/src/http.rs
@@ -0,0 +1,22 @@
+use ureq::{Agent, agent};
+use std::{sync::LazyLock, thread};
+use mlua::prelude::*;
+
+static AGENT: LazyLock<Agent> = LazyLock::new(|| agent());
+
+struct Stream(ureq::Body);
+
+pub fn get(_: &Lua, url: String, callback: LuaFunction, err_callback: LuaFunction) -> LuaResult<()> {
+ thread::spawn(|| {
+ match AGENT.get(url).call() {
+ Ok(body) => {
+
+ },
+ Err(err) => {
+ err_callback.call(err.to_string());
+ }
+ }
+ // callback.call::<>()
+ });
+ Ok(())
+}
diff --git a/.config/awesome/quarrel/native/src/lenses/application.rs b/.config/awesome/quarrel/native/src/lenses/application.rs
index 72aba8d..89b7bb4 100644
--- a/.config/awesome/quarrel/native/src/lenses/application.rs
+++ b/.config/awesome/quarrel/native/src/lenses/application.rs
@@ -1,6 +1,5 @@
use std::{
- fs::read_dir,
- path::PathBuf,
+ fs::read_dir, path::PathBuf
};
use freedesktop_entry_parser as fd;
@@ -8,12 +7,54 @@ use mlua::prelude::*;
use rayon::prelude::*;
use url::Url;
-use crate::lenses::entry::{
- entries_to_lua_table,
+use crate::lenses::{
Entry,
+ Lense,
+ Cache
};
-fn parse_entry(entry: &fd::Entry, path: &PathBuf) -> Result<Entry, ()> {
+#[derive(Default)]
+pub struct Application(pub Cache);
+
+impl Lense for Application {
+ const NAME: &str = "Application";
+
+ fn get_cache(&self) -> &Cache {
+ &self.0
+ }
+
+ fn set_cache(&mut self, cache: Cache) {
+ self.0 = cache;
+ }
+
+ fn query(_: &Lua, input: String) -> Result<Vec<Entry>, anyhow::Error> {
+ let applications_dir = "/usr/share/applications";
+ let entries = read_dir(applications_dir)?
+ .map(|result| result.map(|e| e.path()))
+ .collect::<Result<Vec<_>, std::io::Error>>()?;
+
+ let parsed_entries: Vec<Entry> = entries
+ .into_par_iter()
+ .filter(|path| path.extension().is_some_and(|ext| ext == "desktop"))
+ .filter_map(|path| {
+ parse_entry(path).ok().flatten()
+ })
+ .collect();
+
+ Ok(
+ parsed_entries
+ .into_iter()
+ .filter(|entry| entry.message.to_lowercase().contains(&input.to_lowercase()))
+ .collect(),
+ )
+ }
+}
+
+fn parse_entry(path: PathBuf) -> Result<Option<Entry>, ()> {
+ let Ok(entry) = fd::parse_entry(&path) else {
+ return Err(())
+ };
+
let section = entry.section("Desktop Entry");
let name = section.attr("Name").ok_or(())?.to_string();
@@ -38,14 +79,14 @@ fn parse_entry(entry: &fd::Entry, path: &PathBuf) -> Result<Entry, ()> {
}
}
'c' => new_exec.replace_range(index..index + 2, &name),
- 'k' => new_exec.replace_range(index..index + 2, Url::from_file_path(path)?.as_str()),
+ 'k' => new_exec.replace_range(index..index + 2, Url::from_file_path(&path)?.as_str()),
'f' | 'u' | 'v' | 'm' | 'd' | 'n' => new_exec.replace_range(index..index + 2, ""),
_ => continue,
}
}
- Ok(Entry {
+ Ok(Some(Entry {
message: name,
exec: Some((
new_exec,
@@ -55,33 +96,5 @@ fn parse_entry(entry: &fd::Entry, path: &PathBuf) -> Result<Entry, ()> {
.parse()
.map_err(drop)?,
)),
- provider: "Application".to_string(),
- })
-}
-
-pub fn query(lua: &Lua, input: String) -> LuaResult<LuaTable> {
- let applications_dir = "/usr/share/applications";
- let entries = read_dir(applications_dir)?
- .map(|result| result.map(|e| e.path()))
- .collect::<Result<Vec<_>, std::io::Error>>()?;
-
- let parsed_entries: Vec<Entry> = entries
- .into_par_iter()
- .filter(|path| matches!(path.extension(), Some(ext) if ext == "desktop"))
- .filter_map(|path| {
- let Ok(entry) = fd::parse_entry(&path) else {
- return None
- };
-
- parse_entry(&entry, &path).ok()
- })
- .collect();
-
- Ok(entries_to_lua_table(
- parsed_entries
- .into_iter()
- .filter(|entry| entry.message.to_lowercase().contains(&input.to_lowercase()))
- .collect(),
- lua,
- ))
+ }))
}
diff --git a/.config/awesome/quarrel/native/src/lenses/calculator.rs b/.config/awesome/quarrel/native/src/lenses/calculator.rs
index 07f1ee2..640bdeb 100644
--- a/.config/awesome/quarrel/native/src/lenses/calculator.rs
+++ b/.config/awesome/quarrel/native/src/lenses/calculator.rs
@@ -5,25 +5,36 @@ use cpc::{
};
use mlua::prelude::*;
-use crate::lenses::entry::{
- entries_to_lua_table,
+use crate::lenses::{
Entry,
+ Cache,
+ Lense
};
-pub fn query(lua: &Lua, input: String) -> LuaResult<LuaTable> {
- let result = match eval(input.trim(), true, Unit::Celsius, false) {
- Ok(result) => {
- format!("{result}")
- }
- Err(_) => return lua.create_table(),
- };
-
- Ok(entries_to_lua_table(
- vec![Entry {
- message: result,
- exec: None,
- provider: "Calculator".to_string(),
- }],
- lua,
- ))
+pub struct Calculator;
+
+impl Lense for Calculator {
+ const NAME: &str = "Calculator";
+
+ fn get_cache(&self) -> &Cache {
+ &Cache::Stale
+ }
+
+ fn set_cache(&mut self, _: Cache) {}
+
+ fn query(_: &Lua, input: String) -> Result<Vec<Entry>, anyhow::Error> {
+ let result = match eval(input.trim(), true, Unit::Celsius, false) {
+ Ok(result) => {
+ format!("{result}")
+ }
+ Err(err) => { return Err(anyhow::anyhow!(err)); },
+ };
+
+ Ok(vec![Entry {
+ message: result,
+ exec: None,
+ }; 1]
+ )
+ }
}
+
diff --git a/.config/awesome/quarrel/native/src/lenses/entry.rs b/.config/awesome/quarrel/native/src/lenses/entry.rs
deleted file mode 100644
index c7ac09e..0000000
--- a/.config/awesome/quarrel/native/src/lenses/entry.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use mlua::{
- prelude::*,
- LuaSerdeExt,
-};
-use serde::Serialize;
-
-#[derive(Serialize, Clone)]
-pub struct Entry {
- pub message: String,
- pub exec: Option<(String, bool)>,
- pub provider: String,
-}
-
-pub fn entries_to_lua_table(entries: Vec<Entry>, lua: &Lua) -> LuaTable {
- match lua.to_value(&entries).unwrap() {
- LuaValue::Table(t) => t,
- _ => unreachable!(),
- }
-}
diff --git a/.config/awesome/quarrel/native/src/lenses/mod.rs b/.config/awesome/quarrel/native/src/lenses/mod.rs
index d0db6f7..6eb5b58 100644
--- a/.config/awesome/quarrel/native/src/lenses/mod.rs
+++ b/.config/awesome/quarrel/native/src/lenses/mod.rs
@@ -1,3 +1,79 @@
pub mod application;
pub mod calculator;
-pub mod entry;
+
+use mlua::{
+ prelude::*,
+ LuaSerdeExt,
+};
+use serde::{Serialize, Deserialize};
+
+#[derive(Deserialize, Serialize, Clone)]
+pub struct Entry {
+ pub message: String,
+ pub exec: Option<(String, bool)>,
+}
+
+impl IntoLua for Entry {
+ fn into_lua(self, lua: &Lua) -> LuaResult<LuaValue> {
+ return lua.to_value(&self)
+ }
+}
+
+impl FromLua for Entry {
+ fn from_lua(value: LuaValue, lua: &Lua) -> LuaResult<Self> {
+ return lua.from_value(value);
+ }
+}
+
+#[derive(Default)]
+pub enum Cache {
+ Valid(Vec<Entry>),
+ #[default]
+ Stale
+}
+
+pub struct _Lense<T: Lense>(pub T);
+
+pub trait Lense {
+ const NAME: &'static str;
+
+ fn set_cache(&mut self, cache: Cache);
+ fn get_cache(&self) -> &Cache;
+
+ fn query(lua: &Lua, input: String) -> Result<Vec<Entry>, anyhow::Error>;
+}
+
+impl<T: Lense + 'static> LuaUserData for _Lense<T> {
+ fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {
+ // fields.add_field_method_get("cache", |lua, this| {
+ // let cache = this.0.get_cache();
+ // match cache {
+ // Cache::Valid(cache) => Ok(cache.clone().into_lua(lua)?),
+ // Cache::Stale => Ok(LuaNil)
+ // }
+ // });
+
+ // fields.add_field_method_set("cache", |_, this, cache: Vec<Entry>| {
+ // Ok(this.0.set_cache(Cache::Valid(cache)))
+ // });
+
+ fields.add_field_method_get("stale", |_, this| Ok(matches!(this.0.get_cache(), Cache::Stale)));
+
+ fields.add_field("name", T::NAME);
+ }
+
+ fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
+ methods.add_method_mut("query", |lua, this, input: String| {
+ return Ok(match this.0.get_cache() {
+ Cache::Valid(entries) => entries.clone(),
+ Cache::Stale => {
+ let entries = T::query(lua, input).map_err(LuaError::external)?;
+ this.0.set_cache(Cache::Valid(entries.clone()));
+ entries
+ }
+ });
+ });
+
+ methods.add_method_mut("mark_stale", |_, this, _: ()| Ok(this.0.set_cache(Cache::Stale)) );
+ }
+}
diff --git a/.config/awesome/quarrel/native/src/lib.rs b/.config/awesome/quarrel/native/src/lib.rs
index 472313e..4f1780d 100644
--- a/.config/awesome/quarrel/native/src/lib.rs
+++ b/.config/awesome/quarrel/native/src/lib.rs
@@ -1,29 +1,29 @@
mod lenses;
-mod mpd;
mod net;
+// mod http;
mod util;
+mod moondrop;
use mlua::prelude::*;
+use lenses::{ _Lense };
#[mlua::lua_module]
fn qnative(lua: &Lua) -> LuaResult<LuaTable> {
let lenses = lua.create_table()?;
- lenses.set("1", lua.create_function(lenses::calculator::query)?)?;
- lenses.set("2", lua.create_function(lenses::application::query)?)?;
+ lenses.push(_Lense(lenses::calculator::Calculator))?;
+ lenses.push(_Lense(lenses::application::Application::default()))?;
+ // lenses.set("1", lua.create_function(lenses::calculator::Application::query)?)?;
+ // lenses.set("2", lua.create_function(lenses::application::Application::query)?)?;
let util = lua.create_table()?;
util.set("decode_html", lua.create_function(util::decode_html)?)?;
util.set("open_file", lua.create_function(util::FileHandle::new)?)?;
- let mpd = lua.create_table()?;
- mpd.set("init", lua.create_function(mpd::init)?)?;
-
let net = lua.create_table()?;
net.set("get_essid", lua.create_function(net::get_first_essid)?)?;
let exports = lua.create_table()?;
exports.set("lenses", lenses)?;
- exports.set("mpd", mpd)?;
exports.set("net", net)?;
exports.set("util", util)?;
diff --git a/.config/awesome/quarrel/native/src/moondrop.rs b/.config/awesome/quarrel/native/src/moondrop.rs
new file mode 100644
index 0000000..d416ef6
--- /dev/null
+++ b/.config/awesome/quarrel/native/src/moondrop.rs
@@ -0,0 +1,3 @@
+use mdrop::Moondrop;
+
+
diff --git a/.config/awesome/quarrel/native/src/mpd.rs b/.config/awesome/quarrel/native/src/mpd.rs
deleted file mode 100644
index 08c9e42..0000000
--- a/.config/awesome/quarrel/native/src/mpd.rs
+++ /dev/null
@@ -1,142 +0,0 @@
-use std::{
- ffi::c_void,
- fs::File,
- net::TcpStream,
- path::PathBuf,
- sync::mpsc::channel,
-};
-
-use dirs::home_dir;
-use gdk_pixbuf::{
- ffi::GdkPixbuf,
- glib::translate::IntoGlibPtr,
- traits::PixbufLoaderExt,
- Pixbuf,
- PixbufLoader,
-};
-use mlua::{
- prelude::*,
- LuaSerdeExt,
-};
-use mpd::Client;
-use once_cell::sync::Lazy;
-use symphonia::{
- core::{
- formats::FormatOptions,
- io::{
- MediaSourceStream,
- MediaSourceStreamOptions,
- },
- meta::MetadataOptions,
- probe::Hint,
- },
- default::get_probe,
-};
-
-static MPD_MUSIC_PATH: Lazy<PathBuf> = Lazy::new(|| {
- [
- home_dir().expect("home directory should be set"),
- "Music".into(),
- ]
- .iter()
- .collect()
-});
-
-static COVER_FORMATS: [&str; 2] = ["png", "jpg"];
-
-pub struct Connection(Client<TcpStream>);
-
-impl LuaUserData for Connection {
- fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
- methods.add_method_mut("status", |lua, this: &mut Connection, (): ()| {
- lua.to_value(&this.0.status().map_err(LuaError::external)?)
- });
-
- methods.add_method_mut("song", |lua, this: &mut Connection, (): ()| {
- Ok(
- if let Some(song) = this.0.currentsong().map_err(LuaError::external)? {
- lua.to_value(&song)?
- } else {
- LuaNil
- },
- )
- });
-
- methods.add_method(
- "get_cover_pixbuf",
- |_, _: &Connection, file: String| {
- let song_path = MPD_MUSIC_PATH.join(file);
- let mut has_external_cover = false;
- let mut cover_path = PathBuf::new();
-
- for format in COVER_FORMATS {
- let cover = song_path
- .parent()
- .unwrap()
- .to_owned()
- .join(format!("cover.{}", format));
- if cover.exists() {
- has_external_cover = cover.exists();
- cover_path = cover;
- break;
- }
- }
-
- let mss = MediaSourceStream::new(
- Box::new(File::open(song_path)?),
- MediaSourceStreamOptions::default(),
- );
-
- let mut probed = get_probe()
- .format(
- &Hint::default(),
- mss,
- &FormatOptions::default(),
- &MetadataOptions::default(),
- )
- .map_err(LuaError::external)?;
-
- let visuals;
-
- if let Some(metadata) = probed.format.metadata().skip_to_latest() {
- visuals = metadata.visuals();
- if visuals.is_empty() && has_external_cover {
- let pixbuf = Pixbuf::from_file(cover_path).map_err(LuaError::external)?;
-
- return Ok((
- Some(LuaLightUserData(unsafe {
- <Pixbuf as IntoGlibPtr<*mut GdkPixbuf>>::into_glib_ptr(pixbuf)
- .cast::<c_void>()
- })),
- Some(true),
- ));
- }
-
- let loader = PixbufLoader::new();
- loader
- .write(visuals.first().unwrap().data.as_ref())
- .map_err(LuaError::external)?;
- loader.close().map_err(LuaError::external)?;
-
- return Ok((
- Some(LuaLightUserData(unsafe {
- <Pixbuf as IntoGlibPtr<*mut GdkPixbuf>>::into_glib_ptr(
- loader.pixbuf().expect("Pixbuf should be initialized"),
- )
- .cast::<c_void>()
- })),
- Some(false),
- ));
- }
-
- Ok((None, None))
- },
- );
- }
-}
-
-pub fn init(_: &Lua, _: ()) -> LuaResult<Connection> {
- Ok(Connection(
- Client::connect("localhost:6600").map_err(LuaError::external)?,
- ))
-}
diff --git a/.config/awesome/quarrel/native/src/net/mod.rs b/.config/awesome/quarrel/native/src/net/mod.rs
index 96c853e..dbd87b9 100644
--- a/.config/awesome/quarrel/native/src/net/mod.rs
+++ b/.config/awesome/quarrel/native/src/net/mod.rs
@@ -9,7 +9,7 @@ use std::{
c_void,
},
mem::size_of,
- os::fd::RawFd,
+ os::fd::{IntoRawFd, RawFd},
};
use mlua::prelude::*;
@@ -108,7 +108,7 @@ fn get_first_socket() -> LuaResult<RawFd> {
for family in families {
if let Ok(socket) = open_socket(family, SockType::Datagram, SockFlag::empty(), None) {
- return Ok(socket);
+ return Ok(socket.into_raw_fd());
}
}
diff --git a/.config/awesome/quarrel/native/src/util.rs b/.config/awesome/quarrel/native/src/util.rs
index 85a2574..41096d8 100644
--- a/.config/awesome/quarrel/native/src/util.rs
+++ b/.config/awesome/quarrel/native/src/util.rs
@@ -1,7 +1,6 @@
use std::{
cell::RefCell,
fs::File,
- fs::OpenOptions,
io::{
Read,
Seek,
@@ -49,7 +48,7 @@ enum StringOrNumber {
pub struct FileHandle(Rc<RefCell<File>>);
impl LuaUserData for FileHandle {
- fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'lua, M: LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_method("read", |lua, this: &FileHandle, mode: String| {
let content = this.read()?;
Ok(lua.to_value(&match ReadMode::from_str(&mode).unwrap() {