Skip to content

Instantly share code, notes, and snippets.

@saivert
Created June 5, 2023 20:01
Show Gist options
  • Save saivert/d46b947db914f829026dd0827416fa52 to your computer and use it in GitHub Desktop.
Save saivert/d46b947db914f829026dd0827416fa52 to your computer and use it in GitHub Desktop.
Serialization and Deserialization of pipewire Props
struct SomeProps {
volume: Option<f32>,
mute: Option<bool>,
channel_volumes: Option<Vec<f32>>,
}
const PROPS_KEY_CHANNEL_VOLUMES: u32 = 65544;
const PROPS_KEY_VOLUME: u32 = 65539;
const PROPS_KEY_MUTE: u32 = 65540;
impl<'de> PodDeserialize<'de> for SomeProps {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<(Self, DeserializeSuccess<'de>), DeserializeError<&'de [u8]>>
where
Self: Sized,
{
use pipewire::spa::pod::{Value, ValueArray};
struct ObjectVisitor;
impl<'de> Visitor<'de> for ObjectVisitor {
type Value = SomeProps;
type ArrayElem = std::convert::Infallible;
fn visit_object(
&self,
object_deserializer: &mut ObjectPodDeserializer<'de>,
) -> Result<Self::Value, DeserializeError<&'de [u8]>> {
let mut tmp = SomeProps {
channel_volumes: None,
volume: None,
mute: None,
};
while let Some((value, key, _flags)) =
object_deserializer.deserialize_property::<Value>()?
{
match key {
PROPS_KEY_CHANNEL_VOLUMES => {
if let Value::ValueArray(ValueArray::Float(channel_volumes)) = &value {
dbg!(channel_volumes);
tmp.channel_volumes = Some(channel_volumes.clone());
}
}
PROPS_KEY_VOLUME => {
if let Value::Float(volume) = &value {
tmp.volume = Some(volume.clone());
}
}
PROPS_KEY_MUTE => {
if let Value::Bool(mute) = &value {
tmp.mute = Some(mute.clone());
}
}
_ => {}
}
}
Ok(tmp)
}
}
deserializer.deserialize_object(ObjectVisitor)
}
}
impl PodSerialize for SomeProps {
fn serialize<O: io::Write + io::Seek>(
&self,
serializer: PodSerializer<O>,
) -> Result<SerializeSuccess<O>, GenError> {
use pipewire::spa::pod::{Value, ValueArray};
const OBJECT_TYPE_PROPS: u32 = 262146;
const OBJECT_ID_PROPS: u32 = 2;
let mut object_serializer = serializer.serialize_object(OBJECT_TYPE_PROPS, OBJECT_ID_PROPS)?;
if let Some(channel_volumes) = &self.channel_volumes {
object_serializer.serialize_property(
PROPS_KEY_CHANNEL_VOLUMES,
&Value::ValueArray(ValueArray::Float(channel_volumes.clone())),
pipewire::spa::pod::PropertyFlags::empty())?;
}
if let Some(volume) = &self.volume {
object_serializer.serialize_property(
PROPS_KEY_VOLUME,
&Value::Float(*volume),
pipewire::spa::pod::PropertyFlags::empty())?;
}
if let Some(mute) = &self.mute {
object_serializer.serialize_property(
PROPS_KEY_MUTE,
&Value::Bool(*mute),
pipewire::spa::pod::PropertyFlags::empty())?;
}
object_serializer.end()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment