pnmixer-rust/src/prefs.rs

265 lines
6.2 KiB
Rust
Raw Normal View History

2017-07-04 22:22:23 +00:00
use errors::*;
2017-07-05 19:51:46 +00:00
use std::fmt::Display;
use std::fmt::Formatter;
2017-07-05 18:27:16 +00:00
use std::fs::File;
use std::io::prelude::*;
2017-07-05 19:51:46 +00:00
use std;
use toml;
use which;
use xdg;
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-06 22:28:55 +00:00
#[derive(Deserialize, Debug, Serialize, Clone, Copy)]
#[serde(rename_all = "snake_case")]
2017-07-04 22:22:23 +00:00
pub enum MiddleClickAction {
ToggleMute,
ShowPreferences,
VolumeControl,
2017-07-06 22:28:55 +00:00
CustomCommand,
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-06 22:28:55 +00:00
impl From<i32> for MiddleClickAction {
fn from(i: i32) -> Self {
match i {
0 => MiddleClickAction::ToggleMute,
1 => MiddleClickAction::ShowPreferences,
2 => MiddleClickAction::VolumeControl,
3 => MiddleClickAction::CustomCommand,
2017-07-06 23:00:17 +00:00
_ => MiddleClickAction::ToggleMute,
2017-07-06 22:28:55 +00:00
}
}
}
2017-07-06 23:00:17 +00:00
impl From<MiddleClickAction> for i32 {
fn from(action: MiddleClickAction) -> Self {
match action {
2017-07-06 22:28:55 +00:00
MiddleClickAction::ToggleMute => 0,
MiddleClickAction::ShowPreferences => 1,
MiddleClickAction::VolumeControl => 2,
MiddleClickAction::CustomCommand => 3,
}
}
}
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,
2017-07-07 20:10:45 +00:00
pub channel: String,
2017-07-04 22:22:23 +00:00
// 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 {
2017-07-07 20:10:45 +00:00
card: String::from("(default)"),
channel: String::from("Master"),
};
2017-07-05 18:27:16 +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 ViewPrefs {
2017-07-04 22:22:23 +00:00
pub draw_vol_meter: bool,
2017-07-06 22:28:55 +00:00
pub vol_meter_offset: i32,
2017-07-04 22:22:23 +00:00
pub system_theme: bool,
2017-07-07 20:10:45 +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 {
2017-07-07 20:10:45 +00:00
draw_vol_meter: true,
vol_meter_offset: 10,
system_theme: true,
vol_meter_color: VolColor::default(),
};
2017-07-05 18:27:16 +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 VolColor {
2017-07-12 14:26:41 +00:00
pub red: f64,
pub green: f64,
pub blue: f64,
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 VolColor {
fn default() -> VolColor {
return VolColor {
2017-07-12 14:26:41 +00:00
red: 0.960784313725,
green: 0.705882352941,
blue: 0.0,
2017-07-07 20:10:45 +00:00
};
2017-07-05 18:27:16 +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 BehaviorPrefs {
2017-07-05 19:51:46 +00:00
pub vol_control_cmd: Option<String>,
2017-07-04 22:22:23 +00:00
pub vol_scroll_step: f64,
2017-07-08 22:14:49 +00:00
pub vol_fine_scroll_step: f64,
2017-07-06 14:53:19 +00:00
pub middle_click_action: MiddleClickAction,
2017-07-06 22:28:55 +00:00
pub custom_command: Option<String>, // 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 {
2017-07-07 20:10:45 +00:00
vol_control_cmd: None,
vol_scroll_step: 5.0,
2017-07-08 22:14:49 +00:00
vol_fine_scroll_step: 1.0,
2017-07-07 20:10:45 +00:00
middle_click_action: MiddleClickAction::default(),
custom_command: None,
};
2017-07-05 18:27:16 +00:00
}
}
2017-07-10 19:07:59 +00:00
#[cfg(feature = "notify")]
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,
2017-07-07 20:10:45 +00:00
pub notify_external: bool,
2017-07-04 22:22:23 +00:00
// TODO: notify_hotkeys?
}
2017-07-10 19:07:59 +00:00
#[cfg(feature = "notify")]
2017-07-05 18:27:16 +00:00
impl Default for NotifyPrefs {
fn default() -> NotifyPrefs {
return NotifyPrefs {
2017-07-07 20:10:45 +00:00
enable_notifications: true,
notifcation_timeout: 1500,
notify_mouse_scroll: true,
notify_popup: true,
notify_external: true,
};
2017-07-05 18:27:16 +00:00
}
}
2017-07-04 22:22:23 +00:00
2017-07-05 19:51:46 +00:00
#[derive(Deserialize, Debug, Serialize, Default)]
#[serde(default)]
pub struct Prefs {
pub device_prefs: DevicePrefs,
pub view_prefs: ViewPrefs,
pub behavior_prefs: BehaviorPrefs,
2017-07-10 19:07:59 +00:00
#[cfg(feature = "notify")]
2017-07-07 20:10:45 +00:00
pub notify_prefs: NotifyPrefs,
2017-07-05 19:51:46 +00:00
// TODO: HotKeys?
}
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<()> {
2017-07-07 20:10:45 +00:00
let config_path = get_xdg_dirs().place_config_file("pnmixer.toml")
.from_err()?;
2017-07-05 18:27:16 +00:00
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
2017-07-05 19:51:46 +00:00
pub fn get_avail_vol_control_cmd(&self) -> Option<String> {
match self.behavior_prefs.vol_control_cmd {
Some(ref c) => return Some(c.clone()),
None => {
for command in VOL_CONTROL_COMMANDS.iter() {
if which::which(command).is_ok() {
return Some(String::from(*command));
}
}
}
}
return None;
2017-07-05 18:27:16 +00:00
}
2017-07-04 22:22:23 +00:00
}
2017-07-05 19:51:46 +00:00
impl Display for Prefs {
2017-07-07 20:10:45 +00:00
fn fmt(&self,
f: &mut Formatter)
-> std::result::Result<(), std::fmt::Error> {
2017-07-05 19:51:46 +00:00
let s = self.to_str();
return write!(f, "{}", s);
}
}
2017-07-05 18:27:16 +00:00
fn get_xdg_dirs() -> xdg::BaseDirectories {
return xdg::BaseDirectories::with_prefix("pnmixer-rs").unwrap();
}