use std::sync::mpsc;
use cue_sdk_sys as ffi;
use crate::callback;
use crate::device::DeviceId;
use crate::error::{self, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum MacroKeyId {
Key1 = ffi::CorsairMacroKeyId_CMKI_1,
Key2 = ffi::CorsairMacroKeyId_CMKI_2,
Key3 = ffi::CorsairMacroKeyId_CMKI_3,
Key4 = ffi::CorsairMacroKeyId_CMKI_4,
Key5 = ffi::CorsairMacroKeyId_CMKI_5,
Key6 = ffi::CorsairMacroKeyId_CMKI_6,
Key7 = ffi::CorsairMacroKeyId_CMKI_7,
Key8 = ffi::CorsairMacroKeyId_CMKI_8,
Key9 = ffi::CorsairMacroKeyId_CMKI_9,
Key10 = ffi::CorsairMacroKeyId_CMKI_10,
Key11 = ffi::CorsairMacroKeyId_CMKI_11,
Key12 = ffi::CorsairMacroKeyId_CMKI_12,
Key13 = ffi::CorsairMacroKeyId_CMKI_13,
Key14 = ffi::CorsairMacroKeyId_CMKI_14,
Key15 = ffi::CorsairMacroKeyId_CMKI_15,
Key16 = ffi::CorsairMacroKeyId_CMKI_16,
Key17 = ffi::CorsairMacroKeyId_CMKI_17,
Key18 = ffi::CorsairMacroKeyId_CMKI_18,
Key19 = ffi::CorsairMacroKeyId_CMKI_19,
Key20 = ffi::CorsairMacroKeyId_CMKI_20,
}
impl MacroKeyId {
pub(crate) fn from_ffi(raw: ffi::CorsairMacroKeyId) -> Option<Self> {
match raw {
ffi::CorsairMacroKeyId_CMKI_1 => Some(Self::Key1),
ffi::CorsairMacroKeyId_CMKI_2 => Some(Self::Key2),
ffi::CorsairMacroKeyId_CMKI_3 => Some(Self::Key3),
ffi::CorsairMacroKeyId_CMKI_4 => Some(Self::Key4),
ffi::CorsairMacroKeyId_CMKI_5 => Some(Self::Key5),
ffi::CorsairMacroKeyId_CMKI_6 => Some(Self::Key6),
ffi::CorsairMacroKeyId_CMKI_7 => Some(Self::Key7),
ffi::CorsairMacroKeyId_CMKI_8 => Some(Self::Key8),
ffi::CorsairMacroKeyId_CMKI_9 => Some(Self::Key9),
ffi::CorsairMacroKeyId_CMKI_10 => Some(Self::Key10),
ffi::CorsairMacroKeyId_CMKI_11 => Some(Self::Key11),
ffi::CorsairMacroKeyId_CMKI_12 => Some(Self::Key12),
ffi::CorsairMacroKeyId_CMKI_13 => Some(Self::Key13),
ffi::CorsairMacroKeyId_CMKI_14 => Some(Self::Key14),
ffi::CorsairMacroKeyId_CMKI_15 => Some(Self::Key15),
ffi::CorsairMacroKeyId_CMKI_16 => Some(Self::Key16),
ffi::CorsairMacroKeyId_CMKI_17 => Some(Self::Key17),
ffi::CorsairMacroKeyId_CMKI_18 => Some(Self::Key18),
ffi::CorsairMacroKeyId_CMKI_19 => Some(Self::Key19),
ffi::CorsairMacroKeyId_CMKI_20 => Some(Self::Key20),
_ => None,
}
}
}
#[derive(Debug, Clone)]
pub enum Event {
DeviceConnectionChanged {
device_id: DeviceId,
is_connected: bool,
},
KeyEvent {
device_id: DeviceId,
key_id: MacroKeyId,
is_pressed: bool,
},
}
impl Event {
pub(crate) fn from_ffi(raw: &ffi::CorsairEvent) -> Option<Self> {
match raw.id {
ffi::CorsairEventId_CEI_DeviceConnectionStatusChangedEvent => {
let inner = unsafe { &*raw.event_union.deviceConnectionStatusChangedEvent };
Some(Event::DeviceConnectionChanged {
device_id: DeviceId::from_ffi(inner.deviceId),
is_connected: inner.isConnected,
})
}
ffi::CorsairEventId_CEI_KeyEvent => {
let inner = unsafe { &*raw.event_union.keyEvent };
let key_id = MacroKeyId::from_ffi(inner.keyId)?;
Some(Event::KeyEvent {
device_id: DeviceId::from_ffi(inner.deviceId),
key_id,
is_pressed: inner.isPressed,
})
}
_ => None,
}
}
}
pub struct EventSubscription {
rx: mpsc::Receiver<Event>,
_sender: callback::EventSender,
}
impl EventSubscription {
pub(crate) fn new(sender: callback::EventSender, rx: mpsc::Receiver<Event>) -> Result<Self> {
let ctx = callback::sender_as_context(&sender);
error::check(unsafe {
ffi::CorsairSubscribeForEvents(Some(callback::event_trampoline), ctx)
})?;
Ok(Self {
rx,
_sender: sender,
})
}
pub fn recv(&self) -> Option<Event> {
self.rx.recv().ok()
}
pub fn try_recv(&self) -> Option<Event> {
self.rx.try_recv().ok()
}
pub fn iter(&self) -> impl Iterator<Item = Event> + '_ {
self.rx.iter()
}
}
impl Drop for EventSubscription {
fn drop(&mut self) {
unsafe {
let _ = ffi::CorsairUnsubscribeFromEvents();
}
}
}
#[cfg(feature = "async")]
pub struct AsyncEventSubscription {
rx: tokio::sync::mpsc::UnboundedReceiver<Event>,
_sender: callback::AsyncEventSender,
}
#[cfg(feature = "async")]
impl AsyncEventSubscription {
pub(crate) fn new(
sender: callback::AsyncEventSender,
rx: tokio::sync::mpsc::UnboundedReceiver<Event>,
) -> Result<Self> {
let ctx = callback::async_sender_as_context(&sender);
error::check(unsafe {
ffi::CorsairSubscribeForEvents(Some(callback::async_event_trampoline), ctx)
})?;
Ok(Self {
rx,
_sender: sender,
})
}
pub async fn recv(&mut self) -> Option<Event> {
self.rx.recv().await
}
}
#[cfg(feature = "async")]
impl Drop for AsyncEventSubscription {
fn drop(&mut self) {
unsafe {
let _ = ffi::CorsairUnsubscribeFromEvents();
}
}
}