1pub mod builder;
11pub mod command;
12pub mod deserialize;
13pub mod parser;
14pub mod serialize;
15
16use std::{
17 ffi::{c_char, c_void, CStr},
18 io::{Seek, Write},
19 mem::MaybeUninit,
20 os::fd::RawFd,
21 ptr::addr_of,
22};
23
24use bitflags::bitflags;
25use cookie_factory::{
26 bytes::{ne_f32, ne_f64, ne_i32, ne_i64, ne_u32},
27 gen_simple,
28 sequence::pair,
29 GenError,
30};
31use nix::errno::Errno;
32use nom::{
33 combinator::map,
34 number::{
35 complete::{f32, f64, i32, i64, u32},
36 Endianness,
37 },
38 IResult, Parser,
39};
40
41use deserialize::{BoolVisitor, NoneVisitor, PodDeserialize, PodDeserializer};
42use serialize::{PodSerialize, PodSerializer};
43
44use crate::utils::{Choice, Fd, Fraction, Id, Rectangle, SpaTypes};
45
46use self::deserialize::{
47 ChoiceBoolVisitor, ChoiceDoubleVisitor, ChoiceFdVisitor, ChoiceFloatVisitor,
48 ChoiceFractionVisitor, ChoiceIdVisitor, ChoiceIntVisitor, ChoiceLongVisitor,
49 ChoiceRectangleVisitor, DoubleVisitor, FdVisitor, FloatVisitor, FractionVisitor, IdVisitor,
50 IntVisitor, LongVisitor, PointerVisitor, RectangleVisitor,
51};
52
53#[repr(transparent)]
55pub struct Pod(spa_sys::spa_pod);
56
57impl Pod {
58 pub unsafe fn from_raw(pod: *const spa_sys::spa_pod) -> &'static Self {
73 pod.cast::<Self>().as_ref().unwrap()
74 }
75
76 pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod) -> &'static mut Self {
90 pod.cast::<Self>().as_mut().unwrap()
91 }
92
93 pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod {
94 addr_of!(self.0).cast_mut()
95 }
96
97 pub fn body(&self) -> *mut c_void {
101 unsafe {
102 self.as_raw_ptr()
103 .byte_add(std::mem::size_of::<spa_sys::spa_pod>())
104 .cast()
105 }
106 }
107
108 pub fn from_bytes(bytes: &[u8]) -> Option<&Self> {
112 const HEADER_SIZE: usize = std::mem::size_of::<spa_sys::spa_pod>();
116
117 if bytes.len() < HEADER_SIZE {
118 return None;
119 }
120
121 let pod: *const spa_sys::spa_pod = bytes.as_ptr().cast();
122
123 let size: usize = unsafe { *pod }.size.try_into().unwrap();
125
126 let padding = (8 - (size % 8)) % 8;
127
128 if HEADER_SIZE + size + padding <= bytes.len() {
130 Some(unsafe { Self::from_raw(pod) })
133 } else {
134 None
135 }
136 }
137
138 pub fn as_bytes(&self) -> &[u8] {
139 let ptr: *const u8 = self.as_raw_ptr().cast();
140 let size: usize = self.size().try_into().unwrap();
141 let size = size + std::mem::size_of::<spa_sys::spa_pod>();
142
143 unsafe { std::slice::from_raw_parts(ptr, size) }
144 }
145
146 pub fn type_(&self) -> SpaTypes {
147 SpaTypes::from_raw(self.0.type_)
148 }
149
150 pub fn size(&self) -> u32 {
151 self.0.size
152 }
153
154 pub fn is_none(&self) -> bool {
157 let res = unsafe { spa_sys::spa_pod_is_none(self.as_raw_ptr()) };
158 res != 0
159 }
160
161 pub fn is_bool(&self) -> bool {
162 let res = unsafe { spa_sys::spa_pod_is_bool(self.as_raw_ptr()) };
163 res != 0
164 }
165
166 pub fn get_bool(&self) -> Result<bool, Errno> {
167 unsafe {
168 let mut b: MaybeUninit<bool> = MaybeUninit::uninit();
169 let res = spa_sys::spa_pod_get_bool(self.as_raw_ptr(), b.as_mut_ptr());
170
171 if res >= 0 {
172 Ok(b.assume_init())
173 } else {
174 Err(Errno::from_raw(-res))
175 }
176 }
177 }
178
179 pub fn is_id(&self) -> bool {
180 let res = unsafe { spa_sys::spa_pod_is_id(self.as_raw_ptr()) };
181 res != 0
182 }
183
184 pub fn get_id(&self) -> Result<Id, Errno> {
185 unsafe {
186 let mut id: MaybeUninit<u32> = MaybeUninit::uninit();
187 let res = spa_sys::spa_pod_get_id(self.as_raw_ptr(), id.as_mut_ptr());
188
189 if res >= 0 {
190 Ok(Id(id.assume_init()))
191 } else {
192 Err(Errno::from_raw(-res))
193 }
194 }
195 }
196
197 pub fn is_int(&self) -> bool {
198 let res = unsafe { spa_sys::spa_pod_is_int(self.as_raw_ptr()) };
199 res != 0
200 }
201
202 pub fn get_int(&self) -> Result<i32, Errno> {
203 unsafe {
204 let mut int: MaybeUninit<i32> = MaybeUninit::uninit();
205 let res = spa_sys::spa_pod_get_int(self.as_raw_ptr(), int.as_mut_ptr());
206
207 if res >= 0 {
208 Ok(int.assume_init())
209 } else {
210 Err(Errno::from_raw(-res))
211 }
212 }
213 }
214
215 pub fn is_long(&self) -> bool {
216 let res = unsafe { spa_sys::spa_pod_is_long(self.as_raw_ptr()) };
217 res != 0
218 }
219
220 pub fn get_long(&self) -> Result<i64, Errno> {
221 unsafe {
222 let mut long: MaybeUninit<i64> = MaybeUninit::uninit();
223 let res = spa_sys::spa_pod_get_long(self.as_raw_ptr(), long.as_mut_ptr());
224
225 if res >= 0 {
226 Ok(long.assume_init())
227 } else {
228 Err(Errno::from_raw(-res))
229 }
230 }
231 }
232
233 pub fn is_float(&self) -> bool {
234 let res = unsafe { spa_sys::spa_pod_is_float(self.as_raw_ptr()) };
235 res != 0
236 }
237
238 pub fn get_float(&self) -> Result<f32, Errno> {
239 unsafe {
240 let mut float: MaybeUninit<f32> = MaybeUninit::uninit();
241 let res = spa_sys::spa_pod_get_float(self.as_raw_ptr(), float.as_mut_ptr());
242
243 if res >= 0 {
244 Ok(float.assume_init())
245 } else {
246 Err(Errno::from_raw(-res))
247 }
248 }
249 }
250
251 pub fn is_double(&self) -> bool {
252 let res = unsafe { spa_sys::spa_pod_is_double(self.as_raw_ptr()) };
253 res != 0
254 }
255
256 pub fn get_double(&self) -> Result<f64, Errno> {
257 unsafe {
258 let mut double: MaybeUninit<f64> = MaybeUninit::uninit();
259 let res = spa_sys::spa_pod_get_double(self.as_raw_ptr(), double.as_mut_ptr());
260
261 if res >= 0 {
262 Ok(double.assume_init())
263 } else {
264 Err(Errno::from_raw(-res))
265 }
266 }
267 }
268
269 pub fn is_string(&self) -> bool {
270 let res = unsafe { spa_sys::spa_pod_is_string(self.as_raw_ptr()) };
271 res != 0
272 }
273
274 pub fn get_string_raw(&self) -> Result<Option<&CStr>, Errno> {
275 unsafe {
276 let mut value: MaybeUninit<*const c_char> = MaybeUninit::uninit();
277 let res = spa_sys::spa_pod_get_string(self.as_raw_ptr(), value.as_mut_ptr());
278
279 if res >= 0 {
280 let value = value.assume_init();
281 if value.is_null() {
282 Ok(None)
283 } else {
284 Ok(Some(CStr::from_ptr(value)))
285 }
286 } else {
287 Err(Errno::from_raw(-res))
288 }
289 }
290 }
291
292 pub fn is_bytes(&self) -> bool {
293 let res = unsafe { spa_sys::spa_pod_is_bytes(self.as_raw_ptr()) };
294 res != 0
295 }
296
297 pub fn get_bytes(&self) -> Result<&[u8], Errno> {
298 unsafe {
299 let mut bytes: MaybeUninit<*const c_void> = MaybeUninit::uninit();
300 let mut len: MaybeUninit<u32> = MaybeUninit::uninit();
301 let res =
302 spa_sys::spa_pod_get_bytes(self.as_raw_ptr(), bytes.as_mut_ptr(), len.as_mut_ptr());
303
304 if res >= 0 {
305 let bytes = bytes.assume_init();
306 let len = len.assume_init();
307 let bytes = std::slice::from_raw_parts(bytes.cast(), len.try_into().unwrap());
308 Ok(bytes)
309 } else {
310 Err(Errno::from_raw(-res))
311 }
312 }
313 }
314
315 pub fn is_pointer(&self) -> bool {
316 let res = unsafe { spa_sys::spa_pod_is_pointer(self.as_raw_ptr()) };
317 res != 0
318 }
319
320 pub fn get_pointer(&self) -> Result<(*const c_void, Id), Errno> {
321 unsafe {
322 let mut _type: MaybeUninit<u32> = MaybeUninit::uninit();
323 let mut pointer: MaybeUninit<*const c_void> = MaybeUninit::uninit();
324 let res = spa_sys::spa_pod_get_pointer(
325 self.as_raw_ptr(),
326 _type.as_mut_ptr(),
327 pointer.as_mut_ptr(),
328 );
329
330 if res >= 0 {
331 let _type = Id(_type.assume_init());
332 let pointer = pointer.assume_init();
333 Ok((pointer, _type))
334 } else {
335 Err(Errno::from_raw(-res))
336 }
337 }
338 }
339
340 pub fn is_fd(&self) -> bool {
341 let res = unsafe { spa_sys::spa_pod_is_fd(self.as_raw_ptr()) };
342 res != 0
343 }
344
345 pub fn get_fd(&self) -> Result<RawFd, Errno> {
346 unsafe {
347 let mut fd: MaybeUninit<i64> = MaybeUninit::uninit();
348 let res = spa_sys::spa_pod_get_fd(self.as_raw_ptr(), fd.as_mut_ptr());
349
350 if res >= 0 {
351 let fd = fd.assume_init();
352 let fd: RawFd = fd.try_into().unwrap();
353 Ok(fd)
354 } else {
355 Err(Errno::from_raw(-res))
356 }
357 }
358 }
359
360 pub fn is_rectangle(&self) -> bool {
361 let res = unsafe { spa_sys::spa_pod_is_rectangle(self.as_raw_ptr()) };
362 res != 0
363 }
364
365 pub fn get_rectangle(&self) -> Result<Rectangle, Errno> {
366 unsafe {
367 let mut rectangle: MaybeUninit<spa_sys::spa_rectangle> = MaybeUninit::uninit();
368 let res = spa_sys::spa_pod_get_rectangle(self.as_raw_ptr(), rectangle.as_mut_ptr());
369
370 if res >= 0 {
371 Ok(rectangle.assume_init())
372 } else {
373 Err(Errno::from_raw(-res))
374 }
375 }
376 }
377
378 pub fn is_fraction(&self) -> bool {
379 let res = unsafe { spa_sys::spa_pod_is_fraction(self.as_raw_ptr()) };
380 res != 0
381 }
382
383 pub fn get_fraction(&self) -> Result<Fraction, Errno> {
384 unsafe {
385 let mut fraction: MaybeUninit<spa_sys::spa_fraction> = MaybeUninit::uninit();
386 let res = spa_sys::spa_pod_get_fraction(self.as_raw_ptr(), fraction.as_mut_ptr());
387
388 if res >= 0 {
389 Ok(fraction.assume_init())
390 } else {
391 Err(Errno::from_raw(-res))
392 }
393 }
394 }
395
396 pub fn is_bitmap(&self) -> bool {
397 let res = unsafe { spa_sys::spa_pod_is_bitmap(self.as_raw_ptr()) };
398 res != 0
399 }
400
401 pub fn is_array(&self) -> bool {
402 let res = unsafe { spa_sys::spa_pod_is_array(self.as_raw_ptr()) };
403 res != 0
404 }
405
406 pub fn is_choice(&self) -> bool {
407 let res = unsafe { spa_sys::spa_pod_is_choice(self.as_raw_ptr()) };
408 res != 0
409 }
410
411 pub fn is_struct(&self) -> bool {
412 let res = unsafe { spa_sys::spa_pod_is_struct(self.as_raw_ptr()) };
413 res != 0
414 }
415
416 pub fn as_struct(&self) -> Result<&PodStruct, Errno> {
417 if self.is_struct() {
418 Ok(unsafe { PodStruct::from_raw(self.as_raw_ptr() as *const spa_sys::spa_pod_struct) })
421 } else {
422 Err(Errno::EINVAL)
423 }
424 }
425
426 pub fn is_object(&self) -> bool {
427 let res = unsafe { spa_sys::spa_pod_is_object(self.as_raw_ptr()) };
428 res != 0
429 }
430
431 pub fn as_object(&self) -> Result<&PodObject, Errno> {
434 if self.is_object() {
435 Ok(unsafe { PodObject::from_raw(self.as_raw_ptr() as *const spa_sys::spa_pod_object) })
438 } else {
439 Err(Errno::EINVAL)
440 }
441 }
442
443 pub fn is_sequence(&self) -> bool {
444 let res = unsafe { spa_sys::spa_pod_is_sequence(self.as_raw_ptr()) };
445 res != 0
446 }
447}
448
449impl<'p> From<&'p PodStruct> for &'p Pod {
450 fn from(value: &'p PodStruct) -> Self {
451 value.as_pod()
452 }
453}
454
455impl<'p> From<&'p PodObject> for &'p Pod {
456 fn from(value: &'p PodObject) -> Self {
457 value.as_pod()
458 }
459}
460
461#[repr(transparent)]
463pub struct PodStruct(spa_sys::spa_pod_struct);
464
465impl PodStruct {
466 pub unsafe fn from_raw(pod: *const spa_sys::spa_pod_struct) -> &'static Self {
472 pod.cast::<Self>().as_ref().unwrap()
473 }
474
475 pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod_struct) -> &'static mut Self {
481 pod.cast::<Self>().as_mut().unwrap()
482 }
483
484 pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_struct {
485 std::ptr::addr_of!(self.0).cast_mut()
486 }
487
488 pub fn as_pod(&self) -> &Pod {
489 unsafe { Pod::from_raw(addr_of!(self.0.pod)) }
491 }
492
493 pub fn fields(&self) -> PodStructIter<'_> {
494 PodStructIter::new(self)
495 }
496}
497
498impl<'p> TryFrom<&'p Pod> for &'p PodStruct {
499 type Error = Errno;
500
501 fn try_from(value: &'p Pod) -> Result<Self, Self::Error> {
502 value.as_struct()
503 }
504}
505
506impl AsRef<Pod> for PodStruct {
507 fn as_ref(&self) -> &Pod {
508 self.as_pod()
509 }
510}
511
512pub struct PodStructIter<'s> {
513 struct_pod: &'s PodStruct,
514 next: *mut c_void,
515}
516
517impl<'s> PodStructIter<'s> {
518 fn new(struct_pod: &'s PodStruct) -> Self {
519 let first_field = struct_pod.as_pod().body();
520
521 Self {
522 struct_pod,
523 next: first_field,
524 }
525 }
526}
527
528impl<'s> Iterator for PodStructIter<'s> {
529 type Item = &'s Pod;
530
531 fn next(&mut self) -> Option<Self::Item> {
532 let has_next = unsafe {
534 spa_sys::spa_pod_is_inside(
535 self.struct_pod.as_pod().body(),
536 self.struct_pod.0.pod.size,
537 self.next,
538 )
539 };
540
541 if has_next {
542 let res = unsafe { Pod::from_raw(self.next as *const spa_sys::spa_pod) };
543
544 self.next = unsafe { spa_sys::spa_pod_next(self.next) };
546
547 Some(res)
548 } else {
549 None
550 }
551 }
552}
553
554#[repr(transparent)]
556pub struct PodObject(spa_sys::spa_pod_object);
557
558impl PodObject {
559 pub unsafe fn from_raw(pod: *const spa_sys::spa_pod_object) -> &'static Self {
565 pod.cast::<Self>().as_ref().unwrap()
566 }
567
568 pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod_object) -> &'static mut Self {
574 pod.cast::<Self>().as_mut().unwrap()
575 }
576
577 pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_object {
578 std::ptr::addr_of!(self.0).cast_mut()
579 }
580
581 pub fn as_pod(&self) -> &Pod {
582 unsafe { Pod::from_raw(addr_of!(self.0.pod)) }
584 }
585
586 pub fn type_(&self) -> SpaTypes {
587 SpaTypes::from_raw(self.0.body.type_)
588 }
589
590 pub fn id(&self) -> Id {
591 Id(self.0.body.id)
592 }
593
594 pub fn props(&self) -> PodObjectIter<'_> {
595 PodObjectIter::new(self)
596 }
597
598 pub fn find_prop(&self, key: Id) -> Option<&PodProp> {
599 let prop = unsafe {
600 spa_sys::spa_pod_object_find_prop(self.as_raw_ptr(), std::ptr::null(), key.0)
601 };
602
603 if !prop.is_null() {
604 unsafe { Some(PodProp::from_raw(prop)) }
605 } else {
606 None
607 }
608 }
609
610 pub fn fixate(&mut self) {
611 let _res = unsafe { spa_sys::spa_pod_object_fixate(self.as_raw_ptr()) };
612 }
614
615 #[cfg(feature = "v0_3_40")]
616 pub fn is_fixated(&self) -> bool {
617 let res = unsafe { spa_sys::spa_pod_object_is_fixated(self.as_raw_ptr()) };
618 res != 0
619 }
620}
621
622impl<'p> TryFrom<&'p Pod> for &'p PodObject {
623 type Error = Errno;
624
625 fn try_from(value: &'p Pod) -> Result<Self, Self::Error> {
626 value.as_object()
627 }
628}
629
630impl AsRef<Pod> for PodObject {
631 fn as_ref(&self) -> &Pod {
632 self.as_pod()
633 }
634}
635
636pub struct PodObjectIter<'o> {
637 object: &'o PodObject,
638 next: *mut spa_sys::spa_pod_prop,
639}
640
641impl<'o> PodObjectIter<'o> {
642 fn new(object: &'o PodObject) -> Self {
643 let first_prop = unsafe { spa_sys::spa_pod_prop_first(addr_of!(object.0.body)) };
644
645 Self {
646 object,
647 next: first_prop,
648 }
649 }
650}
651
652impl<'o> Iterator for PodObjectIter<'o> {
653 type Item = &'o PodProp;
654
655 fn next(&mut self) -> Option<Self::Item> {
656 let has_next = unsafe {
658 spa_sys::spa_pod_prop_is_inside(
659 addr_of!(self.object.0.body),
660 self.object.0.pod.size,
661 self.next,
662 )
663 };
664
665 if has_next {
666 let res = unsafe { PodProp::from_raw(self.next.cast_const()) };
667
668 self.next = unsafe { spa_sys::spa_pod_prop_next(self.next) };
670
671 Some(res)
672 } else {
673 None
674 }
675 }
676}
677
678bitflags! {
679 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
680 pub struct PodPropFlags: u32 {
681 const READONLY = spa_sys::SPA_POD_PROP_FLAG_READONLY;
682 const HARDWARE = spa_sys::SPA_POD_PROP_FLAG_HARDWARE;
683 const HINT_DICT = spa_sys::SPA_POD_PROP_FLAG_HINT_DICT;
684 const MANDATORY = spa_sys::SPA_POD_PROP_FLAG_MANDATORY;
685 const DONT_FIXATE = spa_sys::SPA_POD_PROP_FLAG_DONT_FIXATE;
686 }
687}
688
689#[repr(transparent)]
691pub struct PodProp(spa_sys::spa_pod_prop);
692
693impl PodProp {
694 pub unsafe fn from_raw(prop: *const spa_sys::spa_pod_prop) -> &'static Self {
701 prop.cast::<Self>().as_ref().unwrap()
702 }
703
704 pub unsafe fn from_raw_mut(prop: *mut spa_sys::spa_pod_prop) -> &'static mut Self {
711 prop.cast::<Self>().as_mut().unwrap()
712 }
713
714 pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_prop {
715 std::ptr::addr_of!(self.0).cast_mut()
716 }
717
718 pub fn key(&self) -> Id {
719 Id(self.0.key)
720 }
721
722 pub fn flags(&self) -> PodPropFlags {
723 PodPropFlags::from_bits_retain(self.0.flags)
724 }
725
726 pub fn value(&self) -> &Pod {
727 unsafe { Pod::from_raw(addr_of!(self.0.value)) }
731 }
732}
733
734pub trait CanonicalFixedSizedPod: private::CanonicalFixedSizedPodSeal {
745 #[doc(hidden)]
747 const TYPE: u32;
748 #[doc(hidden)]
750 const SIZE: u32;
751 #[doc(hidden)]
752 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError>;
753 #[doc(hidden)]
754 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
755 where
756 Self: Sized;
757}
758
759mod private {
760 pub trait CanonicalFixedSizedPodSeal {}
763 impl CanonicalFixedSizedPodSeal for () {}
764 impl CanonicalFixedSizedPodSeal for bool {}
765 impl CanonicalFixedSizedPodSeal for i32 {}
766 impl CanonicalFixedSizedPodSeal for i64 {}
767 impl CanonicalFixedSizedPodSeal for f32 {}
768 impl CanonicalFixedSizedPodSeal for f64 {}
769 impl CanonicalFixedSizedPodSeal for super::Rectangle {}
770 impl CanonicalFixedSizedPodSeal for super::Fraction {}
771 impl CanonicalFixedSizedPodSeal for super::Id {}
772 impl CanonicalFixedSizedPodSeal for super::Fd {}
773}
774
775impl<T: CanonicalFixedSizedPod + Copy> FixedSizedPod for T {
776 type CanonicalType = Self;
777
778 fn as_canonical_type(&self) -> Self::CanonicalType {
779 *self
780 }
781
782 fn from_canonical_type(canonical: &Self::CanonicalType) -> Self {
783 *canonical
784 }
785}
786
787impl CanonicalFixedSizedPod for () {
789 const TYPE: u32 = spa_sys::SPA_TYPE_None;
790 const SIZE: u32 = 0;
791
792 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
793 Ok(out)
794 }
795
796 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
797 where
798 Self: Sized,
799 {
800 Ok((input, ()))
801 }
802}
803
804impl CanonicalFixedSizedPod for bool {
806 const TYPE: u32 = spa_sys::SPA_TYPE_Bool;
807 const SIZE: u32 = 4;
808
809 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
810 gen_simple(ne_u32(u32::from(*self)), out)
811 }
812
813 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
814 where
815 Self: Sized,
816 {
817 map(u32(Endianness::Native), |b| b != 0).parse(input)
818 }
819}
820
821impl CanonicalFixedSizedPod for i32 {
823 const TYPE: u32 = spa_sys::SPA_TYPE_Int;
824 const SIZE: u32 = 4;
825
826 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
827 gen_simple(ne_i32(*self), out)
828 }
829
830 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
831 where
832 Self: Sized,
833 {
834 i32(Endianness::Native)(input)
835 }
836}
837
838impl CanonicalFixedSizedPod for i64 {
840 const TYPE: u32 = spa_sys::SPA_TYPE_Long;
841 const SIZE: u32 = 8;
842
843 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
844 gen_simple(ne_i64(*self), out)
845 }
846
847 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
848 where
849 Self: Sized,
850 {
851 i64(Endianness::Native)(input)
852 }
853}
854
855impl CanonicalFixedSizedPod for f32 {
857 const TYPE: u32 = spa_sys::SPA_TYPE_Float;
858 const SIZE: u32 = 4;
859
860 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
861 gen_simple(ne_f32(*self), out)
862 }
863
864 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
865 where
866 Self: Sized,
867 {
868 f32(Endianness::Native)(input)
869 }
870}
871
872impl CanonicalFixedSizedPod for f64 {
874 const TYPE: u32 = spa_sys::SPA_TYPE_Double;
875 const SIZE: u32 = 8;
876
877 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
878 gen_simple(ne_f64(*self), out)
879 }
880
881 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
882 where
883 Self: Sized,
884 {
885 f64(Endianness::Native)(input)
886 }
887}
888
889impl CanonicalFixedSizedPod for Rectangle {
891 const TYPE: u32 = spa_sys::SPA_TYPE_Rectangle;
892 const SIZE: u32 = 8;
893
894 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
895 gen_simple(pair(ne_u32(self.width), ne_u32(self.height)), out)
896 }
897
898 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
899 where
900 Self: Sized,
901 {
902 map(
903 nom::sequence::pair(u32(Endianness::Native), u32(Endianness::Native)),
904 |(width, height)| Rectangle { width, height },
905 )
906 .parse(input)
907 }
908}
909
910impl CanonicalFixedSizedPod for Fraction {
912 const TYPE: u32 = spa_sys::SPA_TYPE_Fraction;
913 const SIZE: u32 = 8;
914
915 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
916 gen_simple(pair(ne_u32(self.num), ne_u32(self.denom)), out)
917 }
918
919 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
920 where
921 Self: Sized,
922 {
923 map(
924 nom::sequence::pair(u32(Endianness::Native), u32(Endianness::Native)),
925 |(num, denom)| Fraction { num, denom },
926 )
927 .parse(input)
928 }
929}
930
931impl CanonicalFixedSizedPod for Id {
932 const TYPE: u32 = spa_sys::SPA_TYPE_Id;
933 const SIZE: u32 = 4;
934
935 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
936 gen_simple(ne_u32(self.0), out)
937 }
938
939 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
940 where
941 Self: Sized,
942 {
943 map(u32(Endianness::Native), Id).parse(input)
944 }
945}
946
947impl CanonicalFixedSizedPod for Fd {
948 const TYPE: u32 = spa_sys::SPA_TYPE_Fd;
949 const SIZE: u32 = 8;
950
951 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
952 gen_simple(ne_i64(self.0), out)
953 }
954
955 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
956 where
957 Self: Sized,
958 {
959 map(i64(Endianness::Native), Fd).parse(input)
960 }
961}
962
963pub trait FixedSizedPod {
1002 type CanonicalType: CanonicalFixedSizedPod;
1004
1005 fn as_canonical_type(&self) -> Self::CanonicalType;
1007 fn from_canonical_type(_: &Self::CanonicalType) -> Self;
1009}
1010
1011impl<T: FixedSizedPod> PodSerialize for T {
1012 fn serialize<O: Write + Seek>(
1013 &self,
1014 serializer: PodSerializer<O>,
1015 ) -> Result<serialize::SerializeSuccess<O>, GenError> {
1016 serializer.serialized_fixed_sized_pod(self)
1017 }
1018}
1019
1020impl<'de> PodDeserialize<'de> for () {
1021 fn deserialize(
1022 deserializer: PodDeserializer<'de>,
1023 ) -> Result<
1024 (Self, deserialize::DeserializeSuccess<'de>),
1025 deserialize::DeserializeError<&'de [u8]>,
1026 >
1027 where
1028 Self: Sized,
1029 {
1030 deserializer.deserialize_none(NoneVisitor)
1031 }
1032}
1033
1034impl<'de> PodDeserialize<'de> for bool {
1035 fn deserialize(
1036 deserializer: PodDeserializer<'de>,
1037 ) -> Result<
1038 (Self, deserialize::DeserializeSuccess<'de>),
1039 deserialize::DeserializeError<&'de [u8]>,
1040 >
1041 where
1042 Self: Sized,
1043 {
1044 deserializer.deserialize_bool(BoolVisitor)
1045 }
1046}
1047
1048impl<'de> PodDeserialize<'de> for i32 {
1049 fn deserialize(
1050 deserializer: PodDeserializer<'de>,
1051 ) -> Result<
1052 (Self, deserialize::DeserializeSuccess<'de>),
1053 deserialize::DeserializeError<&'de [u8]>,
1054 >
1055 where
1056 Self: Sized,
1057 {
1058 deserializer.deserialize_int(IntVisitor)
1059 }
1060}
1061
1062impl<'de> PodDeserialize<'de> for i64 {
1063 fn deserialize(
1064 deserializer: PodDeserializer<'de>,
1065 ) -> Result<
1066 (Self, deserialize::DeserializeSuccess<'de>),
1067 deserialize::DeserializeError<&'de [u8]>,
1068 >
1069 where
1070 Self: Sized,
1071 {
1072 deserializer.deserialize_long(LongVisitor)
1073 }
1074}
1075
1076impl<'de> PodDeserialize<'de> for f32 {
1077 fn deserialize(
1078 deserializer: PodDeserializer<'de>,
1079 ) -> Result<
1080 (Self, deserialize::DeserializeSuccess<'de>),
1081 deserialize::DeserializeError<&'de [u8]>,
1082 >
1083 where
1084 Self: Sized,
1085 {
1086 deserializer.deserialize_float(FloatVisitor)
1087 }
1088}
1089
1090impl<'de> PodDeserialize<'de> for f64 {
1091 fn deserialize(
1092 deserializer: PodDeserializer<'de>,
1093 ) -> Result<
1094 (Self, deserialize::DeserializeSuccess<'de>),
1095 deserialize::DeserializeError<&'de [u8]>,
1096 >
1097 where
1098 Self: Sized,
1099 {
1100 deserializer.deserialize_double(DoubleVisitor)
1101 }
1102}
1103
1104impl<'de> PodDeserialize<'de> for Rectangle {
1105 fn deserialize(
1106 deserializer: PodDeserializer<'de>,
1107 ) -> Result<
1108 (Self, deserialize::DeserializeSuccess<'de>),
1109 deserialize::DeserializeError<&'de [u8]>,
1110 >
1111 where
1112 Self: Sized,
1113 {
1114 deserializer.deserialize_rectangle(RectangleVisitor)
1115 }
1116}
1117
1118impl<'de> PodDeserialize<'de> for Fraction {
1119 fn deserialize(
1120 deserializer: PodDeserializer<'de>,
1121 ) -> Result<
1122 (Self, deserialize::DeserializeSuccess<'de>),
1123 deserialize::DeserializeError<&'de [u8]>,
1124 >
1125 where
1126 Self: Sized,
1127 {
1128 deserializer.deserialize_fraction(FractionVisitor)
1129 }
1130}
1131
1132impl<'de> PodDeserialize<'de> for Id {
1133 fn deserialize(
1134 deserializer: PodDeserializer<'de>,
1135 ) -> Result<
1136 (Self, deserialize::DeserializeSuccess<'de>),
1137 deserialize::DeserializeError<&'de [u8]>,
1138 >
1139 where
1140 Self: Sized,
1141 {
1142 deserializer.deserialize_id(IdVisitor)
1143 }
1144}
1145
1146impl<'de> PodDeserialize<'de> for Fd {
1147 fn deserialize(
1148 deserializer: PodDeserializer<'de>,
1149 ) -> Result<
1150 (Self, deserialize::DeserializeSuccess<'de>),
1151 deserialize::DeserializeError<&'de [u8]>,
1152 >
1153 where
1154 Self: Sized,
1155 {
1156 deserializer.deserialize_fd(FdVisitor)
1157 }
1158}
1159
1160impl<'de> PodDeserialize<'de> for Choice<bool> {
1161 fn deserialize(
1162 deserializer: PodDeserializer<'de>,
1163 ) -> Result<
1164 (Self, deserialize::DeserializeSuccess<'de>),
1165 deserialize::DeserializeError<&'de [u8]>,
1166 >
1167 where
1168 Self: Sized,
1169 {
1170 deserializer.deserialize_choice(ChoiceBoolVisitor)
1171 }
1172}
1173
1174impl<'de> PodDeserialize<'de> for Choice<i32> {
1175 fn deserialize(
1176 deserializer: PodDeserializer<'de>,
1177 ) -> Result<
1178 (Self, deserialize::DeserializeSuccess<'de>),
1179 deserialize::DeserializeError<&'de [u8]>,
1180 >
1181 where
1182 Self: Sized,
1183 {
1184 deserializer.deserialize_choice(ChoiceIntVisitor)
1185 }
1186}
1187
1188impl<'de> PodDeserialize<'de> for Choice<i64> {
1189 fn deserialize(
1190 deserializer: PodDeserializer<'de>,
1191 ) -> Result<
1192 (Self, deserialize::DeserializeSuccess<'de>),
1193 deserialize::DeserializeError<&'de [u8]>,
1194 >
1195 where
1196 Self: Sized,
1197 {
1198 deserializer.deserialize_choice(ChoiceLongVisitor)
1199 }
1200}
1201
1202impl<'de> PodDeserialize<'de> for Choice<f32> {
1203 fn deserialize(
1204 deserializer: PodDeserializer<'de>,
1205 ) -> Result<
1206 (Self, deserialize::DeserializeSuccess<'de>),
1207 deserialize::DeserializeError<&'de [u8]>,
1208 >
1209 where
1210 Self: Sized,
1211 {
1212 deserializer.deserialize_choice(ChoiceFloatVisitor)
1213 }
1214}
1215
1216impl<'de> PodDeserialize<'de> for Choice<f64> {
1217 fn deserialize(
1218 deserializer: PodDeserializer<'de>,
1219 ) -> Result<
1220 (Self, deserialize::DeserializeSuccess<'de>),
1221 deserialize::DeserializeError<&'de [u8]>,
1222 >
1223 where
1224 Self: Sized,
1225 {
1226 deserializer.deserialize_choice(ChoiceDoubleVisitor)
1227 }
1228}
1229
1230impl<'de> PodDeserialize<'de> for Choice<Id> {
1231 fn deserialize(
1232 deserializer: PodDeserializer<'de>,
1233 ) -> Result<
1234 (Self, deserialize::DeserializeSuccess<'de>),
1235 deserialize::DeserializeError<&'de [u8]>,
1236 >
1237 where
1238 Self: Sized,
1239 {
1240 deserializer.deserialize_choice(ChoiceIdVisitor)
1241 }
1242}
1243
1244impl<'de> PodDeserialize<'de> for Choice<Rectangle> {
1245 fn deserialize(
1246 deserializer: PodDeserializer<'de>,
1247 ) -> Result<
1248 (Self, deserialize::DeserializeSuccess<'de>),
1249 deserialize::DeserializeError<&'de [u8]>,
1250 >
1251 where
1252 Self: Sized,
1253 {
1254 deserializer.deserialize_choice(ChoiceRectangleVisitor)
1255 }
1256}
1257
1258impl<'de> PodDeserialize<'de> for Choice<Fraction> {
1259 fn deserialize(
1260 deserializer: PodDeserializer<'de>,
1261 ) -> Result<
1262 (Self, deserialize::DeserializeSuccess<'de>),
1263 deserialize::DeserializeError<&'de [u8]>,
1264 >
1265 where
1266 Self: Sized,
1267 {
1268 deserializer.deserialize_choice(ChoiceFractionVisitor)
1269 }
1270}
1271
1272impl<'de> PodDeserialize<'de> for Choice<Fd> {
1273 fn deserialize(
1274 deserializer: PodDeserializer<'de>,
1275 ) -> Result<
1276 (Self, deserialize::DeserializeSuccess<'de>),
1277 deserialize::DeserializeError<&'de [u8]>,
1278 >
1279 where
1280 Self: Sized,
1281 {
1282 deserializer.deserialize_choice(ChoiceFdVisitor)
1283 }
1284}
1285
1286impl<'de, T> PodDeserialize<'de> for (u32, *const T) {
1287 fn deserialize(
1288 deserializer: PodDeserializer<'de>,
1289 ) -> Result<
1290 (Self, deserialize::DeserializeSuccess<'de>),
1291 deserialize::DeserializeError<&'de [u8]>,
1292 >
1293 where
1294 Self: Sized,
1295 {
1296 deserializer.deserialize_pointer(PointerVisitor::<T>::default())
1297 }
1298}
1299
1300impl<'de> PodDeserialize<'de> for Value {
1301 fn deserialize(
1302 deserializer: PodDeserializer<'de>,
1303 ) -> Result<
1304 (Self, deserialize::DeserializeSuccess<'de>),
1305 deserialize::DeserializeError<&'de [u8]>,
1306 >
1307 where
1308 Self: Sized,
1309 {
1310 deserializer.deserialize_any()
1311 }
1312}
1313
1314#[derive(Debug, Clone, PartialEq)]
1316pub enum Value {
1317 None,
1319 Bool(bool),
1321 Id(Id),
1323 Int(i32),
1325 Long(i64),
1327 Float(f32),
1329 Double(f64),
1331 String(String),
1333 Bytes(Vec<u8>),
1335 Rectangle(Rectangle),
1337 Fraction(Fraction),
1339 Fd(Fd),
1341 ValueArray(ValueArray),
1343 Struct(Vec<Value>),
1345 Object(Object),
1347 Choice(ChoiceValue),
1349 Pointer(u32, *const c_void),
1351}
1352
1353#[derive(Debug, Clone, PartialEq)]
1355pub enum ValueArray {
1356 None(Vec<()>),
1358 Bool(Vec<bool>),
1360 Id(Vec<Id>),
1362 Int(Vec<i32>),
1364 Long(Vec<i64>),
1366 Float(Vec<f32>),
1368 Double(Vec<f64>),
1370 Rectangle(Vec<Rectangle>),
1372 Fraction(Vec<Fraction>),
1374 Fd(Vec<Fd>),
1376}
1377
1378#[derive(Debug, Clone, PartialEq)]
1380pub enum ChoiceValue {
1381 Bool(Choice<bool>),
1383 Int(Choice<i32>),
1385 Long(Choice<i64>),
1387 Float(Choice<f32>),
1389 Double(Choice<f64>),
1391 Id(Choice<Id>),
1393 Rectangle(Choice<Rectangle>),
1395 Fraction(Choice<Fraction>),
1397 Fd(Choice<Fd>),
1399}
1400
1401#[derive(Debug, Clone, PartialEq)]
1403pub struct Object {
1404 pub type_: u32,
1406 pub id: u32,
1408 pub properties: Vec<Property>,
1410}
1411
1412#[doc(hidden)]
1437#[macro_export]
1438macro_rules! __object__ {
1439 ($type_:expr, $id:expr, $($properties:expr),* $(,)?) => {
1440 pipewire::spa::pod::Object {
1441 type_: $type_.as_raw(),
1442 id: $id.as_raw(),
1443 properties: [ $( $properties, )* ].to_vec(),
1444 }
1445 };
1446}
1447#[doc(inline)]
1448pub use __object__ as object;
1449
1450#[derive(Debug, Clone, PartialEq)]
1452pub struct Property {
1453 pub key: u32,
1455 pub flags: PropertyFlags,
1457 pub value: Value,
1459}
1460
1461impl Property {
1462 pub fn new(key: u32, value: Value) -> Self {
1463 Self {
1464 key,
1465 value,
1466 flags: PropertyFlags::empty(),
1467 }
1468 }
1469}
1470
1471bitflags! {
1472 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
1474 pub struct PropertyFlags: u32 {
1475 const READONLY = spa_sys::SPA_POD_PROP_FLAG_READONLY;
1479 const HARDWARE = spa_sys::SPA_POD_PROP_FLAG_HARDWARE;
1481 const HINT_DICT = spa_sys::SPA_POD_PROP_FLAG_HINT_DICT;
1483 const MANDATORY = spa_sys::SPA_POD_PROP_FLAG_MANDATORY;
1485 #[cfg(feature = "v0_3_33")]
1487 const DONT_FIXATE = spa_sys::SPA_POD_PROP_FLAG_DONT_FIXATE;
1488 }
1489}
1490
1491#[doc(hidden)]
1513#[macro_export]
1514macro_rules! __property__ {
1515 ($key:expr, $value:expr) => {
1516 pipewire::spa::pod::Property {
1517 key: $key.as_raw(),
1518 flags: pipewire::spa::pod::PropertyFlags::empty(),
1519 value: $value,
1520 }
1521 };
1522
1523 ($key:expr, Id, $value:expr) => {
1524 pipewire::spa::pod::property!($key, pipewire::spa::pod::Value::Id(pipewire::spa::utils::Id($value.as_raw())))
1525 };
1526
1527 ($key:expr, $type_:ident, $value:expr) => {
1528 pipewire::spa::pod::property!($key, pipewire::spa::pod::Value::$type_($value))
1529 };
1530
1531 ($key:expr, Choice, Enum, Id, $default:expr, $($alternative:expr),+ $(,)?) => {
1532 pipewire::spa::pod::property!(
1533 $key,
1534 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::Id(
1535 pipewire::spa::utils::Choice::<pipewire::spa::utils::Id>(
1536 pipewire::spa::utils::ChoiceFlags::empty(),
1537 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::Id>::Enum {
1538 default: pipewire::spa::utils::Id($default.as_raw()),
1539 alternatives: [ $( pipewire::spa::utils::Id($alternative.as_raw()), )+ ].to_vec()
1540 }
1541 )
1542 ))
1543 )
1544 };
1545
1546 ($key:expr, Choice, Enum, $type_:ident, $default:expr, $($alternative:expr),+ $(,)?) => {
1547 pipewire::spa::pod::property!(
1548 $key,
1549 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
1550 pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
1551 pipewire::spa::utils::ChoiceFlags::empty(),
1552 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Enum {
1553 default: $default,
1554 alternatives: [ $( $alternative, )+ ].to_vec()
1555 }
1556 )
1557 ))
1558 )
1559 };
1560
1561 ($key:expr, Choice, Flags, $type_:ident, $default:expr, $($alternative:expr),+ $(,)?) => {
1562 pipewire::spa::pod::property!(
1563 $key,
1564 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
1565 pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
1566 pipewire::spa::utils::ChoiceFlags::empty(),
1567 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Flags {
1568 default: $default,
1569 flags: [ $( $alternative, )+ ].to_vec()
1570 }
1571 )
1572 ))
1573 )
1574 };
1575
1576 ($key:expr, Choice, Step, $type_:ident, $default:expr, $min:expr, $max:expr, $step:expr) => {
1577 pipewire::spa::pod::property!(
1578 $key,
1579 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
1580 pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
1581 pipewire::spa::utils::ChoiceFlags::empty(),
1582 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Step {
1583 default: $default,
1584 min: $min,
1585 max: $max,
1586 step: $step,
1587 }
1588 )
1589 ))
1590 )
1591 };
1592
1593 ($key:expr, Choice, Range, $type_:ident, $default:expr, $min:expr, $max:expr) => {
1594 pipewire::spa::pod::property!(
1595 $key,
1596 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
1597 pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
1598 pipewire::spa::utils::ChoiceFlags::empty(),
1599 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Range {
1600 default: $default,
1601 min: $min,
1602 max: $max,
1603 }
1604 )
1605 ))
1606 )
1607 };
1608}
1609#[doc(inline)]
1610pub use __property__ as property;