Whatnot
This commit is contained in:
parent
92514a2fd0
commit
c1df692fa8
71
src/audio.rs
71
src/audio.rs
@ -15,6 +15,7 @@ use std::mem;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use std::u8;
|
||||
use std::f64;
|
||||
|
||||
|
||||
|
||||
@ -46,6 +47,7 @@ pub enum AlsaEvent {
|
||||
}
|
||||
|
||||
|
||||
// TODO: Audio struct? Separate more cleanly
|
||||
// TODO: implement free/destructor
|
||||
pub struct AlsaCard {
|
||||
_cannot_construct: (),
|
||||
@ -54,7 +56,8 @@ pub struct AlsaCard {
|
||||
pub selem_id: SelemId,
|
||||
pub watch_ids: Vec<u32>,
|
||||
pub last_action_timestamp: RefCell<i64>,
|
||||
pub handlers: RefCell<Vec<Box<Fn(&AlsaCard, AudioSignal, AudioUser)>>>,
|
||||
pub handlers: RefCell<Vec<Box<Fn(AudioSignal, AudioUser)>>>,
|
||||
pub scroll_step: RefCell<u32>,
|
||||
}
|
||||
|
||||
|
||||
@ -77,6 +80,7 @@ impl AlsaCard {
|
||||
.get_id();
|
||||
let vec_pollfd = PollDescriptors::get(&mixer)?;
|
||||
|
||||
// TODO: rework, should probably be a Box?
|
||||
let acard = Rc::new(RefCell::new(AlsaCard {
|
||||
_cannot_construct: (),
|
||||
card: card,
|
||||
@ -86,19 +90,27 @@ impl AlsaCard {
|
||||
last_action_timestamp:
|
||||
RefCell::new(0),
|
||||
handlers: RefCell::new(vec![]),
|
||||
scroll_step: RefCell::new(3),
|
||||
}));
|
||||
|
||||
/* TODO: callback is registered here, which must be unregistered
|
||||
* when the mixer is destroyed!!
|
||||
* poll descriptors must be unwatched too */
|
||||
let watch_ids = watch_poll_descriptors(vec_pollfd,
|
||||
acard.clone().as_ptr());
|
||||
let watch_ids = watch_poll_descriptors(vec_pollfd, acard.as_ptr());
|
||||
acard.borrow_mut().watch_ids = watch_ids;
|
||||
|
||||
return Ok(acard.clone());
|
||||
}
|
||||
|
||||
|
||||
pub fn switch_card(old_card: Rc<RefCell<AlsaCard>>,
|
||||
card_name: Option<String>,
|
||||
elem_name: Option<String>)
|
||||
-> Result<Rc<RefCell<AlsaCard>>> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
pub fn selem(&self) -> Selem {
|
||||
return get_selems(&self.mixer)
|
||||
.nth(self.selem_id.get_index() as usize)
|
||||
@ -123,6 +135,34 @@ impl AlsaCard {
|
||||
}
|
||||
|
||||
|
||||
pub fn increase_vol(&self, user: AudioUser) -> Result<()> {
|
||||
{
|
||||
let mut rc = self.last_action_timestamp.borrow_mut();
|
||||
*rc = glib::get_monotonic_time();
|
||||
}
|
||||
let old_vol = self.vol()?;
|
||||
let new_vol = f64::ceil(old_vol + (*self.scroll_step.borrow() as f64));
|
||||
|
||||
debug!("Increase vol by {:?} to {:?}", (new_vol - old_vol), new_vol);
|
||||
|
||||
return self.set_vol(new_vol, user);
|
||||
}
|
||||
|
||||
|
||||
pub fn decrease_vol(&self, user: AudioUser) -> Result<()> {
|
||||
{
|
||||
let mut rc = self.last_action_timestamp.borrow_mut();
|
||||
*rc = glib::get_monotonic_time();
|
||||
}
|
||||
let old_vol = self.vol()?;
|
||||
let new_vol = old_vol - (*self.scroll_step.borrow() as f64);
|
||||
|
||||
debug!("Decrease vol by {:?} to {:?}", (new_vol - old_vol), new_vol);
|
||||
|
||||
return self.set_vol(new_vol, user);
|
||||
}
|
||||
|
||||
|
||||
pub fn has_mute(&self) -> bool {
|
||||
return has_mute(&self.selem());
|
||||
}
|
||||
@ -176,23 +216,36 @@ impl AlsaCard {
|
||||
signal,
|
||||
user);
|
||||
let handlers = self.handlers.borrow();
|
||||
let x: &Vec<Box<Fn(&AlsaCard, AudioSignal, AudioUser)>> = &*handlers;
|
||||
for handler in x {
|
||||
let handlers_ref: &Vec<Box<Fn(AudioSignal, AudioUser)>> =
|
||||
handlers.as_ref();
|
||||
for handler in handlers_ref {
|
||||
let unboxed = handler.as_ref();
|
||||
unboxed(&self, signal, user);
|
||||
unboxed(signal, user);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn connect_handler(&self,
|
||||
cb: Box<Fn(&AlsaCard, AudioSignal, AudioUser)>) {
|
||||
pub fn connect_handler(&self, cb: Box<Fn(AudioSignal, AudioUser)>) {
|
||||
self.handlers.borrow_mut().push(cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Drop for AlsaCard {
|
||||
fn drop (&mut self) {
|
||||
// call Box::new(x), transmute the Box into a raw pointer, and then
|
||||
// std::mem::forget
|
||||
//
|
||||
// if you unregister the callback, you should keep a raw pointer to the
|
||||
// box
|
||||
//
|
||||
// For instance, `register` could return a raw pointer to the
|
||||
// Box + a std::marker::PhantomData with the appropriate
|
||||
// lifetime (if applicable)
|
||||
//
|
||||
// The struct could implement Drop, which unregisters the
|
||||
// callback and frees the Box, by simply transmuting the
|
||||
// raw pointer to a Box<T>
|
||||
fn drop(&mut self) {
|
||||
debug!("Destructing watch_ids: {:?}", self.watch_ids);
|
||||
unwatch_poll_descriptors(&self.watch_ids);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use ui_tray_icon::*;
|
||||
pub fn init(appstate: Rc<AppS>) {
|
||||
{
|
||||
let apps = appstate.clone();
|
||||
appstate.acard.borrow().connect_handler(Box::new(move |a, s, u| {
|
||||
appstate.acard.borrow().connect_handler(Box::new(move |s, u| {
|
||||
match (s, u) {
|
||||
(AudioSignal::AudioValuesChanged,
|
||||
AudioUser::AudioUserUnknown) => {
|
||||
|
@ -1,16 +1,33 @@
|
||||
use app_state::*;
|
||||
use gdk;
|
||||
use gdk_sys;
|
||||
use glib;
|
||||
use glib_sys;
|
||||
use std::mem;
|
||||
use gtk::prelude::*;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use libc;
|
||||
use audio::AudioUser::*;
|
||||
use errors::*;
|
||||
|
||||
|
||||
|
||||
pub fn init_tray_icon(appstate: Rc<AppS>) {
|
||||
{
|
||||
let apps = appstate.clone();
|
||||
let tray_icon = &appstate.gui.status_icon;
|
||||
tray_icon.connect_activate(move |_| on_tray_icon_activate(&apps));
|
||||
tray_icon.set_visible(true);
|
||||
}
|
||||
{
|
||||
let tray_icon = &appstate.clone().gui.status_icon;
|
||||
tray_icon.connect_scroll_event(move |_, e| {
|
||||
on_tray_icon_scroll_event(&appstate.clone(), &e)
|
||||
});
|
||||
tray_icon.set_visible(true);
|
||||
}
|
||||
|
||||
let tray_icon = &appstate.clone().gui.status_icon;
|
||||
tray_icon.connect_activate(move |_| {
|
||||
on_tray_icon_activate(&appstate.clone())
|
||||
});
|
||||
tray_icon.set_visible(true);
|
||||
}
|
||||
|
||||
|
||||
@ -23,3 +40,24 @@ fn on_tray_icon_activate(appstate: &AppS) {
|
||||
popup_window.show_now();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn on_tray_icon_scroll_event(appstate: &AppS,
|
||||
event: &gdk::EventScroll)
|
||||
-> bool {
|
||||
|
||||
let scroll_dir = event.as_ref().direction;
|
||||
match scroll_dir {
|
||||
gdk_sys::GdkScrollDirection::Up => {
|
||||
try_wr!(appstate.acard.borrow().increase_vol(AudioUserTrayIcon),
|
||||
false);
|
||||
}
|
||||
gdk_sys::GdkScrollDirection::Down => {
|
||||
try_wr!(appstate.acard.borrow().decrease_vol(AudioUserTrayIcon),
|
||||
false);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user