From 11b5c806d9af37483b18dea3a4d26c177850b9e5 Mon Sep 17 00:00:00 2001 From: "Ospald, Julian" Date: Fri, 7 Jul 2017 12:03:53 +0200 Subject: [PATCH] Update --- data/ui/prefs-dialog.glade | 141 +-------------------- src/app_state.rs | 247 ++----------------------------------- src/ui_entry.rs | 34 ++++- src/ui_popup_menu.rs | 12 +- src/ui_popup_window.rs | 117 ++++++++++-------- src/ui_prefs_dialog.rs | 202 +++++++++++++++++++++++++++++- src/ui_tray_icon.rs | 81 +++++++----- 7 files changed, 370 insertions(+), 464 deletions(-) diff --git a/data/ui/prefs-dialog.glade b/data/ui/prefs-dialog.glade index f67e706b1..c074a2228 100644 --- a/data/ui/prefs-dialog.glade +++ b/data/ui/prefs-dialog.glade @@ -443,19 +443,6 @@ 1 - - - True - False - Change volume on a logarithmic scale, closer to human perception. - start - Normalize Volume: - - - 0 - 2 - - True @@ -477,21 +464,6 @@ 1 - - - True - True - False - True - - - - - - 1 - 2 - - @@ -533,87 +505,6 @@ 5 5 vertical - - - True - False - 0 - none - - - True - False - 12 - 6 - 12 - True - - - True - False - start - Text Volume Position: - - - 0 - 1 - - - - - Display Text Volume - False - True - True - False - start - True - - - - 0 - 0 - - - - - True - False - 0 - - Top - Bottom - Left - Right - - - - 1 - 1 - - - - - - - - - - True - False - 5 - <b>Volume Popup</b> - True - - - - - False - False - 5 - 0 - - True @@ -714,7 +605,7 @@ False False 5 - 1 + 0 @@ -749,7 +640,7 @@ False False 5 - 2 + 1 @@ -837,18 +728,6 @@ 0 - - - True - False - start - Fine Scroll Step: - - - 0 - 1 - - True @@ -865,22 +744,6 @@ 0 - - - True - True - - False - False - fine_scroll_step_adjustment - 2 - True - - - 1 - 1 - - diff --git a/src/app_state.rs b/src/app_state.rs index 3fb7c43d3..9fc19345d 100644 --- a/src/app_state.rs +++ b/src/app_state.rs @@ -1,22 +1,19 @@ use audio::Audio; -use gdk; +use errors::*; use gtk; -use gtk::ComboBoxTextExt; -use gtk::ComboBoxExt; -use gtk::ToggleButtonExt; -use gtk::SpinButtonExt; -use gtk::ColorChooserExt; -use gtk::EntryExt; use prefs::*; -use ui_tray_icon::TrayIcon; use std::cell::RefCell; +use ui_entry::Gui; +// TODO: notify popups + // TODO: destructors // TODO: glade stuff, config, alsacard pub struct AppS { + _cant_construct: (), pub gui: Gui, pub audio: Audio, pub prefs: RefCell, @@ -33,240 +30,22 @@ impl AppS { Gui::new(builder_popup_window, builder_popup_menu, &prefs.borrow()); return AppS { + _cant_construct: (), gui: gui, audio: Audio::new(None, Some(String::from("Master"))) .unwrap(), prefs: prefs, }; } -} + pub fn update_tray_icon(&self) -> Result<()> { + debug!("Update tray icon!"); + return self.gui.tray_icon.update_all(&self.prefs.borrow(), &self.audio, None); + } -pub struct Gui { - pub tray_icon: TrayIcon, - pub popup_window: PopupWindow, - pub popup_menu: PopupMenu, - /* prefs_dialog is dynamically created and destroyed */ - pub prefs_dialog: RefCell>, -} - - -impl Gui { - pub fn new(builder_popup_window: gtk::Builder, - builder_popup_menu: gtk::Builder, - prefs: &Prefs) - -> Gui { - return Gui { - tray_icon: TrayIcon::new(prefs).unwrap(), - popup_window: PopupWindow::new(builder_popup_window), - popup_menu: PopupMenu::new(builder_popup_menu), - prefs_dialog: RefCell::new(None), - }; + pub fn update_popup_window(&self) -> Result<()> { + debug!("Update PopupWindow!"); + return self.gui.popup_window.update(&self.audio); } } - -create_builder_item!(PopupWindow, - popup_window: gtk::Window, - vol_scale_adj: gtk::Adjustment, - vol_scale: gtk::Scale, - mute_check: gtk::CheckButton); - - -create_builder_item!(PopupMenu, - menu_window: gtk::Window, - menubar: gtk::MenuBar, - menu: gtk::Menu, - about_item: gtk::MenuItem, - prefs_item: gtk::MenuItem); - - -pub struct PrefsDialog { - pub prefs_dialog: gtk::Dialog, - - /* DevicePrefs */ - pub card_combo: gtk::ComboBoxText, - pub 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, - - /* BehaviorPrefs */ - pub vol_control_entry: gtk::Entry, - pub scroll_step_spin: gtk::SpinButton, - pub middle_click_combo: gtk::ComboBoxText, - pub custom_entry: gtk::Entry, - - /* NotifyPrefs */ - pub noti_enable_check: gtk::CheckButton, - pub 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, -} - -impl PrefsDialog { - pub fn new() -> PrefsDialog { - let builder = gtk::Builder::new_from_string(include_str!("../data/ui/prefs-dialog.glade")); - let prefs_dialog = PrefsDialog { - prefs_dialog: builder.get_object("prefs_dialog").unwrap(), - - card_combo: builder.get_object("card_combo").unwrap(), - chan_combo: builder.get_object("chan_combo").unwrap(), - - vol_meter_draw_check: builder.get_object("vol_meter_draw_check") - .unwrap(), - vol_meter_pos_spin: builder.get_object("vol_meter_pos_spin") - .unwrap(), - vol_meter_color_button: builder.get_object("vol_meter_color_button") - .unwrap(), - system_theme: builder.get_object("system_theme").unwrap(), - - vol_control_entry: builder.get_object("vol_control_entry").unwrap(), - scroll_step_spin: builder.get_object("scroll_step_spin").unwrap(), - middle_click_combo: builder.get_object("middle_click_combo") - .unwrap(), - custom_entry: builder.get_object("custom_entry").unwrap(), - - noti_enable_check: builder.get_object("noti_enable_check").unwrap(), - noti_timeout_spin: builder.get_object("noti_timeout_spin").unwrap(), - // noti_hotkey_check: builder.get_object("noti_hotkey_check").unwrap(), - noti_mouse_check: builder.get_object("noti_mouse_check").unwrap(), - noti_popup_check: builder.get_object("noti_popup_check").unwrap(), - noti_ext_check: builder.get_object("noti_ext_check").unwrap(), - }; - - - return prefs_dialog; - } - - - pub fn from_prefs(&self, prefs: &Prefs) { - /* DevicePrefs */ - self.card_combo.remove_all(); - self.card_combo.append_text(prefs.device_prefs.card.as_str()); - self.card_combo.set_active(0); - - self.chan_combo.remove_all(); - self.chan_combo.append_text(prefs.device_prefs.channel.as_str()); - self.chan_combo.set_active(0); - - /* ViewPrefs */ - self.vol_meter_draw_check.set_active(prefs.view_prefs.draw_vol_meter); - self.vol_meter_pos_spin.set_value(prefs.view_prefs.vol_meter_offset as - f64); - - // TODO don't convert like that - let rgba = gdk::RGBA { - red: prefs.view_prefs.vol_meter_color.red as f64 / 255.0, - green: prefs.view_prefs.vol_meter_color.green as f64 / 255.0, - blue: prefs.view_prefs.vol_meter_color.blue as f64 / 255.0, - alpha: 1.0, - }; - self.vol_meter_color_button.set_rgba(&rgba); - self.system_theme.set_active(prefs.view_prefs.system_theme); - - /* BehaviorPrefs */ - self.vol_control_entry.set_text(prefs.behavior_prefs - .vol_control_cmd - .as_ref() - .unwrap_or(&String::from("")) - .as_str()); - self.scroll_step_spin.set_value(prefs.behavior_prefs.vol_scroll_step); - - // TODO: make sure these values always match, must be a better way - // also check to_prefs() - self.middle_click_combo.append_text("Toggle Mute"); - self.middle_click_combo.append_text("Show Preferences"); - self.middle_click_combo.append_text("Volume Control"); - self.middle_click_combo.append_text("Custom Command"); - self.middle_click_combo.set_active(prefs.behavior_prefs - .middle_click_action - .into()); - self.custom_entry.set_text(prefs.behavior_prefs - .custom_command - .as_ref() - .unwrap_or(&String::from("")) - .as_str()); - - /* NotifyPrefs */ - self.noti_enable_check - .set_active(prefs.notify_prefs.enable_notifications); - self.noti_timeout_spin - .set_value(prefs.notify_prefs.notifcation_timeout as f64); - self.noti_mouse_check - .set_active(prefs.notify_prefs.notify_mouse_scroll); - self.noti_popup_check.set_active(prefs.notify_prefs.notify_popup); - self.noti_ext_check.set_active(prefs.notify_prefs.notify_external); - } - - - pub fn to_prefs(&self) -> Prefs { - // TODO: remove duplication with default instance - let device_prefs = - DevicePrefs { - card: self.card_combo - .get_active_text() - .unwrap_or(String::from("(default)")), - channel: self.chan_combo - .get_active_text() - .unwrap_or(String::from("Master")), - }; - - // TODO don't convert like that - let vol_meter_color = VolColor { - red: (self.vol_meter_color_button.get_rgba().red * 255.0) as u8, - green: (self.vol_meter_color_button.get_rgba().green * 255.0) as u8, - blue: (self.vol_meter_color_button.get_rgba().blue * 255.0) as u8, - }; - - let view_prefs = ViewPrefs { - draw_vol_meter: self.vol_meter_draw_check.get_active(), - vol_meter_offset: self.vol_meter_pos_spin.get_value_as_int(), - system_theme: self.system_theme.get_active(), - vol_meter_color, - }; - - let vol_control_cmd = - self.vol_control_entry.get_text().and_then(|x| if x.is_empty() { - None - } else { - Some(x) - }); - - let custom_command = - self.custom_entry.get_text().and_then(|x| if x.is_empty() { - None - } else { - Some(x) - }); - - let behavior_prefs = BehaviorPrefs { - vol_control_cmd, - vol_scroll_step: self.scroll_step_spin.get_value(), - middle_click_action: self.middle_click_combo.get_active().into(), - custom_command, - }; - - let notify_prefs = NotifyPrefs { - enable_notifications: self.noti_enable_check.get_active(), - notifcation_timeout: self.noti_timeout_spin.get_value_as_int() as - i64, - notify_mouse_scroll: self.noti_mouse_check.get_active(), - notify_popup: self.noti_popup_check.get_active(), - notify_external: self.noti_ext_check.get_active(), - }; - - return Prefs { - device_prefs, - view_prefs, - behavior_prefs, - notify_prefs, - }; - - } -} diff --git a/src/ui_entry.rs b/src/ui_entry.rs index 65a60729c..d6412948f 100644 --- a/src/ui_entry.rs +++ b/src/ui_entry.rs @@ -1,16 +1,40 @@ use app_state::*; -use audio::*; -use std::rc::Rc; +use gtk; +use prefs::*; use std::cell::RefCell; +use std::rc::Rc; use ui_popup_menu::*; use ui_popup_window::*; +use ui_prefs_dialog::PrefsDialog; use ui_tray_icon::*; -use ui_prefs_dialog::*; -use std::ptr; -use gtk::ResponseType; +pub struct Gui { + _cant_construct: (), + pub tray_icon: TrayIcon, + pub popup_window: PopupWindow, + pub popup_menu: PopupMenu, + /* prefs_dialog is dynamically created and destroyed */ + pub prefs_dialog: RefCell>, +} + +impl Gui { + pub fn new(builder_popup_window: gtk::Builder, + builder_popup_menu: gtk::Builder, + prefs: &Prefs) + -> Gui { + return Gui { + _cant_construct: (), + tray_icon: TrayIcon::new(prefs).unwrap(), + popup_window: PopupWindow::new(builder_popup_window), + popup_menu: PopupMenu::new(builder_popup_menu), + prefs_dialog: RefCell::new(None), + }; + } +} + + pub fn init(appstate: Rc) { { let mut apps = appstate.clone(); diff --git a/src/ui_popup_menu.rs b/src/ui_popup_menu.rs index f739c582f..f6bb85f5a 100644 --- a/src/ui_popup_menu.rs +++ b/src/ui_popup_menu.rs @@ -1,7 +1,7 @@ use app_state::*; use gtk::prelude::*; -use std::rc::Rc; use gtk; +use std::rc::Rc; use ui_prefs_dialog::*; @@ -9,6 +9,16 @@ use ui_prefs_dialog::*; const VERSION: &'static str = env!("CARGO_PKG_VERSION"); + +create_builder_item!(PopupMenu, + menu_window: gtk::Window, + menubar: gtk::MenuBar, + menu: gtk::Menu, + about_item: gtk::MenuItem, + prefs_item: gtk::MenuItem); + + + pub fn init_popup_menu(appstate: Rc) { /* about_item.connect_activate_link */ diff --git a/src/ui_popup_window.rs b/src/ui_popup_window.rs index a7f46cc22..d8192b5d5 100644 --- a/src/ui_popup_window.rs +++ b/src/ui_popup_window.rs @@ -6,14 +6,72 @@ use gdk::{GrabOwnership, GrabStatus, BUTTON_PRESS_MASK, KEY_PRESS_MASK}; use gdk; use gdk_sys::{GDK_KEY_Escape, GDK_CURRENT_TIME}; use glib; +use gtk::ToggleButtonExt; use gtk::prelude::*; use gtk; +use std::cell::Cell; use std::rc::Rc; +pub struct PopupWindow { + _cant_construct: (), + pub popup_window: gtk::Window, + pub vol_scale_adj: gtk::Adjustment, + pub vol_scale: gtk::Scale, + pub mute_check: gtk::CheckButton, + pub toggle_signal: Cell, +} + +impl PopupWindow { + pub fn new(builder: gtk::Builder) -> PopupWindow { + return PopupWindow { + _cant_construct: (), + popup_window: builder.get_object("popup_window").unwrap(), + vol_scale_adj: builder.get_object("vol_scale_adj").unwrap(), + vol_scale: builder.get_object("vol_scale").unwrap(), + mute_check: builder.get_object("mute_check").unwrap(), + toggle_signal: Cell::new(0), + }; + } + + pub fn update(&self, audio: &Audio) -> Result<()> { + let cur_vol = audio.vol()?; + set_slider(&self.vol_scale_adj, cur_vol); + + self.update_mute_check(&audio); + + self.vol_scale.grab_focus(); + grab_devices(&self.popup_window)?; + + return Ok(()); + } + + pub fn update_mute_check(&self, audio: &Audio) { + let muted = audio.get_mute(); + + glib::signal_handler_block(&self.mute_check, self.toggle_signal.get()); + + match muted { + Ok(val) => { + self.mute_check.set_active(val); + self.mute_check.set_tooltip_text(""); + } + Err(_) => { + /* can't figure out whether channel is muted, grey out */ + self.mute_check.set_active(true); + self.mute_check.set_sensitive(false); + self.mute_check.set_tooltip_text("Soundcard has no mute switch"); + } + } + + glib::signal_handler_unblock(&self.mute_check, self.toggle_signal.get()); + } +} + + + pub fn init_popup_window(appstate: Rc) { - let mut toggle_signal = 0; /* mute_check.connect_toggled */ { @@ -22,10 +80,11 @@ pub fn init_popup_window(appstate: Rc) { .gui .popup_window .mute_check; - toggle_signal = + let toggle_signal = mute_check.connect_toggled(move |_| { on_mute_check_toggled(&_appstate) }); + appstate.gui.popup_window.toggle_signal.set(toggle_signal); } /* popup_window.connect_show */ @@ -35,10 +94,8 @@ pub fn init_popup_window(appstate: Rc) { .gui .popup_window .popup_window; - popup_window.connect_show(move |w| { - on_popup_window_show(w, - &_appstate, - toggle_signal) + popup_window.connect_show(move |_| { + on_popup_window_show(&_appstate) }); } @@ -56,38 +113,24 @@ pub fn init_popup_window(appstate: Rc) { /* popup_window.connect_event */ { - let _appstate = appstate.clone(); let popup_window = &appstate.clone() .gui .popup_window .popup_window; popup_window.connect_event(move |w, e| { - on_popup_window_event(w, e, &_appstate) + on_popup_window_event(w, e) }); } } -fn on_popup_window_show(window: >k::Window, - appstate: &AppS, - toggle_signal: u64) { - let audio = &appstate.audio; - let popup_window = &appstate.gui.popup_window; - - let cur_vol = try_w!(audio.vol()); - set_slider(&popup_window.vol_scale_adj, cur_vol); - - let muted = audio.get_mute(); - update_mute_check(&appstate, toggle_signal, muted); - - popup_window.vol_scale.grab_focus(); - try_w!(grab_devices(window)); +fn on_popup_window_show(appstate: &AppS) { + try_w!(appstate.gui.popup_window.update(&appstate.audio)); } fn on_popup_window_event(w: >k::Window, - e: &gdk::Event, - appstate: &AppS) + e: &gdk::Event) -> gtk::Inhibit { match gdk::Event::get_event_type(e) { gdk::EventType::GrabBroken => w.hide(), @@ -135,36 +178,12 @@ fn on_mute_check_toggled(appstate: &AppS) { } -pub fn update_mute_check(appstate: &AppS, - toggle_signal: u64, - muted: Result) { - let check_button = &appstate.gui.popup_window.mute_check; - - glib::signal_handler_block(check_button, toggle_signal); - - match muted { - Ok(val) => { - check_button.set_active(val); - check_button.set_tooltip_text(""); - } - Err(_) => { - /* can't figure out whether channel is muted, grey out */ - check_button.set_active(true); - check_button.set_sensitive(false); - check_button.set_tooltip_text("Soundcard has no mute switch"); - } - } - - glib::signal_handler_unblock(check_button, toggle_signal); -} - - pub fn set_slider(vol_scale_adj: >k::Adjustment, scale: f64) { vol_scale_adj.set_value(scale); } -fn grab_devices(window: >k::Window) -> Result<()> { +pub 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 e4d9d8bbd..732554954 100644 --- a/src/ui_prefs_dialog.rs +++ b/src/ui_prefs_dialog.rs @@ -1,10 +1,12 @@ use app_state::*; use audio::AudioUser; +use gdk; +use gtk::ResponseType; use gtk::prelude::*; use gtk; +use prefs::*; use std::rc::Rc; use support_alsa::*; -use gtk::ResponseType; @@ -12,6 +14,199 @@ use gtk::ResponseType; +pub struct PrefsDialog { + _cant_construct: (), + pub prefs_dialog: gtk::Dialog, + + /* DevicePrefs */ + pub card_combo: gtk::ComboBoxText, + pub 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, + + /* BehaviorPrefs */ + pub vol_control_entry: gtk::Entry, + pub scroll_step_spin: gtk::SpinButton, + pub middle_click_combo: gtk::ComboBoxText, + pub custom_entry: gtk::Entry, + + /* NotifyPrefs */ + pub noti_enable_check: gtk::CheckButton, + pub 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, +} + +impl PrefsDialog { + pub fn new() -> PrefsDialog { + let builder = gtk::Builder::new_from_string(include_str!("../data/ui/prefs-dialog.glade")); + let prefs_dialog = PrefsDialog { + _cant_construct: (), + prefs_dialog: builder.get_object("prefs_dialog").unwrap(), + + card_combo: builder.get_object("card_combo").unwrap(), + chan_combo: builder.get_object("chan_combo").unwrap(), + + vol_meter_draw_check: builder.get_object("vol_meter_draw_check") + .unwrap(), + vol_meter_pos_spin: builder.get_object("vol_meter_pos_spin") + .unwrap(), + vol_meter_color_button: builder.get_object("vol_meter_color_button") + .unwrap(), + system_theme: builder.get_object("system_theme").unwrap(), + + vol_control_entry: builder.get_object("vol_control_entry").unwrap(), + scroll_step_spin: builder.get_object("scroll_step_spin").unwrap(), + middle_click_combo: builder.get_object("middle_click_combo") + .unwrap(), + custom_entry: builder.get_object("custom_entry").unwrap(), + + noti_enable_check: builder.get_object("noti_enable_check").unwrap(), + noti_timeout_spin: builder.get_object("noti_timeout_spin").unwrap(), + // noti_hotkey_check: builder.get_object("noti_hotkey_check").unwrap(), + noti_mouse_check: builder.get_object("noti_mouse_check").unwrap(), + noti_popup_check: builder.get_object("noti_popup_check").unwrap(), + noti_ext_check: builder.get_object("noti_ext_check").unwrap(), + }; + + + return prefs_dialog; + } + + + pub fn from_prefs(&self, prefs: &Prefs) { + /* DevicePrefs */ + self.card_combo.remove_all(); + self.card_combo.append_text(prefs.device_prefs.card.as_str()); + self.card_combo.set_active(0); + + self.chan_combo.remove_all(); + self.chan_combo.append_text(prefs.device_prefs.channel.as_str()); + self.chan_combo.set_active(0); + + /* ViewPrefs */ + self.vol_meter_draw_check.set_active(prefs.view_prefs.draw_vol_meter); + self.vol_meter_pos_spin.set_value(prefs.view_prefs.vol_meter_offset as + f64); + + // TODO don't convert like that + let rgba = gdk::RGBA { + red: prefs.view_prefs.vol_meter_color.red as f64 / 255.0, + green: prefs.view_prefs.vol_meter_color.green as f64 / 255.0, + blue: prefs.view_prefs.vol_meter_color.blue as f64 / 255.0, + alpha: 1.0, + }; + self.vol_meter_color_button.set_rgba(&rgba); + self.system_theme.set_active(prefs.view_prefs.system_theme); + + /* BehaviorPrefs */ + self.vol_control_entry.set_text(prefs.behavior_prefs + .vol_control_cmd + .as_ref() + .unwrap_or(&String::from("")) + .as_str()); + self.scroll_step_spin.set_value(prefs.behavior_prefs.vol_scroll_step); + + // TODO: make sure these values always match, must be a better way + // also check to_prefs() + self.middle_click_combo.append_text("Toggle Mute"); + self.middle_click_combo.append_text("Show Preferences"); + self.middle_click_combo.append_text("Volume Control"); + self.middle_click_combo.append_text("Custom Command"); + self.middle_click_combo.set_active(prefs.behavior_prefs + .middle_click_action + .into()); + self.custom_entry.set_text(prefs.behavior_prefs + .custom_command + .as_ref() + .unwrap_or(&String::from("")) + .as_str()); + + /* NotifyPrefs */ + self.noti_enable_check + .set_active(prefs.notify_prefs.enable_notifications); + self.noti_timeout_spin + .set_value(prefs.notify_prefs.notifcation_timeout as f64); + self.noti_mouse_check + .set_active(prefs.notify_prefs.notify_mouse_scroll); + self.noti_popup_check.set_active(prefs.notify_prefs.notify_popup); + self.noti_ext_check.set_active(prefs.notify_prefs.notify_external); + } + + + pub fn to_prefs(&self) -> Prefs { + // TODO: remove duplication with default instance + let device_prefs = + DevicePrefs { + card: self.card_combo + .get_active_text() + .unwrap_or(String::from("(default)")), + channel: self.chan_combo + .get_active_text() + .unwrap_or(String::from("Master")), + }; + + // TODO don't convert like that + let vol_meter_color = VolColor { + red: (self.vol_meter_color_button.get_rgba().red * 255.0) as u8, + green: (self.vol_meter_color_button.get_rgba().green * 255.0) as u8, + blue: (self.vol_meter_color_button.get_rgba().blue * 255.0) as u8, + }; + + let view_prefs = ViewPrefs { + draw_vol_meter: self.vol_meter_draw_check.get_active(), + vol_meter_offset: self.vol_meter_pos_spin.get_value_as_int(), + system_theme: self.system_theme.get_active(), + vol_meter_color, + }; + + let vol_control_cmd = + self.vol_control_entry.get_text().and_then(|x| if x.is_empty() { + None + } else { + Some(x) + }); + + let custom_command = + self.custom_entry.get_text().and_then(|x| if x.is_empty() { + None + } else { + Some(x) + }); + + let behavior_prefs = BehaviorPrefs { + vol_control_cmd, + vol_scroll_step: self.scroll_step_spin.get_value(), + middle_click_action: self.middle_click_combo.get_active().into(), + custom_command, + }; + + let notify_prefs = NotifyPrefs { + enable_notifications: self.noti_enable_check.get_active(), + notifcation_timeout: self.noti_timeout_spin.get_value_as_int() as + i64, + notify_mouse_scroll: self.noti_mouse_check.get_active(), + notify_popup: self.noti_popup_check.get_active(), + notify_external: self.noti_ext_check.get_active(), + }; + + return Prefs { + device_prefs, + view_prefs, + behavior_prefs, + notify_prefs, + }; + + } +} + + pub fn show_prefs_dialog(appstate: Rc) { if appstate.gui .prefs_dialog @@ -54,7 +249,6 @@ pub fn init_prefs_dialog(appstate: &Rc) { let pd = m_pd.as_ref().unwrap(); pd.prefs_dialog.connect_response(move |_, response_id| { - let foo = 1; if response_id == ResponseType::Ok.into() || response_id == ResponseType::Apply.into() { let mut prefs = apps.prefs.borrow_mut(); @@ -72,6 +266,8 @@ pub 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 + try_w!(apps.update_tray_icon()); + try_w!(apps.update_popup_window()); let prefs = apps.prefs.borrow_mut(); try_w!(prefs.store_config()); } @@ -79,6 +275,7 @@ pub fn init_prefs_dialog(appstate: &Rc) { }); } + // TODO: fix combo box behavior and filling /* DEVICE TAB */ /* card_combo.connect_changed */ @@ -194,4 +391,3 @@ fn on_chan_combo_changed(appstate: &AppS) { } -fn prefs_dialog_to_prefs(prefs_dialog: &PrefsDialog) {} diff --git a/src/ui_tray_icon.rs b/src/ui_tray_icon.rs index 69402c676..abcc29213 100644 --- a/src/ui_tray_icon.rs +++ b/src/ui_tray_icon.rs @@ -13,7 +13,7 @@ use std::rc::Rc; use support_ui::*; -// TODO: on_apply +// TODO tooltip const ICON_MIN_SIZE: i32 = 16; @@ -21,7 +21,8 @@ const ICON_MIN_SIZE: i32 = 16; pub struct TrayIcon { - pub volmeter: Option, + _cant_construct: (), + pub volmeter: RefCell>, pub audio_pix: RefCell, pub status_icon: gtk::StatusIcon, pub icon_size: Cell, @@ -34,15 +35,16 @@ impl TrayIcon { let volmeter = { if draw_vol_meter { - Some(VolMeter::new(prefs)) + RefCell::new(Some(VolMeter::new(prefs))) } else { - None + RefCell::new(None) } }; let audio_pix = AudioPix::new(ICON_MIN_SIZE, prefs)?; let status_icon = gtk::StatusIcon::new(); return Ok(TrayIcon { + _cant_construct: (), volmeter, audio_pix: RefCell::new(audio_pix), status_icon, @@ -50,7 +52,33 @@ impl TrayIcon { }); } - fn update(&self, + + fn update_pixbuf(&self, cur_vol: f64, vol_level: VolLevel) -> Result<()> { + let audio_pix = self.audio_pix.borrow(); + let pixbuf = audio_pix.select_pix(vol_level); + + let vol_borrow = self.volmeter.borrow(); + let volmeter = &vol_borrow.as_ref(); + match volmeter { + &Some(v) => { + let vol_pix = v.meter_draw(cur_vol as i64, &pixbuf)?; + self.status_icon.set_from_pixbuf(Some(&vol_pix)); + } + &None => self.status_icon.set_from_pixbuf(Some(pixbuf)), + }; + + return Ok(()); + } + + + pub fn update_audio(&self, + audio: &Audio) -> Result<()> { + + return self.update_pixbuf(audio.vol()?, audio.vol_level()); + } + + + pub fn update_all(&self, prefs: &Prefs, audio: &Audio, m_size: Option) @@ -63,41 +91,30 @@ impl TrayIcon { } else { self.icon_size.set(s); } - /* if icon size changed, we have to re-init audio pix */ - let pixbuf = AudioPix::new(self.icon_size.get(), &prefs)?; - *self.audio_pix.borrow_mut() = pixbuf; } None => (), } - let cur_vol = audio.vol()?; - let audio_pix = self.audio_pix.borrow(); - let pixbuf = audio_pix.select_pix(audio.vol_level()); + 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 volmeter = &self.volmeter.as_ref(); - match volmeter { - &Some(v) => { - let vol_pix = v.meter_draw(cur_vol as i64, &pixbuf)?; - self.status_icon.set_from_pixbuf(Some(&vol_pix)); - } - &None => self.status_icon.set_from_pixbuf(Some(pixbuf)), - }; - - return Ok(()); + return self.update_pixbuf(audio.vol()?, audio.vol_level()); } } pub struct VolMeter { - pub red: u8, - pub green: u8, - pub blue: u8, - pub x_offset_pct: i64, - pub y_offset_pct: i64, + red: u8, + green: u8, + blue: u8, + x_offset_pct: i64, + y_offset_pct: i64, /* dynamic */ - pub width: Cell, - pub row: RefCell>, + width: Cell, + row: RefCell>, } @@ -280,7 +297,7 @@ impl AudioPix { pub fn init_tray_icon(appstate: Rc) { let audio = &appstate.audio; let tray_icon = &appstate.gui.tray_icon; - try_e!(tray_icon.update(&appstate.prefs.borrow_mut(), &audio, None)); + try_e!(tray_icon.update_all(&appstate.prefs.borrow_mut(), &audio, None)); tray_icon.status_icon.set_visible(true); @@ -290,10 +307,8 @@ pub fn init_tray_icon(appstate: Rc) { appstate.audio.connect_handler( Box::new(move |s, u| match (s, u) { (AudioSignal::ValuesChanged, _) => { - try_w!(apps.gui.tray_icon.update( - &apps.prefs.borrow_mut(), + try_w!(apps.gui.tray_icon.update_audio( &apps.audio, - None, )); } _ => (), @@ -305,7 +320,7 @@ pub fn init_tray_icon(appstate: Rc) { { let apps = appstate.clone(); tray_icon.status_icon.connect_size_changed(move |_, size| { - try_wr!(apps.gui.tray_icon.update(&apps.prefs.borrow_mut(), + try_wr!(apps.gui.tray_icon.update_all(&apps.prefs.borrow_mut(), &apps.audio, Some(size)), false);