use std::pin::Pin;
use std::sync::mpsc;
use std::sync::Mutex;
use core::ffi::c_void;
use cue_sdk_sys as ffi;
use crate::event::Event;
#[derive(Debug, Clone)]
pub(crate) struct SessionStateChange {
pub state: ffi::CorsairSessionState,
pub details: ffi::CorsairSessionDetails,
}
static SESSION_STATE_TX: Mutex<Option<mpsc::Sender<SessionStateChange>>> = Mutex::new(None);
pub(crate) fn install_session_sender(tx: mpsc::Sender<SessionStateChange>) {
*SESSION_STATE_TX.lock().unwrap() = Some(tx);
}
pub(crate) fn clear_session_sender() {
*SESSION_STATE_TX.lock().unwrap() = None;
}
pub(crate) fn sender_as_context<T>(sender: &Pin<Box<mpsc::Sender<T>>>) -> *mut c_void {
let ptr: *const mpsc::Sender<T> = &**sender;
ptr as *mut c_void
}
pub(crate) unsafe extern "C" fn session_state_trampoline(
_context: *mut c_void,
event_data: *const ffi::CorsairSessionStateChanged,
) {
let data = unsafe { &*event_data };
if let Ok(guard) = SESSION_STATE_TX.lock() {
if let Some(tx) = guard.as_ref() {
let _ = tx.send(SessionStateChange {
state: data.state,
details: data.details,
});
}
}
}
pub(crate) type EventSender = Pin<Box<mpsc::Sender<Event>>>;
pub(crate) fn event_channel() -> (EventSender, mpsc::Receiver<Event>) {
let (tx, rx) = mpsc::channel();
(Box::pin(tx), rx)
}
pub(crate) unsafe extern "C" fn event_trampoline(
context: *mut c_void,
event: *const ffi::CorsairEvent,
) {
let tx = unsafe { &*(context as *const mpsc::Sender<Event>) };
let ev = unsafe { &*event };
if let Some(parsed) = Event::from_ffi(ev) {
let _ = tx.send(parsed);
}
}
pub(crate) type FlushSender = Pin<Box<mpsc::Sender<ffi::CorsairError>>>;
pub(crate) fn flush_channel() -> (FlushSender, mpsc::Receiver<ffi::CorsairError>) {
let (tx, rx) = mpsc::channel();
(Box::pin(tx), rx)
}
pub(crate) unsafe extern "C" fn flush_trampoline(context: *mut c_void, error: ffi::CorsairError) {
let tx = unsafe { &*(context as *const mpsc::Sender<ffi::CorsairError>) };
let _ = tx.send(error);
}
#[cfg(feature = "async")]
mod async_impl {
use std::pin::Pin;
use core::ffi::c_void;
use cue_sdk_sys as ffi;
use tokio::sync::mpsc as tokio_mpsc;
use crate::event::Event;
pub(crate) type AsyncEventSender = Pin<Box<tokio_mpsc::UnboundedSender<Event>>>;
pub(crate) type AsyncFlushSender = Pin<Box<tokio_mpsc::UnboundedSender<ffi::CorsairError>>>;
pub(crate) fn async_event_channel() -> (AsyncEventSender, tokio_mpsc::UnboundedReceiver<Event>)
{
let (tx, rx) = tokio_mpsc::unbounded_channel();
(Box::pin(tx), rx)
}
pub(crate) fn async_flush_channel() -> (
AsyncFlushSender,
tokio_mpsc::UnboundedReceiver<ffi::CorsairError>,
) {
let (tx, rx) = tokio_mpsc::unbounded_channel();
(Box::pin(tx), rx)
}
pub(crate) fn async_sender_as_context<T>(
sender: &Pin<Box<tokio_mpsc::UnboundedSender<T>>>,
) -> *mut c_void {
let ptr: *const tokio_mpsc::UnboundedSender<T> = &**sender;
ptr as *mut c_void
}
pub(crate) unsafe extern "C" fn async_event_trampoline(
context: *mut c_void,
event: *const ffi::CorsairEvent,
) {
let tx = unsafe { &*(context as *const tokio_mpsc::UnboundedSender<Event>) };
let ev = unsafe { &*event };
if let Some(parsed) = Event::from_ffi(ev) {
let _ = tx.send(parsed);
}
}
pub(crate) unsafe extern "C" fn async_flush_trampoline(
context: *mut c_void,
error: ffi::CorsairError,
) {
let tx = unsafe { &*(context as *const tokio_mpsc::UnboundedSender<ffi::CorsairError>) };
let _ = tx.send(error);
}
}
#[cfg(feature = "async")]
pub(crate) use async_impl::*;