use std::os::fd::RawFd;
use std::ptr::{null_mut, NonNull};
use std::rc::Rc;
use std::time::Duration;
use pipewire_wrapper_proc_macro::{spa_interface, RawWrapper};
use crate::error::Error;
use crate::i32_as_void_result;
use crate::spa::loop_::{
AsLoopRef, EventSource, IOSource, IdleSource, SignalSource, SourceRef, TimerSource,
};
use crate::spa::type_::TimespecRef;
use crate::spa_interface_call;
use crate::wrapper::{RawWrapper, SpaInterface, Wrapper};
#[derive(RawWrapper, Debug)]
#[spa_interface(methods=spa_sys::spa_loop_utils_methods)]
#[repr(transparent)]
pub struct LoopUtilsRef {
#[raw]
raw: spa_sys::spa_loop_utils,
}
impl LoopUtilsRef {
pub fn add_io<'l, F>(
&self,
loop_: &'l dyn AsLoopRef,
fd: RawFd,
mask: u32,
callback: Box<F>,
) -> crate::Result<IOSource<'l>>
where
F: FnMut(RawFd, u32),
F: 'l,
{
unsafe extern "C" fn callback_call<F>(
data: *mut ::std::os::raw::c_void,
fd: ::std::os::raw::c_int,
mask: u32,
) where
F: FnMut(RawFd, u32),
{
if let Some(callback) = (data as *mut F).as_mut() {
callback(fd, mask);
}
}
let data = &*callback as *const F as *mut _;
let func = callback_call::<F>;
let source = spa_interface_call!(self, add_io, fd, mask, false, Some(func), data)?;
Ok(IOSource {
ref_: NonNull::new(source as *mut SourceRef).unwrap(),
loop_,
callback,
})
}
pub fn update_io(&self, source: &IOSource, mask: u32) -> crate::Result<()> {
let result = spa_interface_call!(self, update_io, source.as_raw(), mask)?;
i32_as_void_result(result)
}
pub fn add_idle<'l, F>(
&self,
loop_: &'l dyn AsLoopRef,
enabled: bool,
callback: Box<F>,
) -> crate::Result<IdleSource<'l>>
where
F: FnMut(),
F: 'l,
{
unsafe extern "C" fn callback_call<F>(data: *mut ::std::os::raw::c_void)
where
F: FnMut(),
{
if let Some(callback) = (data as *mut F).as_mut() {
callback();
}
}
let data = &*callback as *const F as *mut _;
let source = spa_interface_call!(self, add_idle, enabled, Some(callback_call::<F>), data)?;
Ok(IdleSource {
ref_: NonNull::new(source as *mut SourceRef).unwrap(),
loop_,
callback,
})
}
pub fn enable_idle(&self, source: &IdleSource, enabled: bool) -> crate::Result<()> {
let result = spa_interface_call!(self, enable_idle, source.as_raw(), enabled)?;
i32_as_void_result(result)
}
pub fn add_event<'l, F>(
&self,
loop_: &'l dyn AsLoopRef,
callback: Box<F>,
) -> crate::Result<EventSource<'l>>
where
F: FnMut(u64),
F: 'l,
{
unsafe extern "C" fn callback_call<F>(data: *mut ::std::os::raw::c_void, count: u64)
where
F: FnMut(u64),
{
if let Some(callback) = (data as *mut F).as_mut() {
callback(count);
}
}
let data = &*callback as *const F as *mut _;
let source = spa_interface_call!(self, add_event, Some(callback_call::<F>), data)?;
Ok(EventSource {
ref_: NonNull::new(source as *mut SourceRef).unwrap(),
loop_,
callback,
})
}
pub fn signal_event(&self, source: &EventSource) -> crate::Result<()> {
let result = spa_interface_call!(self, signal_event, source.as_raw())?;
i32_as_void_result(result)
}
pub fn add_timer<'l, F>(
&self,
loop_: &'l dyn AsLoopRef,
callback: Box<F>,
) -> crate::Result<TimerSource<'l>>
where
F: FnMut(u64),
F: 'l,
{
unsafe extern "C" fn callback_call<F>(data: *mut ::std::os::raw::c_void, count: u64)
where
F: FnMut(u64),
{
if let Some(callback) = (data as *mut F).as_mut() {
callback(count);
}
}
let data = &*callback as *const F as *mut _;
let source = spa_interface_call!(self, add_timer, Some(callback_call::<F>), data)?;
Ok(TimerSource {
ref_: NonNull::new(source as *mut SourceRef).unwrap(),
loop_,
callback,
})
}
pub fn update_timer(
&self,
source: &TimerSource,
value: Duration,
interval: Duration,
absolute: bool,
) -> crate::Result<()> {
let value: TimespecRef = value.try_into()?;
let interval: TimespecRef = interval.try_into()?;
let result = spa_interface_call!(
self,
update_timer,
source.as_raw(),
value.as_raw_ptr(),
interval.as_raw_ptr(),
absolute
)?;
i32_as_void_result(result)
}
pub fn disable_timer(&self, source: &TimerSource) -> crate::Result<()> {
let result = spa_interface_call!(
self,
update_timer,
source.as_raw(),
null_mut(),
null_mut(),
false
)?;
i32_as_void_result(result)
}
pub fn add_signal<'l, F>(
&self,
loop_: &'l dyn AsLoopRef,
signal_number: i32,
callback: Box<F>,
) -> crate::Result<SignalSource<'l>>
where
F: FnMut(i32),
F: 'l,
{
unsafe extern "C" fn callback_call<F>(
data: *mut ::std::os::raw::c_void,
signal_number: ::std::os::raw::c_int,
) where
F: FnMut(i32),
{
if let Some(callback) = (data as *mut F).as_mut() {
callback(signal_number);
}
}
let data = &*callback as *const F as *mut _;
let source = spa_interface_call!(
self,
add_signal,
signal_number,
Some(callback_call::<F>),
data
)?;
Ok(SignalSource {
ref_: NonNull::new(source as *mut SourceRef).unwrap(),
loop_,
callback,
})
}
pub fn destroy_source(&self, source: &SourceRef) -> crate::Result<()> {
spa_interface_call!(self, destroy_source, source.as_raw_ptr())?;
Ok(())
}
}