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