2017-07-04 22:22:23 +00:00
|
|
|
use errors::*;
|
2017-07-05 15:14:55 +00:00
|
|
|
use toml;
|
2017-07-05 18:27:16 +00:00
|
|
|
use xdg;
|
|
|
|
use std::fs::File;
|
|
|
|
use std::io::prelude::*;
|
2017-07-04 22:22:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-07-05 15:14:55 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
const VOL_CONTROL_COMMANDS: [&str; 3] =
|
|
|
|
["gnome-alsamixer", "xfce4-mixer", "alsamixergui"];
|
2017-07-04 22:22:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-07-05 15:14:55 +00:00
|
|
|
#[derive(Deserialize, Debug, Serialize)]
|
2017-07-05 18:27:16 +00:00
|
|
|
#[serde(tag = "action", rename_all = "snake_case")]
|
2017-07-04 22:22:23 +00:00
|
|
|
pub enum MiddleClickAction {
|
|
|
|
ToggleMute,
|
|
|
|
ShowPreferences,
|
|
|
|
VolumeControl,
|
2017-07-05 18:27:16 +00:00
|
|
|
CustomCommand { cmd: String },
|
2017-07-04 22:22:23 +00:00
|
|
|
}
|
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
impl Default for MiddleClickAction {
|
|
|
|
fn default() -> MiddleClickAction {
|
|
|
|
return MiddleClickAction::ToggleMute;
|
|
|
|
}
|
|
|
|
}
|
2017-07-04 22:22:23 +00:00
|
|
|
|
|
|
|
|
2017-07-05 15:14:55 +00:00
|
|
|
#[derive(Deserialize, Debug, Serialize)]
|
2017-07-05 18:27:16 +00:00
|
|
|
#[serde(default)]
|
2017-07-05 15:14:55 +00:00
|
|
|
pub struct Prefs {
|
|
|
|
pub device_prefs: DevicePrefs,
|
|
|
|
pub view_prefs: ViewPrefs,
|
|
|
|
pub behavior_prefs: BehaviorPrefs,
|
|
|
|
pub notify_prefs: NotifyPrefs,
|
|
|
|
// TODO: HotKeys?
|
|
|
|
}
|
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
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(),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-05 15:14:55 +00:00
|
|
|
#[derive(Deserialize, Debug, Serialize)]
|
2017-07-05 18:27:16 +00:00
|
|
|
#[serde(default)]
|
2017-07-05 15:14:55 +00:00
|
|
|
pub struct DevicePrefs {
|
2017-07-04 22:22:23 +00:00
|
|
|
pub card: String,
|
|
|
|
pub channel: String,
|
|
|
|
// TODO: normalize volume?
|
2017-07-05 15:14:55 +00:00
|
|
|
}
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
impl Default for DevicePrefs {
|
|
|
|
fn default() -> DevicePrefs {
|
|
|
|
return DevicePrefs {
|
|
|
|
card: String::from("(default)"),
|
|
|
|
channel: String::from("Master"),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-05 15:14:55 +00:00
|
|
|
#[derive(Deserialize, Debug, Serialize)]
|
2017-07-05 18:27:16 +00:00
|
|
|
#[serde(default)]
|
2017-07-05 15:14:55 +00:00
|
|
|
pub struct ViewPrefs {
|
2017-07-04 22:22:23 +00:00
|
|
|
pub draw_vol_meter: bool,
|
|
|
|
pub vol_meter_offset: i64,
|
|
|
|
pub system_theme: bool,
|
2017-07-05 18:27:16 +00:00
|
|
|
pub vol_meter_color: VolColor,
|
2017-07-04 22:22:23 +00:00
|
|
|
// TODO: Display text folume/text volume pos?
|
2017-07-05 15:14:55 +00:00
|
|
|
}
|
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
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(),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-05 15:14:55 +00:00
|
|
|
#[derive(Deserialize, Debug, Serialize)]
|
2017-07-05 18:27:16 +00:00
|
|
|
#[serde(default)]
|
2017-07-05 15:14:55 +00:00
|
|
|
pub struct VolColor {
|
|
|
|
pub red: u8,
|
|
|
|
pub green: u8,
|
|
|
|
pub blue: u8,
|
|
|
|
}
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
impl Default for VolColor {
|
|
|
|
fn default() -> VolColor {
|
|
|
|
return VolColor {
|
|
|
|
red: 245,
|
|
|
|
green: 180,
|
|
|
|
blue: 0,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-05 15:14:55 +00:00
|
|
|
#[derive(Deserialize, Debug, Serialize)]
|
2017-07-05 18:27:16 +00:00
|
|
|
#[serde(default)]
|
2017-07-05 15:14:55 +00:00
|
|
|
pub struct BehaviorPrefs {
|
2017-07-05 18:27:16 +00:00
|
|
|
vol_control_cmd: Option<String>,
|
2017-07-04 22:22:23 +00:00
|
|
|
pub vol_scroll_step: f64,
|
|
|
|
pub middle_click_action: MiddleClickAction,
|
|
|
|
// TODO: fine scroll step?
|
2017-07-05 15:14:55 +00:00
|
|
|
}
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
impl Default for BehaviorPrefs {
|
|
|
|
fn default() -> BehaviorPrefs {
|
|
|
|
return BehaviorPrefs {
|
|
|
|
vol_control_cmd: None,
|
|
|
|
vol_scroll_step: 5.0,
|
|
|
|
middle_click_action: MiddleClickAction::default(),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-05 15:14:55 +00:00
|
|
|
#[derive(Deserialize, Debug, Serialize)]
|
2017-07-05 18:27:16 +00:00
|
|
|
#[serde(default)]
|
2017-07-05 15:14:55 +00:00
|
|
|
pub struct NotifyPrefs {
|
2017-07-04 22:22:23 +00:00
|
|
|
pub enable_notifications: bool,
|
|
|
|
pub notifcation_timeout: i64,
|
|
|
|
pub notify_mouse_scroll: bool,
|
|
|
|
pub notify_popup: bool,
|
|
|
|
pub notify_external: bool,
|
|
|
|
// TODO: notify_hotkeys?
|
|
|
|
}
|
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
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,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2017-07-04 22:22:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
impl Prefs {
|
|
|
|
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);
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
let mut f = File::open(c)?;
|
|
|
|
let mut buffer = vec![];
|
|
|
|
f.read_to_end(&mut buffer)?;
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
let prefs = toml::from_slice(buffer.as_slice())?;
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
return Ok(prefs);
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
debug!("No config file present, creating one with defaults.");
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
let prefs = Prefs::default();
|
|
|
|
prefs.store_config()?;
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
return Ok(prefs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-07-05 15:14:55 +00:00
|
|
|
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
pub fn reload_config(&mut self) -> Result<()> {
|
|
|
|
debug!("Reloading config...");
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
let new_prefs = Prefs::new()?;
|
|
|
|
*self = new_prefs;
|
2017-07-04 22:22:23 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
return Ok(());
|
2017-07-04 22:22:23 +00:00
|
|
|
}
|
2017-07-05 15:14:55 +00:00
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
|
|
|
|
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(());
|
2017-07-05 15:14:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn to_str(&self) -> String {
|
|
|
|
return toml::to_string(self).unwrap();
|
|
|
|
}
|
2017-07-05 18:27:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
// TODO: implement
|
|
|
|
pub fn vol_control_cmd() -> String {
|
|
|
|
return String::from("");
|
|
|
|
}
|
2017-07-04 22:22:23 +00:00
|
|
|
}
|
|
|
|
|
2017-07-05 18:27:16 +00:00
|
|
|
fn get_xdg_dirs() -> xdg::BaseDirectories {
|
|
|
|
return xdg::BaseDirectories::with_prefix("pnmixer-rs").unwrap();
|
|
|
|
}
|