From 20e5b978427d9649dab49e12239e99f1eb0a0480 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Mon, 10 Jul 2017 21:07:59 +0200 Subject: [PATCH] Update --- Cargo.toml | 5 ++- src/alsa_card.rs | 6 ++-- src/app_state.rs | 13 +++++--- src/audio.rs | 8 ++--- src/errors.rs | 12 +++++--- src/main.rs | 19 +++++------- src/notif.rs | 70 +++++++++++++++++++++++------------------- src/prefs.rs | 3 ++ src/support_ui.rs | 13 ++++---- src/ui_entry.rs | 20 ++++++------ src/ui_prefs_dialog.rs | 34 ++++++++++++++++++-- 11 files changed, 127 insertions(+), 76 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2cc74b413..a7a402b23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ serde_derive = "^1.0.9" toml = "^0.4.2" which = "*" xdg = "*" -libnotify = { path = "3rdparty/rust-libnotify" } +libnotify = { path = "3rdparty/rust-libnotify", optional = true } [dependencies.gtk] git = "https://github.com/gtk-rs/gtk.git" @@ -45,3 +45,6 @@ codegen-units = 1 # controls whether the compiler passes `-C codegen-units` # `codegen-units` is ignored when `lto = true` panic = 'unwind' # panic strategy (`-C panic=...`), can also be 'abort' + +[features] +notify = ["libnotify"] diff --git a/src/alsa_card.rs b/src/alsa_card.rs index 457944d68..f4208dce8 100644 --- a/src/alsa_card.rs +++ b/src/alsa_card.rs @@ -262,17 +262,17 @@ extern "C" fn watch_cb(chan: *mut glib_sys::GIOChannel, glib_sys::G_IO_STATUS_AGAIN => { debug!("G_IO_STATUS_AGAIN"); continue; - }, + } // TODO: handle these failure cases glib_sys::G_IO_STATUS_NORMAL => { error!("Alsa failed to clear the channel"); cb(AlsaEvent::AlsaCardError); - }, + } glib_sys::G_IO_STATUS_ERROR => (), glib_sys::G_IO_STATUS_EOF => { error!("GIO error has occurred"); cb(AlsaEvent::AlsaCardError); - }, + } _ => warn!("Unknown status from g_io_channel_read_chars()"), } return true as glib_sys::gboolean; diff --git a/src/app_state.rs b/src/app_state.rs index 8cef5dc08..eb8baeb4a 100644 --- a/src/app_state.rs +++ b/src/app_state.rs @@ -1,12 +1,12 @@ use audio::Audio; use errors::*; use gtk; -use notif; use prefs::*; use std::cell::RefCell; -use std::rc::Rc; use ui_entry::Gui; +#[cfg(feature = "notify")] +use notif::*; // TODO: notify popups @@ -19,6 +19,8 @@ pub struct AppS { pub gui: Gui, pub audio: Audio, pub prefs: RefCell, + #[cfg(feature = "notify")] + pub notif: Notif, } @@ -42,14 +44,17 @@ impl AppS { .device_prefs .channel .clone(); - - // let notif = Notif::new(&prefs.borrow()); + // TODO: better error handling + #[cfg(feature = "notify")] + let notif = Notif::new(&prefs.borrow()).unwrap(); return AppS { _cant_construct: (), gui, audio: Audio::new(Some(card_name), Some(chan_name)).unwrap(), prefs, + #[cfg(feature = "notify")] + notif, }; } diff --git a/src/audio.rs b/src/audio.rs index feb508600..cf8165c6c 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -141,8 +141,8 @@ impl Audio { } // invoke_handlers(&self.handlers.borrow(), - // AudioSignal::CardCleanedUp, - // user); + // AudioSignal::CardCleanedUp, + // user); invoke_handlers(&self.handlers.borrow(), AudioSignal::CardInitialized, user); @@ -341,12 +341,12 @@ fn on_alsa_event(last_action_timestamp: &mut i64, invoke_handlers(handlers, self::AudioSignal::CardError, self::AudioUser::Unknown); - }, + } AlsaEvent::AlsaCardDiconnected => { invoke_handlers(handlers, self::AudioSignal::CardDisconnected, self::AudioUser::Unknown); - }, + } AlsaEvent::AlsaCardValuesChanged => { invoke_handlers(handlers, self::AudioSignal::ValuesChanged, diff --git a/src/errors.rs b/src/errors.rs index 856a19cef..8def5fa8d 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,10 +1,11 @@ use alsa; -use glib; -use libnotify; use std::convert::From; use std; use toml; +#[cfg(feature = "notify")] +use libnotify; + error_chain! { @@ -12,12 +13,13 @@ error_chain! { Alsa(alsa::Error); IO(std::io::Error); Toml(toml::de::Error); - Libnotify(libnotify::errors::Error); + Libnotify(libnotify::errors::Error) #[cfg(feature = "notify")]; } - } + + #[macro_export] macro_rules! try_w { ($expr:expr) => { @@ -64,7 +66,7 @@ macro_rules! try_wr { macro_rules! try_r { ($expr:expr, $ret:expr) => (match $expr { ::std::result::Result::Ok(val) => val, - ::std::result::Result::Err(err) => { + ::std::result::Result::Err(_) => { return $ret; }, }); diff --git a/src/main.rs b/src/main.rs index bdde16977..1777691ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,6 +29,8 @@ extern crate gtk_sys; extern crate libc; extern crate which; extern crate xdg; + +#[cfg(feature = "notify")] extern crate libnotify; use std::rc::Rc; @@ -52,6 +54,8 @@ mod ui_popup_menu; mod ui_popup_window; mod ui_prefs_dialog; mod ui_tray_icon; + +#[cfg(feature = "notify")] mod notif; @@ -63,19 +67,10 @@ use app_state::*; fn main() { gtk::init().unwrap(); + // TODO: error handling + #[cfg(feature = "notify")] 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 ... @@ -87,5 +82,7 @@ fn main() { ui_entry::init(apps); gtk::main(); + + #[cfg(feature = "notify")] libnotify::uninit(); } diff --git a/src/notif.rs b/src/notif.rs index 127d6c643..62ab1bd33 100644 --- a/src/notif.rs +++ b/src/notif.rs @@ -30,7 +30,6 @@ pub struct Notif { from_popup: Cell, from_tray: Cell, // TODO: from hotkey - from_external: Cell, volume_notif: libnotify::Notification, @@ -58,18 +57,16 @@ impl Notif { 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.from_popup.set(prefs.notify_prefs.notify_popup); + self.from_tray.set(prefs.notify_prefs.notify_mouse_scroll); + self.from_external.set(prefs.notify_prefs.notify_external); - self.volume_notif - .set_notification_timeout(timeout as i32); + 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_notification_timeout(timeout as i32); self.text_notif .set_hint("x-canonical-private-synchronous", Some("".to_variant()))?; @@ -95,17 +92,19 @@ impl Notif { VolLevel::Muted => String::from("Volume muted"), _ => { format!("{} ({})\nVolume: {}", - audio.acard.borrow().card_name()?, - audio.acard.borrow().chan_name()?, + 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.update(summary.as_str(), None, Some(icon))?; + self.volume_notif.set_hint("value", Some((vol as i32).to_variant()))?; self.volume_notif.show()?; return Ok(()); @@ -113,8 +112,7 @@ impl Notif { pub fn show_text_notif(&self, summary: &str, body: &str) -> Result<()> { - self.text_notif - .update(summary, Some(body), None)?; + self.text_notif.update(summary, Some(body), None)?; self.text_notif.show()?; return Ok(()); @@ -124,25 +122,35 @@ impl Notif { pub fn init_notify(appstate: Rc) { + debug!("Blah"); { /* 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)) - }, + appstate.audio.connect_handler(Box::new(move |s, u| { + let notif = &apps.notif; + if !notif.enabled.get() { + return; + } + match (s, + u, + (notif.from_popup.get(), + notif.from_tray.get(), + notif.from_external.get())) { + (AudioSignal::CardDisconnected, _, _) => (), + (AudioSignal::CardError, _, _) => (), + (AudioSignal::ValuesChanged, + AudioUser::TrayIcon, + (_, true, _)) => try_w!(notif.show_volume_notif(&apps.audio)), + (AudioSignal::ValuesChanged, + AudioUser::Popup, + (true, _, _)) => try_w!(notif.show_volume_notif(&apps.audio)), + (AudioSignal::ValuesChanged, + AudioUser::Unknown, + (_, _, true)) => try_w!(notif.show_volume_notif(&apps.audio)), + _ => (), - } - ) - ); + } + })); } } - - - - diff --git a/src/prefs.rs b/src/prefs.rs index 0fc764fa2..a345cf1c9 100644 --- a/src/prefs.rs +++ b/src/prefs.rs @@ -140,6 +140,7 @@ impl Default for BehaviorPrefs { } +#[cfg(feature = "notify")] #[derive(Deserialize, Debug, Serialize)] #[serde(default)] pub struct NotifyPrefs { @@ -151,6 +152,7 @@ pub struct NotifyPrefs { // TODO: notify_hotkeys? } +#[cfg(feature = "notify")] impl Default for NotifyPrefs { fn default() -> NotifyPrefs { return NotifyPrefs { @@ -170,6 +172,7 @@ pub struct Prefs { pub device_prefs: DevicePrefs, pub view_prefs: ViewPrefs, pub behavior_prefs: BehaviorPrefs, + #[cfg(feature = "notify")] pub notify_prefs: NotifyPrefs, // TODO: HotKeys? } diff --git a/src/support_ui.rs b/src/support_ui.rs index 7e5441c10..30a1d28d3 100644 --- a/src/support_ui.rs +++ b/src/support_ui.rs @@ -44,12 +44,13 @@ pub fn pixbuf_new_from_theme(icon_name: &str, pub fn pixbuf_new_from_file(filename: &str) -> Result { ensure!(!filename.is_empty(), "Filename is empty"); let mut syspath = String::new(); - let sysdir = option_env!("PIXMAPSDIR").map(|s|{ - syspath = format!("{}/{}", s, filename); - Path::new(syspath.as_str()) - }); - let cargopath = format!("./data/pixmaps/{}", - filename); + let sysdir = option_env!("PIXMAPSDIR").map(|s| { + syspath = format!("{}/{}", + s, + filename); + Path::new(syspath.as_str()) + }); + let cargopath = format!("./data/pixmaps/{}", filename); let cargodir = Path::new(cargopath.as_str()); // prefer local dir diff --git a/src/ui_entry.rs b/src/ui_entry.rs index 3840a3ad7..ace897619 100644 --- a/src/ui_entry.rs +++ b/src/ui_entry.rs @@ -5,7 +5,7 @@ use gtk::MessageDialogExt; use gtk::WidgetExt; use gtk::WindowExt; use gtk; -use gtk_sys::{GTK_DIALOG_DESTROY_WITH_PARENT, GTK_RESPONSE_YES}; +use gtk_sys::{GTK_RESPONSE_YES}; use prefs::*; use std::cell::RefCell; use std::rc::Rc; @@ -14,8 +14,9 @@ use ui_popup_menu::*; use ui_popup_window::*; use ui_prefs_dialog::*; use ui_tray_icon::*; -use notif::*; +#[cfg(feature = "notify")] +use notif::*; @@ -26,6 +27,7 @@ pub struct Gui { pub popup_menu: PopupMenu, /* prefs_dialog is dynamically created and destroyed */ pub prefs_dialog: RefCell>, + } impl Gui { @@ -72,6 +74,8 @@ pub fn init(appstate: Rc) { init_popup_window(appstate.clone()); init_popup_menu(appstate.clone()); init_prefs_callback(appstate.clone()); + + #[cfg(feature = "notify")] init_notify(appstate.clone()); } @@ -79,13 +83,11 @@ pub fn init(appstate: Rc) { fn run_audio_error_dialog(parent: >k::Window) -> i32 { error!("Connection with audio failed, you probably need to restart pnmixer."); - let dialog = gtk::MessageDialog::new( - Some(parent), - gtk::DIALOG_DESTROY_WITH_PARENT, - gtk::MessageType::Error, - gtk::ButtonsType::YesNo, - "Warning: Connection to sound system failed." - ); + let dialog = gtk::MessageDialog::new(Some(parent), + gtk::DIALOG_DESTROY_WITH_PARENT, + gtk::MessageType::Error, + gtk::ButtonsType::YesNo, + "Warning: Connection to sound system failed."); dialog.set_property_secondary_text(Some("Do you want to re-initialize the audio connection ? If you do not, you will either need to restart PNMixer diff --git a/src/ui_prefs_dialog.rs b/src/ui_prefs_dialog.rs index 150b9bfe8..3b3fcfee5 100644 --- a/src/ui_prefs_dialog.rs +++ b/src/ui_prefs_dialog.rs @@ -19,6 +19,7 @@ use support_audio::*; pub struct PrefsDialog { _cant_construct: (), prefs_dialog: gtk::Dialog, + notebook: gtk::Notebook, /* DevicePrefs */ card_combo: gtk::ComboBoxText, @@ -38,11 +39,16 @@ pub struct PrefsDialog { custom_entry: gtk::Entry, /* NotifyPrefs */ + #[cfg(feature = "notify")] noti_enable_check: gtk::CheckButton, + #[cfg(feature = "notify")] noti_timeout_spin: gtk::SpinButton, // pub noti_hotkey_check: gtk::CheckButton, + #[cfg(feature = "notify")] noti_mouse_check: gtk::CheckButton, + #[cfg(feature = "notify")] noti_popup_check: gtk::CheckButton, + #[cfg(feature = "notify")] noti_ext_check: gtk::CheckButton, } @@ -54,6 +60,7 @@ impl PrefsDialog { let prefs_dialog = PrefsDialog { _cant_construct: (), prefs_dialog: builder.get_object("prefs_dialog").unwrap(), + notebook: builder.get_object("notebook").unwrap(), card_combo: builder.get_object("card_combo").unwrap(), chan_combo: builder.get_object("chan_combo").unwrap(), @@ -74,15 +81,26 @@ impl PrefsDialog { .unwrap(), custom_entry: builder.get_object("custom_entry").unwrap(), + #[cfg(feature = "notify")] noti_enable_check: builder.get_object("noti_enable_check").unwrap(), + #[cfg(feature = "notify")] noti_timeout_spin: builder.get_object("noti_timeout_spin").unwrap(), // noti_hotkey_check: builder.get_object("noti_hotkey_check").unwrap(), + #[cfg(feature = "notify")] noti_mouse_check: builder.get_object("noti_mouse_check").unwrap(), + #[cfg(feature = "notify")] noti_popup_check: builder.get_object("noti_popup_check").unwrap(), + #[cfg(feature = "notify")] noti_ext_check: builder.get_object("noti_ext_check").unwrap(), }; + #[cfg(feature = "notify")] + let notify_tab: gtk::Box = builder.get_object("noti_vbox_enabled").unwrap(); + #[cfg(not(feature = "notify"))] + let notify_tab: gtk::Box = builder.get_object("noti_vbox_disabled").unwrap(); + prefs_dialog.notebook.append_page(¬ify_tab, + Some(>k::Label::new(Some("Notifications")))); return prefs_dialog; } @@ -134,13 +152,18 @@ impl PrefsDialog { .as_str()); /* NotifyPrefs */ + #[cfg(feature = "notify")] self.noti_enable_check .set_active(prefs.notify_prefs.enable_notifications); + #[cfg(feature = "notify")] self.noti_timeout_spin .set_value(prefs.notify_prefs.notifcation_timeout as f64); + #[cfg(feature = "notify")] self.noti_mouse_check .set_active(prefs.notify_prefs.notify_mouse_scroll); + #[cfg(feature = "notify")] self.noti_popup_check.set_active(prefs.notify_prefs.notify_popup); + #[cfg(feature = "notify")] self.noti_ext_check.set_active(prefs.notify_prefs.notify_external); } @@ -193,6 +216,7 @@ impl PrefsDialog { custom_command, }; + #[cfg(feature = "notify")] let notify_prefs = NotifyPrefs { enable_notifications: self.noti_enable_check.get_active(), notifcation_timeout: self.noti_timeout_spin.get_value_as_int() as @@ -206,6 +230,7 @@ impl PrefsDialog { device_prefs, view_prefs, behavior_prefs, + #[cfg(feature = "notify")] notify_prefs, }; @@ -240,7 +265,10 @@ pub fn init_prefs_callback(appstate: Rc) { let apps = appstate.clone(); appstate.audio.connect_handler(Box::new(move |s, u| { /* skip if prefs window is not present */ - if apps.gui.prefs_dialog.borrow().is_none() { + if apps.gui + .prefs_dialog + .borrow() + .is_none() { return; } @@ -249,7 +277,7 @@ pub fn init_prefs_callback(appstate: Rc) { (AudioSignal::CardCleanedUp, _) => { fill_card_combo(&apps); fill_chan_combo(&apps, None); - }, + } _ => (), } })); @@ -308,6 +336,8 @@ fn init_prefs_dialog(appstate: &Rc) { if response_id == ResponseType::Ok.into() || response_id == ResponseType::Apply.into() { // TODO: update popup, tray_icon, hotkeys, notification and audio + #[cfg(feature = "notify")] + try_w!(apps.notif.reload(&apps.prefs.borrow())); try_w!(apps.update_tray_icon()); try_w!(apps.update_popup_window()); {