Update
This commit is contained in:
parent
0847a1087b
commit
c010eb6ba9
@ -21,6 +21,7 @@ error-chain = { path = "3rdparty/error-chain" }
|
||||
toml = "^0.4.2"
|
||||
serde_derive = "^1.0.9"
|
||||
serde = "^1.0.9"
|
||||
xdg = "*"
|
||||
|
||||
[dependencies.gtk]
|
||||
git = "https://github.com/gtk-rs/gtk.git"
|
||||
|
@ -36,11 +36,10 @@ pub struct AlsaCard {
|
||||
|
||||
|
||||
impl AlsaCard {
|
||||
pub fn new(
|
||||
card_name: Option<String>,
|
||||
pub fn new(card_name: Option<String>,
|
||||
elem_name: Option<String>,
|
||||
cb: Rc<Fn(AlsaEvent)>,
|
||||
) -> Result<Box<AlsaCard>> {
|
||||
cb: Rc<Fn(AlsaEvent)>)
|
||||
-> Result<Box<AlsaCard>> {
|
||||
let card = {
|
||||
match card_name {
|
||||
Some(name) => get_alsa_card_by_name(name)?,
|
||||
@ -51,10 +50,10 @@ impl AlsaCard {
|
||||
|
||||
let vec_pollfd = PollDescriptors::get(&mixer)?;
|
||||
|
||||
let selem_id = get_selem_by_name(
|
||||
&mixer,
|
||||
elem_name.unwrap_or(String::from("Master")),
|
||||
).unwrap()
|
||||
let selem_id =
|
||||
get_selem_by_name(&mixer,
|
||||
elem_name.unwrap_or(String::from("Master")))
|
||||
.unwrap()
|
||||
.get_id();
|
||||
|
||||
let acard = Box::new(AlsaCard {
|
||||
@ -69,8 +68,8 @@ impl AlsaCard {
|
||||
/* TODO: callback is registered here, which must be unregistered
|
||||
* when the card is destroyed!!
|
||||
* poll descriptors must be unwatched too */
|
||||
let watch_ids =
|
||||
AlsaCard::watch_poll_descriptors(vec_pollfd, acard.as_ref());
|
||||
let watch_ids = AlsaCard::watch_poll_descriptors(vec_pollfd,
|
||||
acard.as_ref());
|
||||
acard.watch_ids.set(watch_ids);
|
||||
|
||||
return Ok(acard);
|
||||
@ -83,7 +82,9 @@ impl AlsaCard {
|
||||
|
||||
|
||||
pub fn chan_name(&self) -> Result<String> {
|
||||
let n = self.selem_id.get_name().map(|y| String::from(y))?;
|
||||
let n = self.selem_id
|
||||
.get_name()
|
||||
.map(|y| String::from(y))?;
|
||||
return Ok(n);
|
||||
}
|
||||
|
||||
@ -112,9 +113,7 @@ impl AlsaCard {
|
||||
}
|
||||
|
||||
let range = selem.get_playback_volume_range();
|
||||
selem.set_playback_volume_all(
|
||||
percent_to_vol(new_vol, range),
|
||||
)?;
|
||||
selem.set_playback_volume_all(percent_to_vol(new_vol, range))?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
@ -141,10 +140,9 @@ impl AlsaCard {
|
||||
}
|
||||
|
||||
|
||||
fn watch_poll_descriptors(
|
||||
polls: Vec<pollfd>,
|
||||
acard: &AlsaCard,
|
||||
) -> Vec<c_uint> {
|
||||
fn watch_poll_descriptors(polls: Vec<pollfd>,
|
||||
acard: &AlsaCard)
|
||||
-> Vec<c_uint> {
|
||||
let mut watch_ids: Vec<c_uint> = vec![];
|
||||
let acard_ptr =
|
||||
unsafe { mem::transmute::<&AlsaCard, glib_sys::gpointer>(acard) };
|
||||
@ -201,11 +199,10 @@ impl Drop for AlsaCard {
|
||||
}
|
||||
|
||||
|
||||
extern "C" fn watch_cb(
|
||||
chan: *mut glib_sys::GIOChannel,
|
||||
extern "C" fn watch_cb(chan: *mut glib_sys::GIOChannel,
|
||||
cond: glib_sys::GIOCondition,
|
||||
data: glib_sys::gpointer,
|
||||
) -> glib_sys::gboolean {
|
||||
data: glib_sys::gpointer)
|
||||
-> glib_sys::gboolean {
|
||||
|
||||
let acard =
|
||||
unsafe { mem::transmute::<glib_sys::gpointer, &AlsaCard>(data) };
|
||||
@ -224,14 +221,13 @@ extern "C" fn watch_cb(
|
||||
let mut buf: Vec<u8> = vec![0; 256];
|
||||
|
||||
while sread > 0 {
|
||||
let stat: glib_sys::GIOStatus = unsafe {
|
||||
glib_sys::g_io_channel_read_chars(
|
||||
chan,
|
||||
let stat: glib_sys::GIOStatus =
|
||||
unsafe {
|
||||
glib_sys::g_io_channel_read_chars(chan,
|
||||
buf.as_mut_ptr() as *mut u8,
|
||||
256,
|
||||
&mut sread as *mut size_t,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
ptr::null_mut())
|
||||
};
|
||||
|
||||
match stat {
|
||||
@ -250,4 +246,3 @@ extern "C" fn watch_cb(
|
||||
|
||||
return true as glib_sys::gboolean;
|
||||
}
|
||||
|
||||
|
@ -15,16 +15,14 @@ pub struct AppS {
|
||||
|
||||
impl AppS {
|
||||
pub fn new() -> AppS {
|
||||
let builder_popup_window = gtk::Builder::new_from_string(include_str!(
|
||||
"../data/ui/popup-window.glade"
|
||||
));
|
||||
let builder_popup_menu = gtk::Builder::new_from_string(
|
||||
include_str!("../data/ui/popup-menu.glade"),
|
||||
);
|
||||
let builder_popup_window =
|
||||
gtk::Builder::new_from_string(include_str!("../data/ui/popup-window.glade"));
|
||||
let builder_popup_menu = gtk::Builder::new_from_string(include_str!("../data/ui/popup-menu.glade"));
|
||||
|
||||
return AppS {
|
||||
gui: Gui::new(builder_popup_window, builder_popup_menu),
|
||||
audio: Audio::new(None, Some(String::from("Master"))).unwrap(),
|
||||
audio: Audio::new(None, Some(String::from("Master")))
|
||||
.unwrap(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -39,10 +37,9 @@ pub struct Gui {
|
||||
|
||||
|
||||
impl Gui {
|
||||
pub fn new(
|
||||
builder_popup_window: gtk::Builder,
|
||||
builder_popup_menu: gtk::Builder,
|
||||
) -> Gui {
|
||||
pub fn new(builder_popup_window: gtk::Builder,
|
||||
builder_popup_menu: gtk::Builder)
|
||||
-> Gui {
|
||||
return Gui {
|
||||
tray_icon: TrayIcon::new().unwrap(),
|
||||
popup_window: PopupWindow::new(builder_popup_window),
|
||||
@ -52,20 +49,16 @@ impl Gui {
|
||||
}
|
||||
|
||||
|
||||
create_builder_item!(
|
||||
PopupWindow,
|
||||
create_builder_item!(PopupWindow,
|
||||
popup_window: gtk::Window,
|
||||
vol_scale_adj: gtk::Adjustment,
|
||||
vol_scale: gtk::Scale,
|
||||
mute_check: gtk::CheckButton
|
||||
);
|
||||
mute_check: gtk::CheckButton);
|
||||
|
||||
|
||||
create_builder_item!(
|
||||
PopupMenu,
|
||||
create_builder_item!(PopupMenu,
|
||||
menu_window: gtk::Window,
|
||||
menubar: gtk::MenuBar,
|
||||
menu: gtk::Menu,
|
||||
about_item: gtk::MenuItem,
|
||||
prefs_item: gtk::MenuItem
|
||||
);
|
||||
prefs_item: gtk::MenuItem);
|
||||
|
185
src/audio.rs
185
src/audio.rs
@ -73,10 +73,9 @@ pub struct Audio {
|
||||
|
||||
|
||||
impl Audio {
|
||||
pub fn new(
|
||||
card_name: Option<String>,
|
||||
elem_name: Option<String>,
|
||||
) -> Result<Audio> {
|
||||
pub fn new(card_name: Option<String>,
|
||||
elem_name: Option<String>)
|
||||
-> Result<Audio> {
|
||||
|
||||
let handlers = Handlers::new();
|
||||
let last_action_timestamp = Rc::new(RefCell::new(0));
|
||||
@ -85,7 +84,9 @@ impl Audio {
|
||||
let myhandler = handlers.clone();
|
||||
let ts = last_action_timestamp.clone();
|
||||
Rc::new(move |event| {
|
||||
on_alsa_event(&mut *ts.borrow_mut(), &myhandler.borrow(), event)
|
||||
on_alsa_event(&mut *ts.borrow_mut(),
|
||||
&myhandler.borrow(),
|
||||
event)
|
||||
})
|
||||
};
|
||||
|
||||
@ -101,40 +102,44 @@ impl Audio {
|
||||
}
|
||||
|
||||
|
||||
pub fn switch_acard(
|
||||
&self,
|
||||
pub fn switch_acard(&self,
|
||||
card_name: Option<String>,
|
||||
elem_name: Option<String>,
|
||||
user: AudioUser,
|
||||
) -> Result<()> {
|
||||
user: AudioUser)
|
||||
-> Result<()> {
|
||||
debug!("Switching cards");
|
||||
debug!(
|
||||
"Old card name: {}",
|
||||
self.acard.borrow().card_name().unwrap()
|
||||
);
|
||||
debug!(
|
||||
"Old chan name: {}",
|
||||
self.acard.borrow().chan_name().unwrap()
|
||||
);
|
||||
let cb = self.acard.borrow().cb.clone();
|
||||
debug!("Old card name: {}",
|
||||
self.acard
|
||||
.borrow()
|
||||
.card_name()
|
||||
.unwrap());
|
||||
debug!("Old chan name: {}",
|
||||
self.acard
|
||||
.borrow()
|
||||
.chan_name()
|
||||
.unwrap());
|
||||
let cb = self.acard
|
||||
.borrow()
|
||||
.cb
|
||||
.clone();
|
||||
{
|
||||
let mut ac = self.acard.borrow_mut();
|
||||
*ac = AlsaCard::new(card_name, elem_name, cb)?;
|
||||
}
|
||||
debug!(
|
||||
"Old card name: {}",
|
||||
self.acard.borrow().card_name().unwrap()
|
||||
);
|
||||
debug!(
|
||||
"Old chan name: {}",
|
||||
self.acard.borrow().chan_name().unwrap()
|
||||
);
|
||||
debug!("Old card name: {}",
|
||||
self.acard
|
||||
.borrow()
|
||||
.card_name()
|
||||
.unwrap());
|
||||
debug!("Old chan name: {}",
|
||||
self.acard
|
||||
.borrow()
|
||||
.chan_name()
|
||||
.unwrap());
|
||||
|
||||
invoke_handlers(
|
||||
&self.handlers.borrow(),
|
||||
invoke_handlers(&self.handlers.borrow(),
|
||||
AudioSignal::CardInitialized,
|
||||
user,
|
||||
);
|
||||
user);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
@ -167,20 +172,24 @@ impl Audio {
|
||||
*rc = glib::get_monotonic_time();
|
||||
}
|
||||
|
||||
debug!(
|
||||
"Setting vol on card {:?} and chan {:?} to {:?} by user {:?}",
|
||||
self.acard.borrow().card_name().unwrap(),
|
||||
self.acard.borrow().chan_name().unwrap(),
|
||||
debug!("Setting vol on card {:?} and chan {:?} to {:?} by user {:?}",
|
||||
self.acard
|
||||
.borrow()
|
||||
.card_name()
|
||||
.unwrap(),
|
||||
self.acard
|
||||
.borrow()
|
||||
.chan_name()
|
||||
.unwrap(),
|
||||
new_vol,
|
||||
user
|
||||
);
|
||||
self.acard.borrow().set_vol(new_vol)?;
|
||||
user);
|
||||
self.acard
|
||||
.borrow()
|
||||
.set_vol(new_vol)?;
|
||||
|
||||
invoke_handlers(
|
||||
&self.handlers.borrow(),
|
||||
invoke_handlers(&self.handlers.borrow(),
|
||||
AudioSignal::ValuesChanged,
|
||||
user,
|
||||
);
|
||||
user);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -193,21 +202,23 @@ impl Audio {
|
||||
let old_vol = self.vol()?;
|
||||
let new_vol = f64::ceil(old_vol + (self.scroll_step.get() as f64));
|
||||
|
||||
debug!(
|
||||
"Increase vol on card {:?} and chan {:?} by {:?} to {:?}",
|
||||
self.acard.borrow().card_name().unwrap(),
|
||||
self.acard.borrow().chan_name().unwrap(),
|
||||
debug!("Increase vol on card {:?} and chan {:?} by {:?} to {:?}",
|
||||
self.acard
|
||||
.borrow()
|
||||
.card_name()
|
||||
.unwrap(),
|
||||
self.acard
|
||||
.borrow()
|
||||
.chan_name()
|
||||
.unwrap(),
|
||||
(new_vol - old_vol),
|
||||
new_vol
|
||||
);
|
||||
new_vol);
|
||||
|
||||
self.set_vol(new_vol, user)?;
|
||||
|
||||
invoke_handlers(
|
||||
&self.handlers.borrow(),
|
||||
invoke_handlers(&self.handlers.borrow(),
|
||||
AudioSignal::ValuesChanged,
|
||||
user,
|
||||
);
|
||||
user);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -220,21 +231,23 @@ impl Audio {
|
||||
let old_vol = self.vol()?;
|
||||
let new_vol = old_vol - (self.scroll_step.get() as f64);
|
||||
|
||||
debug!(
|
||||
"Decrease vol on card {:?} and chan {:?} by {:?} to {:?}",
|
||||
self.acard.borrow().card_name().unwrap(),
|
||||
self.acard.borrow().chan_name().unwrap(),
|
||||
debug!("Decrease vol on card {:?} and chan {:?} by {:?} to {:?}",
|
||||
self.acard
|
||||
.borrow()
|
||||
.card_name()
|
||||
.unwrap(),
|
||||
self.acard
|
||||
.borrow()
|
||||
.chan_name()
|
||||
.unwrap(),
|
||||
(new_vol - old_vol),
|
||||
new_vol
|
||||
);
|
||||
new_vol);
|
||||
|
||||
self.set_vol(new_vol, user)?;
|
||||
|
||||
invoke_handlers(
|
||||
&self.handlers.borrow(),
|
||||
invoke_handlers(&self.handlers.borrow(),
|
||||
AudioSignal::ValuesChanged,
|
||||
user,
|
||||
);
|
||||
user);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -253,21 +266,25 @@ impl Audio {
|
||||
let mut rc = self.last_action_timestamp.borrow_mut();
|
||||
*rc = glib::get_monotonic_time();
|
||||
|
||||
debug!(
|
||||
"Setting mute to {} on card {:?} and chan {:?} by user {:?}",
|
||||
debug!("Setting mute to {} on card {:?} and chan {:?} by user {:?}",
|
||||
mute,
|
||||
self.acard.borrow().card_name().unwrap(),
|
||||
self.acard.borrow().chan_name().unwrap(),
|
||||
user
|
||||
);
|
||||
self.acard
|
||||
.borrow()
|
||||
.card_name()
|
||||
.unwrap(),
|
||||
self.acard
|
||||
.borrow()
|
||||
.chan_name()
|
||||
.unwrap(),
|
||||
user);
|
||||
|
||||
self.acard.borrow().set_mute(mute)?;
|
||||
self.acard
|
||||
.borrow()
|
||||
.set_mute(mute)?;
|
||||
|
||||
invoke_handlers(
|
||||
&self.handlers.borrow(),
|
||||
invoke_handlers(&self.handlers.borrow(),
|
||||
AudioSignal::ValuesChanged,
|
||||
user,
|
||||
);
|
||||
user);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -284,16 +301,12 @@ impl Audio {
|
||||
}
|
||||
|
||||
|
||||
fn invoke_handlers(
|
||||
handlers: &Vec<Box<Fn(AudioSignal, AudioUser)>>,
|
||||
fn invoke_handlers(handlers: &Vec<Box<Fn(AudioSignal, AudioUser)>>,
|
||||
signal: AudioSignal,
|
||||
user: AudioUser,
|
||||
) {
|
||||
debug!(
|
||||
"Invoking handlers for signal {:?} by user {:?}",
|
||||
user: AudioUser) {
|
||||
debug!("Invoking handlers for signal {:?} by user {:?}",
|
||||
signal,
|
||||
user
|
||||
);
|
||||
user);
|
||||
for handler in handlers {
|
||||
let unboxed = handler.as_ref();
|
||||
unboxed(signal, user);
|
||||
@ -301,11 +314,9 @@ fn invoke_handlers(
|
||||
}
|
||||
|
||||
|
||||
fn on_alsa_event(
|
||||
last_action_timestamp: &mut i64,
|
||||
fn on_alsa_event(last_action_timestamp: &mut i64,
|
||||
handlers: &Vec<Box<Fn(AudioSignal, AudioUser)>>,
|
||||
alsa_event: AlsaEvent,
|
||||
) {
|
||||
alsa_event: AlsaEvent) {
|
||||
let last: i64 = *last_action_timestamp;
|
||||
|
||||
if last != 0 {
|
||||
@ -325,11 +336,9 @@ fn on_alsa_event(
|
||||
AlsaEvent::AlsaCardDiconnected => debug!("AlsaCardDiconnected"),
|
||||
AlsaEvent::AlsaCardValuesChanged => {
|
||||
debug!("AlsaCardValuesChanged");
|
||||
invoke_handlers(
|
||||
handlers,
|
||||
invoke_handlers(handlers,
|
||||
self::AudioSignal::ValuesChanged,
|
||||
self::AudioUser::Unknown,
|
||||
);
|
||||
self::AudioUser::Unknown);
|
||||
}
|
||||
e => warn!("Unhandled alsa event: {:?}", e),
|
||||
}
|
||||
|
@ -2,12 +2,15 @@ use alsa;
|
||||
use glib;
|
||||
use std::convert::From;
|
||||
use std;
|
||||
use toml;
|
||||
|
||||
|
||||
|
||||
error_chain! {
|
||||
foreign_links {
|
||||
Alsa(alsa::Error);
|
||||
IO(std::io::Error);
|
||||
Toml(toml::de::Error);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ extern crate gobject_sys;
|
||||
extern crate gtk;
|
||||
extern crate gtk_sys;
|
||||
extern crate libc;
|
||||
extern crate xdg;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -63,10 +64,11 @@ fn main() {
|
||||
|
||||
let apps = Rc::new(AppS::new());
|
||||
|
||||
let mut prefs = prefs::Prefs::new_from_def();
|
||||
prefs.behavior_prefs.middle_click_action = MiddleClickAction::CustomCommand(String::from("Gaga"));
|
||||
let mut prefs = prefs::Prefs::new().unwrap();
|
||||
println!("Channel: {:?}", prefs.to_str());
|
||||
prefs.store_config();
|
||||
|
||||
// println!("Channel: {:?}", prefs.to_str());
|
||||
|
||||
ui_entry::init(apps);
|
||||
|
||||
|
196
src/prefs.rs
196
src/prefs.rs
@ -1,52 +1,35 @@
|
||||
use errors::*;
|
||||
use std::path::Path;
|
||||
use glib;
|
||||
use toml;
|
||||
use xdg;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
|
||||
|
||||
|
||||
const DEFAULT_PREFS: &str = "[device_prefs]
|
||||
card = \"default\"
|
||||
channel = \"Master\"
|
||||
|
||||
[view_prefs]
|
||||
draw_vol_meter = true
|
||||
vol_meter_offset = 10
|
||||
vol_meter_color = { red = 245, blue = 121, green = 0 }
|
||||
system_theme = true
|
||||
|
||||
[behavior_prefs]
|
||||
vol_control_cmd = \"\"
|
||||
vol_scroll_step = 5.0
|
||||
middle_click_action = \"ToggleMute\"
|
||||
|
||||
[notify_prefs]
|
||||
enable_notifications = true
|
||||
notifcation_timeout = 1500
|
||||
notify_mouse_scroll = true
|
||||
notify_popup = true
|
||||
notify_external = true";
|
||||
|
||||
|
||||
const VOL_CONTROL_COMMANDS: [&str; 3] = [
|
||||
"gnome-alsamixer",
|
||||
"xfce4-mixer",
|
||||
"alsamixergui"
|
||||
];
|
||||
const VOL_CONTROL_COMMANDS: [&str; 3] =
|
||||
["gnome-alsamixer", "xfce4-mixer", "alsamixergui"];
|
||||
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
#[serde(tag = "action", rename_all = "snake_case")]
|
||||
pub enum MiddleClickAction {
|
||||
ToggleMute,
|
||||
ShowPreferences,
|
||||
VolumeControl,
|
||||
CustomCommand(String),
|
||||
CustomCommand { cmd: String },
|
||||
}
|
||||
|
||||
impl Default for MiddleClickAction {
|
||||
fn default() -> MiddleClickAction {
|
||||
return MiddleClickAction::ToggleMute;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct Prefs {
|
||||
pub device_prefs: DevicePrefs,
|
||||
pub view_prefs: ViewPrefs,
|
||||
@ -55,38 +38,99 @@ pub struct Prefs {
|
||||
// TODO: HotKeys?
|
||||
}
|
||||
|
||||
impl Default for Prefs {
|
||||
fn default() -> Prefs {
|
||||
return Prefs {
|
||||
device_prefs: DevicePrefs::default(),
|
||||
view_prefs: ViewPrefs::default(),
|
||||
behavior_prefs: BehaviorPrefs::default(),
|
||||
notify_prefs: NotifyPrefs::default(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct DevicePrefs {
|
||||
pub card: String,
|
||||
pub channel: String,
|
||||
// TODO: normalize volume?
|
||||
}
|
||||
|
||||
impl Default for DevicePrefs {
|
||||
fn default() -> DevicePrefs {
|
||||
return DevicePrefs {
|
||||
card: String::from("(default)"),
|
||||
channel: String::from("Master"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct ViewPrefs {
|
||||
pub draw_vol_meter: bool,
|
||||
pub vol_meter_offset: i64,
|
||||
pub vol_meter_color: VolColor,
|
||||
pub system_theme: bool,
|
||||
pub vol_meter_color: VolColor,
|
||||
// TODO: Display text folume/text volume pos?
|
||||
}
|
||||
|
||||
impl Default for ViewPrefs {
|
||||
fn default() -> ViewPrefs {
|
||||
return ViewPrefs {
|
||||
draw_vol_meter: true,
|
||||
vol_meter_offset: 10,
|
||||
system_theme: true,
|
||||
vol_meter_color: VolColor::default(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct VolColor {
|
||||
pub red: u8,
|
||||
pub green: u8,
|
||||
pub blue: u8,
|
||||
}
|
||||
|
||||
impl Default for VolColor {
|
||||
fn default() -> VolColor {
|
||||
return VolColor {
|
||||
red: 245,
|
||||
green: 180,
|
||||
blue: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct BehaviorPrefs {
|
||||
pub vol_control_cmd: String,
|
||||
vol_control_cmd: Option<String>,
|
||||
pub vol_scroll_step: f64,
|
||||
pub middle_click_action: MiddleClickAction,
|
||||
// TODO: fine scroll step?
|
||||
}
|
||||
|
||||
impl Default for BehaviorPrefs {
|
||||
fn default() -> BehaviorPrefs {
|
||||
return BehaviorPrefs {
|
||||
vol_control_cmd: None,
|
||||
vol_scroll_step: 5.0,
|
||||
middle_click_action: MiddleClickAction::default(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct NotifyPrefs {
|
||||
pub enable_notifications: bool,
|
||||
pub notifcation_timeout: i64,
|
||||
@ -96,44 +140,84 @@ pub struct NotifyPrefs {
|
||||
// TODO: notify_hotkeys?
|
||||
}
|
||||
|
||||
impl Default for NotifyPrefs {
|
||||
fn default() -> NotifyPrefs {
|
||||
return NotifyPrefs {
|
||||
enable_notifications: true,
|
||||
notifcation_timeout: 1500,
|
||||
notify_mouse_scroll: true,
|
||||
notify_popup: true,
|
||||
notify_external: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
impl Prefs {
|
||||
// pub fn set_blah(&mut self) {
|
||||
// self.vol_scroll_step = 5.0;
|
||||
// }
|
||||
pub fn new() -> Result<Prefs> {
|
||||
let m_config_file = get_xdg_dirs().find_config_file("pnmixer.toml");
|
||||
match m_config_file {
|
||||
Some(c) => {
|
||||
debug!("Config file present at {:?}, using it.", c);
|
||||
|
||||
// pub fn new() -> Prefs {
|
||||
// // load from config
|
||||
let mut f = File::open(c)?;
|
||||
let mut buffer = vec![];
|
||||
f.read_to_end(&mut buffer)?;
|
||||
|
||||
// }
|
||||
let prefs = toml::from_slice(buffer.as_slice())?;
|
||||
|
||||
// pub fn reload_from_config(&self) {
|
||||
return Ok(prefs);
|
||||
}
|
||||
None => {
|
||||
debug!("No config file present, creating one with defaults.");
|
||||
|
||||
// }
|
||||
let prefs = Prefs::default();
|
||||
prefs.store_config()?;
|
||||
|
||||
|
||||
// pub fn save_to_config() -> Result<()> {
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// fn config_path() -> String {
|
||||
|
||||
// }
|
||||
|
||||
|
||||
fn ensure_config_path() {
|
||||
return Ok(prefs);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn new_from_def() -> Prefs {
|
||||
let prefs: Prefs = toml::from_str(DEFAULT_PREFS).unwrap();
|
||||
return prefs;
|
||||
|
||||
pub fn reload_config(&mut self) -> Result<()> {
|
||||
debug!("Reloading config...");
|
||||
|
||||
let new_prefs = Prefs::new()?;
|
||||
*self = new_prefs;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
pub fn store_config(&self) -> Result<()> {
|
||||
let config_path = get_xdg_dirs().place_config_file("pnmixer.toml")
|
||||
.from_err()?;
|
||||
|
||||
debug!("Storing config in {:?}", config_path);
|
||||
|
||||
let mut f = File::create(config_path)?;
|
||||
f.write_all(self.to_str().as_bytes())?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
pub fn to_str(&self) -> String {
|
||||
return toml::to_string(self).unwrap();
|
||||
}
|
||||
|
||||
|
||||
// TODO: implement
|
||||
pub fn vol_control_cmd() -> String {
|
||||
return String::from("");
|
||||
}
|
||||
}
|
||||
|
||||
fn get_xdg_dirs() -> xdg::BaseDirectories {
|
||||
return xdg::BaseDirectories::with_prefix("pnmixer-rs").unwrap();
|
||||
}
|
||||
|
@ -81,7 +81,9 @@ pub fn get_selem_names(mixer: &Mixer) -> Vec<String> {
|
||||
|
||||
pub fn get_selem_by_name(mixer: &Mixer, name: String) -> Result<Selem> {
|
||||
for selem in get_selems(mixer) {
|
||||
let n = selem.get_id().get_name().map(|y| String::from(y))?;
|
||||
let n = selem.get_id()
|
||||
.get_name()
|
||||
.map(|y| String::from(y))?;
|
||||
|
||||
if n == name {
|
||||
return Ok(selem);
|
||||
@ -103,4 +105,3 @@ pub fn percent_to_vol(vol: f64, range: (i64, i64)) -> i64 {
|
||||
/* TODO: precision? Use direction. */
|
||||
return _v as i64;
|
||||
}
|
||||
|
||||
|
@ -21,21 +21,18 @@ pub fn copy_pixbuf(pixbuf: &gdk_pixbuf::Pixbuf) -> gdk_pixbuf::Pixbuf {
|
||||
}
|
||||
|
||||
|
||||
pub fn pixbuf_new_from_theme(
|
||||
icon_name: &str,
|
||||
pub fn pixbuf_new_from_theme(icon_name: &str,
|
||||
size: i32,
|
||||
theme: >k::IconTheme,
|
||||
) -> Result<gdk_pixbuf::Pixbuf> {
|
||||
theme: >k::IconTheme)
|
||||
-> Result<gdk_pixbuf::Pixbuf> {
|
||||
|
||||
let icon_info = theme
|
||||
.lookup_icon(icon_name, size, gtk::IconLookupFlags::empty())
|
||||
let icon_info =
|
||||
theme.lookup_icon(icon_name, size, gtk::IconLookupFlags::empty())
|
||||
.ok_or(format!("Couldn't find icon {}", icon_name))?;
|
||||
|
||||
debug!(
|
||||
"Loading stock icon {} from {:?}",
|
||||
debug!("Loading stock icon {} from {:?}",
|
||||
icon_name,
|
||||
icon_info.get_filename().unwrap_or(PathBuf::new())
|
||||
);
|
||||
icon_info.get_filename().unwrap_or(PathBuf::new()));
|
||||
|
||||
// TODO: propagate error
|
||||
let pixbuf = icon_info.load_icon().unwrap();
|
||||
@ -59,5 +56,3 @@ pub fn pixbuf_new_from_file(filename: &str) -> Result<gdk_pixbuf::Pixbuf> {
|
||||
bail!("Uh-oh");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,15 +14,21 @@ pub fn init_popup_menu(appstate: Rc<AppS>) {
|
||||
/* about_item.connect_activate_link */
|
||||
{
|
||||
let apps = appstate.clone();
|
||||
let about_item = &appstate.clone().gui.popup_menu.about_item;
|
||||
about_item.connect_activate(
|
||||
move |_| { on_about_item_activate(&apps); },
|
||||
);
|
||||
let about_item = &appstate.clone()
|
||||
.gui
|
||||
.popup_menu
|
||||
.about_item;
|
||||
about_item.connect_activate(move |_| {
|
||||
on_about_item_activate(&apps);
|
||||
});
|
||||
}
|
||||
|
||||
/* about_item.connect_activate_link */
|
||||
{
|
||||
let prefs_item = &appstate.clone().gui.popup_menu.prefs_item;
|
||||
let prefs_item = &appstate.clone()
|
||||
.gui
|
||||
.popup_menu
|
||||
.prefs_item;
|
||||
prefs_item.connect_activate(
|
||||
move |_| { on_prefs_item_activate(appstate.clone()); },
|
||||
);
|
||||
|
@ -18,25 +18,37 @@ pub fn init_popup_window(appstate: Rc<AppS>) {
|
||||
/* mute_check.connect_toggled */
|
||||
{
|
||||
let _appstate = appstate.clone();
|
||||
let mute_check = &appstate.clone().gui.popup_window.mute_check;
|
||||
toggle_signal = mute_check.connect_toggled(
|
||||
move |_| on_mute_check_toggled(&_appstate),
|
||||
);
|
||||
let mute_check = &appstate.clone()
|
||||
.gui
|
||||
.popup_window
|
||||
.mute_check;
|
||||
toggle_signal =
|
||||
mute_check.connect_toggled(move |_| {
|
||||
on_mute_check_toggled(&_appstate)
|
||||
});
|
||||
}
|
||||
|
||||
/* popup_window.connect_show */
|
||||
{
|
||||
let _appstate = appstate.clone();
|
||||
let popup_window = &appstate.clone().gui.popup_window.popup_window;
|
||||
popup_window.connect_show(
|
||||
move |w| on_popup_window_show(w, &_appstate, toggle_signal),
|
||||
);
|
||||
let popup_window = &appstate.clone()
|
||||
.gui
|
||||
.popup_window
|
||||
.popup_window;
|
||||
popup_window.connect_show(move |w| {
|
||||
on_popup_window_show(w,
|
||||
&_appstate,
|
||||
toggle_signal)
|
||||
});
|
||||
}
|
||||
|
||||
/* vol_scale_adj.connect_value_changed */
|
||||
{
|
||||
let _appstate = appstate.clone();
|
||||
let vol_scale_adj = &appstate.clone().gui.popup_window.vol_scale_adj;
|
||||
let vol_scale_adj = &appstate.clone()
|
||||
.gui
|
||||
.popup_window
|
||||
.vol_scale_adj;
|
||||
vol_scale_adj.connect_value_changed(
|
||||
move |_| on_vol_scale_value_changed(&_appstate),
|
||||
);
|
||||
@ -45,7 +57,10 @@ pub fn init_popup_window(appstate: Rc<AppS>) {
|
||||
/* popup_window.connect_event */
|
||||
{
|
||||
let _appstate = appstate.clone();
|
||||
let popup_window = &appstate.clone().gui.popup_window.popup_window;
|
||||
let popup_window = &appstate.clone()
|
||||
.gui
|
||||
.popup_window
|
||||
.popup_window;
|
||||
popup_window.connect_event(move |w, e| {
|
||||
on_popup_window_event(w, e, &_appstate)
|
||||
});
|
||||
@ -53,11 +68,9 @@ pub fn init_popup_window(appstate: Rc<AppS>) {
|
||||
}
|
||||
|
||||
|
||||
fn on_popup_window_show(
|
||||
window: >k::Window,
|
||||
fn on_popup_window_show(window: >k::Window,
|
||||
appstate: &AppS,
|
||||
toggle_signal: u64,
|
||||
) {
|
||||
toggle_signal: u64) {
|
||||
let audio = &appstate.audio;
|
||||
let popup_window = &appstate.gui.popup_window;
|
||||
|
||||
@ -72,11 +85,10 @@ fn on_popup_window_show(
|
||||
}
|
||||
|
||||
|
||||
fn on_popup_window_event(
|
||||
w: >k::Window,
|
||||
fn on_popup_window_event(w: >k::Window,
|
||||
e: &gdk::Event,
|
||||
appstate: &AppS,
|
||||
) -> gtk::Inhibit {
|
||||
appstate: &AppS)
|
||||
-> gtk::Inhibit {
|
||||
match gdk::Event::get_event_type(e) {
|
||||
gdk::EventType::GrabBroken => w.hide(),
|
||||
gdk::EventType::KeyPress => {
|
||||
@ -108,7 +120,10 @@ fn on_popup_window_event(
|
||||
fn on_vol_scale_value_changed(appstate: &AppS) {
|
||||
let audio = &appstate.audio;
|
||||
|
||||
let val = appstate.gui.popup_window.vol_scale.get_value();
|
||||
let val = appstate.gui
|
||||
.popup_window
|
||||
.vol_scale
|
||||
.get_value();
|
||||
|
||||
try_w!(audio.set_vol(val, AudioUser::Popup));
|
||||
}
|
||||
@ -120,11 +135,9 @@ fn on_mute_check_toggled(appstate: &AppS) {
|
||||
}
|
||||
|
||||
|
||||
pub fn update_mute_check(
|
||||
appstate: &AppS,
|
||||
pub fn update_mute_check(appstate: &AppS,
|
||||
toggle_signal: u64,
|
||||
muted: Result<bool>,
|
||||
) {
|
||||
muted: Result<bool>) {
|
||||
let check_button = &appstate.gui.popup_window.mute_check;
|
||||
|
||||
glib::signal_handler_block(check_button, toggle_signal);
|
||||
@ -157,40 +170,32 @@ fn grab_devices(window: >k::Window) -> Result<()> {
|
||||
let gdk_window = window.get_window().ok_or("No window?!")?;
|
||||
|
||||
/* Grab the mouse */
|
||||
let m_grab_status = device.grab(
|
||||
&gdk_window,
|
||||
let m_grab_status =
|
||||
device.grab(&gdk_window,
|
||||
GrabOwnership::None,
|
||||
true,
|
||||
BUTTON_PRESS_MASK,
|
||||
None,
|
||||
GDK_CURRENT_TIME as u32,
|
||||
);
|
||||
GDK_CURRENT_TIME as u32);
|
||||
|
||||
if m_grab_status != GrabStatus::Success {
|
||||
warn!(
|
||||
"Could not grab {}",
|
||||
device.get_name().unwrap_or(String::from("UNKNOWN DEVICE"))
|
||||
);
|
||||
warn!("Could not grab {}",
|
||||
device.get_name().unwrap_or(String::from("UNKNOWN DEVICE")));
|
||||
}
|
||||
|
||||
/* Grab the keyboard */
|
||||
let k_dev = device.get_associated_device().ok_or(
|
||||
"Couldn't get associated device",
|
||||
)?;
|
||||
let k_dev = device.get_associated_device()
|
||||
.ok_or("Couldn't get associated device")?;
|
||||
|
||||
let k_grab_status = k_dev.grab(
|
||||
&gdk_window,
|
||||
let k_grab_status = k_dev.grab(&gdk_window,
|
||||
GrabOwnership::None,
|
||||
true,
|
||||
KEY_PRESS_MASK,
|
||||
None,
|
||||
GDK_CURRENT_TIME as u32,
|
||||
);
|
||||
GDK_CURRENT_TIME as u32);
|
||||
if k_grab_status != GrabStatus::Success {
|
||||
warn!(
|
||||
"Could not grab {}",
|
||||
k_dev.get_name().unwrap_or(String::from("UNKNOWN DEVICE"))
|
||||
);
|
||||
warn!("Could not grab {}",
|
||||
k_dev.get_name().unwrap_or(String::from("UNKNOWN DEVICE")));
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
|
@ -7,18 +7,14 @@ use support_alsa::*;
|
||||
|
||||
|
||||
|
||||
create_builder_item!(
|
||||
PrefsDialog,
|
||||
create_builder_item!(PrefsDialog,
|
||||
prefs_dialog: gtk::Dialog,
|
||||
card_combo: gtk::ComboBoxText,
|
||||
chan_combo: gtk::ComboBoxText
|
||||
);
|
||||
chan_combo: gtk::ComboBoxText);
|
||||
|
||||
|
||||
pub fn show_prefs_dialog(appstate: Rc<AppS>) {
|
||||
let builder_prefs_dialog = gtk::Builder::new_from_string(
|
||||
include_str!("../data/ui/prefs-dialog.glade"),
|
||||
);
|
||||
let builder_prefs_dialog = gtk::Builder::new_from_string(include_str!("../data/ui/prefs-dialog.glade"));
|
||||
let prefs_dialog = Rc::new(PrefsDialog::new(builder_prefs_dialog));
|
||||
init_prefs_dialog(&appstate, &prefs_dialog);
|
||||
{
|
||||
@ -51,9 +47,9 @@ pub fn init_prefs_dialog(appstate: &Rc<AppS>, prefs_dialog: &Rc<PrefsDialog>) {
|
||||
let pd = prefs_dialog.clone();
|
||||
|
||||
// TODO: refill channel combo
|
||||
card_combo.connect_changed(
|
||||
move |_| { on_card_combo_changed(&apps, &pd); },
|
||||
);
|
||||
card_combo.connect_changed(move |_| {
|
||||
on_card_combo_changed(&apps, &pd);
|
||||
});
|
||||
}
|
||||
/* card_combo.connect_changed */
|
||||
{
|
||||
@ -61,9 +57,9 @@ pub fn init_prefs_dialog(appstate: &Rc<AppS>, prefs_dialog: &Rc<PrefsDialog>) {
|
||||
let chan_combo = &prefs_dialog.chan_combo;
|
||||
let pd = prefs_dialog.clone();
|
||||
|
||||
chan_combo.connect_changed(
|
||||
move |_| { on_chan_combo_changed(&apps, &pd); },
|
||||
);
|
||||
chan_combo.connect_changed(move |_| {
|
||||
on_chan_combo_changed(&apps, &pd);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,8 +71,8 @@ fn on_prefs_dialog_show(appstate: &AppS, prefs_dialog: &PrefsDialog) {
|
||||
|
||||
|
||||
/* set card combo */
|
||||
let cur_card_name =
|
||||
try_w!(acard.card_name(), "Can't get current card name!");
|
||||
let cur_card_name = try_w!(acard.card_name(),
|
||||
"Can't get current card name!");
|
||||
let available_card_names = get_alsa_card_names();
|
||||
|
||||
/* set_active_id doesn't work, so save the index */
|
||||
@ -117,9 +113,8 @@ fn on_prefs_dialog_show(appstate: &AppS, prefs_dialog: &PrefsDialog) {
|
||||
fn on_card_combo_changed(appstate: &AppS, prefs_dialog: &PrefsDialog) {
|
||||
let card_combo = &prefs_dialog.card_combo;
|
||||
let chan_combo = &prefs_dialog.chan_combo;
|
||||
let active_card_item = try_w!(card_combo.get_active_text().ok_or(
|
||||
"No active Card item found",
|
||||
));
|
||||
let active_card_item =
|
||||
try_w!(card_combo.get_active_text().ok_or("No active Card item found"));
|
||||
let active_chan_item = chan_combo.get_active_id();
|
||||
let cur_card_name = {
|
||||
let acard = appstate.audio.acard.borrow();
|
||||
@ -127,11 +122,9 @@ fn on_card_combo_changed(appstate: &AppS, prefs_dialog: &PrefsDialog) {
|
||||
};
|
||||
|
||||
if active_card_item != cur_card_name {
|
||||
appstate.audio.switch_acard(
|
||||
Some(cur_card_name),
|
||||
appstate.audio.switch_acard(Some(cur_card_name),
|
||||
active_chan_item,
|
||||
AudioUser::PrefsWindow
|
||||
);
|
||||
AudioUser::PrefsWindow);
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,9 +132,8 @@ fn on_card_combo_changed(appstate: &AppS, prefs_dialog: &PrefsDialog) {
|
||||
fn on_chan_combo_changed(appstate: &AppS, prefs_dialog: &PrefsDialog) {
|
||||
let card_combo = &prefs_dialog.card_combo;
|
||||
let chan_combo = &prefs_dialog.chan_combo;
|
||||
let active_chan_item = try_w!(chan_combo.get_active_text().ok_or(
|
||||
"No active Chan item found",
|
||||
));
|
||||
let active_chan_item =
|
||||
try_w!(chan_combo.get_active_text().ok_or("No active Chan item found"));
|
||||
let cur_card_name = {
|
||||
let acard = appstate.audio.acard.borrow();
|
||||
acard.card_name().ok()
|
||||
@ -152,10 +144,8 @@ fn on_chan_combo_changed(appstate: &AppS, prefs_dialog: &PrefsDialog) {
|
||||
};
|
||||
|
||||
if active_chan_item != cur_chan_name {
|
||||
appstate.audio.switch_acard(
|
||||
cur_card_name,
|
||||
appstate.audio.switch_acard(cur_card_name,
|
||||
Some(active_chan_item),
|
||||
AudioUser::PrefsWindow
|
||||
);
|
||||
AudioUser::PrefsWindow);
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,12 @@ impl TrayIcon {
|
||||
let audio_pix = AudioPix::new_from_pnmixer()?;
|
||||
let status_icon = gtk::StatusIcon::new();
|
||||
|
||||
return Ok(TrayIcon { volmeter, audio_pix, status_icon, icon_size: Cell::new(ICON_MIN_SIZE) });
|
||||
return Ok(TrayIcon {
|
||||
volmeter,
|
||||
audio_pix,
|
||||
status_icon,
|
||||
icon_size: Cell::new(ICON_MIN_SIZE),
|
||||
});
|
||||
}
|
||||
|
||||
fn update(&self, audio: &Audio, m_size: Option<i64>) {
|
||||
@ -45,14 +50,13 @@ impl TrayIcon {
|
||||
} else {
|
||||
self.icon_size.set(s);
|
||||
}
|
||||
},
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
|
||||
let cur_vol = try_w!(audio.vol());
|
||||
let pixbuf = self.audio_pix.select_pix(audio.vol_level());
|
||||
let vol_pix = try_w!(self.volmeter.meter_draw(cur_vol as i64,
|
||||
&pixbuf));
|
||||
let vol_pix = try_w!(self.volmeter.meter_draw(cur_vol as i64, &pixbuf));
|
||||
|
||||
self.status_icon.set_from_pixbuf(Some(&vol_pix));
|
||||
}
|
||||
@ -88,25 +92,18 @@ impl VolMeter {
|
||||
}
|
||||
|
||||
// TODO: cache input pixbuf?
|
||||
fn meter_draw(
|
||||
&self,
|
||||
fn meter_draw(&self,
|
||||
volume: i64,
|
||||
pixbuf: &gdk_pixbuf::Pixbuf,
|
||||
) -> Result<gdk_pixbuf::Pixbuf> {
|
||||
pixbuf: &gdk_pixbuf::Pixbuf)
|
||||
-> Result<gdk_pixbuf::Pixbuf> {
|
||||
|
||||
ensure!(
|
||||
pixbuf.get_colorspace() == GDK_COLORSPACE_RGB,
|
||||
"Invalid colorspace in pixbuf"
|
||||
);
|
||||
ensure!(
|
||||
pixbuf.get_bits_per_sample() == 8,
|
||||
"Invalid bits per sample in pixbuf"
|
||||
);
|
||||
ensure!(pixbuf.get_colorspace() == GDK_COLORSPACE_RGB,
|
||||
"Invalid colorspace in pixbuf");
|
||||
ensure!(pixbuf.get_bits_per_sample() == 8,
|
||||
"Invalid bits per sample in pixbuf");
|
||||
ensure!(pixbuf.get_has_alpha(), "No alpha channel in pixbuf");
|
||||
ensure!(
|
||||
pixbuf.get_n_channels() == 4,
|
||||
"Invalid number of channels in pixbuf"
|
||||
);
|
||||
ensure!(pixbuf.get_n_channels() == 4,
|
||||
"Invalid number of channels in pixbuf");
|
||||
|
||||
let i_width = pixbuf.get_width() as i64;
|
||||
let i_height = pixbuf.get_height() as i64;
|
||||
@ -115,21 +112,16 @@ impl VolMeter {
|
||||
|
||||
let vm_width = i_width / 6;
|
||||
let x = (self.x_offset_pct as f64 *
|
||||
((i_width - vm_width) as f64 / 100.0)) as
|
||||
i64;
|
||||
ensure!(
|
||||
x >= 0 && (x + vm_width) <= i_width,
|
||||
((i_width - vm_width) as f64 / 100.0)) as i64;
|
||||
ensure!(x >= 0 && (x + vm_width) <= i_width,
|
||||
"x coordinate invalid: {}",
|
||||
x
|
||||
);
|
||||
x);
|
||||
let y = (self.y_offset_pct as f64 * (i_height as f64 / 100.0)) as i64;
|
||||
let vm_height =
|
||||
((i_height - (y * 2)) as f64 * (volume as f64 / 100.0)) as i64;
|
||||
ensure!(
|
||||
y >= 0 && (y + vm_height) <= i_height,
|
||||
ensure!(y >= 0 && (y + vm_height) <= i_height,
|
||||
"y coordinate invalid: {}",
|
||||
y
|
||||
);
|
||||
y);
|
||||
|
||||
/* Let's check if the icon width changed, in which case we
|
||||
* must reinit our internal row of pixels.
|
||||
@ -165,9 +157,8 @@ impl VolMeter {
|
||||
let p_index = ((row_offset * rowstride) + col_offset) as usize;
|
||||
|
||||
let row = self.row.borrow();
|
||||
pixels[p_index..p_index + row.len()].copy_from_slice(
|
||||
row.as_ref(),
|
||||
);
|
||||
pixels[p_index..p_index + row.len()]
|
||||
.copy_from_slice(row.as_ref());
|
||||
|
||||
}
|
||||
}
|
||||
@ -215,9 +206,7 @@ impl AudioPix {
|
||||
}
|
||||
|
||||
pub fn new_from_pnmixer() -> Result<AudioPix> {
|
||||
gtk::IconTheme::get_default().ok_or(
|
||||
"Couldn't get default icon theme",
|
||||
)?;
|
||||
gtk::IconTheme::get_default().ok_or("Couldn't get default icon theme")?;
|
||||
let pix = AudioPix {
|
||||
muted: pixbuf_new_from_file("pnmixer-muted.png")?,
|
||||
low: pixbuf_new_from_file("pnmixer-low.png")?,
|
||||
@ -273,7 +262,9 @@ pub fn init_tray_icon(appstate: Rc<AppS>) {
|
||||
/* tray_icon.connect_activate */
|
||||
{
|
||||
let apps = appstate.clone();
|
||||
tray_icon.status_icon.connect_activate(move |_| on_tray_icon_activate(&apps));
|
||||
tray_icon.status_icon.connect_activate(move |_| {
|
||||
on_tray_icon_activate(&apps)
|
||||
});
|
||||
}
|
||||
|
||||
/* tray_icon.connect_scroll_event */
|
||||
@ -322,10 +313,9 @@ fn on_tray_icon_popup_menu(appstate: &AppS) {
|
||||
}
|
||||
|
||||
|
||||
fn on_tray_icon_scroll_event(
|
||||
appstate: &AppS,
|
||||
event: &gdk::EventScroll,
|
||||
) -> bool {
|
||||
fn on_tray_icon_scroll_event(appstate: &AppS,
|
||||
event: &gdk::EventScroll)
|
||||
-> bool {
|
||||
|
||||
let audio = &appstate.audio;
|
||||
|
||||
@ -344,10 +334,9 @@ fn on_tray_icon_scroll_event(
|
||||
}
|
||||
|
||||
|
||||
fn on_tray_button_release_event(
|
||||
appstate: &AppS,
|
||||
event_button: &gdk::EventButton,
|
||||
) -> bool {
|
||||
fn on_tray_button_release_event(appstate: &AppS,
|
||||
event_button: &gdk::EventButton)
|
||||
-> bool {
|
||||
let button = event_button.get_button();
|
||||
|
||||
if button != 2 {
|
||||
|
Loading…
Reference in New Issue
Block a user