use std::fmt::{Debug, Formatter};
use std::mem::size_of;
use std::ptr::addr_of;
use pipewire_wrapper_proc_macro::RawWrapper;
use crate::enum_wrapper;
use crate::spa::pod::bytes::PodBytesRef;
use crate::spa::pod::iterator::PodIterator;
use crate::spa::pod::object::prop::ObjectPropType;
use crate::spa::pod::object::PodPropRef;
use crate::spa::pod::restricted::PodRawValue;
use crate::spa::pod::{BasicTypePod, PodError, PodRef, PodResult, PodValue, SizedPod};
use crate::wrapper::RawWrapper;
#[derive(RawWrapper)]
#[repr(transparent)]
pub struct PodControlRef {
#[raw]
raw: spa_sys::spa_pod_control,
}
impl Debug for PodControlRef {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PodControlRef")
.field("type", &self.type_())
.field("offset", &self.raw.offset)
.field("value", &self.value())
.finish()
}
}
impl SizedPod for PodControlRef {
fn pod_size(&self) -> usize {
size_of::<PodControlRef>() + self.raw.value.size as usize
}
}
impl PodControlRef {
fn type_(&self) -> Type {
Type::from_raw(self.raw.type_)
}
fn value_pod(&self) -> &PodRef {
unsafe { PodRef::from_raw_ptr(addr_of!(self.raw.value)) }
}
fn content_size(&self) -> usize {
self.raw.value.size as usize
}
}
#[repr(u32)]
#[derive(Debug)]
pub enum ControlType<'a> {
INVALID = Type::INVALID.raw,
PROPERTIES(PodIterator<'a, PodPropRef<'a, ObjectPropType<'a>>>) = Type::PROPERTIES.raw,
MIDI(&'a PodBytesRef) = Type::MIDI.raw,
OSC(&'a PodBytesRef) = Type::OSC.raw,
}
impl<'a> PodRawValue for &'a PodControlRef {
type RawValue = spa_sys::spa_pod_control;
fn raw_value_ptr(&self) -> *const Self::RawValue {
&self.raw
}
fn parse_raw_value(ptr: *const Self::RawValue, _size: usize) -> PodResult<Self::Value> {
let control = unsafe { PodControlRef::from_raw_ptr(ptr) };
match control.type_() {
Type::INVALID => Ok(ControlType::INVALID),
Type::PROPERTIES => Ok(ControlType::PROPERTIES(PodIterator::from_container(
control,
))),
Type::MIDI => control.value_pod().cast().map(ControlType::MIDI),
Type::OSC => control.value_pod().cast().map(ControlType::OSC),
type_ => Err(PodError::UnexpectedControlType(type_.raw)),
}
}
}
impl<'a> PodValue for &'a PodControlRef {
type Value = ControlType<'a>;
fn value(&self) -> PodResult<Self::Value> {
Self::parse_raw_value(
&self.raw,
size_of::<<Self as PodRawValue>::RawValue>() + self.raw.value.size as usize,
)
}
}
enum_wrapper!(
Type,
spa_sys::spa_control_type,
INVALID: spa_sys::SPA_CONTROL_Invalid,
PROPERTIES: spa_sys::SPA_CONTROL_Properties,
MIDI: spa_sys::SPA_CONTROL_Midi,
OSC: spa_sys::SPA_CONTROL_OSC,
_LAST: spa_sys::_SPA_CONTROL_LAST,
);