From 3f19417f75cc936210e38cd010102adbabe3620a Mon Sep 17 00:00:00 2001 From: "Ospald, Julian" Date: Tue, 27 Jun 2017 15:56:33 +0200 Subject: [PATCH] Update --- Cargo.toml | 9 ++++---- src/audio.rs | 61 +++++++++++++++++++++--------------------------- src/errors.rs | 53 ++++++++++++++++++++++++++++++++++++++++++ src/gui.rs | 64 ++++++++++++++++++++++++++++----------------------- src/main.rs | 57 +++++++++++++++++++++++++++------------------ 5 files changed, 154 insertions(+), 90 deletions(-) create mode 100644 src/errors.rs diff --git a/Cargo.toml b/Cargo.toml index 8746b6577..6687e54bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,14 +4,15 @@ version = "0.1.0" authors = ["Julian Ospald "] [dependencies] -alsa = "0.1.8" -libc = "0.2.23" +alsa = "^0.1.8" +libc = "^0.2.23" gdk-sys = { git = "https://github.com/gtk-rs/sys" } gtk-sys = { git = "https://github.com/gtk-rs/sys" } glib = { git = "https://github.com/gtk-rs/glib.git" } -ffi = "0.0.2" +ffi = "^0.0.2" flexi_logger = "^0.5.1" -log = "0.3.8" +log = "^0.3.8" +error-chain = "^0.10.0" [dependencies.gtk] git = "https://github.com/gtk-rs/gtk.git" diff --git a/src/audio.rs b/src/audio.rs index bc5b54671..eceaffa6d 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -7,6 +7,8 @@ use self::alsa::mixer::{Mixer, Selem, Elem}; use alsa::mixer::SelemChannelId::*; use std::iter::Map; use self::libc::c_int; +use errors::*; +use std::convert::From; @@ -22,39 +24,8 @@ pub fn get_alsa_cards() -> alsa::card::Iter { return alsa::card::Iter::new(); } -pub fn get_mixer(card: Card) -> Mixer { - let mixer = Mixer::new(&format!("hw:{}", card.get_index()), false).unwrap(); - - return mixer; -} - -pub fn get_selems(mixer: &Mixer) -> Map Selem> { - return mixer.iter().map(get_selem); -} - -pub fn get_selem_by_name<'a>(mixer: &'a Mixer, name: String) -> Option { - for selem in get_selems(mixer) { - let m_name = selem.get_id() - .get_name() - .map(|y| String::from(y)) - .ok(); - let retval = m_name.map_or(false, |n| { return n == name; }); - - if retval { - return Some(selem); - } - } - - return None; -} - -pub fn get_vol(selem: Selem) -> Result { - let (min, max) = selem.get_playback_volume_range(); - let volume = selem.get_playback_volume(FrontRight).map(|v| { - return ((v - min) as f64) / ((max - min) as f64) * 100.0; - }); - - return volume; +pub fn get_mixer(card: Card) -> Result { + return Mixer::new(&format!("hw:{}", card.get_index()), false).cherr(); } pub fn get_selem(elem: Elem) -> Selem { @@ -64,6 +35,26 @@ pub fn get_selem(elem: Elem) -> Selem { return Selem::new(elem).unwrap(); } -// pub fn list_channels(card: Card, hctl: HCtl) -> [str] { +pub fn get_selems(mixer: &Mixer) -> Map Selem> { + return mixer.iter().map(get_selem); +} -// } +pub fn get_selem_by_name<'a>(mixer: &'a Mixer, name: String) -> Result { + for selem in get_selems(mixer) { + let n = selem.get_id().get_name().map(|y| String::from(y))?; + + if n == name { + return Ok(selem); + } + } + bail!("Not found a matching selem named {}", name); +} + +pub fn get_vol(selem: Selem) -> Result { + let (min, max) = selem.get_playback_volume_range(); + let volume = selem.get_playback_volume(FrontRight).map(|v| { + return ((v - min) as f64) / ((max - min) as f64) * 100.0; + }); + + return volume.cherr(); +} diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 000000000..ba58831fc --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,53 @@ +use alsa; +use std; +use std::convert::From; + +error_chain! { + foreign_links { + Alsa(alsa::Error); + } + +} + +pub trait CHErr { + type Item; + fn cherr(self) -> Result; +} + +impl CHErr for std::result::Result + where Error: std::convert::From { + type Item = A; + fn cherr(self) -> Result { + return self.map_err(From::from); + } +} + + +#[macro_export] +macro_rules! try_w { + ($expr:expr) => { + try_wr!($expr, ()) + }; + ($expr:expr, $fmt:expr, $($arg:tt)+) => { + try_wr!($expr, (), $fmt, $(arg)+) + } +} + +#[macro_export] +macro_rules! try_wr { + ($expr:expr, $ret:expr) => (match $expr { + std::result::Result::Ok(val) => val, + std::result::Result::Err(err) => { + warn!("{:?}", err); + return $ret; + }, + }); + ($expr:expr, $ret:expr, $fmt:expr, $($arg:tt)+) => (match $expr { + std::result::Result::Ok(val) => val, + std::result::Result::Err(err) => { + warn!("Original error: {:?}", err); + warn!(format!($fmt, $(arg)+)); + return $ret; + }, + }) +} diff --git a/src/gui.rs b/src/gui.rs index 34070edd2..4687837c3 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -6,6 +6,8 @@ extern crate glib; extern crate ffi; extern crate libc; + +use errors::*; use gtk::prelude::*; use gdk::DeviceExt; use gdk::{GrabOwnership, GrabStatus, BUTTON_PRESS_MASK, KEY_PRESS_MASK}; @@ -15,44 +17,48 @@ pub fn set_slider(vol_scale_adj: >k::Adjustment, scale: f64) { vol_scale_adj.set_value(scale); } -pub fn grab_devices(window: >k::Window) { - let m_device = gtk::get_current_event_device(); - if m_device.is_none() { - warn!("Couldn't get current device"); - return; - } +pub fn grab_devices(window: >k::Window) -> Result<()> { + let device = gtk::get_current_event_device().ok_or("No current device")?; - let device = m_device.unwrap(); - let gdk_window = window.get_window().unwrap(); + let gdk_window = window.get_window().ok_or("No window?!")?; /* Grab the mouse */ - let m_grab_status = - device.grab(&gdk_window, - GrabOwnership::None, - true, - BUTTON_PRESS_MASK, - None, - GDK_CURRENT_TIME as u32); + let m_grab_status = device.grab( + &gdk_window, + GrabOwnership::None, + true, + BUTTON_PRESS_MASK, + None, + GDK_CURRENT_TIME as u32, + ); if m_grab_status != GrabStatus::Success { - warn!("Could not grab {}", device.get_name().unwrap()); + warn!( + "Could not grab {}", + device.get_name().unwrap_or(String::from("UNKNOWN DEVICE")) + ); } /* Grab the keyboard */ - let m_k_dev = device.get_associated_device(); - if m_k_dev.is_none() { - warn!("Couldn't get associated device"); - return; - } - let k_dev = m_k_dev.unwrap(); + let k_dev = device.get_associated_device().ok_or( + "Couldn't get associated device", + )?; - let k_grab_status = k_dev.grab(&gdk_window, - GrabOwnership::None, - true, - KEY_PRESS_MASK, - None, - GDK_CURRENT_TIME as u32); + let k_grab_status = k_dev.grab( + &gdk_window, + GrabOwnership::None, + true, + KEY_PRESS_MASK, + None, + GDK_CURRENT_TIME as u32, + ); if k_grab_status != GrabStatus::Success { - warn!("Could not grab {}", k_dev.get_name().unwrap()) + warn!( + "Could not grab {}", + k_dev.get_name().unwrap_or(String::from("UNKNOWN DEVICE")) + ); } + + return Ok(()); } + diff --git a/src/main.rs b/src/main.rs index 1230b2abf..64279258c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,9 @@ extern crate flexi_logger; #[macro_use] extern crate log; +#[macro_use] +extern crate error_chain; + extern crate gtk; extern crate gtk_sys; extern crate gdk; @@ -19,9 +22,12 @@ use gtk::prelude::*; use gdk_sys::GDK_KEY_Escape; +#[macro_use] +mod errors; mod audio; mod gui; +mod debug; fn main() { @@ -39,37 +45,39 @@ fn main() { let builder_popup = gtk::Builder::new_from_string(glade_src); { - let popup_window: gtk::Window = builder_popup.get_object("popup_window") - .unwrap(); - let vol_scale: gtk::Scale = builder_popup.get_object("vol_scale") - .unwrap(); + let popup_window: gtk::Window = + builder_popup.get_object("popup_window").unwrap(); + let vol_scale: gtk::Scale = + builder_popup.get_object("vol_scale").unwrap(); tray_icon.connect_activate(move |_| if popup_window.get_visible() { - popup_window.hide(); - } else { - popup_window.show_now(); - vol_scale.grab_focus(); - gui::grab_devices(&popup_window); - }); + popup_window.hide(); + } else { + popup_window.show_now(); + vol_scale.grab_focus(); + gui::grab_devices(&popup_window); + }); } { - let popup_window: gtk::Window = builder_popup.get_object("popup_window") - .unwrap(); - let vol_scale_adj: gtk::Adjustment = builder_popup.get_object("vol_scale_adj") - .unwrap(); + let popup_window: gtk::Window = + builder_popup.get_object("popup_window").unwrap(); + let vol_scale_adj: gtk::Adjustment = + builder_popup.get_object("vol_scale_adj").unwrap(); popup_window.connect_show(move |_| { let alsa_card = audio::get_default_alsa_card(); - let mixer = audio::get_mixer(alsa_card); - let selem = audio::get_selem_by_name(&mixer, - String::from("Master")) - .unwrap(); - gui::set_slider(&vol_scale_adj, audio::get_vol(selem).unwrap()) + let mixer = try_w!(audio::get_mixer(alsa_card)); + let selem = try_w!(audio::get_selem_by_name( + &mixer, + String::from("Master"), + )); + let cur_vol = try_w!(audio::get_vol(selem)); + gui::set_slider(&vol_scale_adj, cur_vol); }); } { - let popup_window: gtk::Window = builder_popup.get_object("popup_window") - .unwrap(); + let popup_window: gtk::Window = + builder_popup.get_object("popup_window").unwrap(); popup_window.connect_event(move |w, e| { match gdk::Event::get_event_type(e) { gdk::EventType::GrabBroken => w.hide(), @@ -80,7 +88,12 @@ fn main() { } } gdk::EventType::ButtonPress => { - let device = gtk::get_current_event_device().unwrap(); + let device = try_wr!( + gtk::get_current_event_device().ok_or( + "No current event device!", + ), + Inhibit(false) + ); let (window, _, _) = gdk::DeviceExt::get_window_at_position(&device); if window.is_none() {