pipewire/
buffer.rs

1use super::stream::Stream;
2
3use spa::buffer::meta::Metadata;
4use spa::buffer::Data;
5use std::convert::TryFrom;
6use std::ptr::NonNull;
7
8pub struct Buffer<'s> {
9    buf: NonNull<pw_sys::pw_buffer>,
10
11    /// In Pipewire, buffers are owned by the stream that generated them.
12    /// This reference ensures that this rule is respected.
13    stream: &'s Stream,
14}
15
16impl Buffer<'_> {
17    pub(crate) unsafe fn from_raw(
18        buf: *mut pw_sys::pw_buffer,
19        stream: &Stream,
20    ) -> Option<Buffer<'_>> {
21        NonNull::new(buf).map(|buf| Buffer { buf, stream })
22    }
23
24    pub fn datas_mut(&mut self) -> &mut [Data] {
25        let buffer: *mut spa_sys::spa_buffer = unsafe { self.buf.as_ref().buffer };
26
27        let slice_of_data = if !buffer.is_null()
28            && unsafe { (*buffer).n_datas > 0 && !(*buffer).datas.is_null() }
29        {
30            unsafe {
31                let datas = (*buffer).datas as *mut Data;
32                std::slice::from_raw_parts_mut(datas, usize::try_from((*buffer).n_datas).unwrap())
33            }
34        } else {
35            &mut []
36        };
37
38        slice_of_data
39    }
40
41    pub fn find_meta<T>(&self) -> Option<&T>
42    where
43        T: Metadata,
44    {
45        let buffer: *mut spa_sys::spa_buffer = unsafe { self.buf.as_ref().buffer };
46        if !buffer.is_null() && unsafe { (*buffer).n_metas != 0 } {
47            unsafe {
48                match T::META_TYPE {
49                    spa_sys::SPA_META_VideoDamage => {
50                        let meta_data =
51                            spa_sys::spa_buffer_find_meta(buffer, T::META_TYPE) as *const T;
52                        if !meta_data.is_null() {
53                            return Some(&*meta_data);
54                        }
55                    }
56                    _ => {
57                        let meta_data = spa_sys::spa_buffer_find_meta_data(
58                            buffer,
59                            T::META_TYPE,
60                            std::mem::size_of::<T>(),
61                        ) as *const T;
62                        if !meta_data.is_null() {
63                            return Some(&*meta_data);
64                        }
65                    }
66                }
67            }
68        }
69        None
70    }
71
72    #[cfg(feature = "v0_3_49")]
73    pub fn requested(&self) -> u64 {
74        unsafe { self.buf.as_ref().requested }
75    }
76}
77
78impl Drop for Buffer<'_> {
79    fn drop(&mut self) {
80        unsafe {
81            self.stream.queue_raw_buffer(self.buf.as_ptr());
82        }
83    }
84}