pnmixer-rust/src/notif.rs

181 lines
5.7 KiB
Rust
Raw Normal View History

2017-07-14 15:23:42 +00:00
//! The notification subsystem.
//!
//! This subsystem utilizes libnotify to send notifications as popups
//! to the desktop.
2017-06-26 07:08:37 +00:00
use app_state::*;
2017-07-19 10:12:08 +00:00
use audio::frontend::*;
2017-06-26 07:08:37 +00:00
use errors::*;
use glib::prelude::*;
use libnotify;
use prefs::*;
use std::cell::Cell;
use std::rc::Rc;
2017-07-14 15:23:42 +00:00
/// An expression of our notification system. Holds all the relevant information
/// needed by Gtk+ callbacks to interact with libnotify.
2017-06-26 07:08:37 +00:00
pub struct Notif {
enabled: Cell<bool>,
from_popup: Cell<bool>,
from_tray: Cell<bool>,
from_hotkeys: Cell<bool>,
2017-06-26 07:08:37 +00:00
from_external: Cell<bool>,
volume_notif: libnotify::Notification,
text_notif: libnotify::Notification,
}
impl Notif {
2017-07-14 15:23:42 +00:00
/// Create a new notification instance from the current preferences.
/// This should only be done once at startup. This also initializes
/// the libnotify system.
2017-06-26 07:08:37 +00:00
pub fn new(prefs: &Prefs) -> Result<Self> {
libnotify::init("PNMixer-rs")?;
2017-06-26 07:08:37 +00:00
let notif = Notif {
enabled: Cell::new(false),
from_popup: Cell::new(false),
from_tray: Cell::new(false),
from_hotkeys: Cell::new(false),
2017-06-26 07:08:37 +00:00
from_external: Cell::new(false),
volume_notif: libnotify::Notification::new("", None, None),
text_notif: libnotify::Notification::new("", None, None),
};
notif.reload(prefs);
2017-06-26 07:08:37 +00:00
return Ok(notif);
}
2017-07-14 15:23:42 +00:00
/// Reload the notification instance from the current
/// preferences.
pub fn reload(&self, prefs: &Prefs) {
2017-06-26 07:08:37 +00:00
let timeout = prefs.notify_prefs.notifcation_timeout;
self.enabled.set(prefs.notify_prefs.enable_notifications);
self.from_popup.set(prefs.notify_prefs.notify_popup);
self.from_tray.set(prefs.notify_prefs.notify_mouse_scroll);
self.from_hotkeys.set(prefs.notify_prefs.notify_hotkeys);
2017-06-26 07:08:37 +00:00
self.from_external.set(prefs.notify_prefs.notify_external);
self.volume_notif.set_timeout(timeout as i32);
2017-07-19 10:12:08 +00:00
self.volume_notif.set_hint(
"x-canonical-private-synchronous",
Some("".to_variant()),
);
2017-06-26 07:08:37 +00:00
self.text_notif.set_timeout(timeout as i32);
2017-07-19 10:12:08 +00:00
self.text_notif.set_hint(
"x-canonical-private-synchronous",
Some("".to_variant()),
);
2017-06-26 07:08:37 +00:00
}
2017-07-14 15:23:42 +00:00
/// Shows a volume notification, e.g. for volume or mute state change.
pub fn show_volume_notif<T>(&self, audio: &T) -> Result<()>
2017-07-19 10:12:08 +00:00
where
T: AudioFrontend,
{
let vol = audio.get_vol()?;
2017-06-26 07:08:37 +00:00
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"),
_ => {
2017-07-19 10:12:08 +00:00
format!(
"{} ({})\nVolume: {}",
audio.card_name()?,
audio.chan_name()?,
vol as i32
)
2017-06-26 07:08:37 +00:00
}
}
};
2017-07-19 10:12:08 +00:00
self.volume_notif
2017-07-22 14:24:32 +00:00
.update(summary.as_str(), None, Some(icon))?;
2017-07-19 10:12:08 +00:00
self.volume_notif.set_hint(
"value",
Some((vol as i32).to_variant()),
);
2017-07-22 14:24:32 +00:00
self.volume_notif.show()?;
2017-06-26 07:08:37 +00:00
return Ok(());
}
2017-07-14 15:23:42 +00:00
/// Shows a text notification, e.g. for warnings or errors.
2017-06-26 07:08:37 +00:00
pub fn show_text_notif(&self, summary: &str, body: &str) -> Result<()> {
2017-07-22 14:24:32 +00:00
self.text_notif.update(summary, Some(body), None)?;
self.text_notif.show()?;
2017-06-26 07:08:37 +00:00
return Ok(());
}
}
impl Drop for Notif {
fn drop(&mut self) {
libnotify::uninit();
}
}
2017-06-26 07:08:37 +00:00
2017-07-14 15:23:42 +00:00
/// Initialize the notification subsystem.
pub fn init_notify<T>(appstate: Rc<AppS<T>>)
2017-07-19 10:12:08 +00:00
where
T: AudioFrontend + 'static,
{
2017-06-26 07:08:37 +00:00
{
/* connect handler */
2017-10-10 06:43:08 +00:00
// let apps = appstate.clone();
// appstate.audio.connect_handler(Box::new(move |s, u| {
// let notif = &apps.notif;
// if notif.is_none() || !notif.as_ref().unwrap().enabled.get() {
// return;
// }
// let notif = notif.as_ref().unwrap();
// match (s,
// u,
// (notif.from_popup.get(),
// notif.from_tray.get(),
// notif.from_external.get(),
// notif.from_hotkeys.get())) {
// (AudioSignal::NoCard, _, _) => try_w!(notif.show_text_notif("No sound card", "No playable soundcard found")),
// (AudioSignal::CardDisconnected, _, _) => try_w!(notif.show_text_notif("Soundcard disconnected", "Soundcard has been disconnected, reloading sound system...")),
// (AudioSignal::CardError, _, _) => (),
// (AudioSignal::ValuesChanged,
// AudioUser::TrayIcon,
// (_, true, _, _)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
// (AudioSignal::ValuesChanged,
// AudioUser::Popup,
// (true, _, _, _)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
// (AudioSignal::ValuesChanged,
// AudioUser::Unknown,
// (_, _, true, _)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
// (AudioSignal::ValuesChanged,
// AudioUser::Hotkeys,
// (_, _, _, true)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
// _ => (),
// }
// }));
2017-06-26 07:08:37 +00:00
}
}