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 // 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 // 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. // 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 // This gets the index of the stream that changed. This is neccessary, since
// there could e.g. be multiple audio streams (english, spanish, ...). // 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); println!("audio tags of audio stream {} changed:", idx);
@ -81,7 +86,7 @@ fn example_main() {
.emit("get-audio-tags", &[&idx.to_value()]) .emit("get-audio-tags", &[&idx.to_value()])
.unwrap() .unwrap()
.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>() { if let Some(artist) = tags.get::<gst::tags::Artist>() {
println!(" Artist: {}", artist.get().unwrap()); println!(" Artist: {}", artist.get().unwrap());

View file

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

View file

@ -119,7 +119,10 @@ fn example_main() -> Result<(), Error> {
pay.link(&q2)?; pay.link(&q2)?;
rtpbin.connect("request-fec-encoder", false, move |values| { 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) { match make_fec_encoder(fec_percentage) {
Ok(elem) => Some(elem.to_value()), 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. // much more corner-cases. This is just for the sake of being an example.
let caps = values[2] let caps = values[2]
.get::<gst::Caps>() .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 let format_name = caps
.get_structure(0) .get_structure(0)
.expect("Failed to get format name") .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 _, b"min-upstream-latency\0".as_ptr() as *const _,
value.to_glib_none_mut().0, 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.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>( pub fn connect_property_timeout_notify<F: Fn(&Self) + Send + Sync + 'static>(

View file

@ -66,7 +66,7 @@ where
let res = let res =
gst_sys::gst_iterator_next(self.to_glib_none_mut().0, value.to_glib_none_mut().0); gst_sys::gst_iterator_next(self.to_glib_none_mut().0, value.to_glib_none_mut().0);
match res { 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)), Some(value) => Ok(Some(value)),
None => Err(IteratorError::Error), None => Err(IteratorError::Error),
}, },
@ -123,7 +123,7 @@ where
func_ptr, func_ptr,
)); ));
if res { if res {
Some(elem.get::<T>().unwrap()) elem.get::<T>().expect("Iterator::find")
} else { } else {
None None
} }
@ -339,7 +339,10 @@ where
let func: &&(dyn Fn(T) -> bool + Send + Sync + 'static) = mem::transmute(func); let func: &&(dyn Fn(T) -> bool + Send + Sync + 'static) = mem::transmute(func);
let value = &*(value as *const glib::Value); 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) { if func(value) {
0 0
@ -408,7 +411,7 @@ where
let func = func as *mut F; let func = func as *mut F;
let value = &*(value as *const glib::Value); 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) { if (*func)(value) {
0 0
@ -425,7 +428,10 @@ unsafe extern "C" fn foreach_trampoline<T, F: FnMut(T)>(
{ {
let func = func as *mut F; let func = func as *mut F;
let value = &*(value as *const glib::Value); 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); (*func)(value);
} }
@ -440,7 +446,7 @@ where
{ {
let func = func as *mut F; let func = func as *mut F;
let value = &*(value as *const glib::Value); 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>); 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) }; unsafe { from_glib_borrow(self.as_ptr() as *mut gobject_sys::GObject) };
obj.connect(signal_name.as_str(), false, move |values| { obj.connect(signal_name.as_str(), false, move |values| {
let obj: O = unsafe { values[0].get::<::Object>().unwrap().unsafe_cast() }; // It would be nice to display the actual signal name in the panic messages below,
let prop_obj: ::Object = values[1].get().unwrap(); // 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 = unsafe {
let pspec = gobject_sys::g_value_get_param(values[2].to_glib_none().0); 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. // except according to those terms.
use std::borrow::{Borrow, BorrowMut, ToOwned}; use std::borrow::{Borrow, BorrowMut, ToOwned};
use std::error;
use std::ffi::CStr; use std::ffi::CStr;
use std::fmt; use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -22,11 +23,62 @@ use glib::translate::{
from_glib, from_glib_full, from_glib_none, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault, from_glib, from_glib_full, from_glib_none, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault,
Stash, StashMut, ToGlib, ToGlibPtr, ToGlibPtrMut, Stash, StashMut, ToGlib, ToGlibPtr, ToGlibPtrMut,
}; };
use glib::value::{FromValueOptional, SendValue, ToSendValue}; use glib::value::{FromValue, FromValueOptional, SendValue, ToSendValue};
use glib_sys::gpointer; use glib_sys::gpointer;
use gobject_sys; use gobject_sys;
use gst_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>); pub struct Structure(ptr::NonNull<StructureRef>, PhantomData<StructureRef>);
unsafe impl Send for Structure {} unsafe impl Send for Structure {}
unsafe impl Sync 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)) } 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> { pub fn get<'structure, 'name, T: FromValueOptional<'structure>>(
self.get_value(name).and_then(|v| v.get()) &'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 { unsafe {
let value = gst_sys::gst_structure_get_value(&self.0, name.to_glib_none().0); let value = gst_sys::gst_structure_get_value(&self.0, name.to_glib_none().0);
if value.is_null() { 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("f2", &String::from("bcd"));
s.set("f3", &123i32); s.set("f3", &123i32);
assert_eq!(s.get::<&str>("f1").unwrap(), "abc"); assert_eq!(s.get::<&str>("f1"), Ok(Some("abc")));
assert_eq!(s.get::<&str>("f2").unwrap(), "bcd"); assert_eq!(s.get::<&str>("f2"), Ok(Some("bcd")));
assert_eq!(s.get::<i32>("f3").unwrap(), 123i32); 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"]); assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f2", "f3"]);
let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>(); let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>();
assert_eq!(v.len(), 3); assert_eq!(v.len(), 3);
assert_eq!(v[0].0, "f1"); 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].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].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)]); let s2 = Structure::new("test", &[("f1", &"abc"), ("f2", &"bcd"), ("f3", &123i32)]);
assert_eq!(s, s2); assert_eq!(s, s2);
@ -709,9 +810,9 @@ mod tests {
.build(); .build();
assert_eq!(s.get_name(), "test"); assert_eq!(s.get_name(), "test");
assert_eq!(s.get::<&str>("f1").unwrap(), "abc"); assert_eq!(s.get::<&str>("f1"), Ok(Some("abc")));
assert_eq!(s.get::<&str>("f2").unwrap(), "bcd"); assert_eq!(s.get::<&str>("f2"), Ok(Some("bcd")));
assert_eq!(s.get::<i32>("f3").unwrap(), 123i32); assert_eq!(s.get_some::<i32>("f3"), Ok(123i32));
} }
#[test] #[test]
@ -721,8 +822,8 @@ mod tests {
let a = "Test, f1=(string)abc, f2=(uint)123;"; let a = "Test, f1=(string)abc, f2=(uint)123;";
let s = Structure::from_string(&a).unwrap(); let s = Structure::from_string(&a).unwrap();
assert_eq!(s.get::<&str>("f1").unwrap(), "abc"); assert_eq!(s.get::<&str>("f1"), Ok(Some("abc")));
assert_eq!(s.get::<u32>("f2").unwrap(), 123); assert_eq!(s.get_some::<u32>("f2"), Ok(123));
assert_eq!(a, s.to_string()); 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>> { pub fn get<'a, T: Tag<'a>>(&self) -> Option<TypedValue<T::TagType>> {
self.get_generic(T::tag_name()) self.get_generic(T::tag_name()).map(|value| {
.and_then(|value| value.downcast().ok()) 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> { pub fn get_generic(&self, tag_name: &str) -> Option<SendValue> {
@ -966,24 +969,24 @@ mod tests {
assert_eq!( assert_eq!(
tags.get_index_generic(&TAG_TITLE, 0).unwrap().get(), tags.get_index_generic(&TAG_TITLE, 0).unwrap().get(),
Some("some title") Ok(Some("some title"))
); );
assert_eq!( assert_eq!(
tags.get_index_generic(&TAG_TITLE, 1).unwrap().get(), tags.get_index_generic(&TAG_TITLE, 1).unwrap().get(),
Some("second title") Ok(Some("second title"))
); );
assert_eq!( assert_eq!(
tags.get_index_generic(&TAG_DURATION, 0).unwrap().get(), tags.get_index_generic(&TAG_DURATION, 0).unwrap().get(),
Some(::SECOND * 120) Ok(Some(::SECOND * 120))
); );
assert_eq!( assert_eq!(
tags.get_index_generic(&TAG_TITLE, 2).unwrap().get(), tags.get_index_generic(&TAG_TITLE, 2).unwrap().get(),
Some("third title") Ok(Some("third title"))
); );
assert_eq!( assert_eq!(
tags.get_generic(&TAG_TITLE).unwrap().get(), 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); assert_eq!(tags.n_tags(), 2);
@ -996,11 +999,11 @@ mod tests {
let mut title_iter = tags.iter_tag_generic(&TAG_TITLE); let mut title_iter = tags.iter_tag_generic(&TAG_TITLE);
assert_eq!(title_iter.size_hint(), (3, Some(3))); assert_eq!(title_iter.size_hint(), (3, Some(3)));
let first_title = title_iter.next().unwrap(); 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(); 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(); 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()); assert!(title_iter.next().is_none());
// GenericIter // GenericIter
@ -1010,17 +1013,17 @@ mod tests {
let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap(); let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap();
assert_eq!(tag_name, *TAG_TITLE); assert_eq!(tag_name, *TAG_TITLE);
let first_title = tag_iter.next().unwrap(); 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(); 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(); 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()); assert!(tag_iter.next().is_none());
let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap(); let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap();
assert_eq!(tag_name, *TAG_DURATION); assert_eq!(tag_name, *TAG_DURATION);
let first_duration = tag_iter.next().unwrap(); 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()); assert!(tag_iter.next().is_none());
// Iter // Iter
@ -1031,12 +1034,12 @@ mod tests {
assert_eq!(tag_name, *TAG_TITLE); assert_eq!(tag_name, *TAG_TITLE);
assert_eq!( assert_eq!(
tag_value.get(), 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(); let (tag_name, tag_value) = tag_list_iter.next().unwrap();
assert_eq!(tag_name, *TAG_DURATION); 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()); assert!(tag_iter.next().is_none());
} }

View file

@ -61,7 +61,9 @@ impl<'de> Deserialize<'de> for Fraction {
macro_rules! ser_value ( macro_rules! ser_value (
($value:expr, $t:ty, $ser_closure:expr) => ( ($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) $ser_closure(stringify!($t), value)
} }
); );
@ -493,30 +495,36 @@ mod tests {
let slice = array.as_slice(); let slice = array.as_slice();
assert_eq!(3, slice.len()); 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.numer(), &1);
assert_eq!(fraction.0.denom(), &3); 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.numer(), &1);
assert_eq!(fraction.0.denom(), &2); 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_json = r#"[["Fraction",[1,3]],["Fraction",[1,2]],["String","test str"]]"#;
let array: Array = serde_json::from_str(array_json).unwrap(); let array: Array = serde_json::from_str(array_json).unwrap();
let slice = array.as_slice(); let slice = array.as_slice();
assert_eq!(3, slice.len()); 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.numer(), &1);
assert_eq!(fraction.0.denom(), &3); 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.numer(), &1);
assert_eq!(fraction.0.denom(), &2); 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 // List
let list_ron = r#"[ let list_ron = r#"[
@ -527,11 +535,14 @@ mod tests {
let slice = list.as_slice(); let slice = list.as_slice();
assert_eq!(2, slice.len()); 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.numer(), &1);
assert_eq!(fraction.0.denom(), &2); 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")] #[cfg(feature = "ser_de")]
@ -556,19 +567,19 @@ mod tests {
let slice = array.as_slice(); let slice = array.as_slice();
assert_eq!(slice_de.len(), slice.len()); assert_eq!(slice_de.len(), slice.len());
let fraction_de = slice_de[0].get::<Fraction>().unwrap(); let fraction_de = slice_de[0].get::<Fraction>().expect("slice_de[0]").unwrap();
let fraction = slice[0].get::<Fraction>().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.numer(), fraction.0.numer());
assert_eq!(fraction_de.0.denom(), fraction.0.denom()); assert_eq!(fraction_de.0.denom(), fraction.0.denom());
let fraction_de = slice_de[1].get::<Fraction>().unwrap(); let fraction_de = slice_de[1].get::<Fraction>().expect("slice_de[1]").unwrap();
let fraction = slice[1].get::<Fraction>().unwrap(); let fraction = slice[1].get::<Fraction>().expect("slice[1]").unwrap();
assert_eq!(fraction_de.0.numer(), fraction.0.numer()); assert_eq!(fraction_de.0.numer(), fraction.0.numer());
assert_eq!(fraction.0.denom(), fraction.0.denom()); assert_eq!(fraction.0.denom(), fraction.0.denom());
assert_eq!( assert_eq!(
slice_de[2].get::<String>().unwrap(), slice_de[2].get::<String>().expect("slice_de[2]").unwrap(),
slice[2].get::<String>().unwrap() slice[2].get::<String>().expect("slice[2]").unwrap()
); );
// List // List
@ -584,14 +595,14 @@ mod tests {
let slice = list.as_slice(); let slice = list.as_slice();
assert_eq!(slice_de.len(), slice.len()); assert_eq!(slice_de.len(), slice.len());
let fraction_de = slice_de[0].get::<Fraction>().unwrap(); let fraction_de = slice_de[0].get::<Fraction>().expect("slice_de[0]").unwrap();
let fraction = slice[0].get::<Fraction>().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.numer(), fraction.0.numer());
assert_eq!(fraction_de.0.denom(), fraction.0.denom()); assert_eq!(fraction_de.0.denom(), fraction.0.denom());
assert_eq!( assert_eq!(
slice_de[1].get::<String>().unwrap(), slice_de[1].get::<String>().expect("slice_de[1]").unwrap(),
slice[1].get::<String>().unwrap() slice[1].get::<String>().expect("slice[1]").unwrap()
); );
} }
} }

View file

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

View file

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