1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{fmt, marker::PhantomData, ptr, str}; |
4 | |
5 | use glib::{ |
6 | translate::{from_glib, from_glib_full, FromGlibPtrFull, IntoGlib, IntoGlibPtr, ToGlibPtr}, |
7 | value::ToSendValue, |
8 | IntoGStr, StaticType, |
9 | }; |
10 | |
11 | use crate::{caps_features::*, structure::*, CapsIntersectMode}; |
12 | |
13 | mini_object_wrapper!(Caps, CapsRef, ffi::GstCaps, || { ffi::gst_caps_get_type() }); |
14 | |
15 | impl Caps { |
16 | #[doc (alias = "gst_caps_new_simple" )] |
17 | pub fn builder(name: impl IntoGStr) -> Builder<NoFeature> { |
18 | assert_initialized_main_thread!(); |
19 | Builder::new(name) |
20 | } |
21 | |
22 | #[doc (alias = "gst_caps_new_full" )] |
23 | pub fn builder_full() -> BuilderFull<SomeFeatures> { |
24 | assert_initialized_main_thread!(); |
25 | BuilderFull::new() |
26 | } |
27 | |
28 | #[doc (alias = "gst_caps_new_full" )] |
29 | pub fn builder_full_with_features(features: CapsFeatures) -> BuilderFull<SomeFeatures> { |
30 | assert_initialized_main_thread!(); |
31 | BuilderFull::with_features(features) |
32 | } |
33 | |
34 | #[doc (alias = "gst_caps_new_full" )] |
35 | pub fn builder_full_with_any_features() -> BuilderFull<AnyFeatures> { |
36 | assert_initialized_main_thread!(); |
37 | BuilderFull::with_any_features() |
38 | } |
39 | |
40 | #[doc (alias = "gst_caps_new_empty" )] |
41 | pub fn new_empty() -> Self { |
42 | assert_initialized_main_thread!(); |
43 | unsafe { from_glib_full(ffi::gst_caps_new_empty()) } |
44 | } |
45 | |
46 | #[doc (alias = "gst_caps_new_any" )] |
47 | pub fn new_any() -> Self { |
48 | assert_initialized_main_thread!(); |
49 | unsafe { from_glib_full(ffi::gst_caps_new_any()) } |
50 | } |
51 | |
52 | #[doc (alias = "gst_caps_new_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 | |
145 | impl 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 | |
160 | impl 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 | |
174 | impl<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 | |
188 | impl 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 | |
202 | impl<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 | |
217 | impl<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 | |
232 | impl 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 | |
246 | impl 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 | |
261 | impl 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 | |
276 | impl 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 | |
291 | impl 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 | |
297 | impl 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 | |
304 | impl 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 | |
311 | impl 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 | |
317 | impl 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)] |
702 | pub enum CapsFilterMapAction { |
703 | Keep, |
704 | Remove, |
705 | } |
706 | |
707 | macro_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 | |
813 | define_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 | ); |
828 | define_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 | ); |
841 | define_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 | ); |
858 | define_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 | |
876 | impl<'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 | |
885 | impl<'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 | |
894 | impl 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 | |
900 | impl 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 | |
906 | impl PartialEq for Caps { |
907 | fn eq(&self, other: &Caps) -> bool { |
908 | CapsRef::eq(self, other) |
909 | } |
910 | } |
911 | |
912 | impl Eq for Caps {} |
913 | |
914 | impl PartialEq<CapsRef> for Caps { |
915 | fn eq(&self, other: &CapsRef) -> bool { |
916 | CapsRef::eq(self, other) |
917 | } |
918 | } |
919 | |
920 | impl PartialEq<Caps> for CapsRef { |
921 | fn eq(&self, other: &Caps) -> bool { |
922 | CapsRef::eq(self:other, self) |
923 | } |
924 | } |
925 | |
926 | impl 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 | |
976 | impl 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 | |
983 | impl 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 | |
990 | impl Eq for CapsRef {} |
991 | |
992 | pub enum NoFeature {} |
993 | pub enum HasFeatures {} |
994 | |
995 | #[must_use = "The builder must be built to be used" ] |
996 | pub struct Builder<T> { |
997 | s: crate::Structure, |
998 | features: Option<CapsFeatures>, |
999 | phantom: PhantomData<T>, |
1000 | } |
1001 | |
1002 | impl<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 | |
1012 | impl 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 | |
1042 | impl<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 | |
1063 | pub enum AnyFeatures {} |
1064 | pub enum SomeFeatures {} |
1065 | |
1066 | #[must_use = "The builder must be built to be used" ] |
1067 | pub struct BuilderFull<T> { |
1068 | caps: crate::Caps, |
1069 | features: Option<CapsFeatures>, |
1070 | phantom: PhantomData<T>, |
1071 | } |
1072 | |
1073 | impl<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 | |
1083 | impl 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 | |
1110 | impl 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 | |
1120 | impl<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)] |
1156 | mod 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 | |