stop using DynResult for error handling
I plan to refactor the code to have a single "fatal_error" channel that all threads get a handle to, and `Box<dyn Error>` can't be sent between threads safely.
This commit is contained in:
@@ -1,57 +1,68 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
||||||
use crate::DynResult;
|
use crate::error::{Error, Result};
|
||||||
|
|
||||||
// This current implementation is incredibly barebones.
|
// This current implementation is incredibly barebones and brittle.
|
||||||
// It literally just reads/writes the last selected mode from the file.
|
// It literally just reads/writes the last selected mode from the file as a raw
|
||||||
|
// index into the modes array. That's it.
|
||||||
//
|
//
|
||||||
// No TOML, No JSON, just raw text.
|
// No TOML, No JSON, just raw text.
|
||||||
//
|
//
|
||||||
// It shouldn't be too hard to get a proper serde-based implementation up and
|
// While it wouldn't be too hard to get a proper serde-based implementation up
|
||||||
// running, it's moreso that it'll bump compile times for no good reason. I'll
|
// and running, it'll just bump compile times up for no good reason, so I'll
|
||||||
// set that all up once I need the complexity.
|
// only set it up once I need the added complexity.
|
||||||
|
|
||||||
|
// TODO: stop using strings for errors lol
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub last_mode: usize,
|
pub last_mode: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_cfg_file() -> DynResult<fs::File> {
|
fn get_cfg_file() -> Result<fs::File> {
|
||||||
let proj_dirs = directories::ProjectDirs::from("com", "prilik", "surface-dial-daemon")
|
let proj_dirs = directories::ProjectDirs::from("com", "prilik", "surface-dial-daemon")
|
||||||
.ok_or("could not open config directory")?;
|
.ok_or_else(|| Error::ConfigFile("could not open config directory".into()))?;
|
||||||
let cfg_folder = proj_dirs.config_dir();
|
let cfg_folder = proj_dirs.config_dir();
|
||||||
let cfg_file_path = proj_dirs.config_dir().join("config.txt");
|
let cfg_file_path = proj_dirs.config_dir().join("config.txt");
|
||||||
|
|
||||||
fs::create_dir_all(cfg_folder).map_err(|_| "could not create config dir")?;
|
fs::create_dir_all(cfg_folder)
|
||||||
|
.map_err(|e| Error::ConfigFile(format!("could not create config dir: {}", e)))?;
|
||||||
|
|
||||||
if !cfg_file_path.exists() {
|
if !cfg_file_path.exists() {
|
||||||
fs::write(&cfg_file_path, "0")?;
|
fs::write(&cfg_file_path, "0")
|
||||||
|
.map_err(|e| Error::ConfigFile(format!("could not write to config file: {}", e)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cfg_file = fs::OpenOptions::new()
|
let cfg_file = fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.read(true)
|
.read(true)
|
||||||
.open(cfg_file_path)
|
.open(cfg_file_path)
|
||||||
.map_err(|e| format!("could not open config file: {}", e))?;
|
.map_err(|e| Error::ConfigFile(format!("could not open config file: {}", e)))?;
|
||||||
|
|
||||||
Ok(cfg_file)
|
Ok(cfg_file)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn from_disk() -> DynResult<Config> {
|
pub fn from_disk() -> Result<Config> {
|
||||||
let mut cfg_file = get_cfg_file()?;
|
let mut cfg_file = get_cfg_file()?;
|
||||||
|
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
cfg_file.read_to_string(&mut content)?;
|
cfg_file
|
||||||
|
.read_to_string(&mut content)
|
||||||
|
.map_err(|e| Error::ConfigFile(format!("could not read the config file: {}", e)))?;
|
||||||
|
|
||||||
let last_mode = content.parse()?;
|
let last_mode = content
|
||||||
|
.parse()
|
||||||
|
.map_err(|e| Error::ConfigFile(format!("could not parse the config file: {}", e)))?;
|
||||||
|
|
||||||
Ok(Config { last_mode })
|
Ok(Config { last_mode })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_disk(&self) -> DynResult<()> {
|
pub fn to_disk(&self) -> Result<()> {
|
||||||
let mut cfg_file = get_cfg_file()?;
|
let mut cfg_file = get_cfg_file()?;
|
||||||
cfg_file.write_all(format!("{}", self.last_mode).as_bytes())?;
|
cfg_file
|
||||||
|
.write_all(format!("{}", self.last_mode).as_bytes())
|
||||||
|
.map_err(|e| Error::ConfigFile(format!("could not write to the config file: {}", e)))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::controller::{ControlMode, ControlModeMeta};
|
use crate::controller::{ControlMode, ControlModeMeta};
|
||||||
use crate::dial_device::DialHaptics;
|
use crate::dial_device::DialHaptics;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
use crate::fake_input::FakeInput;
|
use crate::fake_input::FakeInput;
|
||||||
use crate::DynResult;
|
|
||||||
|
|
||||||
use evdev_rs::enums::EV_KEY;
|
use evdev_rs::enums::EV_KEY;
|
||||||
|
|
||||||
@@ -25,27 +25,33 @@ impl ControlMode for Media {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_start(&mut self, haptics: &DialHaptics) -> DynResult<()> {
|
fn on_start(&mut self, haptics: &DialHaptics) -> Result<()> {
|
||||||
haptics.set_mode(true, Some(36))?;
|
haptics.set_mode(true, Some(36))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_press(&mut self, _: &DialHaptics) -> DynResult<()> {
|
fn on_btn_press(&mut self, _: &DialHaptics) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_release(&mut self, _: &DialHaptics) -> DynResult<()> {
|
fn on_btn_release(&mut self, _: &DialHaptics) -> Result<()> {
|
||||||
self.fake_input.key_click(&[EV_KEY::KEY_PLAYPAUSE])?;
|
self.fake_input
|
||||||
|
.key_click(&[EV_KEY::KEY_PLAYPAUSE])
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> DynResult<()> {
|
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> Result<()> {
|
||||||
if delta > 0 {
|
if delta > 0 {
|
||||||
eprintln!("next song");
|
eprintln!("next song");
|
||||||
self.fake_input.key_click(&[EV_KEY::KEY_NEXTSONG])?;
|
self.fake_input
|
||||||
|
.key_click(&[EV_KEY::KEY_NEXTSONG])
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
} else {
|
} else {
|
||||||
eprintln!("last song");
|
eprintln!("last song");
|
||||||
self.fake_input.key_click(&[EV_KEY::KEY_PREVIOUSSONG])?;
|
self.fake_input
|
||||||
|
.key_click(&[EV_KEY::KEY_PREVIOUSSONG])
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::controller::{ControlMode, ControlModeMeta};
|
use crate::controller::{ControlMode, ControlModeMeta};
|
||||||
use crate::dial_device::DialHaptics;
|
use crate::dial_device::DialHaptics;
|
||||||
use crate::DynResult;
|
use crate::error::Result;
|
||||||
|
|
||||||
impl ControlMode for () {
|
impl ControlMode for () {
|
||||||
fn meta(&self) -> ControlModeMeta {
|
fn meta(&self) -> ControlModeMeta {
|
||||||
@@ -10,20 +10,20 @@ impl ControlMode for () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_start(&mut self, haptics: &DialHaptics) -> DynResult<()> {
|
fn on_start(&mut self, haptics: &DialHaptics) -> Result<()> {
|
||||||
haptics.set_mode(false, Some(0))?;
|
haptics.set_mode(false, Some(0))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_press(&mut self, _haptics: &DialHaptics) -> DynResult<()> {
|
fn on_btn_press(&mut self, _haptics: &DialHaptics) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_release(&mut self, _haptics: &DialHaptics) -> DynResult<()> {
|
fn on_btn_release(&mut self, _haptics: &DialHaptics) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_dial(&mut self, _haptics: &DialHaptics, _delta: i32) -> DynResult<()> {
|
fn on_dial(&mut self, _haptics: &DialHaptics, _delta: i32) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use crate::controller::{ControlMode, ControlModeMeta};
|
use crate::controller::{ControlMode, ControlModeMeta};
|
||||||
use crate::dial_device::DialHaptics;
|
use crate::dial_device::DialHaptics;
|
||||||
|
use crate::error::Result;
|
||||||
use crate::fake_input::FakeInput;
|
use crate::fake_input::FakeInput;
|
||||||
use crate::DynResult;
|
|
||||||
|
|
||||||
use evdev_rs::enums::EV_KEY;
|
use evdev_rs::enums::EV_KEY;
|
||||||
|
|
||||||
@@ -152,29 +152,29 @@ impl ControlMode for Paddle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_start(&mut self, haptics: &DialHaptics) -> DynResult<()> {
|
fn on_start(&mut self, haptics: &DialHaptics) -> Result<()> {
|
||||||
haptics.set_mode(false, Some(3600))?;
|
haptics.set_mode(false, Some(3600))?;
|
||||||
self.msg.send(Msg::Enabled(true))?;
|
let _ = self.msg.send(Msg::Enabled(true));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_end(&mut self, _haptics: &DialHaptics) -> DynResult<()> {
|
fn on_end(&mut self, _haptics: &DialHaptics) -> Result<()> {
|
||||||
self.msg.send(Msg::Enabled(false))?;
|
let _ = self.msg.send(Msg::Enabled(false));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_press(&mut self, _: &DialHaptics) -> DynResult<()> {
|
fn on_btn_press(&mut self, _: &DialHaptics) -> Result<()> {
|
||||||
self.msg.send(Msg::ButtonDown)?;
|
let _ = self.msg.send(Msg::ButtonDown);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_release(&mut self, _: &DialHaptics) -> DynResult<()> {
|
fn on_btn_release(&mut self, _: &DialHaptics) -> Result<()> {
|
||||||
self.msg.send(Msg::ButtonUp)?;
|
let _ = self.msg.send(Msg::ButtonUp);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> DynResult<()> {
|
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> Result<()> {
|
||||||
self.msg.send(Msg::Delta(delta))?;
|
let _ = self.msg.send(Msg::Delta(delta));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::controller::{ControlMode, ControlModeMeta};
|
use crate::controller::{ControlMode, ControlModeMeta};
|
||||||
use crate::dial_device::DialHaptics;
|
use crate::dial_device::DialHaptics;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
use crate::fake_input::{FakeInput, ScrollStep};
|
use crate::fake_input::{FakeInput, ScrollStep};
|
||||||
use crate::DynResult;
|
|
||||||
|
|
||||||
pub struct Scroll {
|
pub struct Scroll {
|
||||||
fake_input: FakeInput,
|
fake_input: FakeInput,
|
||||||
@@ -23,26 +23,30 @@ impl ControlMode for Scroll {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_start(&mut self, haptics: &DialHaptics) -> DynResult<()> {
|
fn on_start(&mut self, haptics: &DialHaptics) -> Result<()> {
|
||||||
haptics.set_mode(false, Some(90))?;
|
haptics.set_mode(false, Some(90))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_press(&mut self, _: &DialHaptics) -> DynResult<()> {
|
fn on_btn_press(&mut self, _: &DialHaptics) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_release(&mut self, _haptics: &DialHaptics) -> DynResult<()> {
|
fn on_btn_release(&mut self, _haptics: &DialHaptics) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> DynResult<()> {
|
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> Result<()> {
|
||||||
if delta > 0 {
|
if delta > 0 {
|
||||||
eprintln!("scroll down");
|
eprintln!("scroll down");
|
||||||
self.fake_input.scroll_step(ScrollStep::Down)?;
|
self.fake_input
|
||||||
|
.scroll_step(ScrollStep::Down)
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
} else {
|
} else {
|
||||||
eprintln!("scroll up");
|
eprintln!("scroll up");
|
||||||
self.fake_input.scroll_step(ScrollStep::Up)?;
|
self.fake_input
|
||||||
|
.scroll_step(ScrollStep::Up)
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::controller::{ControlMode, ControlModeMeta};
|
use crate::controller::{ControlMode, ControlModeMeta};
|
||||||
use crate::dial_device::DialHaptics;
|
use crate::dial_device::DialHaptics;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
use crate::fake_input::FakeInput;
|
use crate::fake_input::FakeInput;
|
||||||
use crate::DynResult;
|
|
||||||
|
|
||||||
pub struct ScrollMT {
|
pub struct ScrollMT {
|
||||||
acc_delta: i32,
|
acc_delta: i32,
|
||||||
@@ -26,35 +26,37 @@ impl ControlMode for ScrollMT {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_start(&mut self, haptics: &DialHaptics) -> DynResult<()> {
|
fn on_start(&mut self, haptics: &DialHaptics) -> Result<()> {
|
||||||
haptics.set_mode(false, Some(3600))?;
|
haptics.set_mode(false, Some(3600))?;
|
||||||
self.acc_delta = 0;
|
self.acc_delta = 0;
|
||||||
|
|
||||||
self.fake_input.scroll_mt_start()?;
|
self.fake_input.scroll_mt_start().map_err(Error::Evdev)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_end(&mut self, _haptics: &DialHaptics) -> DynResult<()> {
|
fn on_end(&mut self, _haptics: &DialHaptics) -> Result<()> {
|
||||||
self.fake_input.scroll_mt_end()?;
|
self.fake_input.scroll_mt_end().map_err(Error::Evdev)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: the button will reset the scroll event, which sometimes helps
|
// HACK: the button will reset the scroll event, which sometimes helps
|
||||||
|
|
||||||
fn on_btn_press(&mut self, _: &DialHaptics) -> DynResult<()> {
|
fn on_btn_press(&mut self, _: &DialHaptics) -> Result<()> {
|
||||||
self.fake_input.scroll_mt_end()?;
|
self.fake_input.scroll_mt_end().map_err(Error::Evdev)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_release(&mut self, _haptics: &DialHaptics) -> DynResult<()> {
|
fn on_btn_release(&mut self, _haptics: &DialHaptics) -> Result<()> {
|
||||||
self.fake_input.scroll_mt_start()?;
|
self.fake_input.scroll_mt_start().map_err(Error::Evdev)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> DynResult<()> {
|
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> Result<()> {
|
||||||
self.acc_delta += delta;
|
self.acc_delta += delta;
|
||||||
self.fake_input.scroll_mt_step(self.acc_delta)?;
|
self.fake_input
|
||||||
|
.scroll_mt_step(self.acc_delta)
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::controller::{ControlMode, ControlModeMeta};
|
use crate::controller::{ControlMode, ControlModeMeta};
|
||||||
use crate::dial_device::DialHaptics;
|
use crate::dial_device::DialHaptics;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
use crate::fake_input::FakeInput;
|
use crate::fake_input::FakeInput;
|
||||||
use crate::DynResult;
|
|
||||||
|
|
||||||
use evdev_rs::enums::EV_KEY;
|
use evdev_rs::enums::EV_KEY;
|
||||||
|
|
||||||
@@ -25,32 +25,36 @@ impl ControlMode for Volume {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_start(&mut self, haptics: &DialHaptics) -> DynResult<()> {
|
fn on_start(&mut self, haptics: &DialHaptics) -> Result<()> {
|
||||||
haptics.set_mode(true, Some(36 * 2))?;
|
haptics.set_mode(true, Some(36 * 2))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_press(&mut self, _: &DialHaptics) -> DynResult<()> {
|
fn on_btn_press(&mut self, _: &DialHaptics) -> Result<()> {
|
||||||
// TODO: support double-click to play/pause
|
// TODO: support double-click to play/pause
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_release(&mut self, _: &DialHaptics) -> DynResult<()> {
|
fn on_btn_release(&mut self, _: &DialHaptics) -> Result<()> {
|
||||||
eprintln!("play/pause");
|
eprintln!("play/pause");
|
||||||
// self.fake_input.mute()?
|
// self.fake_input.mute()?
|
||||||
self.fake_input.key_click(&[EV_KEY::KEY_PLAYPAUSE])?;
|
self.fake_input
|
||||||
|
.key_click(&[EV_KEY::KEY_PLAYPAUSE])
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> DynResult<()> {
|
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> Result<()> {
|
||||||
if delta > 0 {
|
if delta > 0 {
|
||||||
eprintln!("volume up");
|
eprintln!("volume up");
|
||||||
self.fake_input
|
self.fake_input
|
||||||
.key_click(&[EV_KEY::KEY_LEFTSHIFT, EV_KEY::KEY_VOLUMEUP])?;
|
.key_click(&[EV_KEY::KEY_LEFTSHIFT, EV_KEY::KEY_VOLUMEUP])
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
} else {
|
} else {
|
||||||
eprintln!("volume down");
|
eprintln!("volume down");
|
||||||
self.fake_input
|
self.fake_input
|
||||||
.key_click(&[EV_KEY::KEY_LEFTSHIFT, EV_KEY::KEY_VOLUMEDOWN])?;
|
.key_click(&[EV_KEY::KEY_LEFTSHIFT, EV_KEY::KEY_VOLUMEDOWN])
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::controller::{ControlMode, ControlModeMeta};
|
use crate::controller::{ControlMode, ControlModeMeta};
|
||||||
use crate::dial_device::DialHaptics;
|
use crate::dial_device::DialHaptics;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
use crate::fake_input::FakeInput;
|
use crate::fake_input::FakeInput;
|
||||||
use crate::DynResult;
|
|
||||||
|
|
||||||
use evdev_rs::enums::EV_KEY;
|
use evdev_rs::enums::EV_KEY;
|
||||||
|
|
||||||
@@ -25,28 +25,30 @@ impl ControlMode for Zoom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_start(&mut self, haptics: &DialHaptics) -> DynResult<()> {
|
fn on_start(&mut self, haptics: &DialHaptics) -> Result<()> {
|
||||||
haptics.set_mode(true, Some(36))?;
|
haptics.set_mode(true, Some(36))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_press(&mut self, _: &DialHaptics) -> DynResult<()> {
|
fn on_btn_press(&mut self, _: &DialHaptics) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_release(&mut self, _haptics: &DialHaptics) -> DynResult<()> {
|
fn on_btn_release(&mut self, _haptics: &DialHaptics) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> DynResult<()> {
|
fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> Result<()> {
|
||||||
if delta > 0 {
|
if delta > 0 {
|
||||||
eprintln!("zoom in");
|
eprintln!("zoom in");
|
||||||
self.fake_input
|
self.fake_input
|
||||||
.key_click(&[EV_KEY::KEY_LEFTCTRL, EV_KEY::KEY_EQUAL])?;
|
.key_click(&[EV_KEY::KEY_LEFTCTRL, EV_KEY::KEY_EQUAL])
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
} else {
|
} else {
|
||||||
eprintln!("zoom out");
|
eprintln!("zoom out");
|
||||||
self.fake_input
|
self.fake_input
|
||||||
.key_click(&[EV_KEY::KEY_LEFTCTRL, EV_KEY::KEY_MINUS])?;
|
.key_click(&[EV_KEY::KEY_LEFTCTRL, EV_KEY::KEY_MINUS])
|
||||||
|
.map_err(Error::Evdev)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::dial_device::{DialDevice, DialEventKind, DialHaptics};
|
use crate::dial_device::{DialDevice, DialEventKind, DialHaptics};
|
||||||
use crate::DynResult;
|
use crate::error::{Error, Result};
|
||||||
|
|
||||||
pub mod controls;
|
pub mod controls;
|
||||||
|
|
||||||
@@ -13,14 +13,14 @@ pub struct ControlModeMeta {
|
|||||||
pub trait ControlMode {
|
pub trait ControlMode {
|
||||||
fn meta(&self) -> ControlModeMeta;
|
fn meta(&self) -> ControlModeMeta;
|
||||||
|
|
||||||
fn on_start(&mut self, haptics: &DialHaptics) -> DynResult<()>;
|
fn on_start(&mut self, haptics: &DialHaptics) -> Result<()>;
|
||||||
fn on_end(&mut self, _haptics: &DialHaptics) -> DynResult<()> {
|
fn on_end(&mut self, _haptics: &DialHaptics) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_press(&mut self, haptics: &DialHaptics) -> DynResult<()>;
|
fn on_btn_press(&mut self, haptics: &DialHaptics) -> Result<()>;
|
||||||
fn on_btn_release(&mut self, haptics: &DialHaptics) -> DynResult<()>;
|
fn on_btn_release(&mut self, haptics: &DialHaptics) -> Result<()>;
|
||||||
fn on_dial(&mut self, haptics: &DialHaptics, delta: i32) -> DynResult<()>;
|
fn on_dial(&mut self, haptics: &DialHaptics, delta: i32) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ActiveMode {
|
enum ActiveMode {
|
||||||
@@ -59,7 +59,7 @@ impl DialController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) -> DynResult<()> {
|
pub fn run(&mut self) -> Result<()> {
|
||||||
let initial_mode = match self.active_mode {
|
let initial_mode = match self.active_mode {
|
||||||
ActiveMode::Normal(i) => i,
|
ActiveMode::Normal(i) => i,
|
||||||
ActiveMode::Meta => 0,
|
ActiveMode::Meta => 0,
|
||||||
@@ -137,7 +137,7 @@ impl ControlMode for MetaMode {
|
|||||||
unreachable!() // meta mode never queries itself
|
unreachable!() // meta mode never queries itself
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_start(&mut self, haptics: &DialHaptics) -> DynResult<()> {
|
fn on_start(&mut self, haptics: &DialHaptics) -> Result<()> {
|
||||||
use notify_rust::*;
|
use notify_rust::*;
|
||||||
self.notif = Some(
|
self.notif = Some(
|
||||||
Notification::new()
|
Notification::new()
|
||||||
@@ -150,7 +150,8 @@ impl ControlMode for MetaMode {
|
|||||||
self.metas[self.current_mode].name
|
self.metas[self.current_mode].name
|
||||||
))
|
))
|
||||||
.icon("emblem-system")
|
.icon("emblem-system")
|
||||||
.show()?,
|
.show()
|
||||||
|
.map_err(Error::Notif)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
haptics.buzz(1)?;
|
haptics.buzz(1)?;
|
||||||
@@ -161,11 +162,11 @@ impl ControlMode for MetaMode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_press(&mut self, _haptics: &DialHaptics) -> DynResult<()> {
|
fn on_btn_press(&mut self, _haptics: &DialHaptics) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_btn_release(&mut self, haptics: &DialHaptics) -> DynResult<()> {
|
fn on_btn_release(&mut self, haptics: &DialHaptics) -> Result<()> {
|
||||||
if self.first_release {
|
if self.first_release {
|
||||||
self.first_release = false;
|
self.first_release = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -182,7 +183,7 @@ impl ControlMode for MetaMode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_dial(&mut self, _haptics: &DialHaptics, delta: i32) -> DynResult<()> {
|
fn on_dial(&mut self, _haptics: &DialHaptics, delta: i32) -> Result<()> {
|
||||||
if delta > 0 {
|
if delta > 0 {
|
||||||
self.current_mode += 1;
|
self.current_mode += 1;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::time::Duration;
|
|||||||
use evdev_rs::{Device, InputEvent, ReadStatus};
|
use evdev_rs::{Device, InputEvent, ReadStatus};
|
||||||
use hidapi::{HidApi, HidDevice};
|
use hidapi::{HidApi, HidDevice};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::{Error, Result};
|
||||||
|
|
||||||
pub struct DialDevice {
|
pub struct DialDevice {
|
||||||
long_press_timeout: Duration,
|
long_press_timeout: Duration,
|
||||||
@@ -31,7 +31,7 @@ pub enum DialEventKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DialDevice {
|
impl DialDevice {
|
||||||
pub fn new(long_press_timeout: Duration) -> Result<DialDevice, crate::Error> {
|
pub fn new(long_press_timeout: Duration) -> Result<DialDevice> {
|
||||||
let mut control = None;
|
let mut control = None;
|
||||||
let mut axis = None;
|
let mut axis = None;
|
||||||
|
|
||||||
@@ -72,13 +72,13 @@ impl DialDevice {
|
|||||||
let (events_tx, events_rx) = mpsc::channel();
|
let (events_tx, events_rx) = mpsc::channel();
|
||||||
|
|
||||||
// TODO: interleave control events with regular events
|
// TODO: interleave control events with regular events
|
||||||
|
// (once we figure out what control events actually do...)
|
||||||
|
|
||||||
|
// inb4 "y not async/await"
|
||||||
std::thread::spawn({
|
std::thread::spawn({
|
||||||
let events = events_tx;
|
let events = events_tx;
|
||||||
move || loop {
|
move || loop {
|
||||||
events
|
let _ = events.send(axis.next_event(evdev_rs::ReadFlag::NORMAL));
|
||||||
.send(axis.next_event(evdev_rs::ReadFlag::NORMAL))
|
|
||||||
.expect("failed to send axis event");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ impl DialDevice {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_event(&mut self) -> Result<DialEvent, Error> {
|
pub fn next_event(&mut self) -> Result<DialEvent> {
|
||||||
let evt = if self.possible_long_press {
|
let evt = if self.possible_long_press {
|
||||||
self.events.recv_timeout(self.long_press_timeout)
|
self.events.recv_timeout(self.long_press_timeout)
|
||||||
} else {
|
} else {
|
||||||
@@ -166,7 +166,7 @@ pub struct DialHaptics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DialHaptics {
|
impl DialHaptics {
|
||||||
fn new() -> Result<DialHaptics, Error> {
|
fn new() -> Result<DialHaptics> {
|
||||||
let api = HidApi::new().map_err(Error::HidError)?;
|
let api = HidApi::new().map_err(Error::HidError)?;
|
||||||
let hid_device = api.open(0x045e, 0x091b).map_err(|_| Error::MissingDial)?;
|
let hid_device = api.open(0x045e, 0x091b).map_err(|_| Error::MissingDial)?;
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ impl DialHaptics {
|
|||||||
/// `steps` should be a value between 0 and 3600, which corresponds to the
|
/// `steps` should be a value between 0 and 3600, which corresponds to the
|
||||||
/// number of subdivisions the dial should use. If left unspecified, this
|
/// number of subdivisions the dial should use. If left unspecified, this
|
||||||
/// defaults to 36 (an arbitrary choice that "feels good" most of the time)
|
/// defaults to 36 (an arbitrary choice that "feels good" most of the time)
|
||||||
pub fn set_mode(&self, haptics: bool, steps: Option<u16>) -> Result<(), Error> {
|
pub fn set_mode(&self, haptics: bool, steps: Option<u16>) -> Result<()> {
|
||||||
let steps = steps.unwrap_or(36);
|
let steps = steps.unwrap_or(36);
|
||||||
assert!(steps <= 3600);
|
assert!(steps <= 3600);
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ impl DialHaptics {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buzz(&self, repeat: u8) -> Result<(), Error> {
|
pub fn buzz(&self, repeat: u8) -> Result<()> {
|
||||||
let mut buf = [0; 5];
|
let mut buf = [0; 5];
|
||||||
buf[0] = 0x01; // Report ID
|
buf[0] = 0x01; // Report ID
|
||||||
buf[1] = repeat; // RepeatCount
|
buf[1] = repeat; // RepeatCount
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ use std::io;
|
|||||||
|
|
||||||
use evdev_rs::InputEvent;
|
use evdev_rs::InputEvent;
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
ConfigFile(String),
|
||||||
OpenDevInputDir(io::Error),
|
OpenDevInputDir(io::Error),
|
||||||
OpenEventFile(std::path::PathBuf, io::Error),
|
OpenEventFile(std::path::PathBuf, io::Error),
|
||||||
HidError(hidapi::HidError),
|
HidError(hidapi::HidError),
|
||||||
@@ -12,12 +15,13 @@ pub enum Error {
|
|||||||
MultipleDials,
|
MultipleDials,
|
||||||
UnexpectedEvt(InputEvent),
|
UnexpectedEvt(InputEvent),
|
||||||
Evdev(io::Error),
|
Evdev(io::Error),
|
||||||
Io(io::Error),
|
Notif(notify_rust::error::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
Error::ConfigFile(e) => write!(f, "Could not open config file: {}", e),
|
||||||
Error::OpenDevInputDir(e) => write!(f, "Could not open /dev/input directory: {}", e),
|
Error::OpenDevInputDir(e) => write!(f, "Could not open /dev/input directory: {}", e),
|
||||||
Error::OpenEventFile(path, e) => write!(f, "Could not open {:?}: {}", path, e),
|
Error::OpenEventFile(path, e) => write!(f, "Could not open {:?}: {}", path, e),
|
||||||
Error::HidError(e) => write!(f, "HID API Error: {}", e),
|
Error::HidError(e) => write!(f, "HID API Error: {}", e),
|
||||||
@@ -25,7 +29,7 @@ impl fmt::Display for Error {
|
|||||||
Error::MultipleDials => write!(f, "Found multiple dials"),
|
Error::MultipleDials => write!(f, "Found multiple dials"),
|
||||||
Error::UnexpectedEvt(evt) => write!(f, "Unexpected event: {:?}", evt),
|
Error::UnexpectedEvt(evt) => write!(f, "Unexpected event: {:?}", evt),
|
||||||
Error::Evdev(e) => write!(f, "Evdev error: {}", e),
|
Error::Evdev(e) => write!(f, "Evdev error: {}", e),
|
||||||
Error::Io(e) => write!(f, "Io error: {}", e),
|
Error::Notif(e) => write!(f, "Notification error: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
33
src/main.rs
33
src/main.rs
@@ -7,13 +7,11 @@ mod dial_device;
|
|||||||
mod error;
|
mod error;
|
||||||
mod fake_input;
|
mod fake_input;
|
||||||
|
|
||||||
pub type DynResult<T> = Result<T, Box<dyn std::error::Error>>;
|
|
||||||
|
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use crate::controller::DialController;
|
use crate::controller::DialController;
|
||||||
use crate::dial_device::DialDevice;
|
use crate::dial_device::DialDevice;
|
||||||
use crate::error::Error;
|
use crate::error::Result;
|
||||||
|
|
||||||
use notify_rust::{Hint, Notification, Timeout};
|
use notify_rust::{Hint, Notification, Timeout};
|
||||||
use signal_hook::{iterator::Signals, SIGINT, SIGTERM};
|
use signal_hook::{iterator::Signals, SIGINT, SIGTERM};
|
||||||
@@ -58,7 +56,21 @@ fn main() {
|
|||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Err(e) = true_main(kill_notif_tx.clone()) {
|
std::thread::spawn({
|
||||||
|
let kill_notif_tx = kill_notif_tx.clone();
|
||||||
|
move || {
|
||||||
|
let signals = Signals::new(&[SIGTERM, SIGINT]).unwrap();
|
||||||
|
for sig in signals.forever() {
|
||||||
|
eprintln!("received signal {:?}", sig);
|
||||||
|
match kill_notif_tx.send(Some(("Terminated!".into(), "dialog-warning"))) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(_) => std::process::exit(1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Err(e) = true_main() {
|
||||||
println!("{}", e);
|
println!("{}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +78,7 @@ fn main() {
|
|||||||
let _ = handle.join();
|
let _ = handle.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn true_main(kill_notif_tx: mpsc::Sender<Option<(String, &'static str)>>) -> DynResult<()> {
|
fn true_main() -> Result<()> {
|
||||||
println!("Started");
|
println!("Started");
|
||||||
|
|
||||||
let cfg = config::Config::from_disk()?;
|
let cfg = config::Config::from_disk()?;
|
||||||
@@ -74,17 +86,6 @@ fn true_main(kill_notif_tx: mpsc::Sender<Option<(String, &'static str)>>) -> Dyn
|
|||||||
let dial = DialDevice::new(std::time::Duration::from_millis(750))?;
|
let dial = DialDevice::new(std::time::Duration::from_millis(750))?;
|
||||||
println!("Found the dial");
|
println!("Found the dial");
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
let signals = Signals::new(&[SIGTERM, SIGINT]).unwrap();
|
|
||||||
for sig in signals.forever() {
|
|
||||||
eprintln!("received signal {:?}", sig);
|
|
||||||
match kill_notif_tx.send(Some(("Terminated!".into(), "dialog-warning"))) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => std::process::exit(1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut controller = DialController::new(
|
let mut controller = DialController::new(
|
||||||
dial,
|
dial,
|
||||||
cfg.last_mode,
|
cfg.last_mode,
|
||||||
|
|||||||
Reference in New Issue
Block a user