Update
This commit is contained in:
parent
6504c5c5ab
commit
4760355ef1
@ -9,6 +9,7 @@ libc = "^0.2.23"
|
||||
gdk-sys = { git = "https://github.com/gtk-rs/sys" }
|
||||
gtk-sys = { git = "https://github.com/gtk-rs/sys" }
|
||||
glib = { git = "https://github.com/gtk-rs/glib.git" }
|
||||
glib-sys = { git = "https://github.com/gtk-rs/sys" }
|
||||
ffi = "^0.0.2"
|
||||
flexi_logger = "^0.5.1"
|
||||
log = "^0.3.8"
|
||||
|
@ -1,10 +1,14 @@
|
||||
use gtk;
|
||||
|
||||
use alsa::poll::PollDescriptors;
|
||||
use alsa::card::Card;
|
||||
use alsa::mixer::{Mixer, SelemId, Selem};
|
||||
use audio;
|
||||
use errors::*;
|
||||
|
||||
// TODO: fix import
|
||||
use libc::pollfd;
|
||||
|
||||
pub struct AppS {
|
||||
/* we keep this to ensure the lifetime is across the whole application */
|
||||
pub status_icon: gtk::StatusIcon,
|
||||
@ -12,10 +16,13 @@ pub struct AppS {
|
||||
pub builder_popup: gtk::Builder,
|
||||
}
|
||||
|
||||
// TODO: implement free/destructor
|
||||
pub struct AlsaCard {
|
||||
card: Card,
|
||||
mixer: Mixer,
|
||||
selem_id: SelemId,
|
||||
_cannot_construct: (),
|
||||
pub card: Card,
|
||||
pub mixer: Mixer,
|
||||
pub selem_id: SelemId,
|
||||
pub watch_ids: Vec<pollfd>,
|
||||
}
|
||||
|
||||
impl AlsaCard {
|
||||
@ -35,11 +42,15 @@ impl AlsaCard {
|
||||
elem_name.unwrap_or(String::from("Master")),
|
||||
).unwrap()
|
||||
.get_id();
|
||||
let vec_pollfd = PollDescriptors::get(&mixer)?;
|
||||
// let watch_ids =
|
||||
|
||||
return Ok(AlsaCard {
|
||||
_cannot_construct: (),
|
||||
card: card,
|
||||
mixer: mixer,
|
||||
selem_id: selem_id,
|
||||
watch_ids: vec![],
|
||||
});
|
||||
}
|
||||
|
||||
@ -53,6 +64,10 @@ impl AlsaCard {
|
||||
return audio::get_vol(&self.selem());
|
||||
}
|
||||
|
||||
pub fn set_vol(&self, new_vol: f64) -> Result<()> {
|
||||
return audio::set_vol(&self.selem(), new_vol);
|
||||
}
|
||||
|
||||
pub fn has_mute(&self) -> bool {
|
||||
return audio::has_mute(&self.selem());
|
||||
}
|
||||
@ -65,3 +80,19 @@ impl AlsaCard {
|
||||
return audio::set_mute(&self.selem(), mute);
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AudioUser {
|
||||
AudioUserUnknown,
|
||||
AudioUserPopup,
|
||||
AudioUserTrayIcon,
|
||||
AudioUserHotkeys,
|
||||
}
|
||||
|
||||
enum AudioSignal {
|
||||
AudioNoCard,
|
||||
AudioCardInitialized,
|
||||
AudioCardCleanedUp,
|
||||
AudioCardDisconnected,
|
||||
AudioCardError,
|
||||
AudioValuesChanged,
|
||||
}
|
||||
|
73
src/audio.rs
73
src/audio.rs
@ -1,13 +1,18 @@
|
||||
extern crate alsa;
|
||||
extern crate libc;
|
||||
extern crate glib_sys;
|
||||
|
||||
use self::alsa::card::Card;
|
||||
use self::alsa::mixer::{Mixer, Selem, Elem};
|
||||
use alsa::mixer::SelemChannelId::*;
|
||||
use std::iter::Map;
|
||||
use self::libc::c_int;
|
||||
use libc::c_int;
|
||||
use libc::c_uint;
|
||||
use libc::c_void;
|
||||
use errors::*;
|
||||
use std::convert::From;
|
||||
use libc::pollfd;
|
||||
use app_state;
|
||||
use std::cell::RefCell;
|
||||
|
||||
|
||||
|
||||
@ -60,15 +65,41 @@ pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> {
|
||||
bail!("Not found a matching selem named {}", name);
|
||||
}
|
||||
|
||||
pub fn vol_to_percent(vol: i64, range: (i64, i64)) -> f64 {
|
||||
let (min, max) = range;
|
||||
return ((vol - min) as f64) / ((max - min) as f64) * 100.0;
|
||||
}
|
||||
|
||||
pub fn percent_to_vol(vol: f64, range: (i64, i64)) -> i64 {
|
||||
let (min, max) = range;
|
||||
let _v = vol / 100.0 * ((max - min) as f64) + (min as f64);
|
||||
/* TODO: precision? Use direction. */
|
||||
return _v as i64;
|
||||
}
|
||||
|
||||
pub fn get_vol(selem: &Selem) -> Result<f64> {
|
||||
let (min, max) = selem.get_playback_volume_range();
|
||||
let range = selem.get_playback_volume_range();
|
||||
let volume = selem.get_playback_volume(FrontRight).map(|v| {
|
||||
return ((v - min) as f64) / ((max - min) as f64) * 100.0;
|
||||
return vol_to_percent(v, range);
|
||||
});
|
||||
|
||||
return volume.cherr();
|
||||
}
|
||||
|
||||
pub fn set_vol(selem: &Selem, new_vol: f64) -> Result<()> {
|
||||
/* auto-unmute */
|
||||
if get_mute(selem)? {
|
||||
set_mute(selem, false)?;
|
||||
}
|
||||
|
||||
let range = selem.get_playback_volume_range();
|
||||
selem.set_playback_volume_all(
|
||||
percent_to_vol(new_vol, range),
|
||||
)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn has_mute(selem: &Selem) -> bool {
|
||||
return selem.has_playback_switch();
|
||||
}
|
||||
@ -83,3 +114,37 @@ pub fn set_mute(selem: &Selem, mute: bool) -> Result<()> {
|
||||
let _ = selem.set_playback_switch_all(!mute as i32)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* GIO */
|
||||
|
||||
pub fn watch_poll_descriptors(
|
||||
polls: Vec<pollfd>,
|
||||
acard: RefCell<app_state::AlsaCard>,
|
||||
) -> Vec<c_uint> {
|
||||
let mut watch_ids: Vec<c_uint> = vec![];
|
||||
for poll in polls {
|
||||
unsafe {
|
||||
let gioc = glib_sys::g_io_channel_unix_new(poll.fd);
|
||||
watch_ids.push(glib_sys::g_io_add_watch(
|
||||
gioc,
|
||||
glib_sys::GIOCondition::from_bits_truncate(
|
||||
glib_sys::G_IO_IN.bits() | glib_sys::G_IO_ERR.bits(),
|
||||
),
|
||||
Some(watch_cb),
|
||||
acard.as_ptr() as glib_sys::gpointer,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return vec![];
|
||||
}
|
||||
|
||||
extern "C" fn watch_cb(
|
||||
chan: *mut glib_sys::GIOChannel,
|
||||
cond: glib_sys::GIOCondition,
|
||||
data: glib_sys::gpointer,
|
||||
) -> glib_sys::gboolean {
|
||||
return true as glib_sys::gboolean;
|
||||
}
|
||||
|
@ -63,6 +63,23 @@ fn init_popup_window(appstate: &AppS, rc_acard: Rc<RefCell<AlsaCard>>) {
|
||||
});
|
||||
}
|
||||
|
||||
/* vol_scale_adj.connect_value_changed */
|
||||
{
|
||||
let vol_scale_adj: Rc<gtk::Adjustment> =
|
||||
Rc::new(
|
||||
appstate.builder_popup.get_object("vol_scale_adj").unwrap(),
|
||||
);
|
||||
|
||||
let card = rc_acard.clone();
|
||||
let vol_scale = vol_scale_adj.clone();
|
||||
vol_scale_adj.connect_value_changed(move |_| {
|
||||
let acard = card.borrow();
|
||||
let val = vol_scale.get_value();
|
||||
|
||||
try_w!(acard.set_vol(val));
|
||||
});
|
||||
}
|
||||
|
||||
/* mute_check.connect_toggled */
|
||||
{
|
||||
let mute_check: gtk::CheckButton =
|
||||
|
@ -10,6 +10,7 @@ extern crate gtk_sys;
|
||||
extern crate gdk;
|
||||
extern crate gdk_sys;
|
||||
extern crate alsa;
|
||||
extern crate libc;
|
||||
|
||||
use gtk::prelude::*;
|
||||
use gdk_sys::GDK_KEY_Escape;
|
||||
|
Loading…
Reference in New Issue
Block a user