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")]
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 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
132impl 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| {
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
147impl From<Structure> for Caps {
148 fn from(v: Structure) -> Caps {
149 skip_assert_initialized!();
150 let mut caps = Caps::new_empty();
151
152 {
153 let caps = caps.get_mut().unwrap();
154 caps.append_structure(v);
155 }
156
157 caps
158 }
159}
160
161impl<const N: usize> From<[Structure; N]> for Caps {
162 fn from(v: [Structure; N]) -> Caps {
163 skip_assert_initialized!();
164 let mut caps = Caps::new_empty();
165
166 {
167 let caps = caps.get_mut().unwrap();
168 v.into_iter().for_each(|s| caps.append_structure(s));
169 }
170
171 caps
172 }
173}
174
175impl From<(Structure, CapsFeatures)> for Caps {
176 fn from(v: (Structure, CapsFeatures)) -> Caps {
177 skip_assert_initialized!();
178 let mut caps = Caps::new_empty();
179
180 {
181 let caps = caps.get_mut().unwrap();
182 caps.append_structure_full(v.0, Some(v.1));
183 }
184
185 caps
186 }
187}
188
189impl<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::new_empty();
193
194 {
195 let caps = caps.get_mut().unwrap();
196 v.into_iter()
197 .for_each(|s| caps.append_structure_full(s.0, Some(s.1)));
198 }
199
200 caps
201 }
202}
203
204impl<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::new_empty();
208
209 {
210 let caps = caps.get_mut().unwrap();
211 v.into_iter()
212 .for_each(|s| caps.append_structure_full(s.0, s.1));
213 }
214
215 caps
216 }
217}
218
219impl 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::new_empty();
223
224 {
225 let caps = caps.get_mut().unwrap();
226 iter.into_iter().for_each(|s| caps.append_structure(s));
227 }
228
229 caps
230 }
231}
232
233impl 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::new_empty();
237
238 {
239 let caps = caps.get_mut().unwrap();
240 iter.into_iter()
241 .for_each(|(s, f)| caps.append_structure_full(s, Some(f)));
242 }
243
244 caps
245 }
246}
247
248impl 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::new_empty();
252
253 {
254 let caps = caps.get_mut().unwrap();
255 iter.into_iter()
256 .for_each(|(s, f)| caps.append_structure_full(s, f));
257 }
258
259 caps
260 }
261}
262
263impl 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::new_empty();
267
268 {
269 let caps = caps.get_mut().unwrap();
270 iter.into_iter()
271 .for_each(|other_caps| caps.append(other_caps));
272 }
273
274 caps
275 }
276}
277
278impl std::iter::Extend<Structure> for CapsRef {
279 fn extend<T: IntoIterator<Item = Structure>>(&mut self, iter: T) {
280 iter.into_iter().for_each(|s| self.append_structure(s));
281 }
282}
283
284impl std::iter::Extend<(Structure, CapsFeatures)> for CapsRef {
285 fn extend<T: IntoIterator<Item = (Structure, CapsFeatures)>>(&mut self, iter: T) {
286 iter.into_iter()
287 .for_each(|(s, f)| self.append_structure_full(s, Some(f)));
288 }
289}
290
291impl std::iter::Extend<(Structure, Option<CapsFeatures>)> for CapsRef {
292 fn extend<T: IntoIterator<Item = (Structure, Option<CapsFeatures>)>>(&mut self, iter: T) {
293 iter.into_iter()
294 .for_each(|(s, f)| self.append_structure_full(s, f));
295 }
296}
297
298impl std::iter::Extend<Caps> for CapsRef {
299 fn extend<T: IntoIterator<Item = Caps>>(&mut self, iter: T) {
300 iter.into_iter().for_each(|caps| self.append(caps));
301 }
302}
303
304impl CapsRef {
305 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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)]
768pub enum CapsFilterMapAction {
769 Keep,
770 Remove,
771}
772
773macro_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
879define_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);
894define_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);
907define_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);
924define_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
942impl<'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
951impl<'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
960impl 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
966impl 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
972impl PartialEq for Caps {
973 fn eq(&self, other: &Caps) -> bool {
974 CapsRef::eq(self, other)
975 }
976}
977
978impl Eq for Caps {}
979
980impl PartialEq<CapsRef> for Caps {
981 fn eq(&self, other: &CapsRef) -> bool {
982 CapsRef::eq(self, other)
983 }
984}
985
986impl PartialEq<Caps> for CapsRef {
987 fn eq(&self, other: &Caps) -> bool {
988 CapsRef::eq(other, self)
989 }
990}
991
992impl 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
1042impl fmt::Display for CapsRef {
1043 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1044 let s = unsafe { glib::GString::from_glib_full(ffi::gst_caps_to_string(self.as_ptr())) };
1045 f.write_str(&s)
1046 }
1047}
1048
1049impl PartialEq for CapsRef {
1050 #[doc(alias = "gst_caps_is_equal")]
1051 fn eq(&self, other: &CapsRef) -> bool {
1052 unsafe { from_glib(ffi::gst_caps_is_equal(self.as_ptr(), other.as_ptr())) }
1053 }
1054}
1055
1056impl Eq for CapsRef {}
1057
1058pub enum NoFeature {}
1059pub enum HasFeatures {}
1060
1061#[must_use = "The builder must be built to be used"]
1062pub struct Builder<T> {
1063 s: crate::Structure,
1064 features: Option<CapsFeatures>,
1065 phantom: PhantomData<T>,
1066}
1067
1068impl<T> fmt::Debug for Builder<T> {
1069 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1070 f.debug_struct("Builder")
1071 .field("s", &self.s)
1072 .field("features", &self.features)
1073 .field("phantom", &self.phantom)
1074 .finish()
1075 }
1076}
1077
1078impl 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
1108impl<T> Builder<T> {
1109 #[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
1136pub enum AnyFeatures {}
1137pub enum SomeFeatures {}
1138
1139#[must_use = "The builder must be built to be used"]
1140pub struct BuilderFull<T> {
1141 caps: crate::Caps,
1142 features: Option<CapsFeatures>,
1143 phantom: PhantomData<T>,
1144}
1145
1146impl<T> fmt::Debug for BuilderFull<T> {
1147 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1148 f.debug_struct("Builder")
1149 .field("caps", &self.caps)
1150 .field("features", &self.features)
1151 .field("phantom", &self.phantom)
1152 .finish()
1153 }
1154}
1155
1156impl 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
1203impl 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
1213impl<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)]
1257mod 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}