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