diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index 3e206047a..a2ff4b2bb 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -92,6 +92,7 @@ mod element; mod bin; mod bus; mod pad; +mod object; mod gobject; mod proxy_pad; mod ghost_pad; @@ -100,6 +101,7 @@ mod tag_setter; mod iterator; mod device_provider; mod parse_context; +pub use object::GstObjectExtManual; pub use element::{ElementExtManual, ElementMessageType, NotifyWatchId}; pub use element::{ELEMENT_METADATA_AUTHOR, ELEMENT_METADATA_DESCRIPTION, ELEMENT_METADATA_DOC_URI, ELEMENT_METADATA_ICON_NAME, ELEMENT_METADATA_KLASS, ELEMENT_METADATA_LONGNAME}; @@ -164,6 +166,7 @@ pub mod prelude { pub use element::ElementExtManual; pub use bin::BinExtManual; pub use pad::PadExtManual; + pub use object::GstObjectExtManual; pub use gobject::GObjectExtManualGst; pub use child_proxy::ChildProxyExtManual; pub use tag_setter::TagSetterExtManual; diff --git a/gstreamer/src/object.rs b/gstreamer/src/object.rs new file mode 100644 index 000000000..edd2cea59 --- /dev/null +++ b/gstreamer/src/object.rs @@ -0,0 +1,77 @@ +// Copyright (C) 2017 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use glib; +use glib::{IsA, Cast}; +use glib::translate::ToGlibPtr; +use glib::signal::SignalHandlerId; +use glib::object::ObjectExt; + +use gobject_ffi; + +use std::ffi::CStr; + +pub trait GstObjectExtManual { + fn connect_deep_notify( + &self, + f: F, + ) -> SignalHandlerId; +} + +impl + IsA + glib::value::SetValue> GstObjectExtManual for O { + fn connect_deep_notify( + &self, + f: F, + ) -> SignalHandlerId { + self.connect("deep-notify", false, move |values| { + let obj: O = values[0] + .get::() + .unwrap() + .downcast() + .unwrap(); + let prop_obj: ::Object = values[1].get().unwrap(); + + let prop_name = unsafe { + let pspec = gobject_ffi::g_value_get_param(values[2].to_glib_none().0); + CStr::from_ptr((*pspec).name).to_str().unwrap() + }; + + f(&obj, &prop_obj, prop_name); + + None + }).unwrap() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; + use std::sync::{Arc, Mutex}; + + #[test] + fn test_deep_notify() { + ::init().unwrap(); + + let bin = ::Bin::new(None); + let identity = ::ElementFactory::make("identity", "id").unwrap(); + bin.add(&identity).unwrap(); + + let notify = Arc::new(Mutex::new(None)); + let notify_clone = notify.clone(); + bin.connect_deep_notify(move |_, id, prop| { + *notify_clone.lock().unwrap() = Some((id.clone(), String::from(prop))); + }); + + identity.set_property("silent", &false).unwrap(); + assert_eq!( + *notify.lock().unwrap(), + Some((identity.upcast::<::Object>(), String::from("silent"))) + ); + } +}