From 3b943131df608f30d152d02b4628f8f3b536a15b Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Mon, 10 Jul 2017 09:23:09 +0200 Subject: [PATCH] Blah --- Cargo.toml | 1 + src/app_state.rs | 8 +-- src/errors.rs | 2 + src/main.rs | 28 +++++++-- src/notif.rs | 148 +++++++++++++++++++++++++++++++++++++++++++++++ src/ui_entry.rs | 3 +- 6 files changed, 179 insertions(+), 11 deletions(-) create mode 100644 src/notif.rs diff --git a/Cargo.toml b/Cargo.toml index fba25ec7c..2cc74b413 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ serde_derive = "^1.0.9" toml = "^0.4.2" which = "*" xdg = "*" +libnotify = { path = "3rdparty/rust-libnotify" } [dependencies.gtk] git = "https://github.com/gtk-rs/gtk.git" diff --git a/src/app_state.rs b/src/app_state.rs index 38d081272..8cef5dc08 100644 --- a/src/app_state.rs +++ b/src/app_state.rs @@ -1,11 +1,11 @@ use audio::Audio; use errors::*; use gtk; +use notif; use prefs::*; use std::cell::RefCell; +use std::rc::Rc; use ui_entry::Gui; -use ui_prefs_dialog::show_prefs_dialog; -use notif::*; // TODO: notify popups @@ -18,7 +18,6 @@ pub struct AppS { _cant_construct: (), pub gui: Gui, pub audio: Audio, - pub notif: Notif, pub prefs: RefCell, } @@ -44,13 +43,12 @@ impl AppS { .channel .clone(); - let notif = Notif::new(&prefs.borrow()); + // let notif = Notif::new(&prefs.borrow()); return AppS { _cant_construct: (), gui, audio: Audio::new(Some(card_name), Some(chan_name)).unwrap(), - notif, prefs, }; } diff --git a/src/errors.rs b/src/errors.rs index c5c21d48a..856a19cef 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,5 +1,6 @@ use alsa; use glib; +use libnotify; use std::convert::From; use std; use toml; @@ -11,6 +12,7 @@ error_chain! { Alsa(alsa::Error); IO(std::io::Error); Toml(toml::de::Error); + Libnotify(libnotify::errors::Error); } } diff --git a/src/main.rs b/src/main.rs index daeaab569..bdde16977 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,6 +29,7 @@ extern crate gtk_sys; extern crate libc; extern crate which; extern crate xdg; +extern crate libnotify; use std::rc::Rc; @@ -41,16 +42,19 @@ mod glade_helpers; mod alsa_card; mod app_state; mod audio; -mod ui_entry; -mod ui_popup_menu; -mod ui_popup_window; -mod ui_prefs_dialog; -mod ui_tray_icon; mod prefs; mod support_alsa; mod support_audio; mod support_cmd; mod support_ui; +mod ui_entry; +mod ui_popup_menu; +mod ui_popup_window; +mod ui_prefs_dialog; +mod ui_tray_icon; +mod notif; + + use app_state::*; @@ -59,6 +63,19 @@ use app_state::*; fn main() { gtk::init().unwrap(); + libnotify::init("PNMixer-rs").unwrap(); + + { + // Create a new notification and show it + let n = libnotify::Notification::new("Summary", Some("Optional Body"), None) + .unwrap(); + n.show().unwrap(); + // You can also use the .show() convenience method on the context + n.update("I am another notification", None, None).unwrap(); + n.show().unwrap(); + // we are done, deinit + } + flexi_logger::LogOptions::new() .log_to_file(false) // ... your configuration options go here ... @@ -70,4 +87,5 @@ fn main() { ui_entry::init(apps); gtk::main(); + libnotify::uninit(); } diff --git a/src/notif.rs b/src/notif.rs new file mode 100644 index 000000000..127d6c643 --- /dev/null +++ b/src/notif.rs @@ -0,0 +1,148 @@ +use app_state::*; +use audio::*; +use gtk::DialogExt; +use gtk::MessageDialogExt; +use gtk::WidgetExt; +use gtk::WindowExt; +use gtk; +use gtk_sys::{GTK_DIALOG_DESTROY_WITH_PARENT, GTK_RESPONSE_YES}; +use prefs::*; +use std::cell::Cell; +use std::cell::RefCell; +use std::rc::Rc; +use support_audio::*; +use support_ui::*; +use ui_popup_menu::*; +use ui_popup_window::*; +use ui_prefs_dialog::*; +use ui_tray_icon::*; +use errors::*; + +use libnotify; +use std::thread; +use std::time::Duration; +use glib::Variant; +use glib::prelude::*; + + +pub struct Notif { + enabled: Cell, + from_popup: Cell, + from_tray: Cell, + // TODO: from hotkey + + from_external: Cell, + + volume_notif: libnotify::Notification, + text_notif: libnotify::Notification, +} + +impl Notif { + pub fn new(prefs: &Prefs) -> Result { + let notif = Notif { + enabled: Cell::new(false), + from_popup: Cell::new(false), + from_tray: Cell::new(false), + from_external: Cell::new(false), + + volume_notif: libnotify::Notification::new("", None, None).unwrap(), + text_notif: libnotify::Notification::new("", None, None).unwrap(), + }; + + notif.reload(prefs)?; + + return Ok(notif); + } + + pub fn reload(&self, prefs: &Prefs) -> Result<()> { + let timeout = prefs.notify_prefs.notifcation_timeout; + + self.enabled.set(prefs.notify_prefs.enable_notifications); + self.enabled.set(prefs.notify_prefs.notify_popup); + self.enabled.set(prefs.notify_prefs.notify_mouse_scroll); + self.enabled.set(prefs.notify_prefs.notify_external); + + self.volume_notif + .set_notification_timeout(timeout as i32); + self.volume_notif + .set_hint("x-canonical-private-synchronous", Some("".to_variant()))?; + + + self.text_notif + .set_notification_timeout(timeout as i32); + self.text_notif + .set_hint("x-canonical-private-synchronous", Some("".to_variant()))?; + + return Ok(()); + } + + pub fn show_volume_notif(&self, audio: &Audio) -> Result<()> { + let vol = audio.vol()?; + let vol_level = audio.vol_level(); + + let icon = { + match vol_level { + VolLevel::Muted => "audio-volume-muted", + VolLevel::Off => "audio-volume-off", + VolLevel::Low => "audio-volume-low", + VolLevel::Medium => "audio-volume-medium", + VolLevel::High => "audio-volume-high", + } + }; + + let summary = { + match vol_level { + VolLevel::Muted => String::from("Volume muted"), + _ => { + format!("{} ({})\nVolume: {}", + audio.acard.borrow().card_name()?, + audio.acard.borrow().chan_name()?, + vol) + } + } + }; + + self.volume_notif + .update(summary.as_str(), None, Some(icon))?; + self.volume_notif + .set_hint("value", Some(vol.to_variant()))?; + self.volume_notif.show()?; + + return Ok(()); + } + + + pub fn show_text_notif(&self, summary: &str, body: &str) -> Result<()> { + self.text_notif + .update(summary, Some(body), None)?; + self.text_notif.show()?; + + return Ok(()); + } +} + + + +pub fn init_notify(appstate: Rc) { + { + /* connect handler */ + let apps = appstate.clone(); + let notif = try_e!(Notif::new(&apps.prefs.borrow())); + appstate.audio.connect_handler( + Box::new(move |s, u| match (s, u) { + (AudioSignal::CardDisconnected, _) => (), + (AudioSignal::CardError, _) => (), + (AudioSignal::ValuesChanged, AudioUser::TrayIcon) => { + try_w!(notif.show_volume_notif(&apps.audio)) + }, + _ => (), + } + ) + ); + + } +} + + + + diff --git a/src/ui_entry.rs b/src/ui_entry.rs index 9d423abe8..3840a3ad7 100644 --- a/src/ui_entry.rs +++ b/src/ui_entry.rs @@ -6,7 +6,6 @@ use gtk::WidgetExt; use gtk::WindowExt; use gtk; use gtk_sys::{GTK_DIALOG_DESTROY_WITH_PARENT, GTK_RESPONSE_YES}; -use notif::*; use prefs::*; use std::cell::RefCell; use std::rc::Rc; @@ -15,6 +14,7 @@ use ui_popup_menu::*; use ui_popup_window::*; use ui_prefs_dialog::*; use ui_tray_icon::*; +use notif::*; @@ -72,6 +72,7 @@ pub fn init(appstate: Rc) { init_popup_window(appstate.clone()); init_popup_menu(appstate.clone()); init_prefs_callback(appstate.clone()); + init_notify(appstate.clone()); }