diff --git a/gstreamer/src/subclass/mod.rs b/gstreamer/src/subclass/mod.rs index 5df976f60..3841d881d 100644 --- a/gstreamer/src/subclass/mod.rs +++ b/gstreamer/src/subclass/mod.rs @@ -17,6 +17,7 @@ pub mod element; pub mod prelude { pub use super::element::{ElementClassSubclassExt, ElementImpl, ElementImplExt}; + pub use super::uri_handler::URIHandlerImpl; pub use super::PanicPoison; pub use glib::subclass::prelude::*; } diff --git a/gstreamer/src/subclass/uri_handler.rs b/gstreamer/src/subclass/uri_handler.rs new file mode 100644 index 000000000..425f875cb --- /dev/null +++ b/gstreamer/src/subclass/uri_handler.rs @@ -0,0 +1,127 @@ +// Copyright (C) 2017-2018 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 ffi; +use glib_ffi; +use gobject_ffi; + +use glib; +use glib::prelude::*; +use glib::translate::*; + +use glib::subclass::prelude::*; + +use libc; + +use std::ptr; + +use URIHandler; +use URIType; + +pub trait URIHandlerImpl: super::element::ElementImpl + Send + Sync + 'static { + fn get_uri(&self, element: &URIHandler) -> Option; + fn set_uri(&self, element: &URIHandler, uri: Option) -> Result<(), glib::Error>; + fn get_type() -> URIType; + fn get_protocols() -> Vec; +} + +unsafe extern "C" fn uri_handler_get_type( + _type_: glib_ffi::GType, +) -> ffi::GstURIType +where + T: URIHandlerImpl, +{ + ::get_type().to_glib() +} + +unsafe extern "C" fn uri_handler_get_protocols( + _type_: glib_ffi::GType, +) -> *const *const libc::c_char +where + T: URIHandlerImpl, +{ + let data = ::type_data(); + data.as_ref() + .get_interface_data(URIHandler::static_type().to_glib()) as *const _ +} + +unsafe extern "C" fn uri_handler_get_uri( + uri_handler: *mut ffi::GstURIHandler, +) -> *mut libc::c_char +where + T: URIHandlerImpl, +{ + glib_floating_reference_guard!(uri_handler); + let instance = &*(uri_handler as *mut T::Instance); + let imp = instance.get_impl(); + + imp.get_uri(&from_glib_borrow(uri_handler)).to_glib_full() +} + +unsafe extern "C" fn uri_handler_set_uri( + uri_handler: *mut ffi::GstURIHandler, + uri: *const libc::c_char, + err: *mut *mut glib_ffi::GError, +) -> glib_ffi::gboolean +where + T: URIHandlerImpl, +{ + glib_floating_reference_guard!(uri_handler); + let instance = &*(uri_handler as *mut T::Instance); + let imp = instance.get_impl(); + + match imp.set_uri(&from_glib_borrow(uri_handler), from_glib_none(uri)) { + Ok(()) => true.to_glib(), + Err(error) => { + *err = error.to_glib_full() as *mut _; + false.to_glib() + } + } +} + +unsafe extern "C" fn uri_handler_init( + iface: glib_ffi::gpointer, + _iface_data: glib_ffi::gpointer, +) where + T: URIHandlerImpl, +{ + let uri_handler_iface = &mut *(iface as *mut ffi::GstURIHandlerInterface); + + // Store the protocols in the interface data for later use + let mut data = T::type_data(); + let protocols = T::get_protocols(); + let protocols: *mut *const libc::c_char = protocols.to_glib_full(); + let data = &mut *data.as_mut(); + if data.interface_data.is_null() { + data.interface_data = Box::into_raw(Box::new(Vec::new())); + } + (*(data.interface_data as *mut Vec<(glib_ffi::GType, glib_ffi::gpointer)>)) + .push((URIHandler::static_type().to_glib(), protocols as *mut _)); + + uri_handler_iface.get_type = Some(uri_handler_get_type::); + uri_handler_iface.get_protocols = Some(uri_handler_get_protocols::); + uri_handler_iface.get_uri = Some(uri_handler_get_uri::); + uri_handler_iface.set_uri = Some(uri_handler_set_uri::); +} + +pub fn register( + type_: &glib::subclass::InitializingType, +) { + unsafe { + let iface_info = gobject_ffi::GInterfaceInfo { + interface_init: Some(uri_handler_init::), + interface_finalize: None, + interface_data: ptr::null_mut(), + }; + gobject_ffi::g_type_add_interface_static( + type_.to_glib(), + ffi::gst_uri_handler_get_type(), + &iface_info, + ); + } +}