Manual update for new Value::get signature

This commit is contained in:
François Laignel 2019-08-11 09:33:34 +02:00
parent 5d012945df
commit 514a05accd
13 changed files with 247 additions and 78 deletions

View file

@ -60,10 +60,15 @@ fn example_main() {
// The metadata of any of the contained audio streams changed
// In the case of a live-stream from an internet radio, this could for example
// mark the beginning of a new track, or a new DJ.
let playbin = values[0].get::<glib::Object>().unwrap();
let playbin = values[0]
.get::<glib::Object>()
.expect("playbin \"audio-tags-changed\" signal values[1]")
.unwrap();
// This gets the index of the stream that changed. This is neccessary, since
// there could e.g. be multiple audio streams (english, spanish, ...).
let idx = values[1].get::<i32>().unwrap();
let idx = values[1]
.get_some::<i32>()
.expect("playbin \"audio-tags-changed\" signal values[1]");
println!("audio tags of audio stream {} changed:", idx);
@ -81,7 +86,7 @@ fn example_main() {
.emit("get-audio-tags", &[&idx.to_value()])
.unwrap()
.unwrap();
let tags = tags.get::<gst::TagList>().unwrap();
let tags = tags.get::<gst::TagList>().expect("tags").unwrap();
if let Some(artist) = tags.get::<gst::tags::Artist>() {
println!(" Artist: {}", artist.get().unwrap());

View file

@ -151,7 +151,10 @@ fn example_main() -> Result<(), Error> {
src.link(&netsim)?;
rtpbin.connect("new-storage", false, |values| {
let storage = values[1].get::<gst::Element>().expect("Invalid argument");
let storage = values[1]
.get::<gst::Element>()
.expect("rtpbin \"new-storage\" signal values[1]")
.expect("rtpbin \"new-storage\" signal values[1]: no `Element`");
storage
.set_property("size-time", &250_000_000u64.to_value())
.unwrap();
@ -160,7 +163,9 @@ fn example_main() -> Result<(), Error> {
})?;
rtpbin.connect("request-pt-map", false, |values| {
let pt = values[2].get::<u32>().expect("Invalid argument");
let pt = values[2]
.get_some::<u32>()
.expect("rtpbin \"new-storage\" signal values[2]");
match pt {
100 => Some(
gst::Caps::new_simple(
@ -189,8 +194,13 @@ fn example_main() -> Result<(), Error> {
})?;
rtpbin.connect("request-fec-decoder", false, |values| {
let rtpbin = values[0].get::<gst::Element>().expect("Invalid argument");
let sess_id = values[1].get::<u32>().expect("Invalid argument");
let rtpbin = values[0]
.get::<gst::Element>()
.expect("rtpbin \"request-fec-decoder\" signal values[0]")
.expect("rtpbin \"request-fec-decoder\" signal values[0]: no `Element`");
let sess_id = values[1]
.get_some::<u32>()
.expect("rtpbin \"request-fec-decoder\" signal values[1]");
match make_fec_decoder(&rtpbin, sess_id) {
Ok(elem) => Some(elem.to_value()),

View file

@ -119,7 +119,10 @@ fn example_main() -> Result<(), Error> {
pay.link(&q2)?;
rtpbin.connect("request-fec-encoder", false, move |values| {
let rtpbin = values[0].get::<gst::Element>().expect("Invalid argument");
let rtpbin = values[0]
.get::<gst::Element>()
.expect("rtpbin \"request-fec-encoder\" signal values[0]")
.expect("rtpbin \"request-fec-encoder\" signal values[0]: no `Element`");
match make_fec_encoder(fec_percentage) {
Ok(elem) => Some(elem.to_value()),

View file

@ -110,7 +110,8 @@ fn example_main() -> Result<(), Error> {
// much more corner-cases. This is just for the sake of being an example.
let caps = values[2]
.get::<gst::Caps>()
.expect("Failed to automatically detect type");
.expect("typefinder \"have-type\" signal values[2]")
.expect("typefinder \"have-type\" signal values[2]: no `caps`");
let format_name = caps
.get_structure(0)
.expect("Failed to get format name")

View file

@ -57,7 +57,10 @@ impl<O: IsA<Aggregator>> AggregatorExtManual for O {
b"min-upstream-latency\0".as_ptr() as *const _,
value.to_glib_none_mut().0,
);
value.get().unwrap()
value
.get()
.expect("AggregatorExtManual::get_property_min_upstream_latency")
.unwrap()
}
}

View file

@ -45,7 +45,10 @@ impl Discoverer {
value.to_glib_none_mut().0,
);
}
value.get().unwrap()
value
.get()
.expect("Discoverer::get_property_timeout")
.unwrap()
}
pub fn connect_property_timeout_notify<F: Fn(&Self) + Send + Sync + 'static>(

View file

@ -66,7 +66,7 @@ where
let res =
gst_sys::gst_iterator_next(self.to_glib_none_mut().0, value.to_glib_none_mut().0);
match res {
gst_sys::GST_ITERATOR_OK => match value.get::<T>() {
gst_sys::GST_ITERATOR_OK => match value.get::<T>().expect("Iterator::next") {
Some(value) => Ok(Some(value)),
None => Err(IteratorError::Error),
},
@ -123,7 +123,7 @@ where
func_ptr,
));
if res {
Some(elem.get::<T>().unwrap())
elem.get::<T>().expect("Iterator::find")
} else {
None
}
@ -339,7 +339,10 @@ where
let func: &&(dyn Fn(T) -> bool + Send + Sync + 'static) = mem::transmute(func);
let value = &*(value as *const glib::Value);
let value = value.get::<T>().unwrap();
let value = value
.get::<T>()
.expect("Iterator filter_trampoline")
.unwrap();
if func(value) {
0
@ -408,7 +411,7 @@ where
let func = func as *mut F;
let value = &*(value as *const glib::Value);
let value = value.get::<T>().unwrap();
let value = value.get::<T>().expect("Iterator find_trampoline").unwrap();
if (*func)(value) {
0
@ -425,7 +428,10 @@ unsafe extern "C" fn foreach_trampoline<T, F: FnMut(T)>(
{
let func = func as *mut F;
let value = &*(value as *const glib::Value);
let value = value.get::<T>().unwrap();
let value = value
.get::<T>()
.expect("Iterator foreach_trampoline")
.unwrap();
(*func)(value);
}
@ -440,7 +446,7 @@ where
{
let func = func as *mut F;
let value = &*(value as *const glib::Value);
let value = value.get::<T>().unwrap();
let value = value.get::<T>().expect("Iterator fold_trampoline").unwrap();
let accum = &mut *(gobject_sys::g_value_get_pointer(ret) as *mut Option<U>);

View file

@ -46,8 +46,22 @@ impl<O: IsA<::Object>> GstObjectExtManual for O {
unsafe { from_glib_borrow(self.as_ptr() as *mut gobject_sys::GObject) };
obj.connect(signal_name.as_str(), false, move |values| {
let obj: O = unsafe { values[0].get::<::Object>().unwrap().unsafe_cast() };
let prop_obj: ::Object = values[1].get().unwrap();
// It would be nice to display the actual signal name in the panic messages below,
// but that would require to copy `signal_name` so as to move it into the closure
// which seems too much for the messages of development errors
let obj: O = unsafe {
values[0]
.get::<::Object>()
.unwrap_or_else(|err| {
panic!("Object signal \"deep-notify\": values[0]: {}", err)
})
.expect("Object signal \"deep-notify\": values[0] not defined")
.unsafe_cast()
};
let prop_obj: ::Object = values[1]
.get()
.unwrap_or_else(|err| panic!("Object signal \"deep-notify\": values[1]: {}", err))
.expect("Object signal \"deep-notify\": values[1] not defined");
let pspec = unsafe {
let pspec = gobject_sys::g_value_get_param(values[2].to_glib_none().0);

View file

@ -7,6 +7,7 @@
// except according to those terms.
use std::borrow::{Borrow, BorrowMut, ToOwned};
use std::error;
use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
@ -22,11 +23,62 @@ use glib::translate::{
from_glib, from_glib_full, from_glib_none, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault,
Stash, StashMut, ToGlib, ToGlibPtr, ToGlibPtrMut,
};
use glib::value::{FromValueOptional, SendValue, ToSendValue};
use glib::value::{FromValue, FromValueOptional, SendValue, ToSendValue};
use glib_sys::gpointer;
use gobject_sys;
use gst_sys;
/// An error returned from the [`get`](struct.StructureRef.html#method.get)
/// or [`get_some`](struct.StructureRef.html#method.get_some) functions
/// on a [`StructureRef`](struct.StructureRef.html)
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum GetError<'name> {
FieldNotFound {
name: &'name str,
},
ValueGetError {
name: &'name str,
value_get_error: glib::value::GetError,
},
}
impl<'name> GetError<'name> {
fn new_field_not_found(name: &'name str) -> GetError {
GetError::FieldNotFound { name }
}
fn from_value_get_error(name: &'name str, value_get_error: glib::value::GetError) -> GetError {
GetError::ValueGetError {
name,
value_get_error,
}
}
}
impl<'name> fmt::Display for GetError<'name> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GetError::FieldNotFound { name } => {
write!(f, "GetError: Structure field with name {} not found", name)
}
GetError::ValueGetError {
name,
value_get_error,
} => write!(
f,
"GetError: Structure field with name {} value: {}",
name, value_get_error,
),
}
}
}
impl<'name> error::Error for GetError<'name> {
fn description(&self) -> &str {
"GetError: Structure field value"
}
}
pub struct Structure(ptr::NonNull<StructureRef>, PhantomData<StructureRef>);
unsafe impl Send for Structure {}
unsafe impl Sync for Structure {}
@ -326,19 +378,36 @@ impl StructureRef {
unsafe { from_glib_full(gst_sys::gst_structure_to_string(&self.0)) }
}
pub fn get<'a, T: FromValueOptional<'a>>(&'a self, name: &str) -> Option<T> {
self.get_value(name).and_then(|v| v.get())
pub fn get<'structure, 'name, T: FromValueOptional<'structure>>(
&'structure self,
name: &'name str,
) -> Result<Option<T>, GetError<'name>> {
self.get_value(name)?
.get()
.map_err(|err| GetError::from_value_get_error(name, err))
}
pub fn get_value<'a>(&'a self, name: &str) -> Option<&SendValue> {
pub fn get_some<'structure, 'name, T: FromValue<'structure>>(
&'structure self,
name: &'name str,
) -> Result<T, GetError<'name>> {
self.get_value(name)?
.get_some()
.map_err(|err| GetError::from_value_get_error(name, err))
}
pub fn get_value<'structure, 'name>(
&'structure self,
name: &'name str,
) -> Result<&SendValue, GetError<'name>> {
unsafe {
let value = gst_sys::gst_structure_get_value(&self.0, name.to_glib_none().0);
if value.is_null() {
return None;
return Err(GetError::new_field_not_found(name));
}
Some(&*(value as *const SendValue))
Ok(&*(value as *const SendValue))
}
}
@ -679,20 +748,52 @@ mod tests {
s.set("f2", &String::from("bcd"));
s.set("f3", &123i32);
assert_eq!(s.get::<&str>("f1").unwrap(), "abc");
assert_eq!(s.get::<&str>("f2").unwrap(), "bcd");
assert_eq!(s.get::<i32>("f3").unwrap(), 123i32);
assert_eq!(s.get::<&str>("f1"), Ok(Some("abc")));
assert_eq!(s.get::<&str>("f2"), Ok(Some("bcd")));
assert_eq!(s.get_some::<i32>("f3"), Ok(123i32));
// FIXME: use a proper `assert_eq!`, but that requires
// `glib::value::GetError fields to be public
// See https://github.com/gtk-rs/glib/issues/515
match s.get::<i32>("f2") {
Err(GetError::ValueGetError { name, .. }) if name == "f2" => (),
res => panic!(
"Expected GetError::ValueGetError{{ \"f2\", .. }} found {:?}",
res
),
}
match s.get_some::<bool>("f3") {
Err(GetError::ValueGetError { name, .. }) if name == "f3" => (),
res => panic!(
"Expected GetError::ValueGetError{{ \"f3\", .. }} found {:?}",
res
),
}
match s.get::<&str>("f4") {
Err(GetError::FieldNotFound { name }) if name == "f4" => (),
res => panic!(
"Expected GetError::FieldNotFound{{ \"f4\" }} found {:?}",
res
),
}
match s.get_some::<i32>("f4") {
Err(GetError::FieldNotFound { name }) if name == "f4" => (),
res => panic!(
"Expected GetError::FieldNotFound{{ \"f4\" }} found {:?}",
res
),
}
assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f2", "f3"]);
let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>();
assert_eq!(v.len(), 3);
assert_eq!(v[0].0, "f1");
assert_eq!(v[0].1.get::<&str>().unwrap(), "abc");
assert_eq!(v[0].1.get::<&str>(), Ok(Some("abc")));
assert_eq!(v[1].0, "f2");
assert_eq!(v[1].1.get::<&str>().unwrap(), "bcd");
assert_eq!(v[1].1.get::<&str>(), Ok(Some("bcd")));
assert_eq!(v[2].0, "f3");
assert_eq!(v[2].1.get::<i32>().unwrap(), 123i32);
assert_eq!(v[2].1.get_some::<i32>(), Ok(123i32));
let s2 = Structure::new("test", &[("f1", &"abc"), ("f2", &"bcd"), ("f3", &123i32)]);
assert_eq!(s, s2);
@ -709,9 +810,9 @@ mod tests {
.build();
assert_eq!(s.get_name(), "test");
assert_eq!(s.get::<&str>("f1").unwrap(), "abc");
assert_eq!(s.get::<&str>("f2").unwrap(), "bcd");
assert_eq!(s.get::<i32>("f3").unwrap(), 123i32);
assert_eq!(s.get::<&str>("f1"), Ok(Some("abc")));
assert_eq!(s.get::<&str>("f2"), Ok(Some("bcd")));
assert_eq!(s.get_some::<i32>("f3"), Ok(123i32));
}
#[test]
@ -721,8 +822,8 @@ mod tests {
let a = "Test, f1=(string)abc, f2=(uint)123;";
let s = Structure::from_string(&a).unwrap();
assert_eq!(s.get::<&str>("f1").unwrap(), "abc");
assert_eq!(s.get::<u32>("f2").unwrap(), 123);
assert_eq!(s.get::<&str>("f1"), Ok(Some("abc")));
assert_eq!(s.get_some::<u32>("f2"), Ok(123));
assert_eq!(a, s.to_string());
}

View file

@ -406,8 +406,11 @@ impl TagListRef {
}
pub fn get<'a, T: Tag<'a>>(&self) -> Option<TypedValue<T::TagType>> {
self.get_generic(T::tag_name())
.and_then(|value| value.downcast().ok())
self.get_generic(T::tag_name()).map(|value| {
value.downcast().unwrap_or_else(|_| {
panic!("TagListRef::get type mismatch for tag {}", T::tag_name())
})
})
}
pub fn get_generic(&self, tag_name: &str) -> Option<SendValue> {
@ -966,24 +969,24 @@ mod tests {
assert_eq!(
tags.get_index_generic(&TAG_TITLE, 0).unwrap().get(),
Some("some title")
Ok(Some("some title"))
);
assert_eq!(
tags.get_index_generic(&TAG_TITLE, 1).unwrap().get(),
Some("second title")
Ok(Some("second title"))
);
assert_eq!(
tags.get_index_generic(&TAG_DURATION, 0).unwrap().get(),
Some(::SECOND * 120)
Ok(Some(::SECOND * 120))
);
assert_eq!(
tags.get_index_generic(&TAG_TITLE, 2).unwrap().get(),
Some("third title")
Ok(Some("third title"))
);
assert_eq!(
tags.get_generic(&TAG_TITLE).unwrap().get(),
Some("some title, second title, third title"),
Ok(Some("some title, second title, third title"))
);
assert_eq!(tags.n_tags(), 2);
@ -996,11 +999,11 @@ mod tests {
let mut title_iter = tags.iter_tag_generic(&TAG_TITLE);
assert_eq!(title_iter.size_hint(), (3, Some(3)));
let first_title = title_iter.next().unwrap();
assert_eq!(first_title.get(), Some("some title"));
assert_eq!(first_title.get(), Ok(Some("some title")));
let second_title = title_iter.next().unwrap();
assert_eq!(second_title.get(), Some("second title"));
assert_eq!(second_title.get(), Ok(Some("second title")));
let third_title = title_iter.next().unwrap();
assert_eq!(third_title.get(), Some("third title"));
assert_eq!(third_title.get(), Ok(Some("third title")));
assert!(title_iter.next().is_none());
// GenericIter
@ -1010,17 +1013,17 @@ mod tests {
let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap();
assert_eq!(tag_name, *TAG_TITLE);
let first_title = tag_iter.next().unwrap();
assert_eq!(first_title.get(), Some("some title"));
assert_eq!(first_title.get(), Ok(Some("some title")));
let second_title = tag_iter.next().unwrap();
assert_eq!(second_title.get(), Some("second title"));
assert_eq!(second_title.get(), Ok(Some("second title")));
let third_title = tag_iter.next().unwrap();
assert_eq!(third_title.get(), Some("third title"));
assert_eq!(third_title.get(), Ok(Some("third title")));
assert!(tag_iter.next().is_none());
let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap();
assert_eq!(tag_name, *TAG_DURATION);
let first_duration = tag_iter.next().unwrap();
assert_eq!(first_duration.get(), Some(::SECOND * 120));
assert_eq!(first_duration.get_some(), Ok(::SECOND * 120));
assert!(tag_iter.next().is_none());
// Iter
@ -1031,12 +1034,12 @@ mod tests {
assert_eq!(tag_name, *TAG_TITLE);
assert_eq!(
tag_value.get(),
Some("some title, second title, third title")
Ok(Some("some title, second title, third title"))
);
let (tag_name, tag_value) = tag_list_iter.next().unwrap();
assert_eq!(tag_name, *TAG_DURATION);
assert_eq!(tag_value.get(), Some(::SECOND * 120));
assert_eq!(tag_value.get_some(), Ok(::SECOND * 120));
assert!(tag_iter.next().is_none());
}

View file

@ -61,7 +61,9 @@ impl<'de> Deserialize<'de> for Fraction {
macro_rules! ser_value (
($value:expr, $t:ty, $ser_closure:expr) => (
{
let value = $value.get::<$t>().unwrap();
// FIXME: This should serialize to an `Option` when the `Type` allows it
// See https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/issues/215
let value = $value.get::<$t>().expect("Value serialization macro").unwrap();
$ser_closure(stringify!($t), value)
}
);
@ -493,30 +495,36 @@ mod tests {
let slice = array.as_slice();
assert_eq!(3, slice.len());
let fraction = slice[0].get::<Fraction>().unwrap();
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &3);
let fraction = slice[1].get::<Fraction>().unwrap();
let fraction = slice[1].get::<Fraction>().expect("slice[1]").unwrap();
assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &2);
assert_eq!("test str".to_owned(), slice[2].get::<String>().unwrap());
assert_eq!(
"test str".to_owned(),
slice[2].get::<String>().expect("slice[2]").unwrap()
);
let array_json = r#"[["Fraction",[1,3]],["Fraction",[1,2]],["String","test str"]]"#;
let array: Array = serde_json::from_str(array_json).unwrap();
let slice = array.as_slice();
assert_eq!(3, slice.len());
let fraction = slice[0].get::<Fraction>().unwrap();
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &3);
let fraction = slice[1].get::<Fraction>().unwrap();
let fraction = slice[1].get::<Fraction>().expect("slice[1]").unwrap();
assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &2);
assert_eq!("test str".to_owned(), slice[2].get::<String>().unwrap());
assert_eq!(
"test str".to_owned(),
slice[2].get::<String>().expect("slice[2]").unwrap()
);
// List
let list_ron = r#"[
@ -527,11 +535,14 @@ mod tests {
let slice = list.as_slice();
assert_eq!(2, slice.len());
let fraction = slice[0].get::<Fraction>().unwrap();
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &2);
assert_eq!("test str".to_owned(), slice[1].get::<String>().unwrap());
assert_eq!(
"test str".to_owned(),
slice[1].get::<String>().expect("slice[1]").unwrap()
);
}
#[cfg(feature = "ser_de")]
@ -556,19 +567,19 @@ mod tests {
let slice = array.as_slice();
assert_eq!(slice_de.len(), slice.len());
let fraction_de = slice_de[0].get::<Fraction>().unwrap();
let fraction = slice[0].get::<Fraction>().unwrap();
let fraction_de = slice_de[0].get::<Fraction>().expect("slice_de[0]").unwrap();
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
assert_eq!(fraction_de.0.numer(), fraction.0.numer());
assert_eq!(fraction_de.0.denom(), fraction.0.denom());
let fraction_de = slice_de[1].get::<Fraction>().unwrap();
let fraction = slice[1].get::<Fraction>().unwrap();
let fraction_de = slice_de[1].get::<Fraction>().expect("slice_de[1]").unwrap();
let fraction = slice[1].get::<Fraction>().expect("slice[1]").unwrap();
assert_eq!(fraction_de.0.numer(), fraction.0.numer());
assert_eq!(fraction.0.denom(), fraction.0.denom());
assert_eq!(
slice_de[2].get::<String>().unwrap(),
slice[2].get::<String>().unwrap()
slice_de[2].get::<String>().expect("slice_de[2]").unwrap(),
slice[2].get::<String>().expect("slice[2]").unwrap()
);
// List
@ -584,14 +595,14 @@ mod tests {
let slice = list.as_slice();
assert_eq!(slice_de.len(), slice.len());
let fraction_de = slice_de[0].get::<Fraction>().unwrap();
let fraction = slice[0].get::<Fraction>().unwrap();
let fraction_de = slice_de[0].get::<Fraction>().expect("slice_de[0]").unwrap();
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap();
assert_eq!(fraction_de.0.numer(), fraction.0.numer());
assert_eq!(fraction_de.0.denom(), fraction.0.denom());
assert_eq!(
slice_de[1].get::<String>().unwrap(),
slice[1].get::<String>().unwrap()
slice_de[1].get::<String>().expect("slice_de[1]").unwrap(),
slice[1].get::<String>().expect("slice[1]").unwrap()
);
}
}

View file

@ -50,11 +50,11 @@ mod tutorial5 {
let signame: &str = &format!("get-{}-tags", stype);
match playbin.get_property(propname).unwrap().get() {
Some(x) => {
Ok(Some(x)) => {
for i in 0..x {
let tags = playbin.emit(signame, &[&i]).unwrap().unwrap();
if let Some(tags) = tags.get::<gst::TagList>() {
if let Ok(Some(tags)) = tags.get::<gst::TagList>() {
textbuf.insert_at_cursor(&format!("{} stream {}:\n ", stype, i));
if let Some(codec) = tags.get::<gst::tags::VideoCodec>() {
@ -87,7 +87,7 @@ mod tutorial5 {
}
}
}
None => {
_ => {
eprintln!("Could not get {}!", propname);
}
}
@ -345,7 +345,10 @@ mod tutorial5 {
playbin
.connect("video-tags-changed", false, |args| {
let pipeline = args[0].get::<gst::Element>().unwrap();
let pipeline = args[0]
.get::<gst::Element>()
.expect("playbin \"video-tags-changed\" args[0]")
.unwrap();
post_app_message(&pipeline);
None
})
@ -353,7 +356,10 @@ mod tutorial5 {
playbin
.connect("audio-tags-changed", false, |args| {
let pipeline = args[0].get::<gst::Element>().unwrap();
let pipeline = args[0]
.get::<gst::Element>()
.expect("playbin \"audio-tags-changed\" args[0]")
.unwrap();
post_app_message(&pipeline);
None
})
@ -361,7 +367,10 @@ mod tutorial5 {
playbin
.connect("text-tags-changed", false, move |args| {
let pipeline = args[0].get::<gst::Element>().unwrap();
let pipeline = args[0]
.get::<gst::Element>()
.expect("playbin \"text-tags-changed\" args[0]")
.unwrap();
post_app_message(&pipeline);
None
})

View file

@ -15,7 +15,7 @@ use std::env;
mod tutorials_common;
fn send_value_as_str(v: &glib::SendValue) -> Option<String> {
if let Some(s) = v.get::<&str>() {
if let Ok(Some(s)) = v.get::<&str>() {
Some(s.to_string())
} else if let Some(serialized) = v.serialize() {
Some(serialized)