use std::fmt::{Debug, Formatter};
use std::os::fd::RawFd;
use std::ptr::NonNull;
use std::rc::Rc;
use std::time::Duration;
use spa_sys::{spa_interface, spa_source, spa_source_io_func_t};
use pipewire_wrapper_proc_macro::{spa_interface, RawWrapper, Wrapper};
use crate::core_api::main_loop::MainLoop;
use crate::error::Error;
use crate::spa::interface::InterfaceRef;
use crate::spa_interface_call;
use crate::wrapper::{RawWrapper, SpaInterface, Wrapper};
use crate::{i32_as_result, i32_as_void_result};
pub mod utils;
#[derive(RawWrapper, Debug)]
#[spa_interface(methods=spa_sys::spa_loop_methods)]
#[repr(transparent)]
pub struct LoopRef {
#[raw]
raw: spa_sys::spa_loop,
}
#[derive(RawWrapper, Debug)]
#[spa_interface(methods=spa_sys::spa_loop_control_methods)]
#[repr(transparent)]
pub struct LoopControlRef {
#[raw]
raw: spa_sys::spa_loop_control,
}
#[derive(RawWrapper, Debug)]
#[repr(transparent)]
pub struct SourceRef {
#[raw]
raw: spa_sys::spa_source,
}
#[derive(Wrapper)]
pub struct IOSource<'l> {
#[raw_wrapper]
ref_: NonNull<SourceRef>,
loop_: &'l dyn AsLoopRef,
callback: Box<dyn FnMut(RawFd, u32) + 'l>,
}
#[derive(Wrapper)]
pub struct IdleSource<'l> {
#[raw_wrapper]
ref_: NonNull<SourceRef>,
loop_: &'l dyn AsLoopRef,
callback: Box<dyn FnMut() + 'l>,
}
#[derive(Wrapper)]
pub struct EventSource<'l> {
#[raw_wrapper]
ref_: NonNull<SourceRef>,
loop_: &'l dyn AsLoopRef,
callback: Box<dyn FnMut(u64) + 'l>,
}
#[derive(Wrapper)]
pub struct TimerSource<'l> {
#[raw_wrapper]
ref_: NonNull<SourceRef>,
loop_: &'l dyn AsLoopRef,
callback: Box<dyn FnMut(u64) + 'l>,
}
#[derive(Wrapper)]
pub struct SignalSource<'l> {
#[raw_wrapper]
ref_: NonNull<SourceRef>,
loop_: &'l dyn AsLoopRef,
callback: Box<dyn FnMut(i32) + 'l>,
}
pub trait AsLoopRef: Debug {
fn loop_(&self) -> &LoopRef;
}
impl LoopRef {
pub fn add_source(&self, source: &SourceRef) -> crate::Result<RawFd> {
let result = spa_interface_call!(self, add_source, source.as_raw_ptr())?;
i32_as_result(result, result)
}
pub fn update_source(&self, source: &SourceRef) -> crate::Result<()> {
let result = spa_interface_call!(self, update_source, source.as_raw_ptr())?;
i32_as_void_result(result)
}
pub fn remove_source(&self, source: &SourceRef) -> crate::Result<()> {
let result = spa_interface_call!(self, remove_source, source.as_raw_ptr())?;
i32_as_void_result(result)
}
}
impl LoopControlRef {
pub fn get_fd(&self) -> crate::Result<RawFd> {
spa_interface_call!(self, get_fd)
}
pub fn enter(&self) -> crate::Result<()> {
spa_interface_call!(self, enter)
}
pub fn leave(&self) -> crate::Result<()> {
spa_interface_call!(self, leave)
}
pub fn iterate(&self, timeout: i32) -> crate::Result<i32> {
spa_interface_call!(self, iterate, timeout)
}
}
impl Drop for IOSource<'_> {
fn drop(&mut self) {
self.loop_.loop_().remove_source(self.as_ref());
}
}
impl Drop for IdleSource<'_> {
fn drop(&mut self) {
self.loop_.loop_().remove_source(self.as_ref());
}
}
impl Drop for EventSource<'_> {
fn drop(&mut self) {
self.loop_.loop_().remove_source(self.as_ref());
}
}
impl Drop for TimerSource<'_> {
fn drop(&mut self) {
self.loop_.loop_().remove_source(self.as_ref());
}
}
impl Drop for SignalSource<'_> {
fn drop(&mut self) {
self.loop_.loop_().remove_source(self.as_ref());
}
}
impl Debug for IOSource<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("IOSource")
.field("ref_", &self.ref_)
.field("loop_", &self.loop_)
.finish()
}
}
impl Debug for IdleSource<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("IdleSource")
.field("ref_", &self.ref_)
.field("loop_", &self.loop_)
.finish()
}
}
impl Debug for EventSource<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EventSource")
.field("ref_", &self.ref_)
.field("loop_", &self.loop_)
.finish()
}
}
impl Debug for TimerSource<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TimerSource")
.field("ref_", &self.ref_)
.field("loop_", &self.loop_)
.finish()
}
}
impl Debug for SignalSource<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SignalSource")
.field("ref_", &self.ref_)
.field("loop_", &self.loop_)
.finish()
}
}