Update
This commit is contained in:
parent
a5bfb1e27d
commit
f8939ec581
@ -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"),
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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("");
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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 => {
|
||||||
|
Loading…
Reference in New Issue
Block a user