diff --git a/Cargo.toml b/Cargo.toml index 78a3e34ef..a3f2f0afa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,9 +5,11 @@ authors = ["Julian Ospald "] [dependencies] alsa = "0.1.8" -gdk = "0.5.0" -lazy_static = "0.1.*" +libc = "0.2.23" +gdk = "0.5.3" +gdk-sys = "0.3.4" +gtk-sys = "0.3.4" [dependencies.gtk] -version = "0.1.0" -features = [ "v3_10" ] +git = 'https://github.com/gtk-rs/gtk.git' +features = [ "v3_12", "v3_22" ] diff --git a/src/audio.rs b/src/audio.rs index 2c779b29e..4e3eec4c2 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -1,48 +1,68 @@ extern crate alsa; +extern crate std; +extern crate libc; use self::alsa::card::{Card}; -use self::alsa::mixer::{Mixer, Selem}; +use self::alsa::mixer::{Mixer, Selem, Elem}; +use alsa::mixer::SelemChannelId::*; +use std::iter::Map; +use self::libc::c_int; pub fn get_default_alsa_card() -> Card { - let default_card: Card = Card::new(0); + return get_alsa_card_by_id(0); +} - return default_card; +pub fn get_alsa_card_by_id(index: c_int) -> Card { + return alsa::Card::new(index); +} + +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(); - for elem in mixer.iter() { - let selem: Selem = Selem::new(elem).unwrap(); - println!("Elem: {}", selem.get_id().get_name().unwrap()); - } - return mixer; } -pub fn get_channels(mixer: &Mixer) -> alsa::mixer::Iter { - return mixer.iter(); +pub fn get_selems(mixer: &Mixer) -> Map Selem> { + return mixer.iter().map(get_selem); } -pub fn get_channel_by_name<'a>(mixer: &'a Mixer, name: String) -> Option> { - for elem in mixer.iter() { - let m_selem = Selem::new(elem); - let m_name = m_selem.and_then(|x| x.get_id().get_name().ok()); +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 Selem::new(elem); + 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_selem(elem: Elem) -> Selem { + /* in the ALSA API, there are currently only simple elements, + * so this unwrap() should be safe. + *http://www.alsa-project.org/alsa-doc/alsa-lib/group___mixer.html#enum-members */ + return Selem::new(elem).unwrap(); +} // pub fn list_channels(card: Card, hctl: HCtl) -> [str] { diff --git a/src/gui.rs b/src/gui.rs new file mode 100644 index 000000000..edf54c87c --- /dev/null +++ b/src/gui.rs @@ -0,0 +1,9 @@ +extern crate gtk; +extern crate gdk; + +use gtk::prelude::*; + +pub fn set_slider(vol_scale_adj: & gtk::Adjustment, scale: f64) { + vol_scale_adj.set_value(scale); +} + diff --git a/src/main.rs b/src/main.rs index 430d4689a..2194af8b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ extern crate gtk; extern crate gdk; +extern crate gdk_sys; extern crate alsa; // #[macro_use] @@ -19,7 +20,12 @@ use gtk::prelude::*; use alsa::mixer::SelemChannelId::*; +use gdk::EventType; +use gdk_sys::GDK_KEY_Escape; + + mod audio; +mod gui; fn main() { @@ -30,42 +36,72 @@ fn main() { let glade_src = include_str!("../data/ui/popup-window-vertical.glade"); let builder_popup = gtk::Builder::new_from_string(glade_src); - let popup_window: gtk::Window = builder_popup.get_object("popup_window").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(); - // let builder_prefs_dialog = Rc::new(Builder::new_from_file("data/ui/prefs-dialog.glade")); - - // with_builder!(builder_popup_window, - // tray_icon.connect_activate(move |_| { - // let popup_window: gtk::Window = builder - // .get_object("popup_window").unwrap(); - // popup_window.show_all(); - // }) - // ); - - // 2nd binding - - tray_icon.connect_button_press_event(move |_, e| { - let bt = e.as_ref().button; - match bt { - 3 => { + tray_icon.connect_activate(move |_| { + if popup_window.get_visible() { + popup_window.hide(); + } else { popup_window.show_all(); - return true; + vol_scale.grab_focus(); } - _ => { - println!("Blah"); - return false; + }); + } + + { + 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 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(), + gdk::EventType::KeyPress => { + println!("BLAH"); + let key: gdk::EventKey = e.clone().downcast().unwrap(); + if key.get_keyval() == (GDK_KEY_Escape as u32) { + w.hide(); + } + }, + gdk::EventType::ButtonPress => { + unsafe { + let device = gtk::functions::get_current_event_device(); + let (_, x, y) = gdk::Device::get_window_at_position(device); + }; + }, + _ => (), } - } - }); - let alsa_card = audio::get_default_alsa_card(); - let mixer = audio::get_mixer(alsa_card); - let channel = audio::get_channel_by_name(&mixer, String::from("Master")).unwrap(); + return Inhibit(false); + }); + } - println!("Range: {:?}", channel.get_playback_volume_range()); - println!("Channel: {}", channel.get_playback_volume(FrontCenter).unwrap()); + // let alsa_card = audio::get_default_alsa_card(); + // let mixer = audio::get_mixer(alsa_card); + // let elem = audio::get_selem_by_name(&mixer, String::from("Master")).unwrap(); + + // for s in audio::get_selems(&mixer) { + // println!("Name: {}", s.get_id().get_name().unwrap()); + // } + + // println!("Range: {:?}", channel.get_playback_volume_range()); + // println!("Name: {}", elem.get_id().get_name().unwrap()); + // println!("Channel: {}", channel.get_playback_volume(FrontRight).unwrap()); + // println!("Volume: {}", audio::get_vol(elem).unwrap()); tray_icon.set_visible(true); gtk::main(); } + +