diff --git a/Cargo.lock b/Cargo.lock index f6a55b65..b116bbd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,6 +130,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "bumpalo" version = "3.9.1" @@ -238,6 +244,7 @@ name = "cosmic-applet-audio" version = "0.1.0" dependencies = [ "async-io", + "freedesktop-desktop-entry", "futures-util", "libcosmic-widgets", "libpulse-binding", @@ -377,6 +384,35 @@ dependencies = [ "syn", ] +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dlib" version = "0.5.0" @@ -475,6 +511,19 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da1b8f89c5b5a5b7e59405cfcf0bb9588e5ed19f0b57a4cd542bbba3f164a6d" +[[package]] +name = "freedesktop-desktop-entry" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45157175a725e81f3f594382430b6b78af5f8f72db9bd51b94f0785f80fc6d29" +dependencies = [ + "dirs 3.0.2", + "gettext-rs", + "memchr", + "thiserror", + "xdg", +] + [[package]] name = "futures" version = "0.3.21" @@ -711,6 +760,26 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gettext-rs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49ea8a8fad198aaa1f9655a2524b64b70eb06b2f3ff37da407566c93054f364" +dependencies = [ + "gettext-sys", + "locale_config", +] + +[[package]] +name = "gettext-sys" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c63ce2e00f56a206778276704bbe38564c8695249fdc8f354b4ef71c57c3839d" +dependencies = [ + "cc", + "temp-dir", +] + [[package]] name = "gio" version = "0.15.6" @@ -1041,6 +1110,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "locale_config" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d2c35b16f4483f6c26f0e4e9550717a2f6575bcd6f12a53ff0c490a94a6934" +dependencies = [ + "lazy_static", + "objc", + "objc-foundation", + "regex", + "winapi", +] + [[package]] name = "lock_api" version = "0.4.6" @@ -1070,6 +1152,15 @@ dependencies = [ "zvariant", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.4.1" @@ -1200,6 +1291,35 @@ dependencies = [ "libc", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + [[package]] name = "once_cell" version = "1.10.0" @@ -1467,13 +1587,24 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "8ae183fc1b06c149f0c1793e1eb447c8b04bfe46d48e9e48bfb8d2d7ed64ecf0" dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7776223e2696f1aa4c6b0170e83212f47296a00424305117d013dfe86fb0fe55" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + [[package]] name = "regex" version = "1.5.4" @@ -1699,6 +1830,12 @@ dependencies = [ "version-compare", ] +[[package]] +name = "temp-dir" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af547b166dd1ea4b472165569fc456cfb6818116f854690b0ff205e636523dab" + [[package]] name = "thiserror" version = "1.0.30" @@ -2034,6 +2171,15 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "xdg" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4583db5cbd4c4c0303df2d15af80f0539db703fa1c68802d4cbbd2dd0f88f6" +dependencies = [ + "dirs 4.0.0", +] + [[package]] name = "xml-rs" version = "0.8.4" diff --git a/applets/cosmic-applet-audio/Cargo.toml b/applets/cosmic-applet-audio/Cargo.toml index db88c39b..e2d49550 100644 --- a/applets/cosmic-applet-audio/Cargo.toml +++ b/applets/cosmic-applet-audio/Cargo.toml @@ -10,7 +10,10 @@ futures-util = "0.3.21" libcosmic-widgets = { git = "https://github.com/pop-os/libcosmic", branch = "lucy/widgets" } libpulse-binding = "2.26.0" pulsectl-rs = "0.3.2" -relm4 = { git = "https://github.com/AaronErhardt/relm4", branch = "new-approach", features = ["macros"] } +relm4 = { git = "https://github.com/AaronErhardt/relm4", branch = "new-approach", features = [ + "macros", +] } tracker = "0.1.1" +freedesktop-desktop-entry = "0.5.0" [features] diff --git a/applets/cosmic-applet-audio/src/app.rs b/applets/cosmic-applet-audio/src/app.rs index eb920ad1..a68423bf 100644 --- a/applets/cosmic-applet-audio/src/app.rs +++ b/applets/cosmic-applet-audio/src/app.rs @@ -1,3 +1,4 @@ +use crate::icons::{parse_desktop_icons, DesktopApplication}; use futures_util::StreamExt; use libcosmic_widgets::LabeledItem; use libpulse_binding::{ @@ -22,7 +23,7 @@ use relm4::{ }, view, ComponentParts, RelmContainerExt, Sender, SimpleComponent, }; -use std::rc::Rc; +use std::{collections::HashMap, rc::Rc}; use tracker::track; pub enum AppInput { @@ -46,6 +47,8 @@ pub struct App { #[no_eq] now_playing: Vec, #[do_not_track] + desktop_icons: HashMap, + #[do_not_track] handler: Handler, } @@ -60,6 +63,7 @@ impl Default for App { let default_output = output_controller.get_default_device().ok(); let outputs = output_controller.list_devices().unwrap_or_default(); let now_playing = output_controller.list_applications().unwrap_or_default(); + let desktop_icons = parse_desktop_icons(); let handler = Handler::connect("com.system76.cosmic.applets.audio") .expect("failed to connect to pulse"); relm4::spawn_local(clone!(@weak handler.mainloop as main_loop => async move { @@ -75,6 +79,7 @@ impl Default for App { default_output, outputs, now_playing, + desktop_icons, handler, tracker: 0, } @@ -234,7 +239,20 @@ impl App { let icon_name = app .proplist .get_str("application.icon_name") + .or_else(|| { + app.proplist + .get_str("application.name") + .and_then(|name| self.desktop_icons.get(&DesktopApplication::Name(name))) + .cloned() + }) + .or_else(|| { + app.proplist + .get_str("application.process.binary") + .and_then(|name| self.desktop_icons.get(&DesktopApplication::Binary(name))) + .cloned() + }) .unwrap_or_default(); + let name = app.name.clone().unwrap_or_default(); view! { item = GtkBox { diff --git a/applets/cosmic-applet-audio/src/icons.rs b/applets/cosmic-applet-audio/src/icons.rs new file mode 100644 index 00000000..ab9dff14 --- /dev/null +++ b/applets/cosmic-applet-audio/src/icons.rs @@ -0,0 +1,37 @@ +use std::collections::HashMap; + +use freedesktop_desktop_entry::{default_paths, DesktopEntry, Iter}; + +#[derive(Debug, Hash, PartialEq, Eq)] +pub enum DesktopApplication { + Name(String), + Binary(String), +} + +pub fn parse_desktop_icons() -> HashMap { + let mut out = HashMap::new(); + for path in Iter::new(default_paths()) { + let file = match std::fs::read_to_string(&path) { + Ok(data) => data, + _ => continue, + }; + let entry = match DesktopEntry::decode(&path, &file) { + Ok(entry) => entry, + _ => continue, + }; + let icon = match entry.icon() { + Some(icon) => icon, + None => continue, + }; + if let Some(name) = entry.name(None) { + out.insert(DesktopApplication::Name(name.into_owned()), icon.to_owned()); + }; + if let Some(exec) = entry + .exec() + .and_then(|entry| entry.split_whitespace().next()) + { + out.insert(DesktopApplication::Binary(exec.to_owned()), icon.to_owned()); + }; + } + out +} diff --git a/applets/cosmic-applet-audio/src/main.rs b/applets/cosmic-applet-audio/src/main.rs index 3df10542..e8628a12 100644 --- a/applets/cosmic-applet-audio/src/main.rs +++ b/applets/cosmic-applet-audio/src/main.rs @@ -4,19 +4,10 @@ extern crate relm4; mod app; +mod icons; use relm4::RelmApp; fn main() { - figure_out_apps(); RelmApp::::new("com.system76.cosmic.applets.audio").run(()); } - -fn figure_out_apps() { - use pulsectl::controllers::{AppControl, SinkController}; - - let mut sink = SinkController::create().unwrap(); - for app in sink.list_applications().unwrap() { - println!("{:#?}", app); - } -}