1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{fmt, ptr}; |
4 | |
5 | use glib::translate::{from_glib_full, from_glib_none, IntoGlibPtr, ToGlibPtr}; |
6 | |
7 | use crate::{ |
8 | ffi, format::FormattedValueIntrinsic, Buffer, BufferList, BufferListRef, BufferRef, Caps, |
9 | CapsRef, FormattedSegment, Segment, Structure, StructureRef, |
10 | }; |
11 | |
12 | mini_object_wrapper!(Sample, SampleRef, ffi::GstSample, || { |
13 | ffi::gst_sample_get_type() |
14 | }); |
15 | |
16 | #[derive (Debug, Clone)] |
17 | #[must_use = "The builder must be built to be used" ] |
18 | pub struct SampleBuilder<'a> { |
19 | buffer: Option<&'a Buffer>, |
20 | buffer_list: Option<&'a BufferList>, |
21 | caps: Option<&'a Caps>, |
22 | segment: Option<&'a Segment>, |
23 | info: Option<Structure>, |
24 | } |
25 | |
26 | impl<'a> SampleBuilder<'a> { |
27 | pub fn buffer(self, buffer: &'a Buffer) -> Self { |
28 | Self { |
29 | buffer: Some(buffer), |
30 | buffer_list: None, |
31 | ..self |
32 | } |
33 | } |
34 | |
35 | pub fn buffer_if_some(self, buffer: Option<&'a Buffer>) -> Self { |
36 | if let Some(buffer) = buffer { |
37 | self.buffer(buffer) |
38 | } else { |
39 | self |
40 | } |
41 | } |
42 | |
43 | pub fn buffer_list(self, buffer_list: &'a BufferList) -> Self { |
44 | Self { |
45 | buffer: None, |
46 | buffer_list: Some(buffer_list), |
47 | ..self |
48 | } |
49 | } |
50 | |
51 | pub fn buffer_list_if_some(self, buffer_list: Option<&'a BufferList>) -> Self { |
52 | if let Some(buffer_list) = buffer_list { |
53 | self.buffer_list(buffer_list) |
54 | } else { |
55 | self |
56 | } |
57 | } |
58 | |
59 | pub fn caps(self, caps: &'a Caps) -> Self { |
60 | Self { |
61 | caps: Some(caps), |
62 | ..self |
63 | } |
64 | } |
65 | |
66 | pub fn caps_if_some(self, caps: Option<&'a Caps>) -> Self { |
67 | if let Some(caps) = caps { |
68 | self.caps(caps) |
69 | } else { |
70 | self |
71 | } |
72 | } |
73 | |
74 | pub fn segment<F: FormattedValueIntrinsic>(self, segment: &'a FormattedSegment<F>) -> Self { |
75 | Self { |
76 | segment: Some(segment.upcast_ref()), |
77 | ..self |
78 | } |
79 | } |
80 | |
81 | pub fn segment_if_some<F: FormattedValueIntrinsic>( |
82 | self, |
83 | segment: Option<&'a FormattedSegment<F>>, |
84 | ) -> Self { |
85 | if let Some(segment) = segment { |
86 | self.segment(segment) |
87 | } else { |
88 | self |
89 | } |
90 | } |
91 | |
92 | pub fn info(self, info: Structure) -> Self { |
93 | Self { |
94 | info: Some(info), |
95 | ..self |
96 | } |
97 | } |
98 | |
99 | pub fn info_if_some(self, info: Option<Structure>) -> Self { |
100 | if let Some(info) = info { |
101 | self.info(info) |
102 | } else { |
103 | self |
104 | } |
105 | } |
106 | |
107 | #[must_use = "Building the sample without using it has no effect" ] |
108 | pub fn build(self) -> Sample { |
109 | unsafe { |
110 | let info = self |
111 | .info |
112 | .map(|i| i.into_glib_ptr()) |
113 | .unwrap_or(ptr::null_mut()); |
114 | |
115 | let sample: Sample = from_glib_full(ffi::gst_sample_new( |
116 | self.buffer.to_glib_none().0, |
117 | self.caps.to_glib_none().0, |
118 | self.segment.to_glib_none().0, |
119 | info, |
120 | )); |
121 | |
122 | if let Some(buffer_list) = self.buffer_list { |
123 | ffi::gst_sample_set_buffer_list( |
124 | sample.to_glib_none().0, |
125 | buffer_list.to_glib_none().0, |
126 | ); |
127 | } |
128 | |
129 | sample |
130 | } |
131 | } |
132 | } |
133 | |
134 | impl Sample { |
135 | pub fn builder<'a>() -> SampleBuilder<'a> { |
136 | assert_initialized_main_thread!(); |
137 | |
138 | SampleBuilder { |
139 | buffer: None, |
140 | buffer_list: None, |
141 | caps: None, |
142 | segment: None, |
143 | info: None, |
144 | } |
145 | } |
146 | } |
147 | |
148 | impl SampleRef { |
149 | #[doc (alias = "get_buffer" )] |
150 | #[doc (alias = "gst_sample_get_buffer" )] |
151 | pub fn buffer(&self) -> Option<&BufferRef> { |
152 | unsafe { |
153 | let ptr = ffi::gst_sample_get_buffer(self.as_mut_ptr()); |
154 | if ptr.is_null() { |
155 | None |
156 | } else { |
157 | Some(BufferRef::from_ptr(ptr)) |
158 | } |
159 | } |
160 | } |
161 | |
162 | #[doc (alias = "get_buffer_owned" )] |
163 | pub fn buffer_owned(&self) -> Option<Buffer> { |
164 | unsafe { self.buffer().map(|buffer| from_glib_none(buffer.as_ptr())) } |
165 | } |
166 | |
167 | #[doc (alias = "get_buffer_list" )] |
168 | #[doc (alias = "gst_sample_get_buffer_list" )] |
169 | pub fn buffer_list(&self) -> Option<&BufferListRef> { |
170 | unsafe { |
171 | let ptr = ffi::gst_sample_get_buffer_list(self.as_mut_ptr()); |
172 | if ptr.is_null() { |
173 | None |
174 | } else { |
175 | Some(BufferListRef::from_ptr(ptr)) |
176 | } |
177 | } |
178 | } |
179 | |
180 | #[doc (alias = "get_buffer_list_owned" )] |
181 | pub fn buffer_list_owned(&self) -> Option<BufferList> { |
182 | unsafe { self.buffer_list().map(|list| from_glib_none(list.as_ptr())) } |
183 | } |
184 | |
185 | #[doc (alias = "get_caps" )] |
186 | #[doc (alias = "gst_sample_get_caps" )] |
187 | pub fn caps(&self) -> Option<&CapsRef> { |
188 | unsafe { |
189 | let ptr = ffi::gst_sample_get_caps(self.as_mut_ptr()); |
190 | if ptr.is_null() { |
191 | None |
192 | } else { |
193 | Some(CapsRef::from_ptr(ptr)) |
194 | } |
195 | } |
196 | } |
197 | |
198 | #[doc (alias = "get_caps_owned" )] |
199 | pub fn caps_owned(&self) -> Option<Caps> { |
200 | unsafe { self.caps().map(|caps| from_glib_none(caps.as_ptr())) } |
201 | } |
202 | |
203 | #[doc (alias = "get_segment" )] |
204 | #[doc (alias = "gst_sample_get_segment" )] |
205 | pub fn segment(&self) -> Option<&Segment> { |
206 | unsafe { |
207 | let ptr = ffi::gst_sample_get_segment(self.as_mut_ptr()); |
208 | if ptr.is_null() { |
209 | None |
210 | } else { |
211 | Some(crate::Segment::from_glib_ptr_borrow(ptr)) |
212 | } |
213 | } |
214 | } |
215 | |
216 | #[doc (alias = "get_info" )] |
217 | #[doc (alias = "gst_sample_get_info" )] |
218 | pub fn info(&self) -> Option<&StructureRef> { |
219 | unsafe { |
220 | let ptr = ffi::gst_sample_get_info(self.as_mut_ptr()); |
221 | if ptr.is_null() { |
222 | None |
223 | } else { |
224 | Some(StructureRef::from_glib_borrow(ptr)) |
225 | } |
226 | } |
227 | } |
228 | |
229 | #[cfg (feature = "v1_16" )] |
230 | #[cfg_attr (docsrs, doc(cfg(feature = "v1_16" )))] |
231 | #[doc (alias = "gst_sample_set_buffer" )] |
232 | pub fn set_buffer(&mut self, buffer: Option<&Buffer>) { |
233 | unsafe { ffi::gst_sample_set_buffer(self.as_mut_ptr(), buffer.to_glib_none().0) } |
234 | } |
235 | |
236 | #[cfg (feature = "v1_16" )] |
237 | #[cfg_attr (docsrs, doc(cfg(feature = "v1_16" )))] |
238 | #[doc (alias = "gst_sample_set_buffer_list" )] |
239 | pub fn set_buffer_list(&mut self, buffer_list: Option<&BufferList>) { |
240 | unsafe { ffi::gst_sample_set_buffer_list(self.as_mut_ptr(), buffer_list.to_glib_none().0) } |
241 | } |
242 | |
243 | #[cfg (feature = "v1_16" )] |
244 | #[cfg_attr (docsrs, doc(cfg(feature = "v1_16" )))] |
245 | #[doc (alias = "gst_sample_set_caps" )] |
246 | pub fn set_caps(&mut self, caps: Option<&Caps>) { |
247 | unsafe { ffi::gst_sample_set_caps(self.as_mut_ptr(), caps.to_glib_none().0) } |
248 | } |
249 | |
250 | #[cfg (feature = "v1_16" )] |
251 | #[cfg_attr (docsrs, doc(cfg(feature = "v1_16" )))] |
252 | #[doc (alias = "gst_sample_set_segment" )] |
253 | pub fn set_segment(&mut self, segment: Option<&Segment>) { |
254 | unsafe { ffi::gst_sample_set_segment(self.as_mut_ptr(), segment.to_glib_none().0) } |
255 | } |
256 | |
257 | #[cfg (feature = "v1_16" )] |
258 | #[cfg_attr (docsrs, doc(cfg(feature = "v1_16" )))] |
259 | #[doc (alias = "gst_sample_set_info" )] |
260 | pub fn set_info(&mut self, info: Option<Structure>) { |
261 | unsafe { |
262 | ffi::gst_sample_set_info( |
263 | self.as_mut_ptr(), |
264 | info.map(|i| i.into_glib_ptr()).unwrap_or(ptr::null_mut()), |
265 | ); |
266 | } |
267 | } |
268 | } |
269 | |
270 | impl fmt::Debug for Sample { |
271 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
272 | SampleRef::fmt(self, f) |
273 | } |
274 | } |
275 | |
276 | impl fmt::Debug for SampleRef { |
277 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
278 | f&mut DebugStruct<'_, '_>.debug_struct("Sample" ) |
279 | .field("buffer" , &self.buffer()) |
280 | .field("caps" , &self.caps()) |
281 | .field("segment" , &self.segment()) |
282 | .field(name:"info" , &self.info()) |
283 | .finish() |
284 | } |
285 | } |
286 | |
287 | #[cfg (test)] |
288 | mod tests { |
289 | #[test ] |
290 | fn test_sample_new_with_info() { |
291 | use crate::{Sample, Structure}; |
292 | |
293 | crate::init().unwrap(); |
294 | |
295 | let info = Structure::builder("sample.info" ) |
296 | .field("f3" , 123i32) |
297 | .build(); |
298 | let sample = Sample::builder().info(info).build(); |
299 | |
300 | assert!(sample.info().is_some()); |
301 | } |
302 | } |
303 | |