Update
This commit is contained in:
parent
0daff4d6b8
commit
6504c5c5ab
@ -1,8 +1,9 @@
|
||||
use gtk;
|
||||
|
||||
use alsa::card::Card;
|
||||
use alsa::mixer::{Mixer, Selem};
|
||||
use std::cell::Cell;
|
||||
use alsa::mixer::{Mixer, SelemId, Selem};
|
||||
use audio;
|
||||
use errors::*;
|
||||
|
||||
pub struct AppS {
|
||||
/* we keep this to ensure the lifetime is across the whole application */
|
||||
@ -11,9 +12,56 @@ pub struct AppS {
|
||||
pub builder_popup: gtk::Builder,
|
||||
}
|
||||
|
||||
pub struct AlsaCard<'a> {
|
||||
pub card: Cell<Card>,
|
||||
pub mixer: Cell<Mixer>,
|
||||
pub selem: Cell<Selem<'a>>,
|
||||
pub struct AlsaCard {
|
||||
card: Card,
|
||||
mixer: Mixer,
|
||||
selem_id: SelemId,
|
||||
}
|
||||
|
||||
impl AlsaCard {
|
||||
pub fn new(
|
||||
card_name: Option<String>,
|
||||
elem_name: Option<String>,
|
||||
) -> Result<AlsaCard> {
|
||||
let card = {
|
||||
match card_name {
|
||||
Some(name) => audio::get_alsa_card_by_name(name)?,
|
||||
None => audio::get_default_alsa_card(),
|
||||
}
|
||||
};
|
||||
let mixer = audio::get_mixer(&card)?;
|
||||
let selem_id = audio::get_selem_by_name(
|
||||
&mixer,
|
||||
elem_name.unwrap_or(String::from("Master")),
|
||||
).unwrap()
|
||||
.get_id();
|
||||
|
||||
return Ok(AlsaCard {
|
||||
card: card,
|
||||
mixer: mixer,
|
||||
selem_id: selem_id,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn selem(&self) -> Selem {
|
||||
return audio::get_selems(&self.mixer)
|
||||
.nth(self.selem_id.get_index() as usize)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn vol(&self) -> Result<f64> {
|
||||
return audio::get_vol(&self.selem());
|
||||
}
|
||||
|
||||
pub fn has_mute(&self) -> bool {
|
||||
return audio::has_mute(&self.selem());
|
||||
}
|
||||
|
||||
pub fn get_mute(&self) -> Result<bool> {
|
||||
return audio::get_mute(&self.selem());
|
||||
}
|
||||
|
||||
pub fn set_mute(&self, mute: bool) -> Result<()> {
|
||||
return audio::set_mute(&self.selem(), mute);
|
||||
}
|
||||
}
|
||||
|
16
src/audio.rs
16
src/audio.rs
@ -23,6 +23,17 @@ pub fn get_alsa_cards() -> alsa::card::Iter {
|
||||
return alsa::card::Iter::new();
|
||||
}
|
||||
|
||||
pub fn get_alsa_card_by_name(name: String) -> Result<Card> {
|
||||
for r_card in get_alsa_cards() {
|
||||
let card = r_card?;
|
||||
let card_name = card.get_name()?;
|
||||
if name == card_name {
|
||||
return Ok(card);
|
||||
}
|
||||
}
|
||||
bail!("Not found a matching card named {}", name);
|
||||
}
|
||||
|
||||
pub fn get_mixer(card: &Card) -> Result<Mixer> {
|
||||
return Mixer::new(&format!("hw:{}", card.get_index()), false).cherr();
|
||||
}
|
||||
@ -40,9 +51,7 @@ pub fn get_selems(mixer: &Mixer) -> Map<alsa::mixer::Iter, fn(Elem) -> Selem> {
|
||||
|
||||
pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> {
|
||||
for selem in get_selems(mixer) {
|
||||
let n = selem.get_id()
|
||||
.get_name()
|
||||
.map(|y| String::from(y))?;
|
||||
let n = selem.get_id().get_name().map(|y| String::from(y))?;
|
||||
|
||||
if n == name {
|
||||
return Ok(selem);
|
||||
@ -74,4 +83,3 @@ pub fn set_mute(selem: &Selem, mute: bool) -> Result<()> {
|
||||
let _ = selem.set_playback_switch_all(!mute as i32)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
46
src/gui.rs
46
src/gui.rs
@ -23,32 +23,40 @@ pub fn grab_devices(window: >k::Window) -> Result<()> {
|
||||
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_or(String::from("UNKNOWN DEVICE")));
|
||||
warn!(
|
||||
"Could not grab {}",
|
||||
device.get_name().unwrap_or(String::from("UNKNOWN DEVICE"))
|
||||
);
|
||||
}
|
||||
|
||||
/* Grab the keyboard */
|
||||
let k_dev = device.get_associated_device()
|
||||
.ok_or("Couldn't get associated device")?;
|
||||
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_or(String::from("UNKNOWN DEVICE")));
|
||||
warn!(
|
||||
"Could not grab {}",
|
||||
k_dev.get_name().unwrap_or(String::from("UNKNOWN DEVICE"))
|
||||
);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
|
@ -9,15 +9,16 @@ use gtk::prelude::*;
|
||||
use gdk_sys::GDK_KEY_Escape;
|
||||
|
||||
use gui;
|
||||
use audio;
|
||||
use app_state::*;
|
||||
use errors::*;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
pub fn init<'a>(appstate: &'a AppS) {
|
||||
pub fn init<'a>(appstate: &'a AppS, rc_acard: Rc<RefCell<AlsaCard>>) {
|
||||
|
||||
init_tray_icon(&appstate);
|
||||
init_popup_window(&appstate);
|
||||
init_popup_window(&appstate, rc_acard);
|
||||
}
|
||||
|
||||
|
||||
@ -31,16 +32,16 @@ fn init_tray_icon(appstate: &AppS) {
|
||||
appstate.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();
|
||||
try_w!(gui::grab_devices(&popup_window));
|
||||
});
|
||||
popup_window.hide();
|
||||
} else {
|
||||
popup_window.show_now();
|
||||
vol_scale.grab_focus();
|
||||
try_w!(gui::grab_devices(&popup_window));
|
||||
});
|
||||
tray_icon.set_visible(true);
|
||||
}
|
||||
|
||||
fn init_popup_window(appstate: &AppS) {
|
||||
fn init_popup_window(appstate: &AppS, rc_acard: Rc<RefCell<AlsaCard>>) {
|
||||
/* popup_window.connect_show */
|
||||
{
|
||||
let popup_window: gtk::Window =
|
||||
@ -50,17 +51,14 @@ fn init_popup_window(appstate: &AppS) {
|
||||
let mute_check: gtk::CheckButton =
|
||||
appstate.builder_popup.get_object("mute_check").unwrap();
|
||||
|
||||
let card = rc_acard.clone();
|
||||
popup_window.connect_show(move |_| {
|
||||
let alsa_card = audio::get_default_alsa_card();
|
||||
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));
|
||||
let acard = card.borrow();
|
||||
|
||||
let cur_vol = try_w!(acard.vol());
|
||||
gui::set_slider(&vol_scale_adj, cur_vol);
|
||||
|
||||
let muted = audio::get_mute(&selem);
|
||||
let muted = acard.get_mute();
|
||||
update_mute_check(&mute_check, muted);
|
||||
});
|
||||
}
|
||||
@ -70,16 +68,12 @@ fn init_popup_window(appstate: &AppS) {
|
||||
let mute_check: gtk::CheckButton =
|
||||
appstate.builder_popup.get_object("mute_check").unwrap();
|
||||
|
||||
let card = rc_acard.clone();
|
||||
mute_check.connect_toggled(move |_| {
|
||||
let alsa_card = audio::get_default_alsa_card();
|
||||
let mixer = try_w!(audio::get_mixer(&alsa_card));
|
||||
let selem = try_w!(audio::get_selem_by_name(
|
||||
&mixer,
|
||||
String::from("Master"),
|
||||
));
|
||||
let acard = card.borrow();
|
||||
|
||||
let muted = try_w!(audio::get_mute(&selem));
|
||||
let _ = try_w!(audio::set_mute(&selem, !muted));
|
||||
let muted = try_w!(acard.get_mute());
|
||||
let _ = try_w!(acard.set_mute(!muted));
|
||||
});
|
||||
}
|
||||
|
||||
@ -122,7 +116,7 @@ fn update_mute_check(check_button: >k::CheckButton, muted: Result<bool>) {
|
||||
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);
|
||||
@ -131,4 +125,3 @@ fn update_mute_check(check_button: >k::CheckButton, muted: Result<bool>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
28
src/main.rs
28
src/main.rs
@ -14,7 +14,8 @@ extern crate alsa;
|
||||
use gtk::prelude::*;
|
||||
use gdk_sys::GDK_KEY_Escape;
|
||||
use app_state::*;
|
||||
use std::cell::Cell;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::boxed::Box;
|
||||
|
||||
|
||||
@ -27,26 +28,23 @@ mod gui_callbacks;
|
||||
mod app_state;
|
||||
|
||||
|
||||
|
||||
fn main() {
|
||||
gtk::init().unwrap();
|
||||
|
||||
let ref apps = AppS {
|
||||
status_icon: gtk::StatusIcon::new_from_icon_name("pnmixer"),
|
||||
builder_popup: gtk::Builder::new_from_string(include_str!("../data/ui/popup-window-vertical.glade")),
|
||||
builder_popup: gtk::Builder::new_from_string(
|
||||
include_str!("../data/ui/popup-window-vertical.glade"),
|
||||
),
|
||||
};
|
||||
|
||||
let alsa_card = audio::get_default_alsa_card();
|
||||
let mixer = audio::get_mixer(&alsa_card).unwrap();
|
||||
let selem = audio::get_selem_by_name(
|
||||
&mixer,
|
||||
String::from("Master"),
|
||||
).unwrap();
|
||||
|
||||
let ref acard = AlsaCard {
|
||||
card: Cell::new(alsa_card),
|
||||
mixer: Cell::new(mixer),
|
||||
selem: Cell::new(selem),
|
||||
};
|
||||
let acard = Rc::new(RefCell::new(
|
||||
AlsaCard::new(
|
||||
Some(String::from("Intel 82801AA-ICH")),
|
||||
Some(String::from("Master")),
|
||||
).unwrap(),
|
||||
));
|
||||
|
||||
flexi_logger::LogOptions::new()
|
||||
.log_to_file(false)
|
||||
@ -55,7 +53,7 @@ fn main() {
|
||||
.unwrap_or_else(|e| panic!("Logger initialization failed with {}", e));
|
||||
|
||||
|
||||
gui_callbacks::init(apps);
|
||||
gui_callbacks::init(apps, acard);
|
||||
|
||||
gtk::main();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user