#![allow(missing_docs)] // enums #![allow(illegal_floating_point_literal_pattern)] //! High-level audio subsystem. //! //! This is the middleman between the low-level audio backend (alsa), //! and the high-level ui code. //! This abstraction layer allows the high-level code to be completely unaware //! of the underlying audio implementation, may it be alsa or whatever. use alsa_card::*; use errors::*; use glib; use std::cell::Cell; use std::cell::Ref; use std::cell::RefCell; use std::f64; use std::rc::Rc; use support_alsa::*; use support_audio::*; #[derive(Clone, Copy, Debug)] /// The volume level of the current audio configuration. pub enum VolLevel { Muted, Low, Medium, High, Off, } /// An audio user, used to determine from where a signal originated. #[derive(Clone, Copy, Debug)] pub enum AudioUser { Unknown, Popup, TrayIcon, Hotkeys, PrefsWindow, } /// An audio signal. This will be used to connect callbacks to the /// audio system and react appropriately. #[derive(Clone, Copy, Debug)] pub enum AudioSignal { NoCard, CardInitialized, CardCleanedUp, CardDisconnected, CardError, ValuesChanged, } #[derive(Clone)] /// Convenience struct to make handling this madness easier. pub struct Handlers { inner: Rc>>>, } impl Handlers { fn new() -> Handlers { return Handlers { inner: Rc::new(RefCell::new(vec![])) }; } fn borrow(&self) -> Ref>> { return self.inner.borrow(); } fn add_handler(&self, cb: Box) { self.inner.borrow_mut().push(cb); } } /// High-level Audio struct, which could theoretically be backend /// agnostic. pub struct Audio { _cannot_construct: (), /// The alsa card. pub acard: RefCell>, /// Last timestamp of an internal action we triggered, e.g. /// by setting the volume or the mute state. pub last_action_timestamp: Rc>, /// A set of handlers that react to audio signals. We can /// connect to these. pub handlers: Handlers, /// The step at which to increase/decrease the volume. /// This value is basically from the preferences. pub scroll_step: Cell, } impl Audio { /// Create a new Audio instance. This tries very hard to get /// a working configuration from the backend. /// ## `card_name` /// If a card name is provided, it will be tried. If `None` is provided /// or the given card name does not exist or is not playable, any other /// playable card is tried. /// ## `elem_name` /// If an elem name is provided, it will be tried. If `None` is provided /// or the given elem name does not exist or is not playable, any other /// playable elem is tried. /// /// # Returns /// /// `Ok(Audio)` on success, `Err(error)` otherwise. pub fn new(card_name: Option, elem_name: Option) -> Result