1
0

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:
Daniel Prilik
2020-11-04 11:50:13 -05:00
parent 31d86e165a
commit 905c33ad4a
12 changed files with 147 additions and 112 deletions

View File

@@ -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(())
} }

View File

@@ -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(())
} }

View File

@@ -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(())
} }
} }

View File

@@ -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(())
} }
} }

View File

@@ -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(())

View File

@@ -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(())
} }

View File

@@ -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(())

View File

@@ -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(())

View File

@@ -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 {

View File

@@ -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

View File

@@ -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),
} }
} }
} }

View File

@@ -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,