mirror of
https://codeberg.org/Fl1tzi/microdeck.git
synced 2024-05-16 09:51:59 +00:00
rework death notice of device
This commit is contained in:
parent
9690f1f976
commit
953ccd1c32
|
@ -15,6 +15,7 @@ use tokio::{
|
||||||
process::Command,
|
process::Command,
|
||||||
runtime::Runtime,
|
runtime::Runtime,
|
||||||
sync::mpsc::{self, error::TrySendError},
|
sync::mpsc::{self, error::TrySendError},
|
||||||
|
sync::Notify,
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, info_span, trace, warn};
|
use tracing::{debug, error, info_span, trace, warn};
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ pub struct Device {
|
||||||
config: DeviceConfig,
|
config: DeviceConfig,
|
||||||
spaces: Arc<HashMap<String, Space>>,
|
spaces: Arc<HashMap<String, Space>>,
|
||||||
selected_space: Option<String>,
|
selected_space: Option<String>,
|
||||||
is_dead_handle: Arc<std::sync::Mutex<bool>>,
|
is_dead: Arc<Notify>,
|
||||||
serial: String,
|
serial: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ impl Device {
|
||||||
serial: String,
|
serial: String,
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
device_conf: DeviceConfig,
|
device_conf: DeviceConfig,
|
||||||
is_dead_handle: Arc<std::sync::Mutex<bool>>,
|
is_dead: Arc<Notify>,
|
||||||
spaces: Arc<HashMap<String, Space>>,
|
spaces: Arc<HashMap<String, Space>>,
|
||||||
hid: &HidApi,
|
hid: &HidApi,
|
||||||
) -> Result<Device, DeviceError> {
|
) -> Result<Device, DeviceError> {
|
||||||
|
@ -91,7 +92,7 @@ impl Device {
|
||||||
config: device_conf,
|
config: device_conf,
|
||||||
spaces,
|
spaces,
|
||||||
selected_space: None,
|
selected_space: None,
|
||||||
is_dead_handle,
|
is_dead,
|
||||||
serial,
|
serial,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -160,16 +161,12 @@ impl Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shutdown the runtime and therefore kill all the modules and
|
/// Shutdown the runtime and therefore kill all the modules and
|
||||||
/// note death in field [self.is_dead_handle].
|
/// note death in field [self.is_dead].
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(handle) = self.modules_runtime.take() {
|
debug!("Dropped device");
|
||||||
handle.shutdown_background();
|
self.shutdown_modules();
|
||||||
}
|
// notify main that this device is dead now
|
||||||
self.modules = HashMap::new();
|
self.is_dead.notify_one();
|
||||||
*self
|
|
||||||
.is_dead_handle
|
|
||||||
.lock()
|
|
||||||
.expect("Unable to lock Mutex to signal drop of device") = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// shutdown the runtime and therefore kill all the modules.
|
/// shutdown the runtime and therefore kill all the modules.
|
||||||
|
|
62
src/main.rs
62
src/main.rs
|
@ -11,6 +11,7 @@ use std::{
|
||||||
sync::{Arc, Mutex, OnceLock},
|
sync::{Arc, Mutex, OnceLock},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
use tokio::sync::Notify;
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
use tracing_subscriber::{
|
use tracing_subscriber::{
|
||||||
self, prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, EnvFilter,
|
self, prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, EnvFilter,
|
||||||
|
@ -107,25 +108,12 @@ fn load_system_font() -> (Vec<u8>, i32) {
|
||||||
.expect("Unable to load system monospace font. Please specify a custom font in the config.")
|
.expect("Unable to load system monospace font. Please specify a custom font in the config.")
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DeviceHandle<T> {
|
type DeviceHandle<T> = tokio::task::JoinHandle<T>;
|
||||||
handle: tokio::task::JoinHandle<T>,
|
|
||||||
is_dead: Arc<Mutex<bool>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DeviceHandle<T> {
|
|
||||||
fn new(handle: tokio::task::JoinHandle<T>, is_dead: Arc<Mutex<bool>>) -> Self {
|
|
||||||
DeviceHandle { handle, is_dead }
|
|
||||||
}
|
|
||||||
fn is_dead(&self) -> bool {
|
|
||||||
match self.is_dead.lock() {
|
|
||||||
Ok(guard) => *guard,
|
|
||||||
Err(_) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn start(config: Config, mut hid: HidApi) {
|
async fn start(config: Config, mut hid: HidApi) {
|
||||||
let mut devices: HashMap<String, DeviceHandle<_>> = HashMap::new();
|
// This seems far too complex for what its actually doing
|
||||||
|
let devices: Arc<Mutex<HashMap<String, DeviceHandle<_>>>> =
|
||||||
|
Arc::new(Mutex::new(HashMap::new()));
|
||||||
|
|
||||||
// devices which are not configured anyways
|
// devices which are not configured anyways
|
||||||
let mut ignore_devices: Vec<String> = Vec::new();
|
let mut ignore_devices: Vec<String> = Vec::new();
|
||||||
|
@ -138,20 +126,12 @@ async fn start(config: Config, mut hid: HidApi) {
|
||||||
if let Err(e) = streamdeck::refresh_device_list(&mut hid) {
|
if let Err(e) = streamdeck::refresh_device_list(&mut hid) {
|
||||||
warn!("Cannot fetch new devices: {}", e);
|
warn!("Cannot fetch new devices: {}", e);
|
||||||
} else {
|
} else {
|
||||||
|
trace!("Connected devices: {:?}", devices.lock().unwrap().keys());
|
||||||
for hw_device in streamdeck::list_devices(&hid) {
|
for hw_device in streamdeck::list_devices(&hid) {
|
||||||
// if the device is not already started or the device is
|
// if the device is already started or is ignored
|
||||||
// dropped
|
if !ignore_devices.contains(&hw_device.1)
|
||||||
if let Some(d) = devices.get(&hw_device.1) {
|
&& !devices.lock().unwrap().contains_key(&hw_device.1)
|
||||||
if d.is_dead() {
|
{
|
||||||
trace!("Removing dead device {}", &hw_device.1);
|
|
||||||
d.handle.abort();
|
|
||||||
devices.remove(&hw_device.1);
|
|
||||||
} else {
|
|
||||||
// ignore this device
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !ignore_devices.contains(&hw_device.1) {
|
|
||||||
// TODO: match regex for device serial
|
// TODO: match regex for device serial
|
||||||
if let Some(device_config) = config
|
if let Some(device_config) = config
|
||||||
.devices
|
.devices
|
||||||
|
@ -159,7 +139,8 @@ async fn start(config: Config, mut hid: HidApi) {
|
||||||
.find(|d| d.serial == hw_device.1 || d.serial == "*")
|
.find(|d| d.serial == hw_device.1 || d.serial == "*")
|
||||||
{
|
{
|
||||||
// start the device and its functions
|
// start the device and its functions
|
||||||
let is_dead = Arc::new(Mutex::new(false));
|
// TODO: start monitor when device dies and remove from HashMap
|
||||||
|
let is_dead = Arc::new(Notify::new());
|
||||||
if let Some(device) = start_device(
|
if let Some(device) = start_device(
|
||||||
hw_device,
|
hw_device,
|
||||||
&hid,
|
&hid,
|
||||||
|
@ -171,7 +152,22 @@ async fn start(config: Config, mut hid: HidApi) {
|
||||||
{
|
{
|
||||||
let serial = device.serial();
|
let serial = device.serial();
|
||||||
let handle = tokio::spawn(init_device_functions(device));
|
let handle = tokio::spawn(init_device_functions(device));
|
||||||
devices.insert(serial, DeviceHandle::new(handle, is_dead));
|
{
|
||||||
|
let mut devices = devices.lock().unwrap();
|
||||||
|
devices.insert(serial.clone(), handle);
|
||||||
|
}
|
||||||
|
let is_dead_cloned = is_dead.clone();
|
||||||
|
let devices_cloned = devices.clone();
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
is_dead_cloned.notified().await;
|
||||||
|
let mut devices = devices_cloned.lock().unwrap();
|
||||||
|
let device_handle =
|
||||||
|
devices.get(&serial).expect("Can't retrieve device handle");
|
||||||
|
// kill runtime of device
|
||||||
|
device_handle.abort();
|
||||||
|
// remove device from list of active devices
|
||||||
|
devices.remove(&serial);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info!("The device {} is not configured.", hw_device.1);
|
info!("The device {} is not configured.", hw_device.1);
|
||||||
|
@ -198,7 +194,7 @@ async fn start_device(
|
||||||
hid: &HidApi,
|
hid: &HidApi,
|
||||||
device_config: DeviceConfig,
|
device_config: DeviceConfig,
|
||||||
spaces: Arc<HashMap<String, Space>>,
|
spaces: Arc<HashMap<String, Space>>,
|
||||||
is_dead: Arc<Mutex<bool>>,
|
is_dead: Arc<Notify>,
|
||||||
) -> Option<Device> {
|
) -> Option<Device> {
|
||||||
match Device::new(device.1, device.0, device_config, is_dead, spaces, &hid).await {
|
match Device::new(device.1, device.0, device_config, is_dead, spaces, &hid).await {
|
||||||
Ok(device) => {
|
Ok(device) => {
|
||||||
|
|
Loading…
Reference in a new issue