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 {
Some(name) => {
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 {
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 vec_pollfd = PollDescriptors::get(&mixer)?;
let selem_id =
get_selem_by_name(&mixer,
elem_name.unwrap_or(String::from("Master")))
.unwrap()
get_playable_selem_by_name(&mixer,
elem_name.unwrap_or(String::from("Master")))?
.get_id();
let vec_pollfd = PollDescriptors::get(&mixer)?;
let acard = Box::new(AlsaCard {
_cannot_construct: (),
card: card,
@ -114,7 +126,7 @@ impl AlsaCard {
pub fn set_vol(&self, new_vol: f64) -> Result<()> {
let selem = self.selem();
/* auto-unmute */
if self.get_mute()? {
if self.has_mute() && self.get_mute()? {
self.set_mute(false)?;
}
@ -241,6 +253,7 @@ extern "C" fn watch_cb(chan: *mut glib_sys::GIOChannel,
debug!("G_IO_STATUS_AGAIN");
continue;
}
// TODO: handle these failure cases
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_EOF => debug!("G_IO_STATUS_EOF"),

View File

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

View File

@ -1,9 +1,10 @@
use alsa::card::Card;
use alsa::mixer::{Mixer, Selem, Elem};
use alsa::mixer::{Mixer, Selem, SelemId, Elem};
use alsa;
use errors::*;
use libc::c_int;
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![];
for card in get_alsa_cards() {
match card.and_then(|c| c.get_name()) {
Ok(name) => vec.push(name),
for m_card in get_alsa_cards() {
match m_card {
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> {
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> {
return mixer.iter().map(get_selem);
pub fn get_playable_selems(mixer: &Mixer) -> Vec<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![];
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));
match n {
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> {
for selem in get_selems(mixer) {
pub fn get_playable_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> {
for selem in get_playable_selems(mixer) {
let n = selem.get_id()
.get_name()
.map(|y| String::from(y))?;
@ -89,7 +128,12 @@ pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result<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;
}
match (s, u) {
(_, _) => {
let muted = try_w!(apps.audio.get_mute());
apps.gui
.popup_menu
.mute_check
.set_active(muted);
}
(_, _) => set_mute_check(&apps)
}
}));
@ -57,11 +51,7 @@ pub fn init_popup_menu(appstate: Rc<AppS>) {
.popup_menu
.menu
.connect_show(move |_| {
let muted = try_w!(apps.audio.get_mute());
apps.gui
.popup_menu
.mute_check
.set_active(muted);
set_mute_check(&apps)
});
}
@ -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 mute_item = &appstate.gui.popup_menu.mute_item;
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 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 */
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) {
let muted = audio.get_mute();
let m_muted = audio.get_mute();
glib::signal_handler_block(&self.mute_check, self.toggle_signal.get());
match muted {
match m_muted {
Ok(val) => {
self.mute_check.set_sensitive(true);
self.mute_check.set_active(val);
self.mute_check.set_tooltip_text("");
}

View File

@ -329,7 +329,7 @@ fn fill_card_combo(appstate: &AppS) {
/* set card combo */
let cur_card_name = try_w!(acard.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 */
let mut c_index: i32 = -1;
@ -362,7 +362,7 @@ fn fill_chan_combo(appstate: &AppS, cardname: Option<String>) {
/* set chan combo */
let cur_chan_name = try_w!(cur_acard.chan_name());
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 */
let mut c_index: i32 = -1;

View File

@ -415,7 +415,9 @@ fn on_tray_button_release_event(appstate: &AppS,
match middle_click_action {
&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::VolumeControl => {