This commit is contained in:
Ospald, Julian 2017-06-28 14:55:38 +02:00
parent 0daff4d6b8
commit 6504c5c5ab
5 changed files with 127 additions and 72 deletions

View File

@ -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);
}
}

View File

@ -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(());
}

View File

@ -23,32 +23,40 @@ pub fn grab_devices(window: &gtk::Window) -> Result<()> {
let gdk_window = window.get_window().ok_or("No window?!")?;
/* Grab the mouse */
let m_grab_status =
device.grab(&gdk_window,
let m_grab_status = device.grab(
&gdk_window,
GrabOwnership::None,
true,
BUTTON_PRESS_MASK,
None,
GDK_CURRENT_TIME as u32);
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,
let k_grab_status = k_dev.grab(
&gdk_window,
GrabOwnership::None,
true,
KEY_PRESS_MASK,
None,
GDK_CURRENT_TIME as u32);
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(());

View File

@ -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);
}
@ -40,7 +41,7 @@ fn init_tray_icon(appstate: &AppS) {
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: &gtk::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: &gtk::CheckButton, muted: Result<bool>) {
}
}
}

View File

@ -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();
}