This commit is contained in:
Julian Ospald 2017-10-10 08:43:08 +02:00
parent 0f3652a6b2
commit 9e4653fbd1
No known key found for this signature in database
GPG Key ID: 511B62C09D50CD28
13 changed files with 420 additions and 199 deletions

View File

@ -2,6 +2,7 @@
use audio::alsa::backend::*;
use audio::pulseaudio::*;
use audio::frontend::*;
use errors::*;
use gtk;
@ -52,6 +53,19 @@ pub fn new_alsa_appstate() -> AppS<AlsaBackend> {
return AppS::new(prefs, audio);
}
/// Create a new application state using the `PABackend`.
pub fn new_pa_appstate() -> AppS<PABackend> {
let prefs = RefCell::new(unwrap_error!(Prefs::new(), None));
let card_name = prefs.borrow().device_prefs.card.clone();
let chan_name = prefs.borrow().device_prefs.channel.clone();
let audio = Rc::new(unwrap_error!(
PABackend::new(Some(card_name), Some(chan_name)),
None
));
return AppS::new(prefs, audio);
}
impl<T> AppS<T>
where

View File

@ -136,8 +136,20 @@ impl AudioFrontend for AlsaBackend {
return Ok(n);
}
fn playable_chan_names(&self) -> Vec<String> {
return get_playable_selem_names(&self.acard.borrow().mixer);
fn playable_chan_names(&self, cardname: Option<String>) -> Vec<String> {
match cardname {
Some(name) => {
let card = try_r!(get_alsa_card_by_name(name), Vec::default());
let mixer = try_r!(get_mixer(&card), Vec::default());
return get_playable_selem_names(&mixer);
},
None => self.acard.borrow().playable_chan_names(),
}
}
fn playable_card_names(&self) -> Vec<String> {
return get_playable_alsa_card_names();
}
fn get_vol(&self) -> Result<f64> {
@ -286,29 +298,6 @@ impl AudioFrontend for AlsaBackend {
}
/// Invokes the registered handlers.
fn invoke_handlers(
handlers: &Vec<Box<Fn(AudioSignal, AudioUser)>>,
signal: AudioSignal,
user: AudioUser,
) {
debug!(
"Invoking handlers for signal {:?} by user {:?}",
signal,
user
);
if handlers.is_empty() {
debug!("No handler found");
} else {
debug!("Executing handlers")
}
for handler in handlers {
let unboxed = handler.as_ref();
unboxed(signal, user);
}
}
/// The callback for alsa events that is passed to the alsa subsystem.
/// This is the bridge between low-level alsa events and "high-level"
/// audio system signals.

View File

@ -184,6 +184,11 @@ impl AlsaCard {
}
}
}
// Get playable channel names of the given card.
pub fn playable_chan_names(&self) -> Vec<String> {
return get_playable_selem_names(&self.mixer);
}
}

View File

@ -153,8 +153,11 @@ pub trait AudioFrontend {
/// Get the current card name.
fn card_name(&self) -> Result<String>;
/// Get the currently playable card names.
fn playable_card_names(&self) -> Vec<String>;
/// Get the currently playable channel names.
fn playable_chan_names(&self) -> Vec<String>;
fn playable_chan_names(&self, cardname: Option<String>) -> Vec<String>;
/// Get the current active channel name.
fn chan_name(&self) -> Result<String>;

View File

@ -1,18 +1,25 @@
#![allow(missing_docs)]
//! Pulseaudio backend subsystem.
use audio::frontend::*;
use errors::*;
use libc;
use libpulse_sys::*;
use std::cell::Cell;
use std::cell::RefCell;
use std::ffi::{CString, CStr};
use std::mem;
use std::os::raw::c_char;
use std::ffi::{CString};
use std::ptr;
use support::pulseaudio::*;
use support::audio::*;
pub const PA_VOLUME_MUTED: i64 = 0x0;
pub const PA_VOLUME_NORM: i64 = 0x10000;
// TODO: get info based on index, not descr.
//
// TODO: how to hook pulseaudio events? port change?
@ -28,17 +35,47 @@ pub struct Sink {
pub channels: u8,
}
impl Sink {
pub fn new(sink_desc: Option<String>,
chan_name: Option<String>,
mainloop: *mut pa_threaded_mainloop,
context: *mut pa_context) -> Result<Self> {
let sink = {
match sink_desc.as_ref().map(|s| s.as_str()) {
Some("(default)") => get_first_sink(mainloop, context)?,
Some(sd) => {
let mysink = get_sink_by_desc(mainloop, context, sd);
match mysink {
Ok(s) => s,
Err(_) => {
warn!("Could not find sink with name {}, trying others", sd);
get_first_sink(mainloop, context)?
}
}
}
None => get_first_sink(mainloop, context)?
}
};
return Ok(sink);
}
}
pub struct PABackend {
_cannot_construct: (),
m: *mut pa_threaded_mainloop,
c: *mut pa_context,
pub sink: RefCell<Sink>,
pub scroll_step: Cell<u32>,
pub handlers: Handlers,
}
impl PABackend {
pub fn new(sink_desc: Option<String>) -> Result<Self> {
pub fn new(sink_desc: Option<String>, chan_name: Option<String>) -> Result<Self> {
unsafe {
let mainloop: *mut pa_threaded_mainloop = pa_threaded_mainloop_new();
@ -86,35 +123,74 @@ impl PABackend {
pa_threaded_mainloop_unlock(mainloop);
CONTEXT_READY = false;
let sink = {
match sink_desc.as_ref().map(|s| s.as_str()) {
Some("(default)") => get_first_sink(mainloop, context)?,
Some(sd) => {
let mysink = get_sink_by_desc(mainloop, context, sd);
match mysink {
Ok(s) => s,
Err(_) => {
warn!("Could not find sink with name {}, trying others", sd);
get_first_sink(mainloop, context)?
}
}
let sink = Sink::new(sink_desc, chan_name, mainloop, context)?;
}
None => get_first_sink(mainloop, context)?
}
pa_threaded_mainloop_lock(mainloop);
let mut success: bool = false;
let data = &mut(mainloop, &mut success);
let o = pa_context_subscribe(context,
PA_SUBSCRIPTION_MASK_SINK,
Some(context_subscribe_cb),
data as *mut _ as *mut libc::c_void);
if o.is_null() {
pa_threaded_mainloop_unlock(mainloop);
bail!("Failed to initialize PA operation!");
}
while pa_operation_get_state(o) == PA_OPERATION_RUNNING {
pa_threaded_mainloop_wait(mainloop);
}
pa_operation_unref(o);
pa_threaded_mainloop_unlock(mainloop);
let handlers = Handlers::new();
let cb_box = {
let h_ref: &Vec<Box<Fn(AudioSignal, AudioUser)>> = &handlers.borrow();
Box::new((mainloop, h_ref as *const Vec<Box<Fn(AudioSignal, AudioUser)>>))
};
{
pa_context_set_subscribe_callback(context,
Some(sub_callback),
Box::into_raw(cb_box) as *mut libc::c_void);
}
return Ok(PABackend {
_cannot_construct: (),
m: mainloop,
c: context,
sink: RefCell::new(sink),
scroll_step: Cell::new(5),
handlers,
})
}
}
}
pub fn get_vol(&self) -> Result<f64> {
impl AudioFrontend for PABackend {
// TODO
fn switch_card(
&self,
card_name: Option<String>,
elem_name: Option<String>,
user: AudioUser,
) -> Result<()> {
{
let mut ac = self.sink.borrow_mut();
*ac = Sink::new(card_name, elem_name, self.m, self.c)?;
}
return Ok(())
}
fn get_vol(&self) -> Result<f64> {
let mut vol: u32 = 0;
unsafe {
@ -140,19 +216,21 @@ impl PABackend {
let _ = CString::from_raw(sink_name);
}
unsafe {
return Ok(pa_sw_volume_to_linear(vol) * 100.0);
}
return vol_to_percent(vol as i64, (PA_VOLUME_MUTED,
PA_VOLUME_NORM))
}
pub fn set_vol(&self, new_vol: f64, dir: VolDir) -> Result<()> {
fn set_vol(&self, new_vol: f64, user: AudioUser, dir: VolDir, auto_unmute: bool) -> Result<()> {
let mut res: Result<()> = Err("No value".into());
let new_vol = percent_to_vol(new_vol, (PA_VOLUME_MUTED,
PA_VOLUME_NORM), dir)?;
unsafe {
pa_threaded_mainloop_lock(self.m);
let data = &mut(self, &mut res);
let sink_name = CString::new(self.sink.borrow().name.clone()).unwrap().into_raw();
let new_vol = pa_sw_volume_from_linear(new_vol / 100.0);
let mut vol_arr: [u32; 32] = [0; 32];
for c in 0..(self.sink.borrow().channels) {
vol_arr[c as usize] = new_vol as u32;
@ -185,11 +263,44 @@ impl PABackend {
return res;
}
pub fn has_mute(&self) -> bool {
fn vol_level(&self) -> VolLevel {
let muted = self.get_mute().unwrap_or(false);
if muted {
return VolLevel::Muted;
}
let cur_vol = try_r!(self.get_vol(), VolLevel::Muted);
match cur_vol {
0. => return VolLevel::Off,
0.0...33.0 => return VolLevel::Low,
0.0...66.0 => return VolLevel::Medium,
0.0...100.0 => return VolLevel::High,
_ => return VolLevel::Off,
}
}
fn increase_vol(&self, user: AudioUser, auto_unmute: bool) -> Result<()> {
let old_vol = self.get_vol()?;
let new_vol = old_vol + (self.scroll_step.get() as f64);
return self.set_vol(new_vol, user, VolDir::Up, auto_unmute);
}
fn decrease_vol(&self, user: AudioUser, auto_unmute: bool) -> Result<()> {
let old_vol = self.get_vol()?;
let new_vol = old_vol - (self.scroll_step.get() as f64);
return self.set_vol(new_vol, user, VolDir::Down, auto_unmute);
}
fn has_mute(&self) -> bool {
return true;
}
pub fn get_mute(&self) -> Result<bool> {
fn get_mute(&self) -> Result<bool> {
let mut mute: bool = false;
unsafe {
@ -216,7 +327,8 @@ impl PABackend {
return Ok(mute);
}
pub fn set_mute(&self, mute: bool) -> Result<()> {
fn set_mute(&self, mute: bool, user: AudioUser) -> Result<()> {
let mut res: Result<()> = Err("No value".into());
unsafe {
pa_threaded_mainloop_lock(self.m);
@ -243,6 +355,45 @@ impl PABackend {
return res;
}
fn toggle_mute(&self, user: AudioUser) -> Result<()> {
let muted = self.get_mute()?;
return self.set_mute(!muted, user);
}
// TODO
fn connect_handler(&self, cb: Box<Fn(AudioSignal, AudioUser)>) {
self.handlers.add_handler(cb);
}
// TODO: name or desc?
fn card_name(&self) -> Result<String> {
return Ok(self.sink.borrow().description.clone())
}
fn playable_card_names(&self) -> Vec<String> {
let sinks = try_r!(get_sinks(self.m, self.c), vec![]);
return sinks.iter().map(|s| s.description.clone()).collect();
}
// TODO
fn playable_chan_names(&self, cardname: Option<String>) -> Vec<String> {
return vec![]
}
// TODO
fn chan_name(&self) -> Result<String> {
return Ok(String::from("Blah"))
}
fn set_scroll_step(&self, scroll_step: u32) {
self.scroll_step.set(scroll_step);
}
fn get_scroll_step(&self) -> u32 {
return self.scroll_step.get();
}
}
@ -284,13 +435,14 @@ unsafe extern "C" fn context_state_cb(
// TODO: Better error handling.
unsafe extern "C" fn get_sink_vol(
ctx: *mut pa_context,
_: *mut pa_context,
i: *const pa_sink_info,
eol: i32,
_: i32,
data: *mut libc::c_void) {
let (_self, res) = *(data as *mut (*mut PABackend,
*mut u32));
assert!(!(*_self).m.is_null(), "Mainloop is null");
assert!(!res.is_null(), "res is null");
if i.is_null() {
return
@ -303,13 +455,14 @@ unsafe extern "C" fn get_sink_vol(
// TODO: Better error handling.
unsafe extern "C" fn get_sink_mute(
ctx: *mut pa_context,
_: *mut pa_context,
i: *const pa_sink_info,
eol: i32,
_: i32,
data: *mut libc::c_void) {
let (_self, res) = *(data as *mut (*mut PABackend,
*mut bool));
assert!(!(*_self).m.is_null(), "Mainloop is null");
assert!(!res.is_null(), "res is null");
if i.is_null() {
return
@ -322,12 +475,13 @@ unsafe extern "C" fn get_sink_mute(
// TODO: Missing error handling.
unsafe extern "C" fn set_sink_vol(
ctx: *mut pa_context,
_: *mut pa_context,
success: i32,
data: *mut libc::c_void) {
let (_self, res) = *(data as *mut (*mut PABackend,
*mut Result<()>));
assert!(!(*_self).m.is_null(), "Mainloop is null");
assert!(!res.is_null(), "res is null");
if success > 0 {
*res = Ok(());
@ -342,12 +496,13 @@ unsafe extern "C" fn set_sink_vol(
// TODO: Missing error handling.
// TODO: same as 'set_sink_vol'
unsafe extern "C" fn set_sink_mute(
ctx: *mut pa_context,
_: *mut pa_context,
success: i32,
data: *mut libc::c_void) {
let (_self, res) = *(data as *mut (*mut PABackend,
*mut Result<()>));
assert!(!(*_self).m.is_null(), "Mainloop is null");
assert!(!res.is_null(), "res is null");
if success > 0 {
*res = Ok(());
@ -357,3 +512,51 @@ unsafe extern "C" fn set_sink_mute(
pa_threaded_mainloop_signal((*_self).m, 0);
}
unsafe extern "C" fn context_subscribe_cb(c: *mut pa_context,
success: i32,
data: *mut libc::c_void) {
let (mainloop, res) = *(data as *mut (*mut pa_threaded_mainloop,
*mut bool));
assert!(!mainloop.is_null(), "Mainloop is null");
assert!(!res.is_null(), "res is null");
if success > 0 {
*res = true;
} else {
*res = false;
}
pa_threaded_mainloop_signal(mainloop, 0);
}
unsafe extern "C" fn sub_callback(c: *mut pa_context,
t: u32,
idx: u32,
data: *mut libc::c_void) {
let (mainloop, p_handlers) = *(data as *mut (*mut pa_threaded_mainloop,
*mut Vec<Box<Fn(AudioSignal, AudioUser)>>));
assert!(!mainloop.is_null(), "Mainloop is null");
assert!(!p_handlers.is_null(), "Handlers are null");
let handlers: &Vec<Box<Fn(AudioSignal, AudioUser)>> = &*p_handlers;
if (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) ==
PA_SUBSCRIPTION_EVENT_SINK {
if (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE {
// invoke_handlers(
// handlers,
// AudioSignal::ValuesChanged,
// AudioUser::Unknown,
// );
}
}
}

View File

@ -22,6 +22,7 @@ use support::audio::VolDir;
fn main() {
@ -73,22 +74,22 @@ fn main() {
.unwrap_or_else(|e|{panic!("Logger initialization failed with {}",e)});
let pa = PABackend::new(Some(String::from("Built-in Audio Analog Stereo"))).unwrap();
println!("Sink: {:?}", pa.sink);
println!("Volume before: {:?}", pa.get_vol());
pa.set_vol(80.0, VolDir::Up);
println!("Volume after: {:?}", pa.get_vol());
println!("Mute before: {:?}", pa.get_mute());
println!("PA_VOLUME_NORM: {:?}", PA_VOLUME_NORM);
// let pa = PABackend::new(Some(String::from("Built-in Audio Analog Stereo"))).unwrap();
// println!("Sink: {:?}", pa.sink);
// println!("Volume before: {:?}", pa.get_vol());
// pa.set_vol(80.0, VolDir::Up);
// println!("Volume after: {:?}", pa.get_vol());
// println!("Mute before: {:?}", pa.get_mute());
// println!("PA_VOLUME_NORM: {:?}", PA_VOLUME_NORM);
// pa.set_mute(true);
// println!("Mute after: {:?}", pa.get_mute());
return;
// return;
gtk::init()
.unwrap_or_else(|e| panic!("Gtk initialization failed with {}", e));
let apps = Rc::new(new_alsa_appstate());
let apps = Rc::new(new_pa_appstate());
ui::entry::init(apps);

View File

@ -144,37 +144,37 @@ where
{
{
/* connect handler */
let apps = appstate.clone();
appstate.audio.connect_handler(Box::new(move |s, u| {
let notif = &apps.notif;
if notif.is_none() || !notif.as_ref().unwrap().enabled.get() {
return;
}
let notif = notif.as_ref().unwrap();
match (s,
u,
(notif.from_popup.get(),
notif.from_tray.get(),
notif.from_external.get(),
notif.from_hotkeys.get())) {
(AudioSignal::NoCard, _, _) => try_w!(notif.show_text_notif("No sound card", "No playable soundcard found")),
(AudioSignal::CardDisconnected, _, _) => try_w!(notif.show_text_notif("Soundcard disconnected", "Soundcard has been disconnected, reloading sound system...")),
(AudioSignal::CardError, _, _) => (),
(AudioSignal::ValuesChanged,
AudioUser::TrayIcon,
(_, true, _, _)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
(AudioSignal::ValuesChanged,
AudioUser::Popup,
(true, _, _, _)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
(AudioSignal::ValuesChanged,
AudioUser::Unknown,
(_, _, true, _)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
(AudioSignal::ValuesChanged,
AudioUser::Hotkeys,
(_, _, _, true)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
_ => (),
}
}));
// let apps = appstate.clone();
// appstate.audio.connect_handler(Box::new(move |s, u| {
// let notif = &apps.notif;
// if notif.is_none() || !notif.as_ref().unwrap().enabled.get() {
// return;
// }
// let notif = notif.as_ref().unwrap();
// match (s,
// u,
// (notif.from_popup.get(),
// notif.from_tray.get(),
// notif.from_external.get(),
// notif.from_hotkeys.get())) {
// (AudioSignal::NoCard, _, _) => try_w!(notif.show_text_notif("No sound card", "No playable soundcard found")),
// (AudioSignal::CardDisconnected, _, _) => try_w!(notif.show_text_notif("Soundcard disconnected", "Soundcard has been disconnected, reloading sound system...")),
// (AudioSignal::CardError, _, _) => (),
// (AudioSignal::ValuesChanged,
// AudioUser::TrayIcon,
// (_, true, _, _)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
// (AudioSignal::ValuesChanged,
// AudioUser::Popup,
// (true, _, _, _)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
// (AudioSignal::ValuesChanged,
// AudioUser::Unknown,
// (_, _, true, _)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
// (AudioSignal::ValuesChanged,
// AudioUser::Hotkeys,
// (_, _, _, true)) => try_w!(notif.show_volume_notif(apps.audio.as_ref())),
// _ => (),
// }
// }));
}
}

View File

@ -10,8 +10,6 @@ use audio::frontend::*;
use errors::*;
use prefs::*;
// TODO: rm alsa
use support::alsa::*;
#[derive(Clone, Copy, Debug)]
@ -100,16 +98,25 @@ pub fn percent_to_vol(vol: f64, range: (i64, i64), dir: VolDir) -> Result<i64> {
}
/// Get all playable card names.
pub fn get_playable_card_names() -> Vec<String> {
return get_playable_alsa_card_names();
}
/// Get all playable channel names.
pub fn get_playable_chan_names(card_name: String) -> Vec<String> {
let card = try_r!(get_alsa_card_by_name(card_name), Vec::default());
let mixer = try_r!(get_mixer(&card), Vec::default());
return get_playable_selem_names(&mixer);
/// Invokes the registered handlers.
pub fn invoke_handlers(
handlers: &Vec<Box<Fn(AudioSignal, AudioUser)>>,
signal: AudioSignal,
user: AudioUser,
) {
debug!(
"Invoking handlers for signal {:?} by user {:?}",
signal,
user
);
if handlers.is_empty() {
debug!("No handler found");
} else {
debug!("Executing handlers")
}
for handler in handlers {
debug!("Handler executing");
let unboxed = handler.as_ref();
unboxed(signal, user);
}
}

View File

@ -63,31 +63,31 @@ where
{
{
/* "global" audio signal handler */
let apps = appstate.clone();
appstate.audio.connect_handler(
Box::new(move |s, u| match (s, u) {
(AudioSignal::CardDisconnected, _) => {
try_w!(audio_reload(
apps.audio.as_ref(),
&apps.prefs.borrow(),
AudioUser::Unknown,
));
}
(AudioSignal::CardError, _) => {
if run_audio_error_dialog(
&apps.gui.popup_menu.menu_window,
) == (GTK_RESPONSE_YES as i32)
{
try_w!(audio_reload(
apps.audio.as_ref(),
&apps.prefs.borrow(),
AudioUser::Unknown,
));
}
}
_ => (),
}),
);
// let apps = appstate.clone();
// appstate.audio.connect_handler(
// Box::new(move |s, u| match (s, u) {
// (AudioSignal::CardDisconnected, _) => {
// try_w!(audio_reload(
// apps.audio.as_ref(),
// &apps.prefs.borrow(),
// AudioUser::Unknown,
// ));
// }
// (AudioSignal::CardError, _) => {
// if run_audio_error_dialog(
// &apps.gui.popup_menu.menu_window,
// ) == (GTK_RESPONSE_YES as i32)
// {
// try_w!(audio_reload(
// apps.audio.as_ref(),
// &apps.prefs.borrow(),
// AudioUser::Unknown,
// ));
// }
// }
// _ => (),
// }),
// );
}

View File

@ -48,16 +48,16 @@ where
{
/* audio.connect_handler */
{
let apps = appstate.clone();
appstate.audio.connect_handler(Box::new(move |s, u| {
/* skip if window is hidden */
if !apps.gui.popup_menu.menu.get_visible() {
return;
}
match (s, u) {
(_, _) => set_mute_check(&apps),
}
}));
// let apps = appstate.clone();
// appstate.audio.connect_handler(Box::new(move |s, u| {
// /* skip if window is hidden */
// if !apps.gui.popup_menu.menu.get_visible() {
// return;
// }
// match (s, u) {
// (_, _) => set_mute_check(&apps),
// }
// }));
}

View File

@ -125,31 +125,31 @@ where
{
/* audio.connect_handler */
{
let apps = appstate.clone();
appstate.audio.connect_handler(Box::new(move |s, u| {
/* skip if window is hidden */
if !apps.gui.popup_window.popup_window.get_visible() {
return;
}
match (s, u) {
/* Update only mute check here
* If the user changes the volume through the popup window,
* we MUST NOT update the slider value, it's been done already.
* It means that, as long as the popup window is visible,
* the slider value reflects the value set by user,
* and not the real value reported by the audio system.
*/
(_, AudioUser::Popup) => {
apps.gui.popup_window.update_mute_check(
apps.audio.as_ref(),
);
}
/* external change, safe to update slider too */
(_, _) => {
try_w!(apps.gui.popup_window.update(apps.audio.as_ref()));
}
}
}));
// let apps = appstate.clone();
// appstate.audio.connect_handler(Box::new(move |s, u| {
// /* skip if window is hidden */
// if !apps.gui.popup_window.popup_window.get_visible() {
// return;
// }
// match (s, u) {
// /* Update only mute check here
// * If the user changes the volume through the popup window,
// * we MUST NOT update the slider value, it's been done already.
// * It means that, as long as the popup window is visible,
// * the slider value reflects the value set by user,
// * and not the real value reported by the audio system.
// */
// (_, AudioUser::Popup) => {
// apps.gui.popup_window.update_mute_check(
// apps.audio.as_ref(),
// );
// }
// /* external change, safe to update slider too */
// (_, _) => {
// try_w!(apps.gui.popup_window.update(apps.audio.as_ref()));
// }
// }
// }));
}
/* mute_check.connect_toggled */

View File

@ -13,7 +13,6 @@ use prefs::*;
use std::ascii::AsciiExt;
use std::cell::RefCell;
use std::rc::Rc;
use support::audio::*;
use ui::hotkey_dialog::HotkeyDialog;
@ -434,21 +433,21 @@ where
T: AudioFrontend + 'static,
{
let apps = appstate.clone();
appstate.audio.connect_handler(Box::new(move |s, u| {
/* skip if prefs window is not present */
if apps.gui.prefs_dialog.borrow().is_none() {
return;
}
// appstate.audio.connect_handler(Box::new(move |s, u| {
// /* skip if prefs window is not present */
// if apps.gui.prefs_dialog.borrow().is_none() {
// return;
// }
match (s, u) {
(AudioSignal::CardInitialized, _) => (),
(AudioSignal::CardCleanedUp, _) => {
fill_card_combo(&apps);
fill_chan_combo(&apps, None);
}
_ => (),
}
}));
// match (s, u) {
// (AudioSignal::CardInitialized, _) => (),
// (AudioSignal::CardCleanedUp, _) => {
// fill_card_combo(&apps);
// fill_chan_combo(&apps, None);
// }
// _ => (),
// }
// }));
}
@ -586,7 +585,7 @@ where
/* set card combo */
let cur_card_name =
try_w!(audio.card_name(), "Can't get current card name!");
let available_card_names = get_playable_card_names();
let available_card_names = audio.playable_card_names();
/* set_active_id doesn't work, so save the index */
let mut c_index: i32 = -1;
@ -613,10 +612,7 @@ where
chan_combo.remove_all();
let audio = &appstate.audio;
let available_chan_names = match cardname {
Some(name) => get_playable_chan_names(name),
None => audio.playable_chan_names(),
};
let available_chan_names = audio.playable_chan_names(cardname);
/* set chan combo */
let cur_chan_name = try_w!(audio.chan_name());

View File

@ -422,11 +422,14 @@ where
appstate.audio.connect_handler(
Box::new(move |s, u| match (s, u) {
(_, _) => {
apps.gui.tray_icon.update_tooltip(apps.audio.as_ref());
try_w!(apps.gui.tray_icon.update_vol_meter(
try_w!(apps.audio.get_vol()),
apps.audio.vol_level(),
));
// apps.gui.tray_icon.update_tooltip(apps.audio.as_ref());
// try_w!(apps.gui.tray_icon.update_vol_meter(
// try_w!(apps.audio.get_vol()),
// apps.audio.vol_level(),
// ));
let vol = apps.audio.get_vol();
println!("Vol: {:?}", vol)
// println!("Gaga");
}
}),
);