use std::os::fd::RawFd;
use std::time::Duration;
use pipewire_wrapper_proc_macro::{spa_interface, RawWrapper};
use crate::spa;
use crate::spa::loop_::utils::LoopUtilsRef;
use crate::spa::loop_::{
AsLoopRef, EventSource, IOSource, IdleSource, LoopControlRef, SignalSource, SourceRef,
TimerSource,
};
use crate::spa::system::SystemRef;
use crate::wrapper::*;
pub mod channel;
#[derive(RawWrapper, Debug)]
#[repr(transparent)]
pub struct LoopRef {
#[raw]
raw: pw_sys::pw_loop,
}
impl LoopRef {
pub fn system(&self) -> &SystemRef {
unsafe { SystemRef::from_raw_ptr(self.raw.system) }
}
pub fn loop_(&self) -> &spa::loop_::LoopRef {
unsafe { spa::loop_::LoopRef::from_raw_ptr(self.raw.loop_) }
}
pub fn control(&self) -> &LoopControlRef {
unsafe { LoopControlRef::from_raw_ptr(self.raw.control) }
}
pub fn utils(&self) -> &LoopUtilsRef {
unsafe { LoopUtilsRef::from_raw_ptr(self.raw.utils) }
}
pub fn iter(&self, timeout_millis: i32) -> LoopRefIterator {
LoopRefIterator::new(self, timeout_millis)
}
}
impl LoopRef {
pub fn add_io<'l, F>(
&'l self,
fd: RawFd,
mask: u32,
callback: Box<F>,
) -> crate::Result<IOSource<'l>>
where
F: FnMut(RawFd, u32),
F: 'l,
{
self.utils().add_io(self, fd, mask, callback)
}
pub fn update_io(&self, source: &IOSource, mask: u32) -> crate::Result<()> {
self.utils().update_io(source, mask)
}
pub fn add_idle<'l, F>(
&'l self,
enabled: bool,
callback: Box<F>,
) -> crate::Result<IdleSource<'l>>
where
F: FnMut(),
F: 'l,
{
self.utils().add_idle(self, enabled, callback)
}
pub fn enable_idle(&self, source: &IdleSource, enabled: bool) -> crate::Result<()> {
self.utils().enable_idle(source, enabled)
}
pub fn add_event<'l, F>(&'l self, callback: Box<F>) -> crate::Result<EventSource<'l>>
where
F: FnMut(u64),
F: 'l,
{
self.utils().add_event(self, callback)
}
pub fn signal_event(&self, source: &EventSource) -> crate::Result<()> {
self.utils().signal_event(source)
}
pub fn add_timer<'l, F>(&'l self, callback: Box<F>) -> crate::Result<TimerSource<'l>>
where
F: FnMut(u64),
F: 'l,
{
self.utils().add_timer(self, callback)
}
pub fn update_timer(
&self,
source: &TimerSource,
value: Duration,
interval: Duration,
absolute: bool,
) -> crate::Result<()> {
self.utils().update_timer(source, value, interval, absolute)
}
pub fn disable_timer(&self, source: &TimerSource) -> crate::Result<()> {
self.utils().disable_timer(source)
}
pub fn add_signal<'l, F>(
&'l self,
signal_number: i32,
callback: Box<F>,
) -> crate::Result<SignalSource<'l>>
where
F: FnMut(i32),
F: 'l,
{
self.utils().add_signal(self, signal_number, callback)
}
pub fn destroy_source(&self, source: &SourceRef) -> crate::Result<()> {
self.utils().destroy_source(source)
}
}
pub struct LoopRefIterator<'a> {
loop_ref: &'a LoopRef,
timeout_millis: i32,
}
impl<'a> LoopRefIterator<'a> {
fn new(loop_ref: &'a LoopRef, timeout_millis: i32) -> Self {
unsafe {
loop_ref.control().enter();
}
LoopRefIterator {
timeout_millis,
loop_ref,
}
}
pub fn set_timeout(&mut self, timeout_millis: i32) {
self.timeout_millis = timeout_millis;
}
}
impl Iterator for LoopRefIterator<'_> {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
let timeout_millis = self.timeout_millis;
let result = unsafe { self.loop_ref.control().iterate(timeout_millis) };
if let Ok(result) = result {
if result >= 0 {
return Some(result);
}
}
None
}
}
impl Drop for LoopRefIterator<'_> {
fn drop(&mut self) {
unsafe {
self.loop_ref.control().leave();
}
}
}
impl AsLoopRef for LoopRef {
fn loop_(&self) -> &spa::loop_::LoopRef {
self.loop_()
}
}