1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{fmt, marker::PhantomData, ptr, str}; |
4 | |
5 | use glib::{ |
6 | prelude::*, |
7 | translate::*, |
8 | value::{SendValue, ToSendValue}, |
9 | }; |
10 | |
11 | use crate::{caps_features::*, ffi, structure::*, CapsIntersectMode}; |
12 | |
13 | mini_object_wrapper!(Caps, CapsRef, ffi::GstCaps, || { ffi::gst_caps_get_type() }); |
14 | |
15 | impl Caps { |
16 | #[doc (alias = "gst_caps_new_simple" )] |
17 | pub fn builder(name: impl IntoGStr) -> Builder<NoFeature> { |
18 | assert_initialized_main_thread!(); |
19 | Builder::new(name) |
20 | } |
21 | |
22 | #[doc (alias = "gst_caps_new_full" )] |
23 | pub fn builder_full() -> BuilderFull<SomeFeatures> { |
24 | assert_initialized_main_thread!(); |
25 | BuilderFull::new() |
26 | } |
27 | |
28 | #[doc (alias = "gst_caps_new_full" )] |
29 | pub fn builder_full_with_features(features: CapsFeatures) -> BuilderFull<SomeFeatures> { |
30 | assert_initialized_main_thread!(); |
31 | BuilderFull::with_features(features) |
32 | } |
33 | |
34 | #[doc (alias = "gst_caps_new_full" )] |
35 | pub fn builder_full_with_any_features() -> BuilderFull<AnyFeatures> { |
36 | assert_initialized_main_thread!(); |
37 | BuilderFull::with_any_features() |
38 | } |
39 | |
40 | #[doc (alias = "gst_caps_new_empty" )] |
41 | pub fn new_empty() -> Self { |
42 | assert_initialized_main_thread!(); |
43 | unsafe { from_glib_full(ffi::gst_caps_new_empty()) } |
44 | } |
45 | |
46 | #[doc (alias = "gst_caps_new_any" )] |
47 | pub fn new_any() -> Self { |
48 | assert_initialized_main_thread!(); |
49 | unsafe { from_glib_full(ffi::gst_caps_new_any()) } |
50 | } |
51 | |
52 | #[doc (alias = "gst_caps_new_empty_simple" )] |
53 | pub fn new_empty_simple(name: impl IntoGStr) -> Self { |
54 | skip_assert_initialized!(); |
55 | let mut caps = Caps::new_empty(); |
56 | |
57 | let structure = Structure::new_empty(name); |
58 | caps.get_mut().unwrap().append_structure(structure); |
59 | |
60 | caps |
61 | } |
62 | |
63 | #[doc (alias = "gst_caps_fixate" )] |
64 | pub fn fixate(&mut self) { |
65 | unsafe { |
66 | // See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/388 |
67 | assert!(!self.is_any()); |
68 | let ptr = if self.is_empty() { |
69 | ffi::gst_caps_new_empty() |
70 | } else { |
71 | ffi::gst_caps_fixate(self.as_mut_ptr()) |
72 | }; |
73 | self.replace_ptr(ptr); |
74 | } |
75 | } |
76 | |
77 | #[doc (alias = "gst_caps_merge" )] |
78 | pub fn merge(&mut self, other: Self) { |
79 | unsafe { |
80 | let ptr = ffi::gst_caps_merge(self.as_mut_ptr(), other.into_glib_ptr()); |
81 | self.replace_ptr(ptr); |
82 | } |
83 | } |
84 | |
85 | #[doc (alias = "gst_caps_merge_structure" )] |
86 | pub fn merge_structure(&mut self, structure: Structure) { |
87 | unsafe { |
88 | let ptr = ffi::gst_caps_merge_structure(self.as_mut_ptr(), structure.into_glib_ptr()); |
89 | self.replace_ptr(ptr); |
90 | } |
91 | } |
92 | |
93 | #[doc (alias = "gst_caps_merge_structure_full" )] |
94 | pub fn merge_structure_full(&mut self, structure: Structure, features: Option<CapsFeatures>) { |
95 | unsafe { |
96 | let ptr = ffi::gst_caps_merge_structure_full( |
97 | self.as_mut_ptr(), |
98 | structure.into_glib_ptr(), |
99 | features |
100 | .map(|f| f.into_glib_ptr()) |
101 | .unwrap_or(ptr::null_mut()), |
102 | ); |
103 | self.replace_ptr(ptr); |
104 | } |
105 | } |
106 | |
107 | #[doc (alias = "gst_caps_normalize" )] |
108 | pub fn normalize(&mut self) { |
109 | unsafe { |
110 | let ptr = ffi::gst_caps_normalize(self.as_mut_ptr()); |
111 | self.replace_ptr(ptr); |
112 | } |
113 | } |
114 | |
115 | #[doc (alias = "gst_caps_simplify" )] |
116 | pub fn simplify(&mut self) { |
117 | unsafe { |
118 | let ptr = ffi::gst_caps_simplify(self.as_mut_ptr()); |
119 | self.replace_ptr(ptr); |
120 | } |
121 | } |
122 | |
123 | #[doc (alias = "gst_caps_truncate" )] |
124 | pub fn truncate(&mut self) { |
125 | unsafe { |
126 | let ptr = ffi::gst_caps_truncate(self.as_mut_ptr()); |
127 | self.replace_ptr(ptr); |
128 | } |
129 | } |
130 | } |
131 | |
132 | impl str::FromStr for Caps { |
133 | type Err = glib::BoolError; |
134 | |
135 | #[doc (alias = "gst_caps_from_string" )] |
136 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
137 | assert_initialized_main_thread!(); |
138 | unsafe { |
139 | s.run_with_gstr(|s: &GStr| { |
140 | Option::<_>::from_glib_full(ffi::gst_caps_from_string(s.as_ptr())) |
141 | .ok_or_else(|| glib::bool_error!("Failed to parse caps from string" )) |
142 | }) |
143 | } |
144 | } |
145 | } |
146 | |
147 | impl From<Structure> for Caps { |
148 | fn from(v: Structure) -> Caps { |
149 | skip_assert_initialized!(); |
150 | let mut caps: Caps = Caps::new_empty(); |
151 | |
152 | { |
153 | let caps: &mut CapsRef = caps.get_mut().unwrap(); |
154 | caps.append_structure(v); |
155 | } |
156 | |
157 | caps |
158 | } |
159 | } |
160 | |
161 | impl<const N: usize> From<[Structure; N]> for Caps { |
162 | fn from(v: [Structure; N]) -> Caps { |
163 | skip_assert_initialized!(); |
164 | let mut caps: Caps = Caps::new_empty(); |
165 | |
166 | { |
167 | let caps: &mut CapsRef = caps.get_mut().unwrap(); |
168 | v.into_iter().for_each(|s: Structure| caps.append_structure(s)); |
169 | } |
170 | |
171 | caps |
172 | } |
173 | } |
174 | |
175 | impl From<(Structure, CapsFeatures)> for Caps { |
176 | fn from(v: (Structure, CapsFeatures)) -> Caps { |
177 | skip_assert_initialized!(); |
178 | let mut caps: Caps = Caps::new_empty(); |
179 | |
180 | { |
181 | let caps: &mut CapsRef = caps.get_mut().unwrap(); |
182 | caps.append_structure_full(structure:v.0, features:Some(v.1)); |
183 | } |
184 | |
185 | caps |
186 | } |
187 | } |
188 | |
189 | impl<const N: usize> From<[(Structure, CapsFeatures); N]> for Caps { |
190 | fn from(v: [(Structure, CapsFeatures); N]) -> Caps { |
191 | skip_assert_initialized!(); |
192 | let mut caps: Caps = Caps::new_empty(); |
193 | |
194 | { |
195 | let caps: &mut CapsRef = caps.get_mut().unwrap(); |
196 | vIntoIter<(Structure, CapsFeatures), N>.into_iter() |
197 | .for_each(|s: (Structure, CapsFeatures)| caps.append_structure_full(structure:s.0, features:Some(s.1))); |
198 | } |
199 | |
200 | caps |
201 | } |
202 | } |
203 | |
204 | impl<const N: usize> From<[(Structure, Option<CapsFeatures>); N]> for Caps { |
205 | fn from(v: [(Structure, Option<CapsFeatures>); N]) -> Caps { |
206 | skip_assert_initialized!(); |
207 | let mut caps: Caps = Caps::new_empty(); |
208 | |
209 | { |
210 | let caps: &mut CapsRef = caps.get_mut().unwrap(); |
211 | vIntoIter<(Structure, Option<…>), N>.into_iter() |
212 | .for_each(|s: (Structure, Option)| caps.append_structure_full(structure:s.0, features:s.1)); |
213 | } |
214 | |
215 | caps |
216 | } |
217 | } |
218 | |
219 | impl std::iter::FromIterator<Structure> for Caps { |
220 | fn from_iter<T: IntoIterator<Item = Structure>>(iter: T) -> Self { |
221 | skip_assert_initialized!(); |
222 | let mut caps: Caps = Caps::new_empty(); |
223 | |
224 | { |
225 | let caps: &mut CapsRef = caps.get_mut().unwrap(); |
226 | iter.into_iter().for_each(|s: Structure| caps.append_structure(s)); |
227 | } |
228 | |
229 | caps |
230 | } |
231 | } |
232 | |
233 | impl std::iter::FromIterator<(Structure, CapsFeatures)> for Caps { |
234 | fn from_iter<T: IntoIterator<Item = (Structure, CapsFeatures)>>(iter: T) -> Self { |
235 | skip_assert_initialized!(); |
236 | let mut caps: Caps = Caps::new_empty(); |
237 | |
238 | { |
239 | let caps: &mut CapsRef = caps.get_mut().unwrap(); |
240 | iter::IntoIter.into_iter() |
241 | .for_each(|(s: Structure, f: CapsFeatures)| caps.append_structure_full(structure:s, features:Some(f))); |
242 | } |
243 | |
244 | caps |
245 | } |
246 | } |
247 | |
248 | impl std::iter::FromIterator<(Structure, Option<CapsFeatures>)> for Caps { |
249 | fn from_iter<T: IntoIterator<Item = (Structure, Option<CapsFeatures>)>>(iter: T) -> Self { |
250 | skip_assert_initialized!(); |
251 | let mut caps: Caps = Caps::new_empty(); |
252 | |
253 | { |
254 | let caps: &mut CapsRef = caps.get_mut().unwrap(); |
255 | iter::IntoIter.into_iter() |
256 | .for_each(|(s: Structure, f: Option)| caps.append_structure_full(structure:s, features:f)); |
257 | } |
258 | |
259 | caps |
260 | } |
261 | } |
262 | |
263 | impl std::iter::FromIterator<Caps> for Caps { |
264 | fn from_iter<T: IntoIterator<Item = Caps>>(iter: T) -> Self { |
265 | skip_assert_initialized!(); |
266 | let mut caps: Caps = Caps::new_empty(); |
267 | |
268 | { |
269 | let caps: &mut CapsRef = caps.get_mut().unwrap(); |
270 | iter::IntoIter.into_iter() |
271 | .for_each(|other_caps: Caps| caps.append(other_caps)); |
272 | } |
273 | |
274 | caps |
275 | } |
276 | } |
277 | |
278 | impl std::iter::Extend<Structure> for CapsRef { |
279 | fn extend<T: IntoIterator<Item = Structure>>(&mut self, iter: T) { |
280 | iter.into_iter().for_each(|s: Structure| self.append_structure(s)); |
281 | } |
282 | } |
283 | |
284 | impl std::iter::Extend<(Structure, CapsFeatures)> for CapsRef { |
285 | fn extend<T: IntoIterator<Item = (Structure, CapsFeatures)>>(&mut self, iter: T) { |
286 | iter::IntoIter.into_iter() |
287 | .for_each(|(s: Structure, f: CapsFeatures)| self.append_structure_full(structure:s, features:Some(f))); |
288 | } |
289 | } |
290 | |
291 | impl std::iter::Extend<(Structure, Option<CapsFeatures>)> for CapsRef { |
292 | fn extend<T: IntoIterator<Item = (Structure, Option<CapsFeatures>)>>(&mut self, iter: T) { |
293 | iter::IntoIter.into_iter() |
294 | .for_each(|(s: Structure, f: Option)| self.append_structure_full(structure:s, features:f)); |
295 | } |
296 | } |
297 | |
298 | impl std::iter::Extend<Caps> for CapsRef { |
299 | fn extend<T: IntoIterator<Item = Caps>>(&mut self, iter: T) { |
300 | iter.into_iter().for_each(|caps: Caps| self.append(caps)); |
301 | } |
302 | } |
303 | |
304 | impl CapsRef { |
305 | // rustdoc-stripper-ignore-next |
306 | /// Sets field `name` to the given value `value`. |
307 | /// |
308 | /// Overrides any default or previously defined value for `name`. |
309 | #[doc (alias = "gst_caps_set_value" )] |
310 | #[doc (alias = "gst_caps_set_simple" )] |
311 | pub fn set(&mut self, name: impl IntoGStr, value: impl ToSendValue + Sync) { |
312 | let value = value.to_send_value(); |
313 | self.set_value(name, value); |
314 | } |
315 | |
316 | // rustdoc-stripper-ignore-next |
317 | /// Sets field `name` to the given value if the `predicate` evaluates to `true`. |
318 | /// |
319 | /// This has no effect if the `predicate` evaluates to `false`, |
320 | /// i.e. default or previous value for `name` is kept. |
321 | #[doc (alias = "gst_caps_set_value" )] |
322 | #[doc (alias = "gst_caps_set_simple" )] |
323 | pub fn set_if(&mut self, name: impl IntoGStr, value: impl ToSendValue + Sync, predicate: bool) { |
324 | if predicate { |
325 | self.set(name, value); |
326 | } |
327 | } |
328 | |
329 | // rustdoc-stripper-ignore-next |
330 | /// Sets field `name` to the given inner value if `value` is `Some`. |
331 | /// |
332 | /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept. |
333 | #[doc (alias = "gst_caps_set_value" )] |
334 | #[doc (alias = "gst_caps_set_simple" )] |
335 | pub fn set_if_some(&mut self, name: impl IntoGStr, value: Option<impl ToSendValue + Sync>) { |
336 | if let Some(value) = value { |
337 | self.set(name, value); |
338 | } |
339 | } |
340 | |
341 | // rustdoc-stripper-ignore-next |
342 | /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s. |
343 | /// |
344 | /// Overrides any default or previously defined value for `name`. |
345 | #[inline ] |
346 | pub fn set_from_iter<V: ValueType + ToSendValue + FromIterator<SendValue> + Sync>( |
347 | &mut self, |
348 | name: impl IntoGStr, |
349 | iter: impl IntoIterator<Item = impl ToSendValue>, |
350 | ) { |
351 | let iter = iter.into_iter().map(|item| item.to_send_value()); |
352 | self.set(name, V::from_iter(iter)); |
353 | } |
354 | |
355 | // rustdoc-stripper-ignore-next |
356 | /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s, |
357 | /// if `iter` is not empty. |
358 | /// |
359 | /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged. |
360 | #[inline ] |
361 | pub fn set_if_not_empty<V: ValueType + ToSendValue + FromIterator<SendValue> + Sync>( |
362 | &mut self, |
363 | name: impl IntoGStr, |
364 | iter: impl IntoIterator<Item = impl ToSendValue>, |
365 | ) { |
366 | let mut iter = iter.into_iter().peekable(); |
367 | if iter.peek().is_some() { |
368 | let iter = iter.map(|item| item.to_send_value()); |
369 | self.set(name, V::from_iter(iter)); |
370 | } |
371 | } |
372 | |
373 | // rustdoc-stripper-ignore-next |
374 | /// Sets field `name` to the given value `value`. |
375 | /// |
376 | /// Overrides any default or previously defined value for `name`. |
377 | #[doc (alias = "gst_caps_set_value" )] |
378 | pub fn set_value(&mut self, name: impl IntoGStr, value: glib::SendValue) { |
379 | unsafe { |
380 | name.run_with_gstr(|name| { |
381 | ffi::gst_caps_set_value(self.as_mut_ptr(), name.as_ptr(), value.to_glib_none().0) |
382 | }); |
383 | } |
384 | } |
385 | |
386 | // rustdoc-stripper-ignore-next |
387 | /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`. |
388 | /// |
389 | /// This has no effect if the `predicate` evaluates to `false`, |
390 | /// i.e. default or previous value for `name` is kept. |
391 | #[doc (alias = "gst_caps_set_value" )] |
392 | pub fn set_value_if(&mut self, name: impl IntoGStr, value: SendValue, predicate: bool) { |
393 | if predicate { |
394 | self.set_value(name, value); |
395 | } |
396 | } |
397 | |
398 | // rustdoc-stripper-ignore-next |
399 | /// Sets field `name` to the given inner value if `value` is `Some`. |
400 | /// |
401 | /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept. |
402 | #[doc (alias = "gst_caps_set_value" )] |
403 | pub fn set_value_if_some(&mut self, name: impl IntoGStr, value: Option<SendValue>) { |
404 | if let Some(value) = value { |
405 | self.set_value(name, value); |
406 | } |
407 | } |
408 | |
409 | #[doc (alias = "get_structure" )] |
410 | #[doc (alias = "gst_caps_get_structure" )] |
411 | pub fn structure(&self, idx: usize) -> Option<&StructureRef> { |
412 | if idx >= self.size() { |
413 | return None; |
414 | } |
415 | |
416 | unsafe { |
417 | let structure = ffi::gst_caps_get_structure(self.as_ptr(), idx as u32); |
418 | if structure.is_null() { |
419 | return None; |
420 | } |
421 | |
422 | Some(StructureRef::from_glib_borrow(structure)) |
423 | } |
424 | } |
425 | |
426 | #[doc (alias = "get_mut_structure" )] |
427 | #[doc (alias = "gst_caps_get_structure" )] |
428 | pub fn structure_mut(&mut self, idx: usize) -> Option<&mut StructureRef> { |
429 | if idx >= self.size() { |
430 | return None; |
431 | } |
432 | |
433 | unsafe { |
434 | let structure = ffi::gst_caps_get_structure(self.as_ptr(), idx as u32); |
435 | if structure.is_null() { |
436 | return None; |
437 | } |
438 | |
439 | Some(StructureRef::from_glib_borrow_mut(structure)) |
440 | } |
441 | } |
442 | |
443 | #[doc (alias = "get_features" )] |
444 | #[doc (alias = "gst_caps_get_features" )] |
445 | pub fn features(&self, idx: usize) -> Option<&CapsFeaturesRef> { |
446 | if idx >= self.size() { |
447 | return None; |
448 | } |
449 | |
450 | unsafe { |
451 | let features = ffi::gst_caps_get_features(self.as_ptr(), idx as u32); |
452 | Some(CapsFeaturesRef::from_glib_borrow(features)) |
453 | } |
454 | } |
455 | |
456 | #[doc (alias = "get_mut_features" )] |
457 | #[doc (alias = "gst_caps_get_features" )] |
458 | pub fn features_mut(&mut self, idx: usize) -> Option<&mut CapsFeaturesRef> { |
459 | if idx >= self.size() { |
460 | return None; |
461 | } |
462 | |
463 | unsafe { |
464 | let features = ffi::gst_caps_get_features(self.as_ptr(), idx as u32); |
465 | Some(CapsFeaturesRef::from_glib_borrow_mut(features)) |
466 | } |
467 | } |
468 | |
469 | #[doc (alias = "gst_caps_set_features" )] |
470 | pub fn set_features(&mut self, idx: usize, features: Option<CapsFeatures>) { |
471 | assert!(idx < self.size()); |
472 | |
473 | unsafe { |
474 | ffi::gst_caps_set_features( |
475 | self.as_mut_ptr(), |
476 | idx as u32, |
477 | features |
478 | .map(|f| f.into_glib_ptr()) |
479 | .unwrap_or(ptr::null_mut()), |
480 | ) |
481 | } |
482 | } |
483 | |
484 | #[cfg (feature = "v1_16" )] |
485 | #[cfg_attr (docsrs, doc(cfg(feature = "v1_16" )))] |
486 | #[doc (alias = "gst_caps_set_features_simple" )] |
487 | pub fn set_features_simple(&mut self, features: Option<CapsFeatures>) { |
488 | unsafe { |
489 | ffi::gst_caps_set_features_simple( |
490 | self.as_mut_ptr(), |
491 | features |
492 | .map(|f| f.into_glib_ptr()) |
493 | .unwrap_or(ptr::null_mut()), |
494 | ) |
495 | } |
496 | } |
497 | |
498 | #[doc (alias = "get_size" )] |
499 | #[doc (alias = "gst_caps_get_size" )] |
500 | pub fn size(&self) -> usize { |
501 | unsafe { ffi::gst_caps_get_size(self.as_ptr()) as usize } |
502 | } |
503 | |
504 | pub fn len(&self) -> usize { |
505 | self.size() |
506 | } |
507 | |
508 | pub fn iter(&self) -> Iter { |
509 | Iter::new(self) |
510 | } |
511 | |
512 | pub fn iter_mut(&mut self) -> IterMut { |
513 | IterMut::new(self) |
514 | } |
515 | |
516 | pub fn iter_with_features(&self) -> IterFeatures { |
517 | IterFeatures::new(self) |
518 | } |
519 | |
520 | pub fn iter_with_features_mut(&mut self) -> IterFeaturesMut { |
521 | IterFeaturesMut::new(self) |
522 | } |
523 | |
524 | #[doc (alias = "gst_caps_append_structure" )] |
525 | pub fn append_structure(&mut self, structure: Structure) { |
526 | unsafe { ffi::gst_caps_append_structure(self.as_mut_ptr(), structure.into_glib_ptr()) } |
527 | } |
528 | |
529 | #[doc (alias = "gst_caps_append_structure_full" )] |
530 | pub fn append_structure_full(&mut self, structure: Structure, features: Option<CapsFeatures>) { |
531 | unsafe { |
532 | ffi::gst_caps_append_structure_full( |
533 | self.as_mut_ptr(), |
534 | structure.into_glib_ptr(), |
535 | features |
536 | .map(|f| f.into_glib_ptr()) |
537 | .unwrap_or(ptr::null_mut()), |
538 | ) |
539 | } |
540 | } |
541 | |
542 | #[doc (alias = "gst_caps_remove_structure" )] |
543 | pub fn remove_structure(&mut self, idx: usize) { |
544 | assert!(idx < self.size()); |
545 | |
546 | unsafe { ffi::gst_caps_remove_structure(self.as_mut_ptr(), idx as u32) } |
547 | } |
548 | |
549 | #[doc (alias = "gst_caps_append" )] |
550 | pub fn append(&mut self, other: Caps) { |
551 | unsafe { ffi::gst_caps_append(self.as_mut_ptr(), other.into_glib_ptr()) } |
552 | } |
553 | |
554 | #[doc (alias = "gst_caps_can_intersect" )] |
555 | pub fn can_intersect(&self, other: &Self) -> bool { |
556 | unsafe { from_glib(ffi::gst_caps_can_intersect(self.as_ptr(), other.as_ptr())) } |
557 | } |
558 | |
559 | #[doc (alias = "gst_caps_intersect" )] |
560 | pub fn intersect(&self, other: &Self) -> Caps { |
561 | unsafe { |
562 | from_glib_full(ffi::gst_caps_intersect( |
563 | self.as_mut_ptr(), |
564 | other.as_mut_ptr(), |
565 | )) |
566 | } |
567 | } |
568 | |
569 | #[doc (alias = "gst_caps_intersect_full" )] |
570 | pub fn intersect_with_mode(&self, other: &Self, mode: CapsIntersectMode) -> Caps { |
571 | unsafe { |
572 | from_glib_full(ffi::gst_caps_intersect_full( |
573 | self.as_mut_ptr(), |
574 | other.as_mut_ptr(), |
575 | mode.into_glib(), |
576 | )) |
577 | } |
578 | } |
579 | |
580 | #[doc (alias = "gst_caps_is_always_compatible" )] |
581 | pub fn is_always_compatible(&self, other: &Self) -> bool { |
582 | unsafe { |
583 | from_glib(ffi::gst_caps_is_always_compatible( |
584 | self.as_ptr(), |
585 | other.as_ptr(), |
586 | )) |
587 | } |
588 | } |
589 | |
590 | #[doc (alias = "gst_caps_is_any" )] |
591 | pub fn is_any(&self) -> bool { |
592 | unsafe { from_glib(ffi::gst_caps_is_any(self.as_ptr())) } |
593 | } |
594 | |
595 | #[doc (alias = "gst_caps_is_empty" )] |
596 | pub fn is_empty(&self) -> bool { |
597 | unsafe { from_glib(ffi::gst_caps_is_empty(self.as_ptr())) } |
598 | } |
599 | |
600 | #[doc (alias = "gst_caps_is_fixed" )] |
601 | pub fn is_fixed(&self) -> bool { |
602 | unsafe { from_glib(ffi::gst_caps_is_fixed(self.as_ptr())) } |
603 | } |
604 | |
605 | #[doc (alias = "gst_caps_is_equal_fixed" )] |
606 | pub fn is_equal_fixed(&self, other: &Self) -> bool { |
607 | unsafe { from_glib(ffi::gst_caps_is_equal_fixed(self.as_ptr(), other.as_ptr())) } |
608 | } |
609 | |
610 | #[doc (alias = "gst_caps_is_strictly_equal" )] |
611 | pub fn is_strictly_equal(&self, other: &Self) -> bool { |
612 | unsafe { |
613 | from_glib(ffi::gst_caps_is_strictly_equal( |
614 | self.as_ptr(), |
615 | other.as_ptr(), |
616 | )) |
617 | } |
618 | } |
619 | |
620 | #[doc (alias = "gst_caps_is_subset" )] |
621 | pub fn is_subset(&self, superset: &Self) -> bool { |
622 | unsafe { from_glib(ffi::gst_caps_is_subset(self.as_ptr(), superset.as_ptr())) } |
623 | } |
624 | |
625 | #[doc (alias = "gst_caps_is_subset_structure" )] |
626 | pub fn is_subset_structure(&self, structure: &StructureRef) -> bool { |
627 | unsafe { |
628 | from_glib(ffi::gst_caps_is_subset_structure( |
629 | self.as_ptr(), |
630 | structure.as_ptr(), |
631 | )) |
632 | } |
633 | } |
634 | |
635 | #[doc (alias = "gst_caps_is_subset_structure_full" )] |
636 | pub fn is_subset_structure_full( |
637 | &self, |
638 | structure: &StructureRef, |
639 | features: Option<&CapsFeaturesRef>, |
640 | ) -> bool { |
641 | unsafe { |
642 | from_glib(ffi::gst_caps_is_subset_structure_full( |
643 | self.as_ptr(), |
644 | structure.as_ptr(), |
645 | features.map(|f| f.as_ptr()).unwrap_or(ptr::null()), |
646 | )) |
647 | } |
648 | } |
649 | |
650 | #[doc (alias = "gst_caps_subtract" )] |
651 | pub fn subtract(&self, other: &Self) -> Caps { |
652 | unsafe { |
653 | from_glib_full(ffi::gst_caps_subtract( |
654 | self.as_mut_ptr(), |
655 | other.as_mut_ptr(), |
656 | )) |
657 | } |
658 | } |
659 | |
660 | #[cfg (feature = "v1_20" )] |
661 | #[cfg_attr (docsrs, doc(cfg(feature = "v1_20" )))] |
662 | #[doc (alias = "gst_caps_serialize" )] |
663 | pub fn serialize(&self, flags: crate::SerializeFlags) -> glib::GString { |
664 | unsafe { from_glib_full(ffi::gst_caps_serialize(&self.0, flags.into_glib())) } |
665 | } |
666 | |
667 | #[doc (alias = "gst_caps_foreach" )] |
668 | pub fn foreach<F: FnMut(&CapsFeaturesRef, &StructureRef) -> std::ops::ControlFlow<()>>( |
669 | &self, |
670 | mut func: F, |
671 | ) -> bool { |
672 | unsafe { |
673 | unsafe extern "C" fn trampoline< |
674 | F: FnMut(&CapsFeaturesRef, &StructureRef) -> std::ops::ControlFlow<()>, |
675 | >( |
676 | features: *mut ffi::GstCapsFeatures, |
677 | s: *mut ffi::GstStructure, |
678 | user_data: glib::ffi::gpointer, |
679 | ) -> glib::ffi::gboolean { |
680 | let func = &mut *(user_data as *mut F); |
681 | let res = func( |
682 | CapsFeaturesRef::from_glib_borrow(features), |
683 | StructureRef::from_glib_borrow(s), |
684 | ); |
685 | |
686 | matches!(res, std::ops::ControlFlow::Continue(_)).into_glib() |
687 | } |
688 | let func = &mut func as *mut F; |
689 | from_glib(ffi::gst_caps_foreach( |
690 | self.as_ptr(), |
691 | Some(trampoline::<F>), |
692 | func as glib::ffi::gpointer, |
693 | )) |
694 | } |
695 | } |
696 | |
697 | #[doc (alias = "gst_caps_map_in_place" )] |
698 | pub fn map_in_place< |
699 | F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> std::ops::ControlFlow<()>, |
700 | >( |
701 | &mut self, |
702 | mut func: F, |
703 | ) -> bool { |
704 | unsafe { |
705 | unsafe extern "C" fn trampoline< |
706 | F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> std::ops::ControlFlow<()>, |
707 | >( |
708 | features: *mut ffi::GstCapsFeatures, |
709 | s: *mut ffi::GstStructure, |
710 | user_data: glib::ffi::gpointer, |
711 | ) -> glib::ffi::gboolean { |
712 | let func = &mut *(user_data as *mut F); |
713 | let res = func( |
714 | CapsFeaturesRef::from_glib_borrow_mut(features), |
715 | StructureRef::from_glib_borrow_mut(s), |
716 | ); |
717 | |
718 | matches!(res, std::ops::ControlFlow::Continue(_)).into_glib() |
719 | } |
720 | let func = &mut func as *mut F; |
721 | from_glib(ffi::gst_caps_map_in_place( |
722 | self.as_mut_ptr(), |
723 | Some(trampoline::<F>), |
724 | func as glib::ffi::gpointer, |
725 | )) |
726 | } |
727 | } |
728 | |
729 | #[doc (alias = "gst_caps_filter_and_map_in_place" )] |
730 | pub fn filter_map_in_place< |
731 | F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> CapsFilterMapAction, |
732 | >( |
733 | &mut self, |
734 | mut func: F, |
735 | ) { |
736 | unsafe { |
737 | unsafe extern "C" fn trampoline< |
738 | F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> CapsFilterMapAction, |
739 | >( |
740 | features: *mut ffi::GstCapsFeatures, |
741 | s: *mut ffi::GstStructure, |
742 | user_data: glib::ffi::gpointer, |
743 | ) -> glib::ffi::gboolean { |
744 | let func = &mut *(user_data as *mut F); |
745 | |
746 | let res = func( |
747 | CapsFeaturesRef::from_glib_borrow_mut(features), |
748 | StructureRef::from_glib_borrow_mut(s), |
749 | ); |
750 | |
751 | match res { |
752 | CapsFilterMapAction::Keep => glib::ffi::GTRUE, |
753 | CapsFilterMapAction::Remove => glib::ffi::GFALSE, |
754 | } |
755 | } |
756 | |
757 | let func = &mut func as *mut F; |
758 | ffi::gst_caps_filter_and_map_in_place( |
759 | self.as_mut_ptr(), |
760 | Some(trampoline::<F>), |
761 | func as glib::ffi::gpointer, |
762 | ); |
763 | } |
764 | } |
765 | } |
766 | |
767 | #[derive (Debug)] |
768 | pub enum CapsFilterMapAction { |
769 | Keep, |
770 | Remove, |
771 | } |
772 | |
773 | macro_rules! define_iter( |
774 | ($name:ident, $typ:ty, $styp:ty, $get_item:expr) => { |
775 | #[derive(Debug)] |
776 | pub struct $name<'a> { |
777 | caps: $typ, |
778 | idx: usize, |
779 | n_structures: usize, |
780 | } |
781 | |
782 | impl<'a> $name<'a> { |
783 | fn new(caps: $typ) -> $name<'a> { |
784 | skip_assert_initialized!(); |
785 | let n_structures = caps.size(); |
786 | |
787 | $name { |
788 | caps, |
789 | idx: 0, |
790 | n_structures: n_structures as usize, |
791 | } |
792 | } |
793 | } |
794 | |
795 | #[allow(clippy::redundant_closure_call)] |
796 | impl<'a> Iterator for $name<'a> { |
797 | type Item = $styp; |
798 | |
799 | fn next(&mut self) -> Option<Self::Item> { |
800 | if self.idx >= self.n_structures { |
801 | return None; |
802 | } |
803 | |
804 | unsafe { |
805 | let item = $get_item(self.caps, self.idx).unwrap(); |
806 | self.idx += 1; |
807 | Some(item) |
808 | } |
809 | } |
810 | |
811 | fn size_hint(&self) -> (usize, Option<usize>) { |
812 | let remaining = self.n_structures - self.idx; |
813 | |
814 | (remaining, Some(remaining)) |
815 | } |
816 | |
817 | fn count(self) -> usize { |
818 | self.n_structures - self.idx |
819 | } |
820 | |
821 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
822 | let (end, overflow) = self.idx.overflowing_add(n); |
823 | if end >= self.n_structures || overflow { |
824 | self.idx = self.n_structures; |
825 | None |
826 | } else { |
827 | unsafe { |
828 | self.idx = end + 1; |
829 | Some($get_item(self.caps, end).unwrap()) |
830 | } |
831 | } |
832 | } |
833 | |
834 | fn last(self) -> Option<Self::Item> { |
835 | if self.idx == self.n_structures { |
836 | None |
837 | } else { |
838 | unsafe { |
839 | Some($get_item(self.caps, self.n_structures - 1).unwrap()) |
840 | } |
841 | } |
842 | } |
843 | } |
844 | |
845 | #[allow(clippy::redundant_closure_call)] |
846 | impl<'a> DoubleEndedIterator for $name<'a> { |
847 | fn next_back(&mut self) -> Option<Self::Item> { |
848 | if self.idx == self.n_structures { |
849 | return None; |
850 | } |
851 | |
852 | self.n_structures -= 1; |
853 | |
854 | unsafe { |
855 | Some($get_item(self.caps, self.n_structures).unwrap()) |
856 | } |
857 | } |
858 | |
859 | fn nth_back(&mut self, n: usize) -> Option<Self::Item> { |
860 | let (end, overflow) = self.n_structures.overflowing_sub(n); |
861 | if end <= self.idx || overflow { |
862 | self.idx = self.n_structures; |
863 | None |
864 | } else { |
865 | self.n_structures = end - 1; |
866 | unsafe { |
867 | Some($get_item(self.caps, self.n_structures).unwrap()) |
868 | } |
869 | } |
870 | } |
871 | } |
872 | |
873 | impl<'a> ExactSizeIterator for $name<'a> {} |
874 | |
875 | impl<'a> std::iter::FusedIterator for $name<'a> {} |
876 | } |
877 | ); |
878 | |
879 | define_iter!( |
880 | Iter, |
881 | &'a CapsRef, |
882 | &'a StructureRef, |
883 | |caps: &CapsRef, idx| { |
884 | let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32); |
885 | if ptr.is_null() { |
886 | None |
887 | } else { |
888 | Some(StructureRef::from_glib_borrow( |
889 | ptr as *const ffi::GstStructure, |
890 | )) |
891 | } |
892 | } |
893 | ); |
894 | define_iter!( |
895 | IterMut, |
896 | &'a mut CapsRef, |
897 | &'a mut StructureRef, |
898 | |caps: &CapsRef, idx| { |
899 | let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32); |
900 | if ptr.is_null() { |
901 | None |
902 | } else { |
903 | Some(StructureRef::from_glib_borrow_mut(ptr)) |
904 | } |
905 | } |
906 | ); |
907 | define_iter!( |
908 | IterFeatures, |
909 | &'a CapsRef, |
910 | (&'a StructureRef, &'a CapsFeaturesRef), |
911 | |caps: &CapsRef, idx| { |
912 | let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32); |
913 | let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx as u32); |
914 | if ptr1.is_null() || ptr2.is_null() { |
915 | None |
916 | } else { |
917 | Some(( |
918 | StructureRef::from_glib_borrow(ptr1), |
919 | CapsFeaturesRef::from_glib_borrow(ptr2), |
920 | )) |
921 | } |
922 | } |
923 | ); |
924 | define_iter!( |
925 | IterFeaturesMut, |
926 | &'a mut CapsRef, |
927 | (&'a mut StructureRef, &'a mut CapsFeaturesRef), |
928 | |caps: &CapsRef, idx| { |
929 | let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32); |
930 | let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx as u32); |
931 | if ptr1.is_null() || ptr2.is_null() { |
932 | None |
933 | } else { |
934 | Some(( |
935 | StructureRef::from_glib_borrow_mut(ptr1), |
936 | CapsFeaturesRef::from_glib_borrow_mut(ptr2), |
937 | )) |
938 | } |
939 | } |
940 | ); |
941 | |
942 | impl<'a> IntoIterator for &'a CapsRef { |
943 | type IntoIter = IterFeatures<'a>; |
944 | type Item = (&'a StructureRef, &'a CapsFeaturesRef); |
945 | |
946 | fn into_iter(self) -> Self::IntoIter { |
947 | self.iter_with_features() |
948 | } |
949 | } |
950 | |
951 | impl<'a> IntoIterator for &'a mut CapsRef { |
952 | type IntoIter = IterFeaturesMut<'a>; |
953 | type Item = (&'a mut StructureRef, &'a mut CapsFeaturesRef); |
954 | |
955 | fn into_iter(self) -> Self::IntoIter { |
956 | self.iter_with_features_mut() |
957 | } |
958 | } |
959 | |
960 | impl fmt::Debug for Caps { |
961 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
962 | <CapsRef as fmt::Debug>::fmt(self, f) |
963 | } |
964 | } |
965 | |
966 | impl fmt::Display for Caps { |
967 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
968 | <CapsRef as fmt::Display>::fmt(self, f) |
969 | } |
970 | } |
971 | |
972 | impl PartialEq for Caps { |
973 | fn eq(&self, other: &Caps) -> bool { |
974 | CapsRef::eq(self, other) |
975 | } |
976 | } |
977 | |
978 | impl Eq for Caps {} |
979 | |
980 | impl PartialEq<CapsRef> for Caps { |
981 | fn eq(&self, other: &CapsRef) -> bool { |
982 | CapsRef::eq(self, other) |
983 | } |
984 | } |
985 | |
986 | impl PartialEq<Caps> for CapsRef { |
987 | fn eq(&self, other: &Caps) -> bool { |
988 | CapsRef::eq(self:other, self) |
989 | } |
990 | } |
991 | |
992 | impl fmt::Debug for CapsRef { |
993 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
994 | if self.is_any() { |
995 | f.debug_tuple("Caps( \"ANY \")" ).finish() |
996 | } else if self.is_empty() { |
997 | f.debug_tuple("Caps( \"EMPTY \")" ).finish() |
998 | } else { |
999 | let mut debug = f.debug_tuple("Caps" ); |
1000 | |
1001 | for (structure, features) in self.iter_with_features() { |
1002 | struct WithFeatures<'a> { |
1003 | features: &'a CapsFeaturesRef, |
1004 | structure: &'a StructureRef, |
1005 | } |
1006 | |
1007 | impl fmt::Debug for WithFeatures<'_> { |
1008 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1009 | let name = format!(" {}( {})" , self.structure.name(), self.features); |
1010 | let mut debug = f.debug_struct(&name); |
1011 | |
1012 | for (id, field) in self.structure.iter() { |
1013 | if field.type_() == Structure::static_type() { |
1014 | let s = field.get::<Structure>().unwrap(); |
1015 | debug.field(id, &s); |
1016 | } else if field.type_() == crate::Array::static_type() { |
1017 | let arr = field.get::<crate::Array>().unwrap(); |
1018 | debug.field(id, &arr); |
1019 | } else if field.type_() == crate::List::static_type() { |
1020 | let list = field.get::<crate::List>().unwrap(); |
1021 | debug.field(id, &list); |
1022 | } else { |
1023 | debug.field(id, &field); |
1024 | } |
1025 | } |
1026 | |
1027 | debug.finish() |
1028 | } |
1029 | } |
1030 | |
1031 | debug.field(&WithFeatures { |
1032 | structure, |
1033 | features, |
1034 | }); |
1035 | } |
1036 | |
1037 | debug.finish() |
1038 | } |
1039 | } |
1040 | } |
1041 | |
1042 | impl fmt::Display for CapsRef { |
1043 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1044 | let s: GString = unsafe { glib::GString::from_glib_full(ptr:ffi::gst_caps_to_string(self.as_ptr())) }; |
1045 | f.write_str(&s) |
1046 | } |
1047 | } |
1048 | |
1049 | impl PartialEq for CapsRef { |
1050 | #[doc (alias = "gst_caps_is_equal" )] |
1051 | fn eq(&self, other: &CapsRef) -> bool { |
1052 | unsafe { from_glib(val:ffi::gst_caps_is_equal(self.as_ptr(), caps2:other.as_ptr())) } |
1053 | } |
1054 | } |
1055 | |
1056 | impl Eq for CapsRef {} |
1057 | |
1058 | pub enum NoFeature {} |
1059 | pub enum HasFeatures {} |
1060 | |
1061 | #[must_use = "The builder must be built to be used" ] |
1062 | pub struct Builder<T> { |
1063 | s: crate::Structure, |
1064 | features: Option<CapsFeatures>, |
1065 | phantom: PhantomData<T>, |
1066 | } |
1067 | |
1068 | impl<T> fmt::Debug for Builder<T> { |
1069 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1070 | f&mut DebugStruct<'_, '_>.debug_struct("Builder" ) |
1071 | .field("s" , &self.s) |
1072 | .field("features" , &self.features) |
1073 | .field(name:"phantom" , &self.phantom) |
1074 | .finish() |
1075 | } |
1076 | } |
1077 | |
1078 | impl Builder<NoFeature> { |
1079 | fn new(name: impl IntoGStr) -> Builder<NoFeature> { |
1080 | skip_assert_initialized!(); |
1081 | Builder { |
1082 | s: crate::Structure::new_empty(name), |
1083 | features: None, |
1084 | phantom: PhantomData, |
1085 | } |
1086 | } |
1087 | |
1088 | pub fn features( |
1089 | self, |
1090 | features: impl IntoIterator<Item = impl IntoGStr>, |
1091 | ) -> Builder<HasFeatures> { |
1092 | Builder { |
1093 | s: self.s, |
1094 | features: Some(CapsFeatures::new(features)), |
1095 | phantom: PhantomData, |
1096 | } |
1097 | } |
1098 | |
1099 | pub fn any_features(self) -> Builder<HasFeatures> { |
1100 | Builder { |
1101 | s: self.s, |
1102 | features: Some(CapsFeatures::new_any()), |
1103 | phantom: PhantomData, |
1104 | } |
1105 | } |
1106 | } |
1107 | |
1108 | impl<T> Builder<T> { |
1109 | // rustdoc-stripper-ignore-next |
1110 | /// Sets field `name` to the given value `value`. |
1111 | /// |
1112 | /// Overrides any default or previously defined value for `name`. |
1113 | #[inline ] |
1114 | pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self { |
1115 | self.s.set(name, value); |
1116 | self |
1117 | } |
1118 | |
1119 | impl_builder_gvalue_extra_setters!(field); |
1120 | |
1121 | #[must_use = "Building the caps without using them has no effect" ] |
1122 | pub fn build(self) -> Caps { |
1123 | let mut caps = Caps::new_empty(); |
1124 | |
1125 | caps.get_mut() |
1126 | .unwrap() |
1127 | .append_structure_full(self.s, self.features); |
1128 | caps |
1129 | } |
1130 | |
1131 | pub fn structure(&self) -> &crate::Structure { |
1132 | &self.s |
1133 | } |
1134 | } |
1135 | |
1136 | pub enum AnyFeatures {} |
1137 | pub enum SomeFeatures {} |
1138 | |
1139 | #[must_use = "The builder must be built to be used" ] |
1140 | pub struct BuilderFull<T> { |
1141 | caps: crate::Caps, |
1142 | features: Option<CapsFeatures>, |
1143 | phantom: PhantomData<T>, |
1144 | } |
1145 | |
1146 | impl<T> fmt::Debug for BuilderFull<T> { |
1147 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1148 | f&mut DebugStruct<'_, '_>.debug_struct("Builder" ) |
1149 | .field("caps" , &self.caps) |
1150 | .field("features" , &self.features) |
1151 | .field(name:"phantom" , &self.phantom) |
1152 | .finish() |
1153 | } |
1154 | } |
1155 | |
1156 | impl BuilderFull<SomeFeatures> { |
1157 | fn new() -> Self { |
1158 | BuilderFull { |
1159 | caps: Caps::new_empty(), |
1160 | features: None, |
1161 | phantom: PhantomData, |
1162 | } |
1163 | } |
1164 | |
1165 | fn with_features(features: CapsFeatures) -> Self { |
1166 | skip_assert_initialized!(); |
1167 | BuilderFull { |
1168 | caps: Caps::new_empty(), |
1169 | features: Some(features), |
1170 | phantom: PhantomData, |
1171 | } |
1172 | } |
1173 | |
1174 | pub fn structure_with_features(self, structure: Structure, features: CapsFeatures) -> Self { |
1175 | self.append_structure(structure, Some(features)) |
1176 | } |
1177 | |
1178 | pub fn structure_with_features_if_some( |
1179 | self, |
1180 | structure: Option<Structure>, |
1181 | features: CapsFeatures, |
1182 | ) -> Self { |
1183 | if let Some(structure) = structure { |
1184 | self.structure_with_features(structure, features) |
1185 | } else { |
1186 | self |
1187 | } |
1188 | } |
1189 | |
1190 | pub fn structure_with_any_features(self, structure: Structure) -> Self { |
1191 | self.append_structure(structure, Some(CapsFeatures::new_any())) |
1192 | } |
1193 | |
1194 | pub fn structure_with_any_features_if_some(self, structure: Option<Structure>) -> Self { |
1195 | if let Some(structure) = structure { |
1196 | self.structure_with_any_features(structure) |
1197 | } else { |
1198 | self |
1199 | } |
1200 | } |
1201 | } |
1202 | |
1203 | impl BuilderFull<AnyFeatures> { |
1204 | fn with_any_features() -> Self { |
1205 | BuilderFull { |
1206 | caps: Caps::new_empty(), |
1207 | features: Some(CapsFeatures::new_any()), |
1208 | phantom: PhantomData, |
1209 | } |
1210 | } |
1211 | } |
1212 | |
1213 | impl<T> BuilderFull<T> { |
1214 | fn append_structure(mut self, structure: Structure, features: Option<CapsFeatures>) -> Self { |
1215 | let features = { |
1216 | match self.features { |
1217 | None => features, |
1218 | Some(ref result) => { |
1219 | let mut result = result.clone(); |
1220 | match features { |
1221 | None => Some(result), |
1222 | Some(features) => { |
1223 | features.iter().for_each(|feat| result.add(feat)); |
1224 | Some(result) |
1225 | } |
1226 | } |
1227 | } |
1228 | } |
1229 | }; |
1230 | |
1231 | self.caps |
1232 | .get_mut() |
1233 | .unwrap() |
1234 | .append_structure_full(structure, features); |
1235 | self |
1236 | } |
1237 | |
1238 | pub fn structure(self, structure: Structure) -> Self { |
1239 | self.append_structure(structure, None) |
1240 | } |
1241 | |
1242 | pub fn structure_if_some(self, structure: Option<Structure>) -> Self { |
1243 | if let Some(structure) = structure { |
1244 | self.structure(structure) |
1245 | } else { |
1246 | self |
1247 | } |
1248 | } |
1249 | |
1250 | #[must_use = "Building the caps without using them has no effect" ] |
1251 | pub fn build(self) -> Caps { |
1252 | self.caps |
1253 | } |
1254 | } |
1255 | |
1256 | #[cfg (test)] |
1257 | mod tests { |
1258 | use super::*; |
1259 | use crate::{Array, Fraction}; |
1260 | |
1261 | #[test ] |
1262 | fn test_builder() { |
1263 | crate::init().unwrap(); |
1264 | |
1265 | let mut caps = Caps::builder("foo/bar" ) |
1266 | .field("int" , 12) |
1267 | .field("bool" , true) |
1268 | .field("string" , "bla" ) |
1269 | .field("fraction" , Fraction::new(1, 2)) |
1270 | .field("array" , Array::new([1, 2])) |
1271 | .build(); |
1272 | assert_eq!( |
1273 | caps.to_string(), |
1274 | "foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >" |
1275 | ); |
1276 | |
1277 | assert!(caps |
1278 | .features(0) |
1279 | .unwrap() |
1280 | .is_equal(crate::CAPS_FEATURES_MEMORY_SYSTEM_MEMORY.as_ref())); |
1281 | |
1282 | { |
1283 | let caps = caps.get_mut().unwrap(); |
1284 | caps.set_features(0, Some(CapsFeatures::new(["foo:bla" ]))); |
1285 | } |
1286 | assert!(caps |
1287 | .features(0) |
1288 | .unwrap() |
1289 | .is_equal(CapsFeatures::new(["foo:bla" ]).as_ref())); |
1290 | |
1291 | let caps = Caps::builder("foo/bar" ) |
1292 | .field("int" , 12) |
1293 | .any_features() |
1294 | .build(); |
1295 | assert_eq!(caps.to_string(), "foo/bar(ANY), int=(int)12" ); |
1296 | |
1297 | let caps = Caps::builder("foo/bar" ) |
1298 | .field("int" , 12) |
1299 | .features(["foo:bla" , "foo:baz" ]) |
1300 | .build(); |
1301 | assert_eq!(caps.to_string(), "foo/bar(foo:bla, foo:baz), int=(int)12" ); |
1302 | |
1303 | let caps = Caps::builder("foo/bar" ) |
1304 | .field_if_some("int0" , Option::<i32>::None) |
1305 | .field_if_some("int1" , Some(12)) |
1306 | .field_if_some("string0" , Option::<String>::None) |
1307 | .field_if_some("string1" , Some("bla" )) |
1308 | .build(); |
1309 | assert_eq!( |
1310 | caps.to_string(), |
1311 | "foo/bar, int1=(int)12, string1=(string)bla" |
1312 | ); |
1313 | } |
1314 | |
1315 | #[test ] |
1316 | fn test_display() { |
1317 | crate::init().unwrap(); |
1318 | |
1319 | let caps = Caps::builder("foo/bar" ).build(); |
1320 | let _ = format!("{caps}" ); |
1321 | } |
1322 | |
1323 | #[test ] |
1324 | fn test_builder_full() { |
1325 | crate::init().unwrap(); |
1326 | |
1327 | let caps = Caps::builder_full() |
1328 | .structure(Structure::builder("audio/x-raw" ).build()) |
1329 | .structure(Structure::builder("video/x-raw" ).build()) |
1330 | .build(); |
1331 | assert_eq!(caps.to_string(), "audio/x-raw; video/x-raw" ); |
1332 | |
1333 | let caps = Caps::builder_full() |
1334 | .structure( |
1335 | Structure::builder("audio/x-raw" ) |
1336 | .field("format" , "S16LE" ) |
1337 | .build(), |
1338 | ) |
1339 | .structure(Structure::builder("video/x-raw" ).build()) |
1340 | .build(); |
1341 | assert_eq!( |
1342 | caps.to_string(), |
1343 | "audio/x-raw, format=(string)S16LE; video/x-raw" |
1344 | ); |
1345 | |
1346 | let caps = Caps::builder_full() |
1347 | .structure_with_any_features(Structure::builder("audio/x-raw" ).build()) |
1348 | .structure_with_features( |
1349 | Structure::builder("video/x-raw" ).build(), |
1350 | CapsFeatures::new(["foo:bla" , "foo:baz" ]), |
1351 | ) |
1352 | .build(); |
1353 | assert_eq!( |
1354 | caps.to_string(), |
1355 | "audio/x-raw(ANY); video/x-raw(foo:bla, foo:baz)" |
1356 | ); |
1357 | |
1358 | let caps = Caps::builder_full() |
1359 | .structure_if_some(Option::<Structure>::None) |
1360 | .build(); |
1361 | assert!(caps.is_empty()); |
1362 | |
1363 | let caps = Caps::builder_full() |
1364 | .structure_if_some(Some(Structure::builder("audio/x-raw" ).build())) |
1365 | .build(); |
1366 | assert_eq!(caps.to_string(), "audio/x-raw" ); |
1367 | |
1368 | let caps = Caps::builder_full() |
1369 | .structure_with_any_features_if_some(Some(Structure::builder("audio/x-raw" ).build())) |
1370 | .structure_with_features_if_some( |
1371 | Some(Structure::builder("video/x-raw" ).build()), |
1372 | CapsFeatures::new(["foo:bla" , "foo:baz" ]), |
1373 | ) |
1374 | .build(); |
1375 | assert_eq!( |
1376 | caps.to_string(), |
1377 | "audio/x-raw(ANY); video/x-raw(foo:bla, foo:baz)" |
1378 | ); |
1379 | |
1380 | let caps = Caps::builder_full() |
1381 | .structure_with_any_features_if_some(Option::<Structure>::None) |
1382 | .structure_with_features_if_some( |
1383 | Option::<Structure>::None, |
1384 | CapsFeatures::new(["foo:bla" , "foo:baz" ]), |
1385 | ) |
1386 | .build(); |
1387 | assert!(caps.is_empty()); |
1388 | } |
1389 | |
1390 | #[test ] |
1391 | fn test_builder_full_with_features() { |
1392 | crate::init().unwrap(); |
1393 | |
1394 | let caps = Caps::builder_full_with_features(CapsFeatures::new(["foo:bla" ])) |
1395 | .structure(Structure::builder("audio/x-raw" ).build()) |
1396 | .structure_with_features( |
1397 | Structure::builder("video/x-raw" ).build(), |
1398 | CapsFeatures::new(["foo:baz" ]), |
1399 | ) |
1400 | .build(); |
1401 | assert_eq!( |
1402 | caps.to_string(), |
1403 | "audio/x-raw(foo:bla); video/x-raw(foo:bla, foo:baz)" |
1404 | ); |
1405 | } |
1406 | |
1407 | #[test ] |
1408 | fn test_builder_full_with_any_features() { |
1409 | crate::init().unwrap(); |
1410 | |
1411 | let caps = Caps::builder_full_with_any_features() |
1412 | .structure(Structure::builder("audio/x-raw" ).build()) |
1413 | .structure(Structure::builder("video/x-raw" ).build()) |
1414 | .build(); |
1415 | assert_eq!(caps.to_string(), "audio/x-raw(ANY); video/x-raw(ANY)" ); |
1416 | |
1417 | let caps = Caps::builder_full_with_any_features() |
1418 | .structure(Structure::builder("audio/x-raw" ).build()) |
1419 | .build(); |
1420 | assert_eq!(caps.to_string(), "audio/x-raw(ANY)" ); |
1421 | } |
1422 | |
1423 | #[test ] |
1424 | fn test_new_from_iter() { |
1425 | crate::init().unwrap(); |
1426 | |
1427 | let caps = Caps::builder_full_with_any_features() |
1428 | .structure(Structure::builder("audio/x-raw" ).build()) |
1429 | .structure(Structure::builder("video/x-raw" ).build()) |
1430 | .build(); |
1431 | |
1432 | let audio = caps |
1433 | .iter() |
1434 | .filter(|s| s.name() == "audio/x-raw" ) |
1435 | .map(|s| s.to_owned()) |
1436 | .collect::<Caps>(); |
1437 | assert_eq!(audio.to_string(), "audio/x-raw" ); |
1438 | |
1439 | let audio = caps |
1440 | .iter_with_features() |
1441 | .filter(|(s, _)| s.name() == "audio/x-raw" ) |
1442 | .map(|(s, c)| (s.to_owned(), c.to_owned())) |
1443 | .collect::<Caps>(); |
1444 | assert_eq!(audio.to_string(), "audio/x-raw(ANY)" ); |
1445 | } |
1446 | |
1447 | #[test ] |
1448 | fn test_debug() { |
1449 | crate::init().unwrap(); |
1450 | |
1451 | let caps = Caps::new_any(); |
1452 | assert_eq!(format!("{caps:?}" ), "Caps( \"ANY \")" ); |
1453 | |
1454 | let caps = Caps::new_empty(); |
1455 | assert_eq!(format!("{caps:?}" ), "Caps( \"EMPTY \")" ); |
1456 | |
1457 | let caps = Caps::builder_full_with_any_features() |
1458 | .structure(Structure::builder("audio/x-raw" ).build()) |
1459 | .build(); |
1460 | assert_eq!(format!("{caps:?}" ), "Caps(audio/x-raw(ANY))" ); |
1461 | |
1462 | let caps = Caps::builder_full_with_features(CapsFeatures::new(["foo:bla" ])) |
1463 | .structure( |
1464 | Structure::builder("audio/x-raw" ) |
1465 | .field( |
1466 | "struct" , |
1467 | Structure::builder("nested" ).field("badger" , true).build(), |
1468 | ) |
1469 | .build(), |
1470 | ) |
1471 | .structure( |
1472 | Structure::builder("video/x-raw" ) |
1473 | .field("width" , 800u32) |
1474 | .build(), |
1475 | ) |
1476 | .build(); |
1477 | |
1478 | assert_eq!(format!("{caps:?}" ), "Caps(audio/x-raw(foo:bla) { struct: Structure(nested { badger: (gboolean) TRUE }) }, video/x-raw(foo:bla) { width: (guint) 800 })" ); |
1479 | |
1480 | let caps = Caps::builder_full() |
1481 | .structure( |
1482 | Structure::builder("video/x-raw" ) |
1483 | .field("array" , crate::Array::new(["a" , "b" , "c" ])) |
1484 | .field("list" , crate::List::new(["d" , "e" , "f" ])) |
1485 | .build(), |
1486 | ) |
1487 | .build(); |
1488 | |
1489 | assert_eq!(format!("{caps:?}" ), "Caps(video/x-raw(memory:SystemMemory) { array: Array([(gchararray) \"a \", (gchararray) \"b \", (gchararray) \"c \"]), list: List([(gchararray) \"d \", (gchararray) \"e \", (gchararray) \"f \"]) })" ); |
1490 | } |
1491 | } |
1492 | |