use std::os::raw::c_void;
use bitflags::bitflags;
use num_derive::{FromPrimitive, ToPrimitive};
use super::{ContextInternal, Context};
use crate::operation;
use crate::callbacks::{box_closure_get_capi_ptr, MultiUseCallback};
pub use capi::context::subscribe::pa_subscription_event_type_t as EventType;
bitflags! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct InterestMaskSet: u32 {
const NULL = capi::PA_SUBSCRIPTION_MASK_NULL;
const SINK = capi::PA_SUBSCRIPTION_MASK_SINK;
const SOURCE = capi::PA_SUBSCRIPTION_MASK_SOURCE;
const SINK_INPUT = capi::PA_SUBSCRIPTION_MASK_SINK_INPUT;
const SOURCE_OUTPUT = capi::PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT;
const MODULE = capi::PA_SUBSCRIPTION_MASK_MODULE;
const CLIENT = capi::PA_SUBSCRIPTION_MASK_CLIENT;
const SAMPLE_CACHE = capi::PA_SUBSCRIPTION_MASK_SAMPLE_CACHE;
const SERVER = capi::PA_SUBSCRIPTION_MASK_SERVER;
const CARD = capi::PA_SUBSCRIPTION_MASK_CARD;
const ALL = capi::PA_SUBSCRIPTION_MASK_ALL;
}
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[derive(FromPrimitive, ToPrimitive)]
pub enum Facility {
Sink = 0,
Source = 1,
SinkInput = 2,
SourceOutput = 3,
Module = 4,
Client = 5,
SampleCache = 6,
Server = 7,
Card = 9,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[derive(FromPrimitive, ToPrimitive)]
pub enum Operation {
New = 0,
Changed = 0x10,
Removed = 0x20,
}
impl Facility {
pub const MASK: EventType = capi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
fn from_event(value: EventType) -> Option<Facility> {
match value & Self::MASK {
0 => Some(Facility::Sink),
1 => Some(Facility::Source),
2 => Some(Facility::SinkInput),
3 => Some(Facility::SourceOutput),
4 => Some(Facility::Module),
5 => Some(Facility::Client),
6 => Some(Facility::SampleCache),
7 => Some(Facility::Server),
9 => Some(Facility::Card),
_ => None,
}
}
#[inline(always)]
pub const fn to_interest_mask(self) -> InterestMaskSet {
InterestMaskSet::from_bits_truncate(1u32 << (self as u32))
}
}
impl Operation {
pub const MASK: EventType = capi::PA_SUBSCRIPTION_EVENT_TYPE_MASK;
fn from_event(value: EventType) -> Option<Operation> {
match value & Self::MASK {
0 => Some(Operation::New),
0x10 => Some(Operation::Changed),
0x20 => Some(Operation::Removed),
_ => None,
}
}
}
pub(super) type Callback = MultiUseCallback<dyn FnMut(Option<Facility>, Option<Operation>, u32),
extern "C" fn(*mut ContextInternal, EventType, u32, *mut c_void)>;
impl Context {
pub fn subscribe<F>(&mut self, mask: InterestMaskSet, callback: F)
-> operation::Operation<dyn FnMut(bool)>
where F: FnMut(bool) + 'static
{
let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
let ptr = unsafe { capi::pa_context_subscribe(self.ptr, mask.bits(),
Some(super::success_cb_proxy), cb_data) };
operation::Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
}
pub fn set_subscribe_callback(&mut self,
callback: Option<Box<dyn FnMut(Option<Facility>, Option<Operation>, u32) + 'static>>)
{
let saved = &mut self.cb_ptrs.subscribe;
*saved = Callback::new(callback);
let (cb_fn, cb_data) = saved.get_capi_params(cb_proxy);
unsafe { capi::pa_context_set_subscribe_callback(self.ptr, cb_fn, cb_data); }
}
}
extern "C"
fn cb_proxy(_: *mut ContextInternal, et: EventType, index: u32, userdata: *mut c_void) {
let _ = std::panic::catch_unwind(|| {
let facility = Facility::from_event(et);
let operation = Operation::from_event(et);
let callback = Callback::get_callback(userdata);
(callback)(facility, operation, index);
});
}