From 5e0d7f95501bb29a8fa289c7c198bfb1266c32a7 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Sat, 8 Jul 2017 02:38:49 +0200 Subject: [PATCH] Update --- src/alsa_card.rs | 21 ++++++--- src/app_state.rs | 21 ++++++--- src/main.rs | 1 + src/support_alsa.rs | 17 +++++-- src/support_audio.rs | 15 ++++++ src/ui_entry.rs | 23 +++++---- src/ui_popup_menu.rs | 47 +++++++++---------- src/ui_popup_window.rs | 2 +- src/ui_prefs_dialog.rs | 104 +++++++++++++++++++---------------------- src/ui_tray_icon.rs | 28 +++++------ 10 files changed, 158 insertions(+), 121 deletions(-) create mode 100644 src/support_audio.rs diff --git a/src/alsa_card.rs b/src/alsa_card.rs index f40c7c5e8..9fd3963a9 100644 --- a/src/alsa_card.rs +++ b/src/alsa_card.rs @@ -56,21 +56,30 @@ impl AlsaCard { match mycard { Ok(card) => card, Err(_) => { - warn!("Card {} not playable, trying others", name); + warn!("Card {} not playable, trying others", + name); get_first_playable_alsa_card()? } } } - }, + } None => get_first_playable_alsa_card()?, } }; let mixer = get_mixer(&card)?; - let selem_id = - get_playable_selem_by_name(&mixer, - elem_name.unwrap_or(String::from("Master")))? - .get_id(); + let selem_id = { + let requested_selem = + get_playable_selem_by_name(&mixer, + elem_name.unwrap_or(String::from("Master"))); + match requested_selem { + Ok(s) => s.get_id(), + Err(_) => { + warn!("No playable Selem found, trying others"); + get_first_playable_selem(&mixer)?.get_id() + } + } + }; let vec_pollfd = PollDescriptors::get(&mixer)?; diff --git a/src/app_state.rs b/src/app_state.rs index b1ef1cf46..13f829d56 100644 --- a/src/app_state.rs +++ b/src/app_state.rs @@ -24,21 +24,28 @@ pub struct AppS { impl AppS { pub fn new() -> AppS { let builder_popup_window = - gtk::Builder::new_from_string(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/data/ui/popup-window.glade"))); - let builder_popup_menu = gtk::Builder::new_from_string(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/data/ui/popup-menu.glade"))); + gtk::Builder::new_from_string(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), + "/data/ui/popup-window.glade"))); + let builder_popup_menu = + gtk::Builder::new_from_string(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), + "/data/ui/popup-menu.glade"))); let prefs = RefCell::new(Prefs::new().unwrap()); let gui = Gui::new(builder_popup_window, builder_popup_menu, &prefs.borrow()); - let card_name = prefs.borrow().device_prefs.card.clone(); - let chan_name = prefs.borrow().device_prefs.channel.clone(); + let card_name = prefs.borrow() + .device_prefs + .card + .clone(); + let chan_name = prefs.borrow() + .device_prefs + .channel + .clone(); return AppS { _cant_construct: (), gui: gui, - audio: Audio::new(Some(card_name), - Some(chan_name)) - .unwrap(), + audio: Audio::new(Some(card_name), Some(chan_name)).unwrap(), prefs: prefs, }; } diff --git a/src/main.rs b/src/main.rs index 7a187f507..3b40eb5cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,6 +47,7 @@ mod ui_prefs_dialog; mod ui_tray_icon; mod prefs; mod support_alsa; +mod support_audio; mod support_cmd; mod support_ui; diff --git a/src/support_alsa.rs b/src/support_alsa.rs index 0ce860e19..046678658 100644 --- a/src/support_alsa.rs +++ b/src/support_alsa.rs @@ -30,7 +30,7 @@ pub fn get_first_playable_alsa_card() -> Result { if alsa_card_has_playable_selem(&card) { return Ok(card); } - }, + } _ => (), } } @@ -50,7 +50,7 @@ pub fn get_playable_alsa_card_names() -> Vec { vec.push(m_name.unwrap()) } } - }, + } _ => (), } } @@ -104,6 +104,15 @@ pub fn get_playable_selems(mixer: &Mixer) -> Vec { } +pub fn get_first_playable_selem(mixer: &Mixer) -> Result { + for s in mixer.iter().map(get_selem).filter(selem_is_playable) { + return Ok(s); + } + + bail!("No playable Selem found!") +} + + pub fn get_playable_selem_names(mixer: &Mixer) -> Vec { let mut vec = vec![]; for selem in get_playable_selems(mixer) { @@ -118,7 +127,9 @@ pub fn get_playable_selem_names(mixer: &Mixer) -> Vec { } -pub fn get_playable_selem_by_name(mixer: &Mixer, name: String) -> Result { +pub fn get_playable_selem_by_name(mixer: &Mixer, + name: String) + -> Result { for selem in get_playable_selems(mixer) { let n = selem.get_id() .get_name() diff --git a/src/support_audio.rs b/src/support_audio.rs new file mode 100644 index 000000000..25abeb0ff --- /dev/null +++ b/src/support_audio.rs @@ -0,0 +1,15 @@ +use audio::{Audio, AudioUser}; +use errors::*; +use prefs::*; + + + +pub fn audio_reload(audio: &Audio, + prefs: &Prefs, + user: AudioUser) + -> Result<()> { + let card = &prefs.device_prefs.card; + let channel = &prefs.device_prefs.channel; + // TODO: is this clone safe? + return audio.switch_acard(Some(card.clone()), Some(channel.clone()), user); +} diff --git a/src/ui_entry.rs b/src/ui_entry.rs index d6412948f..e5e475cfe 100644 --- a/src/ui_entry.rs +++ b/src/ui_entry.rs @@ -5,8 +5,10 @@ use std::cell::RefCell; use std::rc::Rc; use ui_popup_menu::*; use ui_popup_window::*; -use ui_prefs_dialog::PrefsDialog; +use ui_prefs_dialog::*; use ui_tray_icon::*; +use audio::{AudioUser, AudioSignal}; + @@ -37,20 +39,21 @@ impl Gui { pub fn init(appstate: Rc) { { - let mut apps = appstate.clone(); - // appstate.audio.connect_handler( - // Box::new(move |s, u| match (s, u) { - // (AudioSignal::ValuesChanged, AudioUser::Unknown) => { - // debug!("External volume change!"); + let apps = appstate.clone(); + appstate.audio.connect_handler( + Box::new(move |s, u| match (s, u) { + (AudioSignal::ValuesChanged, AudioUser::Unknown) => { + debug!("Appstate references: {}!", Rc::strong_count(&apps)); - // } - // _ => debug!("Nix"), - // }), - // ); + } + _ => debug!("Nix"), + }), + ); } init_tray_icon(appstate.clone()); init_popup_window(appstate.clone()); init_popup_menu(appstate.clone()); + init_prefs_callback(appstate.clone()); } diff --git a/src/ui_popup_menu.rs b/src/ui_popup_menu.rs index 3eaa9fa00..8dea6e062 100644 --- a/src/ui_popup_menu.rs +++ b/src/ui_popup_menu.rs @@ -3,6 +3,7 @@ use audio::{AudioUser, AudioSignal}; use gtk::prelude::*; use gtk; use std::rc::Rc; +use support_audio::*; use support_cmd::*; use ui_prefs_dialog::*; @@ -38,7 +39,7 @@ pub fn init_popup_menu(appstate: Rc) { return; } match (s, u) { - (_, _) => set_mute_check(&apps) + (_, _) => set_mute_check(&apps), } })); @@ -50,9 +51,7 @@ pub fn init_popup_menu(appstate: Rc) { appstate.gui .popup_menu .menu - .connect_show(move |_| { - set_mute_check(&apps) - }); + .connect_show(move |_| set_mute_check(&apps)); } @@ -94,13 +93,22 @@ pub fn init_popup_menu(appstate: Rc) { }); } + /* reload_item.connect_activate_link */ + { + let apps = appstate.clone(); + let reload_item = &appstate.gui.popup_menu.reload_item; + reload_item.connect_activate(move |_| { + try_w!(audio_reload(&apps.audio, + &apps.prefs.borrow(), + AudioUser::Popup)) + }); + } + /* quit_item.connect_activate_link */ { let quit_item = &appstate.gui.popup_menu.quit_item; - quit_item.connect_activate(|_| { - gtk::main_quit(); - }); + quit_item.connect_activate(|_| { gtk::main_quit(); }); } } @@ -152,27 +160,18 @@ fn on_prefs_item_activate(appstate: &Rc) { fn set_mute_check(apps: &Rc) { - let mute_check = &apps.gui - .popup_menu - .mute_check; + let mute_check = &apps.gui.popup_menu.mute_check; let m_muted = apps.audio.get_mute(); match m_muted { Ok(muted) => { - mute_check - .set_sensitive(false); - mute_check - .set_active(muted); - mute_check.set_tooltip_text( - ""); - }, + mute_check.set_sensitive(false); + mute_check.set_active(muted); + mute_check.set_tooltip_text(""); + } Err(_) => { - mute_check - .set_active(true); - mute_check - .set_sensitive(false); - mute_check.set_tooltip_text( - "Soundcard has no mute switch", - ); + mute_check.set_active(true); + mute_check.set_sensitive(false); + mute_check.set_tooltip_text("Soundcard has no mute switch"); } } } diff --git a/src/ui_popup_window.rs b/src/ui_popup_window.rs index ec9ec89ba..dd2c216c7 100644 --- a/src/ui_popup_window.rs +++ b/src/ui_popup_window.rs @@ -235,7 +235,7 @@ pub fn set_slider(vol_scale_adj: >k::Adjustment, scale: f64) { } -pub fn grab_devices(window: >k::Window) -> Result<()> { +fn grab_devices(window: >k::Window) -> Result<()> { let device = gtk::get_current_event_device().ok_or("No current device")?; let gdk_window = window.get_window().ok_or("No window?!")?; diff --git a/src/ui_prefs_dialog.rs b/src/ui_prefs_dialog.rs index 6da6cf7f4..0173b63c0 100644 --- a/src/ui_prefs_dialog.rs +++ b/src/ui_prefs_dialog.rs @@ -1,52 +1,56 @@ use app_state::*; use audio::{AudioUser, AudioSignal}; +use errors::*; use gdk; use gtk::ResponseType; use gtk::prelude::*; use gtk; use prefs::*; +use std::mem; use std::rc::Rc; use support_alsa::*; -use errors::*; +use support_audio::*; -// TODO: misbehavior when popup_window is open +// TODO: reference count leak pub struct PrefsDialog { _cant_construct: (), - pub prefs_dialog: gtk::Dialog, + prefs_dialog: gtk::Dialog, /* DevicePrefs */ - pub card_combo: gtk::ComboBoxText, - pub chan_combo: gtk::ComboBoxText, + card_combo: gtk::ComboBoxText, + chan_combo: gtk::ComboBoxText, /* ViewPrefs */ - pub vol_meter_draw_check: gtk::CheckButton, - pub vol_meter_pos_spin: gtk::SpinButton, - pub vol_meter_color_button: gtk::ColorButton, - pub system_theme: gtk::CheckButton, + vol_meter_draw_check: gtk::CheckButton, + vol_meter_pos_spin: gtk::SpinButton, + vol_meter_color_button: gtk::ColorButton, + system_theme: gtk::CheckButton, /* BehaviorPrefs */ - pub vol_control_entry: gtk::Entry, - pub scroll_step_spin: gtk::SpinButton, - pub middle_click_combo: gtk::ComboBoxText, - pub custom_entry: gtk::Entry, + vol_control_entry: gtk::Entry, + scroll_step_spin: gtk::SpinButton, + middle_click_combo: gtk::ComboBoxText, + custom_entry: gtk::Entry, /* NotifyPrefs */ - pub noti_enable_check: gtk::CheckButton, - pub noti_timeout_spin: gtk::SpinButton, + noti_enable_check: gtk::CheckButton, + noti_timeout_spin: gtk::SpinButton, // pub noti_hotkey_check: gtk::CheckButton, - pub noti_mouse_check: gtk::CheckButton, - pub noti_popup_check: gtk::CheckButton, - pub noti_ext_check: gtk::CheckButton, + noti_mouse_check: gtk::CheckButton, + noti_popup_check: gtk::CheckButton, + noti_ext_check: gtk::CheckButton, } impl PrefsDialog { - pub fn new() -> PrefsDialog { - let builder = gtk::Builder::new_from_string(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/data/ui/prefs-dialog.glade"))); + fn new() -> PrefsDialog { + let builder = + gtk::Builder::new_from_string(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), + "/data/ui/prefs-dialog.glade"))); let prefs_dialog = PrefsDialog { _cant_construct: (), prefs_dialog: builder.get_object("prefs_dialog").unwrap(), @@ -81,7 +85,7 @@ impl PrefsDialog { } - pub fn from_prefs(&self, prefs: &Prefs) { + fn from_prefs(&self, prefs: &Prefs) { /* DevicePrefs */ /* filled on show signal with audio info */ self.card_combo.remove_all(); @@ -137,7 +141,7 @@ impl PrefsDialog { } - pub fn to_prefs(&self) -> Prefs { + fn to_prefs(&self) -> Prefs { // TODO: remove duplication with default instance let device_prefs = DevicePrefs { @@ -227,36 +231,32 @@ pub fn show_prefs_dialog(appstate: &Rc) { } -/* TODO: do the references get dropped when the dialog window is gone? */ -pub fn init_prefs_dialog(appstate: &Rc) { - /* audio.connect_handler */ - { - let apps = appstate.clone(); - appstate.audio.connect_handler(Box::new(move |s, u| { - match (s, u) { - (AudioSignal::CardInitialized, _) => (), - (AudioSignal::CardCleanedUp, _) => { - fill_card_combo(&apps); - fill_chan_combo(&apps, None); - }, - _ => (), - } - })); +pub fn init_prefs_callback(appstate: Rc) { + let apps = appstate.clone(); + appstate.audio.connect_handler(Box::new(move |s, u| { + match (s, u) { + (AudioSignal::CardInitialized, _) => (), + (AudioSignal::CardCleanedUp, _) => { + fill_card_combo(&apps); + fill_chan_combo(&apps, None); + }, + _ => (), + } + })); +} - } +fn init_prefs_dialog(appstate: &Rc) { /* prefs_dialog.connect_show */ { let apps = appstate.clone(); let m_pd = appstate.gui.prefs_dialog.borrow(); let pd = m_pd.as_ref().unwrap(); - pd.prefs_dialog.connect_show( - move |_| { - fill_card_combo(&apps); - fill_chan_combo(&apps, None); - } - ); + pd.prefs_dialog.connect_show(move |_| { + fill_card_combo(&apps); + fill_chan_combo(&apps, None); + }); } /* card_combo.connect_changed */ @@ -268,8 +268,7 @@ pub fn init_prefs_dialog(appstate: &Rc) { card_combo.connect_changed(move |_| { let m_cc = apps.gui.prefs_dialog.borrow(); let card_combo = &m_cc.as_ref().unwrap().card_combo; - let card_name = card_combo - .get_active_text().unwrap(); + let card_name = card_combo.get_active_text().unwrap(); fill_chan_combo(&apps, Some(card_name)); return; }); @@ -290,7 +289,6 @@ pub fn init_prefs_dialog(appstate: &Rc) { } - // TODO: does Rc get dropped?! if response_id != ResponseType::Apply.into() { let mut prefs_dialog = apps.gui.prefs_dialog.borrow_mut(); prefs_dialog.as_ref().unwrap().prefs_dialog.destroy(); @@ -304,12 +302,7 @@ pub fn init_prefs_dialog(appstate: &Rc) { try_w!(apps.update_popup_window()); { let prefs = apps.prefs.borrow(); - let card = &prefs.device_prefs.card; - let channel = &prefs.device_prefs.channel; - try_w!(apps.audio.switch_acard( - Some(card.clone()), - Some(channel.clone()), - AudioUser::PrefsWindow)); + try_w!(audio_reload(&apps.audio, &prefs, AudioUser::PrefsWindow)); } let prefs = apps.prefs.borrow_mut(); try_w!(prefs.store_config()); @@ -353,9 +346,7 @@ fn fill_chan_combo(appstate: &AppS, cardname: Option) { let cur_acard = appstate.audio.acard.borrow(); let card = match cardname { - Some(name) => { - try_w!(get_alsa_card_by_name(name).from_err()) - }, + Some(name) => try_w!(get_alsa_card_by_name(name).from_err()), None => cur_acard.as_ref().card, }; @@ -378,4 +369,3 @@ fn fill_chan_combo(appstate: &AppS, cardname: Option) { chan_combo.set_active(c_index); } - diff --git a/src/ui_tray_icon.rs b/src/ui_tray_icon.rs index 65dafad63..6ac9454eb 100644 --- a/src/ui_tray_icon.rs +++ b/src/ui_tray_icon.rs @@ -72,7 +72,7 @@ impl TrayIcon { } - pub fn update_audio(&self, audio: &Audio) -> Result<()> { + fn update_audio(&self, audio: &Audio) -> Result<()> { return self.update_pixbuf(audio.vol()?, audio.vol_level()); } @@ -97,8 +97,12 @@ impl TrayIcon { let audio_pix = AudioPix::new(self.icon_size.get(), &prefs)?; *self.audio_pix.borrow_mut() = audio_pix; - let volmeter = VolMeter::new(&prefs); - *self.volmeter.borrow_mut() = Some(volmeter); + + let draw_vol_meter = prefs.view_prefs.draw_vol_meter; + if draw_vol_meter { + let volmeter = VolMeter::new(&prefs); + *self.volmeter.borrow_mut() = Some(volmeter); + } return self.update_pixbuf(audio.vol()?, audio.vol_level()); } @@ -119,7 +123,7 @@ pub struct VolMeter { impl VolMeter { - pub fn new(prefs: &Prefs) -> VolMeter { + fn new(prefs: &Prefs) -> VolMeter { return VolMeter { red: prefs.view_prefs.vol_meter_color.red, green: prefs.view_prefs.vol_meter_color.green, @@ -223,7 +227,7 @@ pub struct AudioPix { impl AudioPix { - pub fn new(size: i32, prefs: &Prefs) -> Result { + fn new(size: i32, prefs: &Prefs) -> Result { let system_theme = prefs.view_prefs.system_theme; let pix = { @@ -282,7 +286,7 @@ impl AudioPix { } - pub fn select_pix(&self, vol_level: VolLevel) -> &gdk_pixbuf::Pixbuf { + fn select_pix(&self, vol_level: VolLevel) -> &gdk_pixbuf::Pixbuf { match vol_level { VolLevel::Muted => &self.muted, VolLevel::Low => &self.low, @@ -304,13 +308,11 @@ pub fn init_tray_icon(appstate: Rc) { /* connect audio handler */ { let apps = appstate.clone(); - appstate.audio.connect_handler( - Box::new(move |s, u| match (s, u) { - (_, _) => { - try_w!(apps.gui.tray_icon.update_audio(&apps.audio)); - }, - }), - ); + appstate.audio.connect_handler(Box::new(move |s, u| match (s, u) { + (_, _) => { + try_w!(apps.gui.tray_icon.update_audio(&apps.audio)); + } + })); } /* tray_icon.connect_size_changed */