pnmixer-rust/src/ui_popup_window.rs

282 lines
8.6 KiB
Rust
Raw Normal View History

2017-06-27 22:23:12 +00:00
use app_state::*;
2017-07-03 21:38:39 +00:00
use audio::*;
2017-06-27 22:23:12 +00:00
use errors::*;
2017-06-29 12:55:07 +00:00
use gdk::DeviceExt;
use gdk::{GrabOwnership, GrabStatus, BUTTON_PRESS_MASK, KEY_PRESS_MASK};
2017-06-29 12:25:40 +00:00
use gdk;
2017-06-29 12:55:07 +00:00
use gdk_sys::{GDK_KEY_Escape, GDK_CURRENT_TIME};
2017-06-30 15:24:26 +00:00
use glib;
2017-07-07 10:03:53 +00:00
use gtk::ToggleButtonExt;
2017-06-29 12:25:40 +00:00
use gtk::prelude::*;
use gtk;
2017-07-08 22:14:49 +00:00
use prefs::*;
2017-07-07 10:03:53 +00:00
use std::cell::Cell;
2017-06-28 12:55:38 +00:00
use std::rc::Rc;
2017-07-07 15:00:04 +00:00
use support_cmd::*;
2017-06-27 22:23:12 +00:00
2017-07-07 10:03:53 +00:00
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,
2017-07-07 15:00:04 +00:00
pub mixer_button: gtk::Button,
2017-07-07 10:03:53 +00:00
pub toggle_signal: Cell<u64>,
}
impl PopupWindow {
pub fn new(builder: gtk::Builder) -> PopupWindow {
return PopupWindow {
2017-07-07 20:10:45 +00:00
_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(),
mixer_button: builder.get_object("mixer_button").unwrap(),
toggle_signal: Cell::new(0),
};
2017-07-07 10:03:53 +00:00
}
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);
return Ok(());
}
pub fn update_mute_check(&self, audio: &Audio) {
2017-07-07 23:35:13 +00:00
let m_muted = audio.get_mute();
2017-07-07 10:03:53 +00:00
glib::signal_handler_block(&self.mute_check, self.toggle_signal.get());
2017-07-07 23:35:13 +00:00
match m_muted {
2017-07-07 10:03:53 +00:00
Ok(val) => {
2017-07-07 23:35:13 +00:00
self.mute_check.set_sensitive(true);
2017-07-07 10:03:53 +00:00
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);
2017-07-07 15:00:04 +00:00
self.mute_check.set_tooltip_text(
"Soundcard has no mute switch",
);
2017-07-07 10:03:53 +00:00
}
}
2017-07-07 20:10:45 +00:00
glib::signal_handler_unblock(&self.mute_check,
self.toggle_signal.get());
2017-07-07 10:03:53 +00:00
}
2017-07-08 22:14:49 +00:00
fn set_vol_increment(&self, prefs: &Prefs) {
self.vol_scale_adj
.set_page_increment(prefs.behavior_prefs.vol_scroll_step);
self.vol_scale_adj
.set_step_increment(prefs.behavior_prefs.vol_fine_scroll_step);
}
2017-07-07 10:03:53 +00:00
}
2017-06-30 15:24:26 +00:00
pub fn init_popup_window(appstate: Rc<AppS>) {
2017-07-07 15:00:04 +00:00
/* audio.connect_handler */
{
let apps = appstate.clone();
appstate.audio.connect_handler(Box::new(move |s, u| {
/* skip if window is hidden */
2017-07-07 20:10:45 +00:00
if !apps.gui
.popup_window
.popup_window
.get_visible() {
2017-07-07 15:00:04 +00:00
return;
}
match (s, u) {
/* Update only mute check here
* If the user changes the volume through the popup window,
* we MUST NOT update the slider value, it's been done already.
* It means that, as long as the popup window is visible,
* the slider value reflects the value set by user,
* and not the real value reported by the audio system.
*/
2017-07-07 20:10:45 +00:00
(_, AudioUser::Popup) => {
2017-07-07 15:00:04 +00:00
apps.gui.popup_window.update_mute_check(&apps.audio);
}
/* external change, safe to update slider too */
2017-07-07 20:10:45 +00:00
(_, _) => {
2017-07-07 15:00:04 +00:00
try_w!(apps.gui.popup_window.update(&apps.audio));
}
}
}));
}
2017-06-30 15:24:26 +00:00
/* mute_check.connect_toggled */
2017-06-27 22:23:12 +00:00
{
2017-06-30 15:24:26 +00:00
let _appstate = appstate.clone();
2017-07-07 20:10:45 +00:00
let mute_check = &appstate.clone()
.gui
.popup_window
.mute_check;
let toggle_signal =
mute_check.connect_toggled(move |_| {
on_mute_check_toggled(&_appstate)
});
appstate.gui
.popup_window
.toggle_signal
.set(toggle_signal);
2017-06-27 22:23:12 +00:00
}
2017-06-30 15:24:26 +00:00
/* popup_window.connect_show */
2017-06-28 15:53:19 +00:00
{
2017-06-30 15:24:26 +00:00
let _appstate = appstate.clone();
2017-07-07 20:10:45 +00:00
let popup_window = &appstate.clone()
.gui
.popup_window
.popup_window;
2017-07-07 15:00:04 +00:00
popup_window.connect_show(move |_| on_popup_window_show(&_appstate));
2017-06-28 15:53:19 +00:00
}
2017-06-30 15:24:26 +00:00
/* vol_scale_adj.connect_value_changed */
2017-06-27 22:23:12 +00:00
{
2017-06-30 15:24:26 +00:00
let _appstate = appstate.clone();
2017-07-07 20:10:45 +00:00
let vol_scale_adj = &appstate.clone()
.gui
.popup_window
.vol_scale_adj;
2017-06-30 15:24:26 +00:00
vol_scale_adj.connect_value_changed(
move |_| on_vol_scale_value_changed(&_appstate),
);
2017-06-27 22:23:12 +00:00
}
/* popup_window.connect_event */
{
2017-07-07 20:10:45 +00:00
let popup_window = &appstate.clone()
.gui
.popup_window
.popup_window;
2017-07-07 15:00:04 +00:00
popup_window.connect_event(move |w, e| on_popup_window_event(w, e));
}
/* mixer_button.connect_clicked */
{
let apps = appstate.clone();
2017-07-07 20:10:45 +00:00
let mixer_button = &appstate.clone()
.gui
.popup_window
.mixer_button;
2017-07-07 15:00:04 +00:00
mixer_button.connect_clicked(move |_| {
2017-07-07 20:10:45 +00:00
apps.gui
.popup_window
.popup_window
.hide();
2017-07-07 15:00:04 +00:00
try_w!(execute_vol_control_command(&apps.prefs.borrow()));
});
2017-06-27 22:23:12 +00:00
}
}
2017-06-29 12:55:07 +00:00
2017-07-07 10:03:53 +00:00
fn on_popup_window_show(appstate: &AppS) {
2017-07-08 22:14:49 +00:00
appstate.gui.popup_window.set_vol_increment(&appstate.prefs.borrow());
2017-07-07 10:03:53 +00:00
try_w!(appstate.gui.popup_window.update(&appstate.audio));
2017-07-07 20:10:45 +00:00
appstate.gui
.popup_window
.vol_scale
.grab_focus();
2017-07-07 15:00:04 +00:00
try_w!(grab_devices(&appstate.gui.popup_window.popup_window));
2017-06-30 15:24:26 +00:00
}
2017-07-07 15:00:04 +00:00
fn on_popup_window_event(w: &gtk::Window, e: &gdk::Event) -> gtk::Inhibit {
2017-06-30 15:24:26 +00:00
match gdk::Event::get_event_type(e) {
gdk::EventType::GrabBroken => w.hide(),
gdk::EventType::KeyPress => {
let key: gdk::EventKey = e.clone().downcast().unwrap();
if key.get_keyval() == (GDK_KEY_Escape as u32) {
w.hide();
}
}
gdk::EventType::ButtonPress => {
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() {
w.hide();
}
}
_ => (),
}
return Inhibit(false);
}
fn on_vol_scale_value_changed(appstate: &AppS) {
2017-07-01 22:03:21 +00:00
let audio = &appstate.audio;
2017-06-30 15:24:26 +00:00
2017-07-07 20:10:45 +00:00
let val = appstate.gui
.popup_window
.vol_scale
.get_value();
2017-06-30 15:24:26 +00:00
2017-07-03 21:38:39 +00:00
try_w!(audio.set_vol(val, AudioUser::Popup));
2017-06-30 15:24:26 +00:00
}
fn on_mute_check_toggled(appstate: &AppS) {
2017-07-01 22:03:21 +00:00
let audio = &appstate.audio;
2017-07-03 21:52:41 +00:00
try_w!(audio.toggle_mute(AudioUser::Popup))
2017-06-30 15:24:26 +00:00
}
2017-06-30 19:10:33 +00:00
pub fn set_slider(vol_scale_adj: &gtk::Adjustment, scale: f64) {
2017-06-29 12:55:07 +00:00
vol_scale_adj.set_value(scale);
}
2017-07-08 00:38:49 +00:00
fn grab_devices(window: &gtk::Window) -> Result<()> {
2017-06-29 12:55:07 +00:00
let device = gtk::get_current_event_device().ok_or("No current device")?;
let gdk_window = window.get_window().ok_or("No window?!")?;
/* Grab the mouse */
2017-07-07 20:10:45 +00:00
let m_grab_status =
device.grab(&gdk_window,
GrabOwnership::None,
true,
BUTTON_PRESS_MASK,
None,
GDK_CURRENT_TIME as u32);
2017-06-29 12:55:07 +00:00
if m_grab_status != GrabStatus::Success {
2017-07-07 20:10:45 +00:00
warn!("Could not grab {}",
device.get_name().unwrap_or(String::from("UNKNOWN DEVICE")));
2017-06-29 12:55:07 +00:00
}
/* Grab the keyboard */
2017-07-07 20:10:45 +00:00
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);
2017-06-29 12:55:07 +00:00
if k_grab_status != GrabStatus::Success {
2017-07-07 20:10:45 +00:00
warn!("Could not grab {}",
k_dev.get_name().unwrap_or(String::from("UNKNOWN DEVICE")));
2017-06-29 12:55:07 +00:00
}
return Ok(());
}