gst: caps: update for IdStr

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1531>
This commit is contained in:
François Laignel 2024-10-10 14:08:54 -04:00
parent 2d2ded555e
commit 0d28cbceac
4 changed files with 696 additions and 12 deletions

View file

@ -61,6 +61,30 @@ impl AudioCapsBuilder<gst::caps::NoFeature> {
} }
} }
// rustdoc-stripper-ignore-next
/// Constructs an `AudioCapsBuilder` for the specified encoding.
///
/// The resulting `Caps` will use the `encoding` argument as name
/// and will not contain any additional fields unless explicitly added.
pub fn for_encoding_from_static(encoding: impl AsRef<glib::GStr> + 'static) -> Self {
assert_initialized_main_thread!();
AudioCapsBuilder {
builder: Caps::builder_from_static(encoding),
}
}
// rustdoc-stripper-ignore-next
/// Constructs an `AudioCapsBuilder` for the specified encoding.
///
/// The resulting `Caps` will use the `encoding` argument as name
/// and will not contain any additional fields unless explicitly added.
pub fn for_encoding_from_id(encoding: impl AsRef<IdStr>) -> Self {
assert_initialized_main_thread!();
AudioCapsBuilder {
builder: Caps::builder_from_id(encoding),
}
}
pub fn any_features(self) -> AudioCapsBuilder<gst::caps::HasFeatures> { pub fn any_features(self) -> AudioCapsBuilder<gst::caps::HasFeatures> {
AudioCapsBuilder { AudioCapsBuilder {
builder: self.builder.any_features(), builder: self.builder.any_features(),
@ -75,6 +99,24 @@ impl AudioCapsBuilder<gst::caps::NoFeature> {
builder: self.builder.features(features), builder: self.builder.features(features),
} }
} }
pub fn features_from_statics(
self,
features: impl IntoIterator<Item = impl AsRef<glib::GStr> + 'static>,
) -> AudioCapsBuilder<gst::caps::HasFeatures> {
AudioCapsBuilder {
builder: self.builder.features_from_statics(features),
}
}
pub fn features_from_ids(
self,
features: impl IntoIterator<Item = impl AsRef<IdStr>>,
) -> AudioCapsBuilder<gst::caps::HasFeatures> {
AudioCapsBuilder {
builder: self.builder.features_from_ids(features),
}
}
} }
impl Default for AudioCapsBuilder<gst::caps::NoFeature> { impl Default for AudioCapsBuilder<gst::caps::NoFeature> {

View file

@ -43,6 +43,30 @@ impl VideoCapsBuilder<gst::caps::NoFeature> {
} }
} }
// rustdoc-stripper-ignore-next
/// Constructs an `VideoCapsBuilder` for the specified encoding.
///
/// The resulting `Caps` will use the `encoding` argument as name
/// and will not contain any additional fields unless explicitly added.
pub fn for_encoding_from_static(encoding: impl AsRef<glib::GStr> + 'static) -> Self {
assert_initialized_main_thread!();
VideoCapsBuilder {
builder: Caps::builder_from_static(encoding),
}
}
// rustdoc-stripper-ignore-next
/// Constructs an `VideoCapsBuilder` for the specified encoding.
///
/// The resulting `Caps` will use the `encoding` argument as name
/// and will not contain any additional fields unless explicitly added.
pub fn for_encoding_from_id(encoding: impl AsRef<IdStr>) -> Self {
assert_initialized_main_thread!();
VideoCapsBuilder {
builder: Caps::builder_from_id(encoding),
}
}
pub fn any_features(self) -> VideoCapsBuilder<gst::caps::HasFeatures> { pub fn any_features(self) -> VideoCapsBuilder<gst::caps::HasFeatures> {
VideoCapsBuilder { VideoCapsBuilder {
builder: self.builder.any_features(), builder: self.builder.any_features(),
@ -57,6 +81,24 @@ impl VideoCapsBuilder<gst::caps::NoFeature> {
builder: self.builder.features(features), builder: self.builder.features(features),
} }
} }
pub fn features_from_statics(
self,
features: impl IntoIterator<Item = impl AsRef<glib::GStr> + 'static>,
) -> VideoCapsBuilder<gst::caps::HasFeatures> {
VideoCapsBuilder {
builder: self.builder.features_from_statics(features),
}
}
pub fn features_from_ids(
self,
features: impl IntoIterator<Item = impl AsRef<IdStr>>,
) -> VideoCapsBuilder<gst::caps::HasFeatures> {
VideoCapsBuilder {
builder: self.builder.features_from_ids(features),
}
}
} }
impl Default for VideoCapsBuilder<gst::caps::NoFeature> { impl Default for VideoCapsBuilder<gst::caps::NoFeature> {

View file

@ -2,10 +2,12 @@
use std::{fmt, marker::PhantomData, ptr, str}; use std::{fmt, marker::PhantomData, ptr, str};
use cfg_if::cfg_if;
use glib::{ use glib::{
prelude::*, prelude::*,
translate::*, translate::*,
value::{SendValue, ToSendValue}, value::{SendValue, ToSendValue},
GStr,
}; };
use crate::{caps_features::*, ffi, structure::*, CapsIntersectMode, IdStr}; use crate::{caps_features::*, ffi, structure::*, CapsIntersectMode, IdStr};
@ -19,6 +21,18 @@ impl Caps {
Builder::new(name) Builder::new(name)
} }
#[doc(alias = "gst_caps_new_static_str_simple")]
pub fn builder_from_static(name: impl AsRef<GStr> + 'static) -> Builder<NoFeature> {
assert_initialized_main_thread!();
Builder::from_static(name)
}
#[doc(alias = "gst_caps_new_id_str_simple")]
pub fn builder_from_id(name: impl AsRef<IdStr>) -> Builder<NoFeature> {
assert_initialized_main_thread!();
Builder::from_id(name)
}
#[doc(alias = "gst_caps_new_full")] #[doc(alias = "gst_caps_new_full")]
pub fn builder_full() -> BuilderFull<SomeFeatures> { pub fn builder_full() -> BuilderFull<SomeFeatures> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
@ -60,6 +74,28 @@ impl Caps {
caps caps
} }
#[doc(alias = "gst_caps_new_static_str_empty_simple")]
pub fn new_empty_simple_from_static(name: impl AsRef<GStr> + 'static) -> Self {
skip_assert_initialized!();
let mut caps = Caps::new_empty();
let structure = Structure::new_empty_from_static(name);
caps.get_mut().unwrap().append_structure(structure);
caps
}
#[doc(alias = "gst_caps_new_id_str_empty_simple")]
pub fn new_empty_simple_from_id(name: impl AsRef<IdStr>) -> Self {
skip_assert_initialized!();
let mut caps = Caps::new_empty();
let structure = Structure::new_empty_from_id(name);
caps.get_mut().unwrap().append_structure(structure);
caps
}
#[doc(alias = "gst_caps_fixate")] #[doc(alias = "gst_caps_fixate")]
pub fn fixate(&mut self) { pub fn fixate(&mut self) {
unsafe { unsafe {
@ -313,6 +349,32 @@ impl CapsRef {
self.set_value(name, value); self.set_value(name, value);
} }
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given value `value`.
///
/// Overrides any default or previously defined value for `name`.
#[doc(alias = "gst_caps_set_value_static_str")]
#[doc(alias = "gst_caps_set_simple_static_str")]
pub fn set_with_static(
&mut self,
name: impl AsRef<GStr> + 'static,
value: impl ToSendValue + Sync,
) {
let value = value.to_send_value();
self.set_value_with_static(name, value);
}
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given value `value`.
///
/// Overrides any default or previously defined value for `name`.
#[doc(alias = "gst_caps_id_str_set_value")]
#[doc(alias = "gst_caps_id_str_set_simple")]
pub fn set_with_id(&mut self, name: impl AsRef<IdStr>, value: impl ToSendValue + Sync) {
let value = value.to_send_value();
self.set_value_with_id(name, value);
}
// rustdoc-stripper-ignore-next // rustdoc-stripper-ignore-next
/// Sets field `name` to the given value if the `predicate` evaluates to `true`. /// Sets field `name` to the given value if the `predicate` evaluates to `true`.
/// ///
@ -326,6 +388,42 @@ impl CapsRef {
} }
} }
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given value if the `predicate` evaluates to `true`.
///
/// This has no effect if the `predicate` evaluates to `false`,
/// i.e. default or previous value for `name` is kept.
#[doc(alias = "gst_caps_set_value_static_str")]
#[doc(alias = "gst_caps_set_simple_static_str")]
pub fn set_with_static_if(
&mut self,
name: impl AsRef<GStr> + 'static,
value: impl ToSendValue + Sync,
predicate: bool,
) {
if predicate {
self.set_with_static(name, value);
}
}
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given value if the `predicate` evaluates to `true`.
///
/// This has no effect if the `predicate` evaluates to `false`,
/// i.e. default or previous value for `name` is kept.
#[doc(alias = "gst_caps_id_str_set_value")]
#[doc(alias = "gst_caps_id_str_set_simple")]
pub fn set_with_id_if(
&mut self,
name: impl AsRef<IdStr>,
value: impl ToSendValue + Sync,
predicate: bool,
) {
if predicate {
self.set_with_id(name, value);
}
}
// rustdoc-stripper-ignore-next // rustdoc-stripper-ignore-next
/// Sets field `name` to the given inner value if `value` is `Some`. /// Sets field `name` to the given inner value if `value` is `Some`.
/// ///
@ -338,6 +436,38 @@ impl CapsRef {
} }
} }
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given inner value if `value` is `Some`.
///
/// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
#[doc(alias = "gst_caps_set_value_static_str")]
#[doc(alias = "gst_caps_set_simple_static_str")]
pub fn set_with_static_if_some(
&mut self,
name: impl AsRef<GStr> + 'static,
value: Option<impl ToSendValue + Sync>,
) {
if let Some(value) = value {
self.set_with_static(name, value);
}
}
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given inner value if `value` is `Some`.
///
/// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
#[doc(alias = "gst_caps_id_str_set_value")]
#[doc(alias = "gst_caps_id_str_set_simple")]
pub fn set_with_id_if_some(
&mut self,
name: impl AsRef<IdStr>,
value: Option<impl ToSendValue + Sync>,
) {
if let Some(value) = value {
self.set_with_id(name, value);
}
}
// rustdoc-stripper-ignore-next // rustdoc-stripper-ignore-next
/// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s. /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
/// ///
@ -352,6 +482,36 @@ impl CapsRef {
self.set(name, V::from_iter(iter)); self.set(name, V::from_iter(iter));
} }
// rustdoc-stripper-ignore-next
/// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
///
/// Overrides any default or previously defined value for `name`.
#[inline]
pub fn set_with_static_from_iter<
V: ValueType + ToSendValue + FromIterator<SendValue> + Sync,
>(
&mut self,
name: impl AsRef<GStr> + 'static,
iter: impl IntoIterator<Item = impl ToSendValue>,
) {
let iter = iter.into_iter().map(|item| item.to_send_value());
self.set_with_static(name, V::from_iter(iter));
}
// rustdoc-stripper-ignore-next
/// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
///
/// Overrides any default or previously defined value for `name`.
#[inline]
pub fn set_with_id_from_iter<V: ValueType + ToSendValue + FromIterator<SendValue> + Sync>(
&mut self,
name: impl AsRef<IdStr>,
iter: impl IntoIterator<Item = impl ToSendValue>,
) {
let iter = iter.into_iter().map(|item| item.to_send_value());
self.set_with_id(name, V::from_iter(iter));
}
// rustdoc-stripper-ignore-next // rustdoc-stripper-ignore-next
/// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s, /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
/// if `iter` is not empty. /// if `iter` is not empty.
@ -370,6 +530,44 @@ impl CapsRef {
} }
} }
// rustdoc-stripper-ignore-next
/// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
/// if `iter` is not empty.
///
/// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
#[inline]
pub fn set_with_static_if_not_empty<
V: ValueType + ToSendValue + FromIterator<SendValue> + Sync,
>(
&mut self,
name: impl AsRef<GStr> + 'static,
iter: impl IntoIterator<Item = impl ToSendValue>,
) {
let mut iter = iter.into_iter().peekable();
if iter.peek().is_some() {
let iter = iter.map(|item| item.to_send_value());
self.set_with_static(name, V::from_iter(iter));
}
}
// rustdoc-stripper-ignore-next
/// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
/// if `iter` is not empty.
///
/// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
#[inline]
pub fn set_with_id_if_not_empty<V: ValueType + ToSendValue + FromIterator<SendValue> + Sync>(
&mut self,
name: impl AsRef<IdStr>,
iter: impl IntoIterator<Item = impl ToSendValue>,
) {
let mut iter = iter.into_iter().peekable();
if iter.peek().is_some() {
let iter = iter.map(|item| item.to_send_value());
self.set_with_id(name, V::from_iter(iter));
}
}
// rustdoc-stripper-ignore-next // rustdoc-stripper-ignore-next
/// Sets field `name` to the given value `value`. /// Sets field `name` to the given value `value`.
/// ///
@ -383,6 +581,52 @@ impl CapsRef {
} }
} }
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given value `value`.
///
/// Overrides any default or previously defined value for `name`.
#[doc(alias = "gst_caps_set_value_static_str")]
pub fn set_value_with_static(
&mut self,
name: impl AsRef<GStr> + 'static,
value: glib::SendValue,
) {
unsafe {
cfg_if! {
if #[cfg(feature = "v1_26")] {
ffi::gst_caps_set_value_static_str(
self.as_mut_ptr(),
name.as_ref().as_ptr(),
value.to_glib_none().0,
)
} else {
ffi::gst_caps_set_value(self.as_mut_ptr(), name.as_ref().as_ptr(), value.to_glib_none().0)
}
}
}
}
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given value `value`.
///
/// Overrides any default or previously defined value for `name`.
#[doc(alias = "gst_caps_id_str_set_value")]
pub fn set_value_with_id(&mut self, name: impl AsRef<IdStr>, value: glib::SendValue) {
unsafe {
cfg_if! {
if #[cfg(feature = "v1_26")] {
ffi::gst_caps_id_str_set_value(
self.as_mut_ptr(),
name.as_ref().as_ptr(),
value.to_glib_none().0,
)
} else {
ffi::gst_caps_set_value(self.as_mut_ptr(), name.as_ref().as_gstr().as_ptr(), value.to_glib_none().0)
}
}
}
}
// rustdoc-stripper-ignore-next // rustdoc-stripper-ignore-next
/// Sets field `name` to the given `value` if the `predicate` evaluates to `true`. /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
/// ///
@ -395,6 +639,40 @@ impl CapsRef {
} }
} }
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
///
/// This has no effect if the `predicate` evaluates to `false`,
/// i.e. default or previous value for `name` is kept.
#[doc(alias = "gst_caps_set_value_static_str")]
pub fn set_value_with_static_if(
&mut self,
name: impl AsRef<GStr> + 'static,
value: SendValue,
predicate: bool,
) {
if predicate {
self.set_value_with_static(name, value);
}
}
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
///
/// This has no effect if the `predicate` evaluates to `false`,
/// i.e. default or previous value for `name` is kept.
#[doc(alias = "gst_caps_id_str_set_value")]
pub fn set_value_with_id_if(
&mut self,
name: impl AsRef<IdStr>,
value: SendValue,
predicate: bool,
) {
if predicate {
self.set_value_with_id(name, value);
}
}
// rustdoc-stripper-ignore-next // rustdoc-stripper-ignore-next
/// Sets field `name` to the given inner value if `value` is `Some`. /// Sets field `name` to the given inner value if `value` is `Some`.
/// ///
@ -406,6 +684,32 @@ impl CapsRef {
} }
} }
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given inner value if `value` is `Some`.
///
/// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
#[doc(alias = "gst_caps_set_value_static_str")]
pub fn set_value_with_static_if_some(
&mut self,
name: impl AsRef<GStr> + 'static,
value: Option<SendValue>,
) {
if let Some(value) = value {
self.set_value_with_static(name, value);
}
}
// rustdoc-stripper-ignore-next
/// Sets field `name` to the given inner value if `value` is `Some`.
///
/// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
#[doc(alias = "gst_caps_id_str_set_value")]
pub fn set_value_with_id_if_some(&mut self, name: impl AsRef<IdStr>, value: Option<SendValue>) {
if let Some(value) = value {
self.set_value_with_id(name, value);
}
}
#[doc(alias = "get_structure")] #[doc(alias = "get_structure")]
#[doc(alias = "gst_caps_get_structure")] #[doc(alias = "gst_caps_get_structure")]
pub fn structure(&self, idx: usize) -> Option<&StructureRef> { pub fn structure(&self, idx: usize) -> Option<&StructureRef> {
@ -700,7 +1004,7 @@ impl CapsRef {
>( >(
&mut self, &mut self,
mut func: F, mut func: F,
) -> bool { ) {
unsafe { unsafe {
unsafe extern "C" fn trampoline< unsafe extern "C" fn trampoline<
F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> std::ops::ControlFlow<()>, F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> std::ops::ControlFlow<()>,
@ -718,11 +1022,11 @@ impl CapsRef {
matches!(res, std::ops::ControlFlow::Continue(_)).into_glib() matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
} }
let func = &mut func as *mut F; let func = &mut func as *mut F;
from_glib(ffi::gst_caps_map_in_place( let _ = ffi::gst_caps_map_in_place(
self.as_mut_ptr(), self.as_mut_ptr(),
Some(trampoline::<F>), Some(trampoline::<F>),
func as glib::ffi::gpointer, func as glib::ffi::gpointer,
)) );
} }
} }
@ -1085,6 +1389,24 @@ impl Builder<NoFeature> {
} }
} }
fn from_static(name: impl AsRef<GStr> + 'static) -> Builder<NoFeature> {
skip_assert_initialized!();
Builder {
s: crate::Structure::new_empty_from_static(name),
features: None,
phantom: PhantomData,
}
}
fn from_id(name: impl AsRef<IdStr>) -> Builder<NoFeature> {
skip_assert_initialized!();
Builder {
s: crate::Structure::new_empty_from_id(name),
features: None,
phantom: PhantomData,
}
}
pub fn features( pub fn features(
self, self,
features: impl IntoIterator<Item = impl IntoGStr>, features: impl IntoIterator<Item = impl IntoGStr>,
@ -1096,6 +1418,28 @@ impl Builder<NoFeature> {
} }
} }
pub fn features_from_statics(
self,
features: impl IntoIterator<Item = impl AsRef<GStr> + 'static>,
) -> Builder<HasFeatures> {
Builder {
s: self.s,
features: Some(CapsFeatures::new_from_static(features)),
phantom: PhantomData,
}
}
pub fn features_from_ids(
self,
features: impl IntoIterator<Item = impl AsRef<IdStr>>,
) -> Builder<HasFeatures> {
Builder {
s: self.s,
features: Some(CapsFeatures::new_from_id(features)),
phantom: PhantomData,
}
}
pub fn any_features(self) -> Builder<HasFeatures> { pub fn any_features(self) -> Builder<HasFeatures> {
Builder { Builder {
s: self.s, s: self.s,
@ -1285,6 +1629,7 @@ impl<T> BuilderFull<T> {
mod tests { mod tests {
use super::*; use super::*;
use crate::{Array, Fraction}; use crate::{Array, Fraction};
use glib::gstr;
#[test] #[test]
fn test_builder() { fn test_builder() {
@ -1292,10 +1637,10 @@ mod tests {
let mut caps = Caps::builder("foo/bar") let mut caps = Caps::builder("foo/bar")
.field("int", 12) .field("int", 12)
.field("bool", true) .field_with_static(gstr!("bool"), true)
.field("string", "bla") .field_with_id(idstr!("string"), "bla")
.field("fraction", Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", Array::new([1, 2])) .field_with_id(idstr!("array"), Array::new([1, 2]))
.build(); .build();
assert_eq!( assert_eq!(
caps.to_string(), caps.to_string(),
@ -1331,8 +1676,8 @@ mod tests {
let caps = Caps::builder("foo/bar") let caps = Caps::builder("foo/bar")
.field_if_some("int0", Option::<i32>::None) .field_if_some("int0", Option::<i32>::None)
.field_if_some("int1", Some(12)) .field_if_some("int1", Some(12))
.field_if_some("string0", Option::<String>::None) .field_with_static_if_some(gstr!("string0"), Option::<String>::None)
.field_if_some("string1", Some("bla")) .field_with_id_if_some(idstr!("string1"), Some("bla"))
.build(); .build();
assert_eq!( assert_eq!(
caps.to_string(), caps.to_string(),
@ -1397,7 +1742,7 @@ mod tests {
.structure_with_any_features_if_some(Some(Structure::builder("audio/x-raw").build())) .structure_with_any_features_if_some(Some(Structure::builder("audio/x-raw").build()))
.structure_with_features_if_some( .structure_with_features_if_some(
Some(Structure::builder("video/x-raw").build()), Some(Structure::builder("video/x-raw").build()),
CapsFeatures::new(["foo:bla", "foo:baz"]), CapsFeatures::new_from_id([idstr!("foo:bla"), idstr!("foo:baz")]),
) )
.build(); .build();
assert_eq!( assert_eq!(

View file

@ -9,7 +9,8 @@ use std::{
ptr, str, ptr, str,
}; };
use crate::ffi; use crate::{ffi, IdStr};
use cfg_if::cfg_if;
use glib::{prelude::*, translate::*}; use glib::{prelude::*, translate::*};
use std::sync::LazyLock; use std::sync::LazyLock;
@ -32,6 +33,34 @@ impl CapsFeatures {
f f
} }
#[doc(alias = "gst_caps_features_new_static_str")]
pub fn new_from_static(
features: impl IntoIterator<Item = impl AsRef<glib::GStr> + 'static>,
) -> Self {
skip_assert_initialized!();
let mut f = Self::new_empty();
for feature in features {
f.add_from_static(feature);
}
f
}
#[doc(alias = "gst_caps_features_new_id_str")]
pub fn new_from_id(features: impl IntoIterator<Item = impl AsRef<IdStr>>) -> Self {
skip_assert_initialized!();
let mut f = Self::new_empty();
for feature in features {
f.add_from_id(feature);
}
f
}
#[deprecated = "use `new_by_id()` instead"]
#[allow(deprecated)]
#[doc(alias = "gst_caps_features_new_id")] #[doc(alias = "gst_caps_features_new_id")]
pub fn from_quarks(features: impl IntoIterator<Item = glib::Quark>) -> Self { pub fn from_quarks(features: impl IntoIterator<Item = glib::Quark>) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
@ -372,6 +401,26 @@ impl CapsFeaturesRef {
} }
} }
#[doc(alias = "gst_caps_features_contains_id_str")]
pub fn contains_by_id(&self, feature: impl AsRef<IdStr>) -> bool {
unsafe {
cfg_if! {
if #[cfg(feature = "v1_26")] {
from_glib(ffi::gst_caps_features_contains_id_str(
self.as_ptr(),
feature.as_ref().as_ptr(),
))
} else {
from_glib(ffi::gst_caps_features_contains(
self.as_ptr(),
feature.as_ref().as_gstr().as_ptr(),
))
}
}
}
}
#[deprecated = "use `contains_by_id()` instead"]
#[doc(alias = "gst_caps_features_contains_id")] #[doc(alias = "gst_caps_features_contains_id")]
pub fn contains_quark(&self, feature: glib::Quark) -> bool { pub fn contains_quark(&self, feature: glib::Quark) -> bool {
unsafe { unsafe {
@ -401,12 +450,29 @@ impl CapsFeaturesRef {
return None; return None;
} }
// Safety: we can return a GStr based on the feature here because
// the lifetime of the returned value is constrained by &self.
Some(glib::GStr::from_ptr(feature)) Some(glib::GStr::from_ptr(feature))
} }
} }
#[cfg(feature = "v1_26")]
#[doc(alias = "get_nth_by_id")]
#[doc(alias = "gst_caps_features_get_nth_id_str")]
pub fn nth_id(&self, idx: usize) -> Option<&IdStr> {
if idx >= self.size() {
return None;
}
unsafe {
let feature = ffi::gst_caps_features_get_nth_id_str(self.as_ptr(), idx as u32);
if feature.is_null() {
return None;
}
Some(&*(feature as *const IdStr))
}
}
#[deprecated = "use `nth_by_id()` instead"]
#[doc(alias = "gst_caps_features_get_nth_id")] #[doc(alias = "gst_caps_features_get_nth_id")]
pub fn nth_quark(&self, idx: usize) -> Option<glib::Quark> { pub fn nth_quark(&self, idx: usize) -> Option<glib::Quark> {
if idx >= self.size() { if idx >= self.size() {
@ -428,6 +494,32 @@ impl CapsFeaturesRef {
} }
} }
#[doc(alias = "gst_caps_features_add_static_str")]
pub fn add_from_static(&mut self, feature: impl AsRef<glib::GStr> + 'static) {
unsafe {
cfg_if! {
if #[cfg(feature = "v1_26")] {
ffi::gst_caps_features_add_static_str(self.as_mut_ptr(), feature.as_ref().as_ptr())
} else {
ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ref().as_ptr())
}
}
}
}
#[doc(alias = "gst_caps_features_add_id_str")]
pub fn add_from_id(&mut self, feature: impl AsRef<IdStr>) {
unsafe {
cfg_if! {
if #[cfg(feature = "v1_26")] {
ffi::gst_caps_features_add_id_str(self.as_mut_ptr(), feature.as_ref().as_ptr())
} else {
ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ref().as_gstr().as_ptr())
}
}
}
}
#[doc(alias = "gst_caps_features_remove")] #[doc(alias = "gst_caps_features_remove")]
pub fn remove(&mut self, feature: impl IntoGStr) { pub fn remove(&mut self, feature: impl IntoGStr) {
unsafe { unsafe {
@ -437,11 +529,26 @@ impl CapsFeaturesRef {
} }
} }
#[doc(alias = "gst_caps_features_remove_id_str")]
pub fn remove_by_id(&mut self, feature: impl AsRef<IdStr>) {
unsafe {
cfg_if! {
if #[cfg(feature = "v1_26")] {
ffi::gst_caps_features_remove_id_str(self.as_mut_ptr(), feature.as_ref().as_ptr())
} else {
ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.as_ref().as_gstr().as_ptr())
}
}
}
}
#[deprecated = "use `add_by_id()` instead"]
#[doc(alias = "gst_caps_features_add_id")] #[doc(alias = "gst_caps_features_add_id")]
pub fn add_from_quark(&mut self, feature: glib::Quark) { pub fn add_from_quark(&mut self, feature: glib::Quark) {
unsafe { ffi::gst_caps_features_add_id(self.as_mut_ptr(), feature.into_glib()) } unsafe { ffi::gst_caps_features_add_id(self.as_mut_ptr(), feature.into_glib()) }
} }
#[deprecated = "use `remove_by_id()` instead"]
#[doc(alias = "gst_caps_features_remove_id")] #[doc(alias = "gst_caps_features_remove_id")]
pub fn remove_by_quark(&mut self, feature: glib::Quark) { pub fn remove_by_quark(&mut self, feature: glib::Quark) {
unsafe { ffi::gst_caps_features_remove_id(self.as_mut_ptr(), feature.into_glib()) } unsafe { ffi::gst_caps_features_remove_id(self.as_mut_ptr(), feature.into_glib()) }
@ -494,7 +601,14 @@ impl std::iter::Extend<glib::GString> for CapsFeaturesRef {
} }
} }
impl<Id: AsRef<IdStr>> std::iter::Extend<Id> for CapsFeaturesRef {
fn extend<T: IntoIterator<Item = Id>>(&mut self, iter: T) {
iter.into_iter().for_each(|f| self.add_from_id(f));
}
}
impl std::iter::Extend<glib::Quark> for CapsFeaturesRef { impl std::iter::Extend<glib::Quark> for CapsFeaturesRef {
#[allow(deprecated)]
fn extend<T: IntoIterator<Item = glib::Quark>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = glib::Quark>>(&mut self, iter: T) {
iter.into_iter().for_each(|f| self.add_from_quark(f)); iter.into_iter().for_each(|f| self.add_from_quark(f));
} }
@ -706,7 +820,19 @@ impl<'a> From<&'a glib::GStr> for CapsFeatures {
} }
} }
impl<Id: AsRef<IdStr>> From<Id> for CapsFeatures {
fn from(value: Id) -> Self {
skip_assert_initialized!();
let mut features = CapsFeatures::new_empty();
features.add_from_id(value);
features
}
}
impl From<glib::Quark> for CapsFeatures { impl From<glib::Quark> for CapsFeatures {
#[allow(deprecated)]
fn from(value: glib::Quark) -> Self { fn from(value: glib::Quark) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
let mut features = CapsFeatures::new_empty(); let mut features = CapsFeatures::new_empty();
@ -761,7 +887,19 @@ impl<const N: usize> From<[glib::GString; N]> for CapsFeatures {
} }
} }
impl<const N: usize, Id: AsRef<IdStr>> From<[Id; N]> for CapsFeatures {
fn from(value: [Id; N]) -> Self {
skip_assert_initialized!();
let mut features = CapsFeatures::new_empty();
value.into_iter().for_each(|f| features.add_from_id(f));
features
}
}
impl<const N: usize> From<[glib::Quark; N]> for CapsFeatures { impl<const N: usize> From<[glib::Quark; N]> for CapsFeatures {
#[allow(deprecated)]
fn from(value: [glib::Quark; N]) -> Self { fn from(value: [glib::Quark; N]) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
let mut features = CapsFeatures::new_empty(); let mut features = CapsFeatures::new_empty();
@ -818,7 +956,20 @@ impl std::iter::FromIterator<glib::GString> for CapsFeatures {
} }
} }
impl<Id: AsRef<IdStr>> std::iter::FromIterator<Id> for CapsFeatures {
#[allow(deprecated)]
fn from_iter<T: IntoIterator<Item = Id>>(iter: T) -> Self {
skip_assert_initialized!();
let mut features = CapsFeatures::new_empty();
iter.into_iter().for_each(|f| features.add_from_id(f));
features
}
}
impl std::iter::FromIterator<glib::Quark> for CapsFeatures { impl std::iter::FromIterator<glib::Quark> for CapsFeatures {
#[allow(deprecated)]
fn from_iter<T: IntoIterator<Item = glib::Quark>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = glib::Quark>>(iter: T) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
let mut features = CapsFeatures::new_empty(); let mut features = CapsFeatures::new_empty();
@ -866,6 +1017,8 @@ pub static CAPS_FEATURES_MEMORY_SYSTEM_MEMORY: LazyLock<CapsFeatures> =
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::idstr;
use glib::gstr;
#[test] #[test]
fn test_from_value_optional() { fn test_from_value_optional() {
@ -878,4 +1031,106 @@ mod tests {
let b = glib::value::Value::from(&CapsFeatures::new_empty()); let b = glib::value::Value::from(&CapsFeatures::new_empty());
assert!(b.get::<Option<CapsFeatures>>().unwrap().is_some()); assert!(b.get::<Option<CapsFeatures>>().unwrap().is_some());
} }
#[test]
fn trait_impls() {
crate::init().unwrap();
let cf = CapsFeatures::from(gstr!("memory:DMABuf"));
assert!(cf.contains(gstr!("memory:DMABuf")));
let cf = CapsFeatures::from([
gstr!("memory:DMABuf"),
gstr!("meta:GstVideoOverlayComposition"),
]);
assert!(cf.contains(gstr!("memory:DMABuf")));
assert!(cf.contains("meta:GstVideoOverlayComposition"));
assert!(!cf.contains("memory:GLMemory"));
let cf = CapsFeatures::from_iter(vec![
gstr!("memory:DMABuf"),
gstr!("meta:GstVideoOverlayComposition"),
]);
assert!(cf.contains(gstr!("memory:DMABuf")));
assert!(cf.contains("meta:GstVideoOverlayComposition"));
assert!(!cf.contains("memory:GLMemory"));
let mut cf = CapsFeatures::new_empty();
cf.extend([
gstr!("memory:DMABuf"),
gstr!("meta:GstVideoOverlayComposition"),
]);
assert!(cf.contains(gstr!("memory:DMABuf")));
assert!(cf.contains("meta:GstVideoOverlayComposition"));
assert!(!cf.contains("memory:GLMemory"));
}
#[test]
fn trait_impls_from_id() {
crate::init().unwrap();
let cf = CapsFeatures::from(idstr!("memory:DMABuf"));
assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
let cf = CapsFeatures::from([
idstr!("memory:DMABuf"),
idstr!("meta:GstVideoOverlayComposition"),
]);
assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
assert!(cf.contains("meta:GstVideoOverlayComposition"));
assert!(!cf.contains("memory:GLMemory"));
let cf = CapsFeatures::from_iter(vec![
idstr!("memory:DMABuf"),
idstr!("meta:GstVideoOverlayComposition"),
]);
assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
assert!(cf.contains("meta:GstVideoOverlayComposition"));
assert!(!cf.contains("memory:GLMemory"));
let mut cf = CapsFeatures::new_empty();
cf.extend([
idstr!("memory:DMABuf"),
idstr!("meta:GstVideoOverlayComposition"),
]);
assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
assert!(cf.contains("meta:GstVideoOverlayComposition"));
assert!(!cf.contains("memory:GLMemory"));
}
#[test]
fn trait_impls_from_ref_id() {
crate::init().unwrap();
let dma_buf = idstr!("memory:DMABuf");
let overlay_comp = idstr!("meta:GstVideoOverlayComposition");
let cf = CapsFeatures::from(&dma_buf);
assert!(cf.contains_by_id(&dma_buf));
let cf = CapsFeatures::from([&dma_buf, &overlay_comp]);
assert!(cf.contains_by_id(&dma_buf));
assert!(cf.contains_by_id(&overlay_comp));
assert!(!cf.contains("memory:GLMemory"));
let cf = CapsFeatures::from_iter(vec![&dma_buf, &overlay_comp]);
assert!(cf.contains_by_id(&dma_buf));
assert!(cf.contains_by_id(&overlay_comp));
assert!(!cf.contains("memory:GLMemory"));
let mut cf = CapsFeatures::new_empty();
cf.extend([&dma_buf, &overlay_comp]);
assert!(cf.contains_by_id(dma_buf));
assert!(cf.contains_by_id(overlay_comp));
assert!(!cf.contains("memory:GLMemory"));
}
} }