use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::error::Result;
use crate::protocol::constants;
use crate::timed;
use crate::types::{Button, CatchEvent};
use crate::device::Device;
use super::EventHandle;
use super::events::POLL_INTERVAL;
impl Device {
pub fn start_catch(&self, button: Button) -> Result<()> {
timed!("start_catch", {
let target = constants::button_to_lock_target(button);
self.set_lock(target, true)?;
self.enable_catch(button)
})
}
pub fn stop_catch(&self, button: Button) -> Result<()> {
timed!("stop_catch", {
let target = constants::button_to_lock_target(button);
self.set_lock(target, false)
})
}
pub fn on_catch<F>(&self, button: Button, f: F) -> Result<EventHandle>
where
F: Fn(bool) + Send + 'static,
{
let alive = Arc::new(AtomicBool::new(true));
let alive_clone = Arc::clone(&alive);
let rx = self.catch_events();
std::thread::Builder::new()
.name("makcu-event-catch".into())
.spawn(move || {
while alive_clone.load(Ordering::Acquire) {
match rx.recv_timeout(POLL_INTERVAL) {
Ok(event) => {
if event.button == button {
f(event.pressed);
}
}
Err(crossbeam_channel::RecvTimeoutError::Timeout) => continue,
Err(crossbeam_channel::RecvTimeoutError::Disconnected) => break,
}
}
})?;
Ok(EventHandle::new(alive))
}
pub fn on_catch_event<F>(&self, f: F) -> Result<EventHandle>
where
F: Fn(CatchEvent) + Send + 'static,
{
let alive = Arc::new(AtomicBool::new(true));
let alive_clone = Arc::clone(&alive);
let rx = self.catch_events();
std::thread::Builder::new()
.name("makcu-event-catch-all".into())
.spawn(move || {
while alive_clone.load(Ordering::Acquire) {
match rx.recv_timeout(POLL_INTERVAL) {
Ok(event) => f(event),
Err(crossbeam_channel::RecvTimeoutError::Timeout) => continue,
Err(crossbeam_channel::RecvTimeoutError::Disconnected) => break,
}
}
})?;
Ok(EventHandle::new(alive))
}
}
#[cfg(feature = "async")]
use crate::device::AsyncDevice;
#[cfg(feature = "async")]
impl AsyncDevice {
pub async fn start_catch(&self, button: Button) -> Result<()> {
timed!("start_catch", {
let target = constants::button_to_lock_target(button);
self.set_lock(target, true).await?;
self.enable_catch(button).await
})
}
pub async fn stop_catch(&self, button: Button) -> Result<()> {
timed!("stop_catch", {
let target = constants::button_to_lock_target(button);
self.set_lock(target, false).await
})
}
pub async fn on_catch<F>(&self, button: Button, f: F) -> Result<EventHandle>
where
F: Fn(bool) + Send + 'static,
{
let alive = Arc::new(AtomicBool::new(true));
let alive_clone = Arc::clone(&alive);
let rx = self.catch_events();
std::thread::Builder::new()
.name("makcu-async-event-catch".into())
.spawn(move || {
while alive_clone.load(Ordering::Acquire) {
match rx.recv_timeout(POLL_INTERVAL) {
Ok(event) => {
if event.button == button {
f(event.pressed);
}
}
Err(crossbeam_channel::RecvTimeoutError::Timeout) => continue,
Err(crossbeam_channel::RecvTimeoutError::Disconnected) => break,
}
}
})?;
Ok(EventHandle::new(alive))
}
pub async fn on_catch_event<F>(&self, f: F) -> Result<EventHandle>
where
F: Fn(CatchEvent) + Send + 'static,
{
let alive = Arc::new(AtomicBool::new(true));
let alive_clone = Arc::clone(&alive);
let rx = self.catch_events();
std::thread::Builder::new()
.name("makcu-async-event-catch-all".into())
.spawn(move || {
while alive_clone.load(Ordering::Acquire) {
match rx.recv_timeout(POLL_INTERVAL) {
Ok(event) => f(event),
Err(crossbeam_channel::RecvTimeoutError::Timeout) => continue,
Err(crossbeam_channel::RecvTimeoutError::Disconnected) => break,
}
}
})?;
Ok(EventHandle::new(alive))
}
}