1 // Take a look at the license at the top of the repository in the LICENSE file. 2 3 use crate::caps_features::*; 4 use crate::structure::*; 5 use std::fmt; 6 use std::marker::PhantomData; 7 use std::ptr; 8 use std::str; 9 10 use crate::CapsIntersectMode; 11 12 use glib::translate::{from_glib, from_glib_full, FromGlibPtrFull, IntoGlib, ToGlibPtr}; 13 use glib::value::ToSendValue; 14 15 mini_object_wrapper!(Caps, CapsRef, ffi::GstCaps, || { ffi::gst_caps_get_type() }); 16 17 impl Caps { builder(name: &str) -> Builder<NoFeature>18 pub fn builder(name: &str) -> Builder<NoFeature> { 19 assert_initialized_main_thread!(); 20 Builder::new(name) 21 } 22 builder_full() -> BuilderFull<SomeFeatures>23 pub fn builder_full() -> BuilderFull<SomeFeatures> { 24 assert_initialized_main_thread!(); 25 BuilderFull::new() 26 } 27 builder_full_with_features(features: CapsFeatures) -> BuilderFull<SomeFeatures>28 pub fn builder_full_with_features(features: CapsFeatures) -> BuilderFull<SomeFeatures> { 29 assert_initialized_main_thread!(); 30 BuilderFull::with_features(features) 31 } 32 builder_full_with_any_features() -> BuilderFull<AnyFeatures>33 pub fn builder_full_with_any_features() -> BuilderFull<AnyFeatures> { 34 assert_initialized_main_thread!(); 35 BuilderFull::with_any_features() 36 } 37 38 #[doc(alias = "gst_caps_new_empty")] new_empty() -> Self39 pub fn new_empty() -> Self { 40 assert_initialized_main_thread!(); 41 unsafe { from_glib_full(ffi::gst_caps_new_empty()) } 42 } 43 44 #[doc(alias = "gst_caps_new_any")] new_any() -> Self45 pub fn new_any() -> Self { 46 assert_initialized_main_thread!(); 47 unsafe { from_glib_full(ffi::gst_caps_new_any()) } 48 } 49 new_simple(name: &str, values: &[(&str, &(dyn ToSendValue + Sync))]) -> Self50 pub fn new_simple(name: &str, values: &[(&str, &(dyn ToSendValue + Sync))]) -> Self { 51 assert_initialized_main_thread!(); 52 let mut caps = Caps::new_empty(); 53 54 let structure = Structure::new(name, values); 55 caps.get_mut().unwrap().append_structure(structure); 56 57 caps 58 } 59 60 #[allow(clippy::should_implement_trait)] from_iter<'a, I>(iter: I) -> Self where I: IntoIterator<Item = &'a StructureRef>,61 pub fn from_iter<'a, I>(iter: I) -> Self 62 where 63 I: IntoIterator<Item = &'a StructureRef>, 64 { 65 assert_initialized_main_thread!(); 66 let mut caps = Caps::new_empty(); 67 68 iter.into_iter() 69 .for_each(|s| caps.get_mut().unwrap().append_structure(s.to_owned())); 70 71 caps 72 } 73 from_iter_with_features<'a, 'b, I>(iter: I) -> Self where I: IntoIterator<Item = (&'a StructureRef, &'b CapsFeaturesRef)>,74 pub fn from_iter_with_features<'a, 'b, I>(iter: I) -> Self 75 where 76 I: IntoIterator<Item = (&'a StructureRef, &'b CapsFeaturesRef)>, 77 { 78 assert_initialized_main_thread!(); 79 let mut caps = Caps::new_empty(); 80 81 iter.into_iter().for_each(|(s, f)| { 82 caps.get_mut() 83 .unwrap() 84 .append_structure_full(s.to_owned(), Some(f.to_owned())) 85 }); 86 87 caps 88 } 89 90 #[doc(alias = "gst_caps_fixate")] fixate(&mut self)91 pub fn fixate(&mut self) { 92 skip_assert_initialized!(); 93 unsafe { 94 // See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/388 95 assert!(!self.is_any()); 96 let ptr = if self.is_empty() { 97 ffi::gst_caps_new_empty() 98 } else { 99 ffi::gst_caps_fixate(self.as_mut_ptr()) 100 }; 101 self.replace_ptr(ptr); 102 } 103 } 104 105 #[doc(alias = "gst_caps_merge")] merge(&mut self, other: Self)106 pub fn merge(&mut self, other: Self) { 107 skip_assert_initialized!(); 108 unsafe { 109 let ptr = ffi::gst_caps_merge(self.as_mut_ptr(), other.into_ptr()); 110 self.replace_ptr(ptr); 111 } 112 } 113 114 #[doc(alias = "gst_caps_merge_structure")] merge_structure(&mut self, structure: Structure)115 pub fn merge_structure(&mut self, structure: Structure) { 116 skip_assert_initialized!(); 117 unsafe { 118 let ptr = ffi::gst_caps_merge_structure(self.as_mut_ptr(), structure.into_ptr()); 119 self.replace_ptr(ptr); 120 } 121 } 122 123 #[doc(alias = "gst_caps_merge_structure_full")] merge_structure_full(&mut self, structure: Structure, features: Option<CapsFeatures>)124 pub fn merge_structure_full(&mut self, structure: Structure, features: Option<CapsFeatures>) { 125 skip_assert_initialized!(); 126 unsafe { 127 let ptr = ffi::gst_caps_merge_structure_full( 128 self.as_mut_ptr(), 129 structure.into_ptr(), 130 features.map(|f| f.into_ptr()).unwrap_or(ptr::null_mut()), 131 ); 132 self.replace_ptr(ptr); 133 } 134 } 135 136 #[doc(alias = "gst_caps_normalize")] normalize(&mut self)137 pub fn normalize(&mut self) { 138 skip_assert_initialized!(); 139 unsafe { 140 let ptr = ffi::gst_caps_normalize(self.as_mut_ptr()); 141 self.replace_ptr(ptr); 142 } 143 } 144 145 #[doc(alias = "gst_caps_simplify")] simplify(&mut self)146 pub fn simplify(&mut self) { 147 skip_assert_initialized!(); 148 unsafe { 149 let ptr = ffi::gst_caps_simplify(self.as_mut_ptr()); 150 self.replace_ptr(ptr); 151 } 152 } 153 154 #[doc(alias = "gst_caps_truncate")] truncate(&mut self)155 pub fn truncate(&mut self) { 156 skip_assert_initialized!(); 157 unsafe { 158 let ptr = ffi::gst_caps_truncate(self.as_mut_ptr()); 159 self.replace_ptr(ptr); 160 } 161 } 162 } 163 164 impl str::FromStr for Caps { 165 type Err = glib::BoolError; 166 167 #[doc(alias = "gst_caps_from_string")] from_str(s: &str) -> Result<Self, Self::Err>168 fn from_str(s: &str) -> Result<Self, Self::Err> { 169 assert_initialized_main_thread!(); 170 unsafe { 171 Option::<_>::from_glib_full(ffi::gst_caps_from_string(s.to_glib_none().0)) 172 .ok_or_else(|| glib::bool_error!("Failed to parse caps from string")) 173 } 174 } 175 } 176 177 impl CapsRef { set_simple(&mut self, values: &[(&str, &(dyn ToSendValue + Sync))])178 pub fn set_simple(&mut self, values: &[(&str, &(dyn ToSendValue + Sync))]) { 179 for &(name, value) in values { 180 let value = value.to_value(); 181 182 unsafe { 183 ffi::gst_caps_set_value( 184 self.as_mut_ptr(), 185 name.to_glib_none().0, 186 value.to_glib_none().0, 187 ); 188 } 189 } 190 } 191 192 #[doc(alias = "get_structure")] 193 #[doc(alias = "gst_caps_get_structure")] structure(&self, idx: u32) -> Option<&StructureRef>194 pub fn structure(&self, idx: u32) -> Option<&StructureRef> { 195 if idx >= self.size() { 196 return None; 197 } 198 199 unsafe { 200 let structure = ffi::gst_caps_get_structure(self.as_ptr(), idx); 201 if structure.is_null() { 202 return None; 203 } 204 205 Some(StructureRef::from_glib_borrow(structure)) 206 } 207 } 208 209 #[doc(alias = "get_mut_structure")] structure_mut(&mut self, idx: u32) -> Option<&mut StructureRef>210 pub fn structure_mut(&mut self, idx: u32) -> Option<&mut StructureRef> { 211 if idx >= self.size() { 212 return None; 213 } 214 215 unsafe { 216 let structure = ffi::gst_caps_get_structure(self.as_ptr(), idx); 217 if structure.is_null() { 218 return None; 219 } 220 221 Some(StructureRef::from_glib_borrow_mut(structure)) 222 } 223 } 224 225 #[doc(alias = "get_features")] 226 #[doc(alias = "gst_caps_get_features")] features(&self, idx: u32) -> Option<&CapsFeaturesRef>227 pub fn features(&self, idx: u32) -> Option<&CapsFeaturesRef> { 228 if idx >= self.size() { 229 return None; 230 } 231 232 unsafe { 233 let features = ffi::gst_caps_get_features(self.as_ptr(), idx); 234 Some(CapsFeaturesRef::from_glib_borrow(features)) 235 } 236 } 237 238 #[doc(alias = "get_mut_features")] features_mut(&mut self, idx: u32) -> Option<&mut CapsFeaturesRef>239 pub fn features_mut(&mut self, idx: u32) -> Option<&mut CapsFeaturesRef> { 240 if idx >= self.size() { 241 return None; 242 } 243 244 unsafe { 245 let features = ffi::gst_caps_get_features(self.as_ptr(), idx); 246 Some(CapsFeaturesRef::from_glib_borrow_mut(features)) 247 } 248 } 249 250 #[doc(alias = "gst_caps_set_features")] set_features(&mut self, idx: u32, features: Option<CapsFeatures>)251 pub fn set_features(&mut self, idx: u32, features: Option<CapsFeatures>) { 252 assert!(idx < self.size()); 253 254 unsafe { 255 ffi::gst_caps_set_features( 256 self.as_mut_ptr(), 257 idx, 258 features.map(|f| f.into_ptr()).unwrap_or(ptr::null_mut()), 259 ) 260 } 261 } 262 263 #[cfg(any(feature = "v1_16", feature = "dox"))] 264 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] 265 #[doc(alias = "gst_caps_set_features_simple")] set_features_simple(&mut self, features: Option<CapsFeatures>)266 pub fn set_features_simple(&mut self, features: Option<CapsFeatures>) { 267 unsafe { 268 ffi::gst_caps_set_features_simple( 269 self.as_mut_ptr(), 270 features.map(|f| f.into_ptr()).unwrap_or(ptr::null_mut()), 271 ) 272 } 273 } 274 275 #[doc(alias = "get_size")] 276 #[doc(alias = "gst_caps_get_size")] size(&self) -> u32277 pub fn size(&self) -> u32 { 278 unsafe { ffi::gst_caps_get_size(self.as_ptr()) } 279 } 280 iter(&self) -> Iter281 pub fn iter(&self) -> Iter { 282 Iter::new(self) 283 } 284 iter_mut(&mut self) -> IterMut285 pub fn iter_mut(&mut self) -> IterMut { 286 IterMut::new(self) 287 } 288 iter_with_features(&self) -> IterFeatures289 pub fn iter_with_features(&self) -> IterFeatures { 290 IterFeatures::new(self) 291 } 292 iter_with_features_mut(&mut self) -> IterFeaturesMut293 pub fn iter_with_features_mut(&mut self) -> IterFeaturesMut { 294 IterFeaturesMut::new(self) 295 } 296 297 #[doc(alias = "gst_caps_append_structure")] append_structure(&mut self, structure: Structure)298 pub fn append_structure(&mut self, structure: Structure) { 299 unsafe { ffi::gst_caps_append_structure(self.as_mut_ptr(), structure.into_ptr()) } 300 } 301 302 #[doc(alias = "gst_caps_append_structure_full")] append_structure_full(&mut self, structure: Structure, features: Option<CapsFeatures>)303 pub fn append_structure_full(&mut self, structure: Structure, features: Option<CapsFeatures>) { 304 unsafe { 305 ffi::gst_caps_append_structure_full( 306 self.as_mut_ptr(), 307 structure.into_ptr(), 308 features.map(|f| f.into_ptr()).unwrap_or(ptr::null_mut()), 309 ) 310 } 311 } 312 313 #[doc(alias = "gst_caps_remove_structure")] remove_structure(&mut self, idx: u32)314 pub fn remove_structure(&mut self, idx: u32) { 315 unsafe { ffi::gst_caps_remove_structure(self.as_mut_ptr(), idx) } 316 } 317 318 #[doc(alias = "gst_caps_append")] append(&mut self, other: Caps)319 pub fn append(&mut self, other: Caps) { 320 unsafe { ffi::gst_caps_append(self.as_mut_ptr(), other.into_ptr()) } 321 } 322 323 #[doc(alias = "gst_caps_can_intersect")] can_intersect(&self, other: &Self) -> bool324 pub fn can_intersect(&self, other: &Self) -> bool { 325 unsafe { from_glib(ffi::gst_caps_can_intersect(self.as_ptr(), other.as_ptr())) } 326 } 327 328 #[doc(alias = "gst_caps_intersect")] intersect(&self, other: &Self) -> Caps329 pub fn intersect(&self, other: &Self) -> Caps { 330 unsafe { 331 from_glib_full(ffi::gst_caps_intersect( 332 self.as_mut_ptr(), 333 other.as_mut_ptr(), 334 )) 335 } 336 } 337 intersect_with_mode(&self, other: &Self, mode: CapsIntersectMode) -> Caps338 pub fn intersect_with_mode(&self, other: &Self, mode: CapsIntersectMode) -> Caps { 339 unsafe { 340 from_glib_full(ffi::gst_caps_intersect_full( 341 self.as_mut_ptr(), 342 other.as_mut_ptr(), 343 mode.into_glib(), 344 )) 345 } 346 } 347 348 #[doc(alias = "gst_caps_is_always_compatible")] is_always_compatible(&self, other: &Self) -> bool349 pub fn is_always_compatible(&self, other: &Self) -> bool { 350 unsafe { 351 from_glib(ffi::gst_caps_is_always_compatible( 352 self.as_ptr(), 353 other.as_ptr(), 354 )) 355 } 356 } 357 358 #[doc(alias = "gst_caps_is_any")] is_any(&self) -> bool359 pub fn is_any(&self) -> bool { 360 unsafe { from_glib(ffi::gst_caps_is_any(self.as_ptr())) } 361 } 362 363 #[doc(alias = "gst_caps_is_empty")] is_empty(&self) -> bool364 pub fn is_empty(&self) -> bool { 365 unsafe { from_glib(ffi::gst_caps_is_empty(self.as_ptr())) } 366 } 367 368 #[doc(alias = "gst_caps_is_fixed")] is_fixed(&self) -> bool369 pub fn is_fixed(&self) -> bool { 370 unsafe { from_glib(ffi::gst_caps_is_fixed(self.as_ptr())) } 371 } 372 373 #[doc(alias = "gst_caps_is_equal_fixed")] is_equal_fixed(&self, other: &Self) -> bool374 pub fn is_equal_fixed(&self, other: &Self) -> bool { 375 unsafe { from_glib(ffi::gst_caps_is_equal_fixed(self.as_ptr(), other.as_ptr())) } 376 } 377 378 #[doc(alias = "gst_caps_is_strictly_equal")] is_strictly_equal(&self, other: &Self) -> bool379 pub fn is_strictly_equal(&self, other: &Self) -> bool { 380 unsafe { 381 from_glib(ffi::gst_caps_is_strictly_equal( 382 self.as_ptr(), 383 other.as_ptr(), 384 )) 385 } 386 } 387 388 #[doc(alias = "gst_caps_is_subset")] is_subset(&self, superset: &Self) -> bool389 pub fn is_subset(&self, superset: &Self) -> bool { 390 unsafe { from_glib(ffi::gst_caps_is_subset(self.as_ptr(), superset.as_ptr())) } 391 } 392 393 #[doc(alias = "gst_caps_is_subset_structure")] is_subset_structure(&self, structure: &StructureRef) -> bool394 pub fn is_subset_structure(&self, structure: &StructureRef) -> bool { 395 unsafe { 396 from_glib(ffi::gst_caps_is_subset_structure( 397 self.as_ptr(), 398 structure.as_ptr(), 399 )) 400 } 401 } 402 403 #[doc(alias = "gst_caps_is_subset_structure_full")] is_subset_structure_full( &self, structure: &StructureRef, features: Option<&CapsFeaturesRef>, ) -> bool404 pub fn is_subset_structure_full( 405 &self, 406 structure: &StructureRef, 407 features: Option<&CapsFeaturesRef>, 408 ) -> bool { 409 unsafe { 410 from_glib(ffi::gst_caps_is_subset_structure_full( 411 self.as_ptr(), 412 structure.as_ptr(), 413 features.map(|f| f.as_ptr()).unwrap_or(ptr::null()), 414 )) 415 } 416 } 417 418 #[doc(alias = "gst_caps_subtract")] subtract(&self, other: &Self) -> Caps419 pub fn subtract(&self, other: &Self) -> Caps { 420 skip_assert_initialized!(); 421 unsafe { 422 from_glib_full(ffi::gst_caps_subtract( 423 self.as_mut_ptr(), 424 other.as_mut_ptr(), 425 )) 426 } 427 } 428 429 #[cfg(any(feature = "v1_20", feature = "dox"))] 430 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] 431 #[doc(alias = "gst_caps_serialize")] serialize(&self, flags: crate::SerializeFlags) -> glib::GString432 pub fn serialize(&self, flags: crate::SerializeFlags) -> glib::GString { 433 unsafe { from_glib_full(ffi::gst_caps_serialize(&self.0, flags.into_glib())) } 434 } 435 } 436 437 macro_rules! define_iter( 438 ($name:ident, $typ:ty, $styp:ty, $get_item:expr) => { 439 #[derive(Debug)] 440 pub struct $name<'a> { 441 caps: $typ, 442 idx: u32, 443 n_structures: u32, 444 } 445 446 impl<'a> $name<'a> { 447 fn new(caps: $typ) -> $name<'a> { 448 skip_assert_initialized!(); 449 let n_structures = caps.size(); 450 451 $name { 452 caps, 453 idx: 0, 454 n_structures, 455 } 456 } 457 } 458 459 impl<'a> Iterator for $name<'a> { 460 type Item = $styp; 461 462 fn next(&mut self) -> Option<Self::Item> { 463 if self.idx >= self.n_structures { 464 return None; 465 } 466 467 unsafe { 468 let item = $get_item(self.caps, self.idx)?; 469 self.idx += 1; 470 Some(item) 471 } 472 } 473 474 fn size_hint(&self) -> (usize, Option<usize>) { 475 if self.idx == self.n_structures { 476 return (0, Some(0)); 477 } 478 479 let remaining = (self.n_structures - self.idx) as usize; 480 481 (remaining, Some(remaining)) 482 } 483 } 484 485 impl<'a> DoubleEndedIterator for $name<'a> { 486 fn next_back(&mut self) -> Option<Self::Item> { 487 if self.idx == self.n_structures { 488 return None; 489 } 490 491 self.n_structures -= 1; 492 493 unsafe { 494 $get_item(self.caps, self.n_structures) 495 } 496 } 497 } 498 499 impl<'a> ExactSizeIterator for $name<'a> {} 500 } 501 ); 502 503 define_iter!( 504 Iter, 505 &'a CapsRef, 506 &'a StructureRef, 507 |caps: &CapsRef, idx| { 508 let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx); 509 if ptr.is_null() { 510 None 511 } else { 512 Some(StructureRef::from_glib_borrow( 513 ptr as *const ffi::GstStructure, 514 )) 515 } 516 } 517 ); 518 define_iter!( 519 IterMut, 520 &'a mut CapsRef, 521 &'a mut StructureRef, 522 |caps: &CapsRef, idx| { 523 let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx); 524 if ptr.is_null() { 525 None 526 } else { 527 Some(StructureRef::from_glib_borrow_mut( 528 ptr as *mut ffi::GstStructure, 529 )) 530 } 531 } 532 ); 533 define_iter!( 534 IterFeatures, 535 &'a CapsRef, 536 (&'a StructureRef, &'a CapsFeaturesRef), 537 |caps: &CapsRef, idx| { 538 let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx); 539 let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx); 540 if ptr1.is_null() || ptr2.is_null() { 541 None 542 } else { 543 Some(( 544 StructureRef::from_glib_borrow(ptr1 as *const ffi::GstStructure), 545 CapsFeaturesRef::from_glib_borrow(ptr2 as *const ffi::GstCapsFeatures), 546 )) 547 } 548 } 549 ); 550 define_iter!( 551 IterFeaturesMut, 552 &'a mut CapsRef, 553 (&'a mut StructureRef, &'a mut CapsFeaturesRef), 554 |caps: &CapsRef, idx| { 555 let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx); 556 let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx); 557 if ptr1.is_null() || ptr2.is_null() { 558 None 559 } else { 560 Some(( 561 StructureRef::from_glib_borrow_mut(ptr1 as *mut ffi::GstStructure), 562 CapsFeaturesRef::from_glib_borrow_mut(ptr2 as *mut ffi::GstCapsFeatures), 563 )) 564 } 565 } 566 ); 567 568 impl fmt::Debug for Caps { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result569 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 570 <CapsRef as fmt::Debug>::fmt(self, f) 571 } 572 } 573 574 impl fmt::Display for Caps { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result575 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 576 <CapsRef as fmt::Display>::fmt(self, f) 577 } 578 } 579 580 impl PartialEq for Caps { eq(&self, other: &Caps) -> bool581 fn eq(&self, other: &Caps) -> bool { 582 CapsRef::eq(self, other) 583 } 584 } 585 586 impl Eq for Caps {} 587 588 impl fmt::Debug for CapsRef { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result589 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 590 f.debug_tuple("Caps").field(&self.to_string()).finish() 591 } 592 } 593 594 impl fmt::Display for CapsRef { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result595 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 596 let s = unsafe { glib::GString::from_glib_full(ffi::gst_caps_to_string(self.as_ptr())) }; 597 f.write_str(&s) 598 } 599 } 600 601 impl PartialEq for CapsRef { 602 #[doc(alias = "gst_caps_is_equal")] eq(&self, other: &CapsRef) -> bool603 fn eq(&self, other: &CapsRef) -> bool { 604 unsafe { from_glib(ffi::gst_caps_is_equal(self.as_ptr(), other.as_ptr())) } 605 } 606 } 607 608 impl Eq for CapsRef {} 609 610 pub enum NoFeature {} 611 pub enum HasFeatures {} 612 613 pub struct Builder<T> { 614 s: crate::Structure, 615 features: Option<CapsFeatures>, 616 phantom: PhantomData<T>, 617 } 618 619 impl<T> fmt::Debug for Builder<T> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result620 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 621 f.debug_struct("Builder") 622 .field("s", &self.s) 623 .field("features", &self.features) 624 .field("phantom", &self.phantom) 625 .finish() 626 } 627 } 628 629 impl Builder<NoFeature> { new(name: &str) -> Builder<NoFeature>630 fn new(name: &str) -> Builder<NoFeature> { 631 skip_assert_initialized!(); 632 Builder { 633 s: crate::Structure::new_empty(name), 634 features: None, 635 phantom: PhantomData, 636 } 637 } 638 features(self, features: &[&str]) -> Builder<HasFeatures>639 pub fn features(self, features: &[&str]) -> Builder<HasFeatures> { 640 Builder { 641 s: self.s, 642 features: Some(CapsFeatures::new(features)), 643 phantom: PhantomData, 644 } 645 } 646 any_features(self) -> Builder<HasFeatures>647 pub fn any_features(self) -> Builder<HasFeatures> { 648 Builder { 649 s: self.s, 650 features: Some(CapsFeatures::new_any()), 651 phantom: PhantomData, 652 } 653 } 654 } 655 656 impl<T> Builder<T> { field<V: ToSendValue + Sync>(mut self, name: &str, value: V) -> Self657 pub fn field<V: ToSendValue + Sync>(mut self, name: &str, value: V) -> Self { 658 self.s.set(name, value); 659 self 660 } 661 build(self) -> Caps662 pub fn build(self) -> Caps { 663 let mut caps = Caps::new_empty(); 664 665 caps.get_mut() 666 .unwrap() 667 .append_structure_full(self.s, self.features); 668 caps 669 } 670 } 671 672 pub enum AnyFeatures {} 673 pub enum SomeFeatures {} 674 675 pub struct BuilderFull<T> { 676 caps: crate::Caps, 677 features: Option<CapsFeatures>, 678 phantom: PhantomData<T>, 679 } 680 681 impl<T> fmt::Debug for BuilderFull<T> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result682 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 683 f.debug_struct("Builder") 684 .field("caps", &self.caps) 685 .field("features", &self.features) 686 .field("phantom", &self.phantom) 687 .finish() 688 } 689 } 690 691 impl BuilderFull<SomeFeatures> { new() -> Self692 fn new() -> Self { 693 BuilderFull { 694 caps: Caps::new_empty(), 695 features: None, 696 phantom: PhantomData, 697 } 698 } 699 with_features(features: CapsFeatures) -> Self700 fn with_features(features: CapsFeatures) -> Self { 701 skip_assert_initialized!(); 702 BuilderFull { 703 caps: Caps::new_empty(), 704 features: Some(features), 705 phantom: PhantomData, 706 } 707 } 708 structure_with_features(self, structure: Structure, features: CapsFeatures) -> Self709 pub fn structure_with_features(self, structure: Structure, features: CapsFeatures) -> Self { 710 self.append_structure(structure, Some(features)) 711 } 712 structure_with_any_features(self, structure: Structure) -> Self713 pub fn structure_with_any_features(self, structure: Structure) -> Self { 714 self.append_structure(structure, Some(CapsFeatures::new_any())) 715 } 716 } 717 718 impl BuilderFull<AnyFeatures> { with_any_features() -> Self719 fn with_any_features() -> Self { 720 BuilderFull { 721 caps: Caps::new_empty(), 722 features: Some(CapsFeatures::new_any()), 723 phantom: PhantomData, 724 } 725 } 726 } 727 728 impl<T> BuilderFull<T> { append_structure(mut self, structure: Structure, features: Option<CapsFeatures>) -> Self729 fn append_structure(mut self, structure: Structure, features: Option<CapsFeatures>) -> Self { 730 let features = { 731 match self.features { 732 None => features, 733 Some(ref result) => { 734 let mut result = result.clone(); 735 match features { 736 None => Some(result), 737 Some(features) => { 738 features.iter().for_each(|feat| result.add(feat)); 739 Some(result) 740 } 741 } 742 } 743 } 744 }; 745 746 self.caps 747 .get_mut() 748 .unwrap() 749 .append_structure_full(structure, features); 750 self 751 } 752 structure(self, structure: Structure) -> Self753 pub fn structure(self, structure: Structure) -> Self { 754 self.append_structure(structure, None) 755 } 756 build(self) -> Caps757 pub fn build(self) -> Caps { 758 self.caps 759 } 760 } 761 762 #[cfg(test)] 763 mod tests { 764 use super::*; 765 use crate::Array; 766 use crate::Fraction; 767 768 #[test] test_simple()769 fn test_simple() { 770 crate::init().unwrap(); 771 772 let mut caps = Caps::new_simple( 773 "foo/bar", 774 &[ 775 ("int", &12), 776 ("bool", &true), 777 ("string", &"bla"), 778 ("fraction", &Fraction::new(1, 2)), 779 ("array", &Array::new(&[&1, &2])), 780 ], 781 ); 782 assert_eq!( 783 caps.to_string(), 784 "foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >" 785 ); 786 787 { 788 let s = caps.structure(0).unwrap(); 789 assert_eq!( 790 s, 791 Structure::new( 792 "foo/bar", 793 &[ 794 ("int", &12), 795 ("bool", &true), 796 ("string", &"bla"), 797 ("fraction", &Fraction::new(1, 2)), 798 ("array", &Array::new(&[&1, &2])), 799 ], 800 ) 801 .as_ref() 802 ); 803 } 804 assert!(caps 805 .features(0) 806 .unwrap() 807 .is_equal(crate::CAPS_FEATURES_MEMORY_SYSTEM_MEMORY.as_ref())); 808 809 { 810 let caps = caps.get_mut().unwrap(); 811 caps.set_features(0, Some(CapsFeatures::new(&["foo:bla"]))); 812 } 813 assert!(caps 814 .features(0) 815 .unwrap() 816 .is_equal(CapsFeatures::new(&["foo:bla"]).as_ref())); 817 } 818 819 #[test] test_builder()820 fn test_builder() { 821 crate::init().unwrap(); 822 823 let caps = Caps::builder("foo/bar") 824 .field("int", 12) 825 .field("bool", true) 826 .field("string", "bla") 827 .field("fraction", Fraction::new(1, 2)) 828 .field("array", Array::new(&[&1, &2])) 829 .build(); 830 assert_eq!( 831 caps.to_string(), 832 "foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >" 833 ); 834 835 let caps = Caps::builder("foo/bar") 836 .field("int", &12) 837 .any_features() 838 .build(); 839 assert_eq!(caps.to_string(), "foo/bar(ANY), int=(int)12"); 840 841 let caps = Caps::builder("foo/bar") 842 .field("int", &12) 843 .features(&["foo:bla", "foo:baz"]) 844 .build(); 845 assert_eq!(caps.to_string(), "foo/bar(foo:bla, foo:baz), int=(int)12"); 846 } 847 848 #[test] test_display()849 fn test_display() { 850 crate::init().unwrap(); 851 852 let caps = Caps::new_simple("foo/bar", &[]); 853 format!("{}", caps); 854 } 855 856 #[test] test_builder_full()857 fn test_builder_full() { 858 crate::init().unwrap(); 859 860 let caps = Caps::builder_full() 861 .structure(Structure::builder("audio/x-raw").build()) 862 .structure(Structure::builder("video/x-raw").build()) 863 .build(); 864 assert_eq!(caps.to_string(), "audio/x-raw; video/x-raw"); 865 866 let caps = Caps::builder_full() 867 .structure( 868 Structure::builder("audio/x-raw") 869 .field("format", &"S16LE") 870 .build(), 871 ) 872 .structure(Structure::builder("video/x-raw").build()) 873 .build(); 874 assert_eq!( 875 caps.to_string(), 876 "audio/x-raw, format=(string)S16LE; video/x-raw" 877 ); 878 879 let caps = Caps::builder_full() 880 .structure_with_any_features(Structure::builder("audio/x-raw").build()) 881 .structure_with_features( 882 Structure::builder("video/x-raw").build(), 883 CapsFeatures::new(&["foo:bla", "foo:baz"]), 884 ) 885 .build(); 886 assert_eq!( 887 caps.to_string(), 888 "audio/x-raw(ANY); video/x-raw(foo:bla, foo:baz)" 889 ); 890 } 891 892 #[test] test_builder_full_with_features()893 fn test_builder_full_with_features() { 894 crate::init().unwrap(); 895 896 let caps = Caps::builder_full_with_features(CapsFeatures::new(&["foo:bla"])) 897 .structure(Structure::builder("audio/x-raw").build()) 898 .structure_with_features( 899 Structure::builder("video/x-raw").build(), 900 CapsFeatures::new(&["foo:baz"]), 901 ) 902 .build(); 903 assert_eq!( 904 caps.to_string(), 905 "audio/x-raw(foo:bla); video/x-raw(foo:bla, foo:baz)" 906 ); 907 } 908 909 #[test] test_builder_full_with_any_features()910 fn test_builder_full_with_any_features() { 911 crate::init().unwrap(); 912 913 let caps = Caps::builder_full_with_any_features() 914 .structure(Structure::builder("audio/x-raw").build()) 915 .structure(Structure::builder("video/x-raw").build()) 916 .build(); 917 assert_eq!(caps.to_string(), "audio/x-raw(ANY); video/x-raw(ANY)"); 918 919 let caps = Caps::builder_full_with_any_features() 920 .structure(Structure::builder("audio/x-raw").build()) 921 .build(); 922 assert_eq!(caps.to_string(), "audio/x-raw(ANY)"); 923 } 924 925 #[test] test_new_from_iter()926 fn test_new_from_iter() { 927 crate::init().unwrap(); 928 929 let caps = Caps::builder_full_with_any_features() 930 .structure(Structure::builder("audio/x-raw").build()) 931 .structure(Structure::builder("video/x-raw").build()) 932 .build(); 933 934 let audio = Caps::from_iter(caps.iter().filter(|s| s.name() == "audio/x-raw")); 935 assert_eq!(audio.to_string(), "audio/x-raw"); 936 937 let audio = Caps::from_iter_with_features( 938 caps.iter_with_features() 939 .filter(|(s, _)| s.name() == "audio/x-raw"), 940 ); 941 assert_eq!(audio.to_string(), "audio/x-raw(ANY)"); 942 } 943 } 944