This commit is contained in:
Julian Ospald 2017-07-01 01:56:32 +02:00
parent 92514a2fd0
commit c1df692fa8
No known key found for this signature in database
GPG Key ID: 511B62C09D50CD28
3 changed files with 106 additions and 15 deletions

View File

@ -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);
}

View File

@ -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) => {

View File

@ -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;
}