This commit is contained in:
Julian Ospald 2017-07-08 01:35:13 +02:00
parent a5bfb1e27d
commit f8939ec581
No known key found for this signature in database
GPG Key ID: 511B62C09D50CD28
7 changed files with 126 additions and 42 deletions

View File

@ -44,24 +44,36 @@ impl AlsaCard {
match card_name { match card_name {
Some(name) => { Some(name) => {
if name == "(default)" { if name == "(default)" {
get_default_alsa_card() let default = get_default_alsa_card();
if alsa_card_has_playable_selem(&default) {
default
} else {
warn!("Default alsa card not playabla, trying others");
get_first_playable_alsa_card()?
}
} else { } else {
get_alsa_card_by_name(name)? let mycard = get_alsa_card_by_name(name.clone());
match mycard {
Ok(card) => card,
Err(_) => {
warn!("Card {} not playable, trying others", name);
get_first_playable_alsa_card()?
}
}
} }
}, },
None => get_default_alsa_card(), None => get_first_playable_alsa_card()?,
} }
}; };
let mixer = get_mixer(&card)?; let mixer = get_mixer(&card)?;
let vec_pollfd = PollDescriptors::get(&mixer)?;
let selem_id = let selem_id =
get_selem_by_name(&mixer, get_playable_selem_by_name(&mixer,
elem_name.unwrap_or(String::from("Master"))) elem_name.unwrap_or(String::from("Master")))?
.unwrap()
.get_id(); .get_id();
let vec_pollfd = PollDescriptors::get(&mixer)?;
let acard = Box::new(AlsaCard { let acard = Box::new(AlsaCard {
_cannot_construct: (), _cannot_construct: (),
card: card, card: card,
@ -114,7 +126,7 @@ impl AlsaCard {
pub fn set_vol(&self, new_vol: f64) -> Result<()> { pub fn set_vol(&self, new_vol: f64) -> Result<()> {
let selem = self.selem(); let selem = self.selem();
/* auto-unmute */ /* auto-unmute */
if self.get_mute()? { if self.has_mute() && self.get_mute()? {
self.set_mute(false)?; self.set_mute(false)?;
} }
@ -241,6 +253,7 @@ extern "C" fn watch_cb(chan: *mut glib_sys::GIOChannel,
debug!("G_IO_STATUS_AGAIN"); debug!("G_IO_STATUS_AGAIN");
continue; continue;
} }
// TODO: handle these failure cases
glib_sys::G_IO_STATUS_NORMAL => debug!("G_IO_STATUS_NORMAL"), glib_sys::G_IO_STATUS_NORMAL => debug!("G_IO_STATUS_NORMAL"),
glib_sys::G_IO_STATUS_ERROR => debug!("G_IO_STATUS_ERROR"), glib_sys::G_IO_STATUS_ERROR => debug!("G_IO_STATUS_ERROR"),
glib_sys::G_IO_STATUS_EOF => debug!("G_IO_STATUS_EOF"), glib_sys::G_IO_STATUS_EOF => debug!("G_IO_STATUS_EOF"),

View File

@ -30,10 +30,14 @@ impl AppS {
let gui = let gui =
Gui::new(builder_popup_window, builder_popup_menu, &prefs.borrow()); 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();
return AppS { return AppS {
_cant_construct: (), _cant_construct: (),
gui: gui, gui: gui,
audio: Audio::new(None, Some(String::from("Master"))) audio: Audio::new(Some(card_name),
Some(chan_name))
.unwrap(), .unwrap(),
prefs: prefs, prefs: prefs,
}; };
@ -54,6 +58,7 @@ impl AppS {
return self.gui.popup_window.update(&self.audio); return self.gui.popup_window.update(&self.audio);
} }
// TODO
pub fn show_preferences(&self) { pub fn show_preferences(&self) {
// show_prefs_dialog(self); // show_prefs_dialog(self);
} }

View File

@ -1,9 +1,10 @@
use alsa::card::Card; use alsa::card::Card;
use alsa::mixer::{Mixer, Selem, Elem}; use alsa::mixer::{Mixer, Selem, SelemId, Elem};
use alsa; use alsa;
use errors::*; use errors::*;
use libc::c_int; use libc::c_int;
use std::iter::Map; use std::iter::Map;
use std::iter::Filter;
@ -22,11 +23,34 @@ pub fn get_alsa_cards() -> alsa::card::Iter {
} }
pub fn get_alsa_card_names() -> Vec<String> { pub fn get_first_playable_alsa_card() -> Result<Card> {
for m_card in get_alsa_cards() {
match m_card {
Ok(card) => {
if alsa_card_has_playable_selem(&card) {
return Ok(card);
}
},
_ => (),
}
}
bail!("No playable alsa card found!")
}
pub fn get_playable_alsa_card_names() -> Vec<String> {
let mut vec = vec![]; let mut vec = vec![];
for card in get_alsa_cards() { for m_card in get_alsa_cards() {
match card.and_then(|c| c.get_name()) { match m_card {
Ok(name) => vec.push(name), Ok(card) => {
if alsa_card_has_playable_selem(&card) {
let m_name = card.get_name();
if m_name.is_ok() {
vec.push(m_name.unwrap())
}
}
},
_ => (), _ => (),
} }
} }
@ -47,6 +71,17 @@ pub fn get_alsa_card_by_name(name: String) -> Result<Card> {
} }
pub fn alsa_card_has_playable_selem(card: &Card) -> bool {
let mixer = try_wr!(get_mixer(&card), false);
for selem in get_playable_selems(&mixer) {
if selem_is_playable(&selem) {
return true;
}
}
return false;
}
pub fn get_mixer(card: &Card) -> Result<Mixer> { pub fn get_mixer(card: &Card) -> Result<Mixer> {
return Mixer::new(&format!("hw:{}", card.get_index()), false).from_err(); return Mixer::new(&format!("hw:{}", card.get_index()), false).from_err();
} }
@ -60,14 +95,18 @@ pub fn get_selem(elem: Elem) -> Selem {
} }
pub fn get_selems(mixer: &Mixer) -> Map<alsa::mixer::Iter, fn(Elem) -> Selem> { pub fn get_playable_selems(mixer: &Mixer) -> Vec<Selem> {
return mixer.iter().map(get_selem); let mut v = vec![];
for s in mixer.iter().map(get_selem).filter(selem_is_playable) {
v.push(s);
}
return v;
} }
pub fn get_selem_names(mixer: &Mixer) -> Vec<String> { pub fn get_playable_selem_names(mixer: &Mixer) -> Vec<String> {
let mut vec = vec![]; let mut vec = vec![];
for selem in get_selems(mixer) { for selem in get_playable_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));
match n { match n {
Ok(name) => vec.push(name), Ok(name) => vec.push(name),
@ -79,8 +118,8 @@ pub fn get_selem_names(mixer: &Mixer) -> Vec<String> {
} }
pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> { pub fn get_playable_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> {
for selem in get_selems(mixer) { for selem in get_playable_selems(mixer) {
let n = selem.get_id() let n = selem.get_id()
.get_name() .get_name()
.map(|y| String::from(y))?; .map(|y| String::from(y))?;
@ -89,7 +128,12 @@ pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> {
return Ok(selem); return Ok(selem);
} }
} }
bail!("Not found a matching selem named {}", name); bail!("Not found a matching playable selem named {}", name);
}
pub fn selem_is_playable(selem: &Selem) -> bool {
return selem.has_playback_volume();
} }

View File

@ -38,13 +38,7 @@ pub fn init_popup_menu(appstate: Rc<AppS>) {
return; return;
} }
match (s, u) { match (s, u) {
(_, _) => { (_, _) => set_mute_check(&apps)
let muted = try_w!(apps.audio.get_mute());
apps.gui
.popup_menu
.mute_check
.set_active(muted);
}
} }
})); }));
@ -57,11 +51,7 @@ pub fn init_popup_menu(appstate: Rc<AppS>) {
.popup_menu .popup_menu
.menu .menu
.connect_show(move |_| { .connect_show(move |_| {
let muted = try_w!(apps.audio.get_mute()); set_mute_check(&apps)
apps.gui
.popup_menu
.mute_check
.set_active(muted);
}); });
} }
@ -75,12 +65,14 @@ pub fn init_popup_menu(appstate: Rc<AppS>) {
}); });
} }
/* about_item.connect_activate_link */ /* mute_item.connect_activate_link */
{ {
let apps = appstate.clone(); let apps = appstate.clone();
let mute_item = &appstate.gui.popup_menu.mute_item; let mute_item = &appstate.gui.popup_menu.mute_item;
mute_item.connect_activate(move |_| { mute_item.connect_activate(move |_| {
try_w!(apps.audio.toggle_mute(AudioUser::Popup)); if apps.audio.has_mute() {
try_w!(apps.audio.toggle_mute(AudioUser::Popup));
}
}); });
} }
@ -93,7 +85,7 @@ pub fn init_popup_menu(appstate: Rc<AppS>) {
}); });
} }
/* about_item.connect_activate_link */ /* prefs_item.connect_activate_link */
{ {
let apps = appstate.clone(); let apps = appstate.clone();
let prefs_item = &appstate.gui.popup_menu.prefs_item; let prefs_item = &appstate.gui.popup_menu.prefs_item;
@ -157,3 +149,30 @@ fn on_prefs_item_activate(appstate: &Rc<AppS>) {
/* TODO: only create if needed */ /* TODO: only create if needed */
show_prefs_dialog(appstate); show_prefs_dialog(appstate);
} }
fn set_mute_check(apps: &Rc<AppS>) {
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(
"");
},
Err(_) => {
mute_check
.set_active(true);
mute_check
.set_sensitive(false);
mute_check.set_tooltip_text(
"Soundcard has no mute switch",
);
}
}
}

View File

@ -48,12 +48,13 @@ impl PopupWindow {
} }
pub fn update_mute_check(&self, audio: &Audio) { pub fn update_mute_check(&self, audio: &Audio) {
let muted = audio.get_mute(); let m_muted = audio.get_mute();
glib::signal_handler_block(&self.mute_check, self.toggle_signal.get()); glib::signal_handler_block(&self.mute_check, self.toggle_signal.get());
match muted { match m_muted {
Ok(val) => { Ok(val) => {
self.mute_check.set_sensitive(true);
self.mute_check.set_active(val); self.mute_check.set_active(val);
self.mute_check.set_tooltip_text(""); self.mute_check.set_tooltip_text("");
} }

View File

@ -329,7 +329,7 @@ fn fill_card_combo(appstate: &AppS) {
/* set card combo */ /* set card combo */
let cur_card_name = try_w!(acard.card_name(), let cur_card_name = try_w!(acard.card_name(),
"Can't get current card name!"); "Can't get current card name!");
let available_card_names = get_alsa_card_names(); let available_card_names = get_playable_alsa_card_names();
/* set_active_id doesn't work, so save the index */ /* set_active_id doesn't work, so save the index */
let mut c_index: i32 = -1; let mut c_index: i32 = -1;
@ -362,7 +362,7 @@ fn fill_chan_combo(appstate: &AppS, cardname: Option<String>) {
/* set chan combo */ /* set chan combo */
let cur_chan_name = try_w!(cur_acard.chan_name()); let cur_chan_name = try_w!(cur_acard.chan_name());
let mixer = try_w!(get_mixer(&card)); let mixer = try_w!(get_mixer(&card));
let available_chan_names = get_selem_names(&mixer); let available_chan_names = get_playable_selem_names(&mixer);
/* set_active_id doesn't work, so save the index */ /* set_active_id doesn't work, so save the index */
let mut c_index: i32 = -1; let mut c_index: i32 = -1;

View File

@ -415,7 +415,9 @@ fn on_tray_button_release_event(appstate: &AppS,
match middle_click_action { match middle_click_action {
&MiddleClickAction::ToggleMute => { &MiddleClickAction::ToggleMute => {
try_wr!(audio.toggle_mute(AudioUser::Popup), false); if audio.has_mute() {
try_wr!(audio.toggle_mute(AudioUser::Popup), false);
}
} }
&MiddleClickAction::ShowPreferences => (), &MiddleClickAction::ShowPreferences => (),
&MiddleClickAction::VolumeControl => { &MiddleClickAction::VolumeControl => {