mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-10-31 22:59:14 +00:00
builders: add field_if_any and field_from_iter variants
This commit adds `field_if_any` variants for `IntoIterator` builders fields. The field will only be set if the provided collection is not empty. For `Element` properties and other `Value` based setters, the function takes a parameter to indicate the `ValueType` to use for the resulting `Value`. This allows converting this code: ```rust let webrtcsrc = gst::ElementFactory::make("webrtcsrc") .build() .unwrap(); if !args.audio_codecs.is_empty() { webrtcsrc.set_property("audio-codecs", gst::Array::new(&args.audio_codecs)); } ``` to: ```rust let webrtcsrc = gst::ElementFactory::make("webrtcsrc") .property_if_any::<gst::Array>("audio-codecs", &args.audio_codecs) .build() .unwrap(); ```` Similarly, a new function `field_from_iter()` allows settings the property or field, regardless of whether it is empty or not: ```rust let webrtcsrc = gst::ElementFactory::make("webrtcsrc") .property_from_iter::<gst::Array>("audio-codecs", &args.audio_codecs) .build() .unwrap(); ```` The above will override the default value if `args.audio_codecs` is empty.
This commit is contained in:
parent
e117010bc0
commit
e9b8029685
7 changed files with 405 additions and 7 deletions
|
@ -2,6 +2,7 @@ use std::ops::{Bound::*, RangeBounds};
|
||||||
|
|
||||||
use gst::Caps;
|
use gst::Caps;
|
||||||
|
|
||||||
|
use glib::value::{SendValue, Value, ValueType};
|
||||||
use glib::IntoGStr;
|
use glib::IntoGStr;
|
||||||
|
|
||||||
use crate::{AudioFormat, AudioLayout};
|
use crate::{AudioFormat, AudioLayout};
|
||||||
|
@ -118,6 +119,15 @@ impl<T> AudioCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn format_list_if_any(self, formats: impl IntoIterator<Item = AudioFormat>) -> Self {
|
||||||
|
let mut formats = formats.into_iter().peekable();
|
||||||
|
if formats.peek().is_some() {
|
||||||
|
self.format_list(formats)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rate(self, rate: i32) -> Self {
|
pub fn rate(self, rate: i32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self.builder.field(glib::gstr!("rate"), rate),
|
builder: self.builder.field(glib::gstr!("rate"), rate),
|
||||||
|
@ -164,6 +174,15 @@ impl<T> AudioCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rate_list_if_any(self, rates: impl IntoIterator<Item = i32>) -> Self {
|
||||||
|
let mut rates = rates.into_iter().peekable();
|
||||||
|
if rates.peek().is_some() {
|
||||||
|
self.rate_list(rates)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn channels(self, channels: i32) -> Self {
|
pub fn channels(self, channels: i32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self.builder.field(glib::gstr!("channels"), channels),
|
builder: self.builder.field(glib::gstr!("channels"), channels),
|
||||||
|
@ -210,6 +229,15 @@ impl<T> AudioCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn channels_list_if_any(self, channels: impl IntoIterator<Item = i32>) -> Self {
|
||||||
|
let mut channels = channels.into_iter().peekable();
|
||||||
|
if channels.peek().is_some() {
|
||||||
|
self.channels_list(channels)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn layout(self, layout: AudioLayout) -> Self {
|
pub fn layout(self, layout: AudioLayout) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self
|
builder: self
|
||||||
|
@ -246,6 +274,15 @@ impl<T> AudioCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn layout_list_if_any(self, layouts: impl IntoIterator<Item = AudioLayout>) -> Self {
|
||||||
|
let mut layouts = layouts.into_iter().peekable();
|
||||||
|
if layouts.peek().is_some() {
|
||||||
|
self.layout_list(layouts)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn channel_mask(self, channel_mask: u64) -> Self {
|
pub fn channel_mask(self, channel_mask: u64) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self
|
builder: self
|
||||||
|
@ -275,13 +312,13 @@ impl<T> AudioCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field(self, name: &str, value: impl Into<glib::Value> + Send) -> Self {
|
pub fn field(self, name: &str, value: impl Into<Value> + Send) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self.builder.field(name, value),
|
builder: self.builder.field(name, value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field_if_some(self, name: &str, value: Option<impl Into<glib::Value> + Send>) -> Self {
|
pub fn field_if_some(self, name: &str, value: Option<impl Into<Value> + Send>) -> Self {
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
self.field(name, value)
|
self.field(name, value)
|
||||||
} else {
|
} else {
|
||||||
|
@ -289,6 +326,20 @@ impl<T> AudioCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn field_if_any<V: ValueType + FromIterator<SendValue> + Into<Value> + Send>(
|
||||||
|
self,
|
||||||
|
name: &str,
|
||||||
|
iter: impl IntoIterator<Item = impl Into<SendValue>>,
|
||||||
|
) -> Self {
|
||||||
|
let mut iter = iter.into_iter().peekable();
|
||||||
|
if iter.peek().is_some() {
|
||||||
|
let iter = iter.map(|item| item.into());
|
||||||
|
self.field(name, V::from_iter(iter))
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn build(self) -> gst::Caps {
|
pub fn build(self) -> gst::Caps {
|
||||||
self.builder.build()
|
self.builder.build()
|
||||||
|
@ -321,7 +372,7 @@ fn layout_str(layout: AudioLayout) -> &'static glib::GStr {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::AudioCapsBuilder;
|
use super::{AudioCapsBuilder, AudioFormat};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_encoding() {
|
fn default_encoding() {
|
||||||
|
@ -336,4 +387,42 @@ mod tests {
|
||||||
let caps = AudioCapsBuilder::for_encoding("audio/mpeg").build();
|
let caps = AudioCapsBuilder::for_encoding("audio/mpeg").build();
|
||||||
assert_eq!(caps.structure(0).unwrap().name(), "audio/mpeg");
|
assert_eq!(caps.structure(0).unwrap().name(), "audio/mpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_if() {
|
||||||
|
gst::init().unwrap();
|
||||||
|
|
||||||
|
let formats = [AudioFormat::S24be, AudioFormat::S16be, AudioFormat::U8];
|
||||||
|
let caps_with_format = AudioCapsBuilder::for_encoding("audio/x-raw")
|
||||||
|
.format_list(formats)
|
||||||
|
.build();
|
||||||
|
assert!(caps_with_format
|
||||||
|
.structure(0)
|
||||||
|
.unwrap()
|
||||||
|
.get::<gst::List>("format")
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|f| f.get::<String>().unwrap())
|
||||||
|
.eq(formats.iter().map(|f| f.to_string())));
|
||||||
|
|
||||||
|
let caps = AudioCapsBuilder::for_encoding("audio/x-raw")
|
||||||
|
.format_list_if_some(Some(formats))
|
||||||
|
.build();
|
||||||
|
assert_eq!(caps, caps_with_format);
|
||||||
|
|
||||||
|
let caps = AudioCapsBuilder::for_encoding("audio/x-raw")
|
||||||
|
.format_list_if_some(Option::<Vec<AudioFormat>>::None)
|
||||||
|
.build();
|
||||||
|
assert!(!caps.structure(0).unwrap().has_field("format"));
|
||||||
|
|
||||||
|
let caps = AudioCapsBuilder::for_encoding("audio/x-raw")
|
||||||
|
.format_list_if_any(formats)
|
||||||
|
.build();
|
||||||
|
assert_eq!(caps, caps_with_format);
|
||||||
|
|
||||||
|
let caps = AudioCapsBuilder::for_encoding("audio/x-raw")
|
||||||
|
.format_list_if_any(Vec::<AudioFormat>::new())
|
||||||
|
.build();
|
||||||
|
assert!(!caps.structure(0).unwrap().has_field("format"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::ops::{Bound::*, RangeBounds};
|
use std::ops::{Bound::*, RangeBounds};
|
||||||
|
|
||||||
use glib::translate::*;
|
use glib::translate::*;
|
||||||
|
use glib::value::{SendValue, Value, ValueType};
|
||||||
use gst::Caps;
|
use gst::Caps;
|
||||||
|
|
||||||
use crate::VideoFormat;
|
use crate::VideoFormat;
|
||||||
|
@ -100,6 +101,15 @@ impl<T> VideoCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn format_list_if_any(self, formats: impl IntoIterator<Item = VideoFormat>) -> Self {
|
||||||
|
let mut formats = formats.into_iter().peekable();
|
||||||
|
if formats.peek().is_some() {
|
||||||
|
self.format_list(formats)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn width(self, width: i32) -> Self {
|
pub fn width(self, width: i32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self.builder.field(glib::gstr!("width"), width),
|
builder: self.builder.field(glib::gstr!("width"), width),
|
||||||
|
@ -146,6 +156,15 @@ impl<T> VideoCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn width_list_if_any(self, widths: impl IntoIterator<Item = i32>) -> Self {
|
||||||
|
let mut widths = widths.into_iter().peekable();
|
||||||
|
if widths.peek().is_some() {
|
||||||
|
self.width_list(widths)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn height(self, height: i32) -> Self {
|
pub fn height(self, height: i32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self.builder.field(glib::gstr!("height"), height),
|
builder: self.builder.field(glib::gstr!("height"), height),
|
||||||
|
@ -192,6 +211,15 @@ impl<T> VideoCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn height_list_if_any(self, heights: impl IntoIterator<Item = i32>) -> Self {
|
||||||
|
let mut heights = heights.into_iter().peekable();
|
||||||
|
if heights.peek().is_some() {
|
||||||
|
self.height_list(heights)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn framerate(self, framerate: gst::Fraction) -> Self {
|
pub fn framerate(self, framerate: gst::Fraction) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self.builder.field(glib::gstr!("framerate"), framerate),
|
builder: self.builder.field(glib::gstr!("framerate"), framerate),
|
||||||
|
@ -260,6 +288,18 @@ impl<T> VideoCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn framerate_list_if_any(
|
||||||
|
self,
|
||||||
|
framerates: impl IntoIterator<Item = gst::Fraction>,
|
||||||
|
) -> Self {
|
||||||
|
let mut framerates = framerates.into_iter().peekable();
|
||||||
|
if framerates.peek().is_some() {
|
||||||
|
self.framerate_list(framerates)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pixel_aspect_ratio(self, pixel_aspect_ratio: gst::Fraction) -> Self {
|
pub fn pixel_aspect_ratio(self, pixel_aspect_ratio: gst::Fraction) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self.builder.field("pixel-aspect-ratio", pixel_aspect_ratio),
|
builder: self.builder.field("pixel-aspect-ratio", pixel_aspect_ratio),
|
||||||
|
@ -336,13 +376,25 @@ impl<T> VideoCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field(self, name: &str, value: impl Into<glib::Value> + Send) -> Self {
|
pub fn pixel_aspect_ratio_list_if_any(
|
||||||
|
self,
|
||||||
|
pixel_aspect_ratios: impl IntoIterator<Item = gst::Fraction>,
|
||||||
|
) -> Self {
|
||||||
|
let mut pixel_aspect_ratios = pixel_aspect_ratios.into_iter().peekable();
|
||||||
|
if pixel_aspect_ratios.peek().is_some() {
|
||||||
|
self.pixel_aspect_ratio_list(pixel_aspect_ratios)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn field(self, name: &str, value: impl Into<Value> + Send) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: self.builder.field(name, value),
|
builder: self.builder.field(name, value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field_if_some(self, name: &str, value: Option<impl Into<glib::Value> + Send>) -> Self {
|
pub fn field_if_some(self, name: &str, value: Option<impl Into<Value> + Send>) -> Self {
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
self.field(name, value)
|
self.field(name, value)
|
||||||
} else {
|
} else {
|
||||||
|
@ -350,6 +402,20 @@ impl<T> VideoCapsBuilder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn field_if_any<V: ValueType + FromIterator<SendValue> + Into<Value> + Send>(
|
||||||
|
self,
|
||||||
|
name: &str,
|
||||||
|
iter: impl IntoIterator<Item = impl Into<SendValue>>,
|
||||||
|
) -> Self {
|
||||||
|
let mut iter = iter.into_iter().peekable();
|
||||||
|
if iter.peek().is_some() {
|
||||||
|
let iter = iter.map(|item| item.into());
|
||||||
|
self.field(name, V::from_iter(iter))
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn build(self) -> gst::Caps {
|
pub fn build(self) -> gst::Caps {
|
||||||
self.builder.build()
|
self.builder.build()
|
||||||
|
|
|
@ -277,6 +277,42 @@ impl<'a> ElementBuilder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Set property `name` using the given `ValueType` `V` built from the `Item`s of `iter`.
|
||||||
|
#[inline]
|
||||||
|
pub fn property_from_iter<
|
||||||
|
V: ValueType + FromIterator<glib::SendValue> + Into<glib::Value> + 'a,
|
||||||
|
>(
|
||||||
|
self,
|
||||||
|
name: &'a str,
|
||||||
|
iter: impl IntoIterator<Item = impl Into<glib::SendValue>>,
|
||||||
|
) -> Self {
|
||||||
|
let iter = iter.into_iter().map(|item| item.into());
|
||||||
|
self.property(name, V::from_iter(iter))
|
||||||
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Set property `name` using the given `ValueType` `V` built from the `Item`s of `iter`
|
||||||
|
/// if `iter` is not empty.
|
||||||
|
///
|
||||||
|
/// This has no effect if `iter` is empty.
|
||||||
|
#[inline]
|
||||||
|
pub fn property_if_any<
|
||||||
|
V: ValueType + FromIterator<glib::SendValue> + Into<glib::Value> + 'a,
|
||||||
|
>(
|
||||||
|
self,
|
||||||
|
name: &'a str,
|
||||||
|
iter: impl IntoIterator<Item = impl Into<glib::SendValue>>,
|
||||||
|
) -> Self {
|
||||||
|
let mut iter = iter.into_iter().peekable();
|
||||||
|
if iter.peek().is_some() {
|
||||||
|
let iter = iter.map(|item| item.into());
|
||||||
|
self.property(name, V::from_iter(iter))
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// rustdoc-stripper-ignore-next
|
// rustdoc-stripper-ignore-next
|
||||||
/// Build the element with the provided properties.
|
/// Build the element with the provided properties.
|
||||||
///
|
///
|
||||||
|
|
|
@ -3773,6 +3773,18 @@ impl<'a> StreamsSelectedBuilder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn streams_if_any(
|
||||||
|
self,
|
||||||
|
streams: impl IntoIterator<Item = impl std::borrow::Borrow<crate::Stream>>,
|
||||||
|
) -> Self {
|
||||||
|
let mut streams = streams.into_iter().peekable();
|
||||||
|
if streams.peek().is_some() {
|
||||||
|
self.streams(streams)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message_builder_generic_impl!(|s: &mut Self, src| {
|
message_builder_generic_impl!(|s: &mut Self, src| {
|
||||||
let msg = ffi::gst_message_new_streams_selected(src, s.collection.to_glib_none().0);
|
let msg = ffi::gst_message_new_streams_selected(src, s.collection.to_glib_none().0);
|
||||||
if let Some(ref streams) = s.streams {
|
if let Some(ref streams) = s.streams {
|
||||||
|
|
|
@ -145,6 +145,15 @@ impl StreamCollectionBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn streams_if_any(self, streams: impl IntoIterator<Item = Stream>) -> Self {
|
||||||
|
let mut streams = streams.into_iter().peekable();
|
||||||
|
if streams.peek().is_some() {
|
||||||
|
self.streams(streams)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use = "Building the stream collection without using it has no effect"]
|
#[must_use = "Building the stream collection without using it has no effect"]
|
||||||
pub fn build(self) -> StreamCollection {
|
pub fn build(self) -> StreamCollection {
|
||||||
self.0
|
self.0
|
||||||
|
|
|
@ -12,7 +12,7 @@ use std::{
|
||||||
use glib::{
|
use glib::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
translate::*,
|
translate::*,
|
||||||
value::{FromValue, SendValue},
|
value::{FromValue, SendValue, Value},
|
||||||
IntoGStr,
|
IntoGStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1176,6 +1176,38 @@ impl Builder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Set field `name` using the given `ValueType` `V` built from the `Item`s of `iter`.
|
||||||
|
#[inline]
|
||||||
|
pub fn field_from_iter<V: ValueType + FromIterator<SendValue> + Into<Value> + Send>(
|
||||||
|
self,
|
||||||
|
name: impl IntoGStr,
|
||||||
|
iter: impl IntoIterator<Item = impl Into<SendValue>>,
|
||||||
|
) -> Self {
|
||||||
|
let iter = iter.into_iter().map(|item| item.into());
|
||||||
|
self.field(name, V::from_iter(iter))
|
||||||
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Set field `name` using the given `ValueType` `V` built from the `Item`s of `iter`
|
||||||
|
/// if `iter` is not empty.
|
||||||
|
///
|
||||||
|
/// This has no effect if `iter` is empty.
|
||||||
|
#[inline]
|
||||||
|
pub fn field_if_any<V: ValueType + FromIterator<SendValue> + Into<Value> + Send>(
|
||||||
|
self,
|
||||||
|
name: impl IntoGStr,
|
||||||
|
iter: impl IntoIterator<Item = impl Into<SendValue>>,
|
||||||
|
) -> Self {
|
||||||
|
let mut iter = iter.into_iter().peekable();
|
||||||
|
if iter.peek().is_some() {
|
||||||
|
let iter = iter.map(|item| item.into());
|
||||||
|
self.field(name, V::from_iter(iter))
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use = "Building the structure without using it has no effect"]
|
#[must_use = "Building the structure without using it has no effect"]
|
||||||
pub fn build(self) -> Structure {
|
pub fn build(self) -> Structure {
|
||||||
self.s
|
self.s
|
||||||
|
@ -1329,4 +1361,64 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(format!("{s:?}"), "Structure(test { f1: (gchararray) \"abc\", f2: (gchararray) \"bcd\", f3: (gint) 123, f4: Structure(nested { badger: (gboolean) TRUE }), f5: Array([(gchararray) \"a\", (gchararray) \"b\", (gchararray) \"c\"]), f6: List([(gchararray) \"d\", (gchararray) \"e\", (gchararray) \"f\"]) })");
|
assert_eq!(format!("{s:?}"), "Structure(test { f1: (gchararray) \"abc\", f2: (gchararray) \"bcd\", f3: (gint) 123, f4: Structure(nested { badger: (gboolean) TRUE }), f5: Array([(gchararray) \"a\", (gchararray) \"b\", (gchararray) \"c\"]), f6: List([(gchararray) \"d\", (gchararray) \"e\", (gchararray) \"f\"]) })");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn builder_field_from_iter() {
|
||||||
|
crate::init().unwrap();
|
||||||
|
|
||||||
|
let s = Structure::builder("test")
|
||||||
|
.field_from_iter::<crate::Array>("array", [&1, &2, &3])
|
||||||
|
.field_from_iter::<crate::List>("list", [&4, &5, &6])
|
||||||
|
.build();
|
||||||
|
assert!(s
|
||||||
|
.get::<crate::Array>("array")
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.get::<i32>().unwrap())
|
||||||
|
.eq([1, 2, 3]));
|
||||||
|
assert!(s
|
||||||
|
.get::<crate::List>("list")
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.get::<i32>().unwrap())
|
||||||
|
.eq([4, 5, 6]));
|
||||||
|
|
||||||
|
let array = Vec::<i32>::new();
|
||||||
|
let s = Structure::builder("test")
|
||||||
|
.field_from_iter::<crate::Array>("array", &array)
|
||||||
|
.field_from_iter::<crate::List>("list", &array)
|
||||||
|
.build();
|
||||||
|
assert!(s.get::<crate::Array>("array").unwrap().as_ref().is_empty());
|
||||||
|
assert!(s.get::<crate::List>("list").unwrap().as_ref().is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn builder_field_if_any() {
|
||||||
|
crate::init().unwrap();
|
||||||
|
|
||||||
|
let s = Structure::builder("test")
|
||||||
|
.field_if_any::<crate::Array>("array", [&1, &2, &3])
|
||||||
|
.field_if_any::<crate::List>("list", [&4, &5, &6])
|
||||||
|
.build();
|
||||||
|
assert!(s
|
||||||
|
.get::<crate::Array>("array")
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.get::<i32>().unwrap())
|
||||||
|
.eq([1, 2, 3]));
|
||||||
|
assert!(s
|
||||||
|
.get::<crate::List>("list")
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.get::<i32>().unwrap())
|
||||||
|
.eq([4, 5, 6]));
|
||||||
|
|
||||||
|
let array = Vec::<i32>::new();
|
||||||
|
let s = Structure::builder("test")
|
||||||
|
.field_if_any::<crate::Array>("array", &array)
|
||||||
|
.field_if_any::<crate::List>("list", &array)
|
||||||
|
.build();
|
||||||
|
assert!(!s.has_field("array"));
|
||||||
|
assert!(!s.has_field("list"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -551,7 +551,7 @@ unsafe extern "C" fn element_post_message<T: ElementImpl>(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::sync::atomic;
|
use std::sync::{atomic, Arc, Mutex, OnceLock};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::ElementFactory;
|
use crate::ElementFactory;
|
||||||
|
@ -564,6 +564,7 @@ mod tests {
|
||||||
pub(super) sinkpad: crate::Pad,
|
pub(super) sinkpad: crate::Pad,
|
||||||
pub(super) n_buffers: atomic::AtomicU32,
|
pub(super) n_buffers: atomic::AtomicU32,
|
||||||
pub(super) reached_playing: atomic::AtomicBool,
|
pub(super) reached_playing: atomic::AtomicBool,
|
||||||
|
pub(super) array: Arc<Mutex<Vec<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestElement {
|
impl TestElement {
|
||||||
|
@ -648,6 +649,10 @@ mod tests {
|
||||||
reached_playing: atomic::AtomicBool::new(false),
|
reached_playing: atomic::AtomicBool::new(false),
|
||||||
srcpad,
|
srcpad,
|
||||||
sinkpad,
|
sinkpad,
|
||||||
|
array: Arc::new(Mutex::new(vec![
|
||||||
|
"default0".to_string(),
|
||||||
|
"default1".to_string(),
|
||||||
|
])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,6 +665,30 @@ mod tests {
|
||||||
element.add_pad(&self.sinkpad).unwrap();
|
element.add_pad(&self.sinkpad).unwrap();
|
||||||
element.add_pad(&self.srcpad).unwrap();
|
element.add_pad(&self.srcpad).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn properties() -> &'static [glib::ParamSpec] {
|
||||||
|
static PROPERTIES: OnceLock<Vec<glib::ParamSpec>> = OnceLock::new();
|
||||||
|
PROPERTIES.get_or_init(|| vec![crate::ParamSpecArray::builder("array").build()])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
||||||
|
match pspec.name() {
|
||||||
|
"array" => {
|
||||||
|
let value = value.get::<crate::Array>().unwrap();
|
||||||
|
let mut array = self.array.lock().unwrap();
|
||||||
|
array.clear();
|
||||||
|
array.extend(value.iter().map(|v| v.get().unwrap()));
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||||
|
match pspec.name() {
|
||||||
|
"array" => crate::Array::new(&*self.array.lock().unwrap()).to_value(),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GstObjectImpl for TestElement {}
|
impl GstObjectImpl for TestElement {}
|
||||||
|
@ -729,6 +758,27 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn plugin_init(plugin: &crate::Plugin) -> Result<(), glib::BoolError> {
|
||||||
|
crate::Element::register(
|
||||||
|
Some(plugin),
|
||||||
|
"testelement",
|
||||||
|
crate::Rank::MARGINAL,
|
||||||
|
TestElement::static_type(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::plugin_define!(
|
||||||
|
rssubclasstestelem,
|
||||||
|
env!("CARGO_PKG_DESCRIPTION"),
|
||||||
|
plugin_init,
|
||||||
|
env!("CARGO_PKG_VERSION"),
|
||||||
|
"MPL-2.0",
|
||||||
|
env!("CARGO_PKG_NAME"),
|
||||||
|
env!("CARGO_PKG_NAME"),
|
||||||
|
env!("CARGO_PKG_REPOSITORY"),
|
||||||
|
"1970-01-01"
|
||||||
|
);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_element_subclass() {
|
fn test_element_subclass() {
|
||||||
crate::init().unwrap();
|
crate::init().unwrap();
|
||||||
|
@ -766,4 +816,48 @@ mod tests {
|
||||||
assert_eq!(imp.n_buffers.load(atomic::Ordering::SeqCst), 100);
|
assert_eq!(imp.n_buffers.load(atomic::Ordering::SeqCst), 100);
|
||||||
assert!(imp.reached_playing.load(atomic::Ordering::SeqCst));
|
assert!(imp.reached_playing.load(atomic::Ordering::SeqCst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn property_from_iter_if_any() {
|
||||||
|
crate::init().unwrap();
|
||||||
|
plugin_register_static().unwrap();
|
||||||
|
|
||||||
|
let elem = crate::ElementFactory::make("testelement").build().unwrap();
|
||||||
|
assert!(elem
|
||||||
|
.property::<crate::Array>("array")
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.get::<&str>().unwrap())
|
||||||
|
.eq(["default0", "default1"]));
|
||||||
|
|
||||||
|
let elem = crate::ElementFactory::make("testelement")
|
||||||
|
.property_from_iter::<crate::Array>("array", ["value0", "value1"])
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
assert!(elem
|
||||||
|
.property::<crate::Array>("array")
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.get::<&str>().unwrap())
|
||||||
|
.eq(["value0", "value1"]));
|
||||||
|
|
||||||
|
let array = Vec::<String>::new();
|
||||||
|
let elem = crate::ElementFactory::make("testelement")
|
||||||
|
.property_if_any::<crate::Array>("array", &array)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
assert!(elem
|
||||||
|
.property::<crate::Array>("array")
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.get::<&str>().unwrap())
|
||||||
|
.eq(["default0", "default1"]));
|
||||||
|
|
||||||
|
let elem = crate::ElementFactory::make("testelement")
|
||||||
|
.property_if_any::<crate::Array>("array", ["value0", "value1"])
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
assert!(elem
|
||||||
|
.property::<crate::Array>("array")
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.get::<&str>().unwrap())
|
||||||
|
.eq(["value0", "value1"]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue