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::ptr;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::u8;
|
use std::u8;
|
||||||
|
use std::f64;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ pub enum AlsaEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Audio struct? Separate more cleanly
|
||||||
// TODO: implement free/destructor
|
// TODO: implement free/destructor
|
||||||
pub struct AlsaCard {
|
pub struct AlsaCard {
|
||||||
_cannot_construct: (),
|
_cannot_construct: (),
|
||||||
@ -54,7 +56,8 @@ pub struct AlsaCard {
|
|||||||
pub selem_id: SelemId,
|
pub selem_id: SelemId,
|
||||||
pub watch_ids: Vec<u32>,
|
pub watch_ids: Vec<u32>,
|
||||||
pub last_action_timestamp: RefCell<i64>,
|
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();
|
.get_id();
|
||||||
let vec_pollfd = PollDescriptors::get(&mixer)?;
|
let vec_pollfd = PollDescriptors::get(&mixer)?;
|
||||||
|
|
||||||
|
// TODO: rework, should probably be a Box?
|
||||||
let acard = Rc::new(RefCell::new(AlsaCard {
|
let acard = Rc::new(RefCell::new(AlsaCard {
|
||||||
_cannot_construct: (),
|
_cannot_construct: (),
|
||||||
card: card,
|
card: card,
|
||||||
@ -86,19 +90,27 @@ impl AlsaCard {
|
|||||||
last_action_timestamp:
|
last_action_timestamp:
|
||||||
RefCell::new(0),
|
RefCell::new(0),
|
||||||
handlers: RefCell::new(vec![]),
|
handlers: RefCell::new(vec![]),
|
||||||
|
scroll_step: RefCell::new(3),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/* TODO: callback is registered here, which must be unregistered
|
/* TODO: callback is registered here, which must be unregistered
|
||||||
* when the mixer is destroyed!!
|
* when the mixer is destroyed!!
|
||||||
* poll descriptors must be unwatched too */
|
* poll descriptors must be unwatched too */
|
||||||
let watch_ids = watch_poll_descriptors(vec_pollfd,
|
let watch_ids = watch_poll_descriptors(vec_pollfd, acard.as_ptr());
|
||||||
acard.clone().as_ptr());
|
|
||||||
acard.borrow_mut().watch_ids = watch_ids;
|
acard.borrow_mut().watch_ids = watch_ids;
|
||||||
|
|
||||||
return Ok(acard.clone());
|
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 {
|
pub fn selem(&self) -> Selem {
|
||||||
return get_selems(&self.mixer)
|
return get_selems(&self.mixer)
|
||||||
.nth(self.selem_id.get_index() as usize)
|
.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 {
|
pub fn has_mute(&self) -> bool {
|
||||||
return has_mute(&self.selem());
|
return has_mute(&self.selem());
|
||||||
}
|
}
|
||||||
@ -176,23 +216,36 @@ impl AlsaCard {
|
|||||||
signal,
|
signal,
|
||||||
user);
|
user);
|
||||||
let handlers = self.handlers.borrow();
|
let handlers = self.handlers.borrow();
|
||||||
let x: &Vec<Box<Fn(&AlsaCard, AudioSignal, AudioUser)>> = &*handlers;
|
let handlers_ref: &Vec<Box<Fn(AudioSignal, AudioUser)>> =
|
||||||
for handler in x {
|
handlers.as_ref();
|
||||||
|
for handler in handlers_ref {
|
||||||
let unboxed = handler.as_ref();
|
let unboxed = handler.as_ref();
|
||||||
unboxed(&self, signal, user);
|
unboxed(signal, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn connect_handler(&self,
|
pub fn connect_handler(&self, cb: Box<Fn(AudioSignal, AudioUser)>) {
|
||||||
cb: Box<Fn(&AlsaCard, AudioSignal, AudioUser)>) {
|
|
||||||
self.handlers.borrow_mut().push(cb);
|
self.handlers.borrow_mut().push(cb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Drop for AlsaCard {
|
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);
|
debug!("Destructing watch_ids: {:?}", self.watch_ids);
|
||||||
unwatch_poll_descriptors(&self.watch_ids);
|
unwatch_poll_descriptors(&self.watch_ids);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ use ui_tray_icon::*;
|
|||||||
pub fn init(appstate: Rc<AppS>) {
|
pub fn init(appstate: Rc<AppS>) {
|
||||||
{
|
{
|
||||||
let apps = appstate.clone();
|
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) {
|
match (s, u) {
|
||||||
(AudioSignal::AudioValuesChanged,
|
(AudioSignal::AudioValuesChanged,
|
||||||
AudioUser::AudioUserUnknown) => {
|
AudioUser::AudioUserUnknown) => {
|
||||||
|
@ -1,16 +1,33 @@
|
|||||||
use app_state::*;
|
use app_state::*;
|
||||||
|
use gdk;
|
||||||
|
use gdk_sys;
|
||||||
|
use glib;
|
||||||
|
use glib_sys;
|
||||||
|
use std::mem;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use libc;
|
||||||
|
use audio::AudioUser::*;
|
||||||
|
use errors::*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn init_tray_icon(appstate: Rc<AppS>) {
|
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();
|
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