1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ptr;
4
5use glib::{prelude::*, subclass::prelude::*, translate::*};
6
7use crate::{URIHandler, URIType};
8
9pub trait URIHandlerImpl: super::element::ElementImpl {
10 const URI_TYPE: URIType;
11 fn protocols() -> &'static [&'static str];
12 fn uri(&self) -> Option<String>;
13 fn set_uri(&self, uri: &str) -> Result<(), glib::Error>;
14}
15
16mod sealed {
17 pub trait Sealed {}
18 impl<T: super::URIHandlerImplExt> Sealed for T {}
19}
20
21pub trait URIHandlerImplExt: sealed::Sealed + ObjectSubclass {
22 fn parent_protocols() -> Vec<String> {
23 unsafe {
24 let type_data = Self::type_data();
25 let parent_iface = type_data.as_ref().parent_interface::<URIHandler>()
26 as *const ffi::GstURIHandlerInterface;
27
28 let func = (*parent_iface)
29 .get_protocols
30 .expect("no parent \"protocols\" implementation");
31 let ret = func(Self::ParentType::static_type().into_glib());
32 FromGlibPtrContainer::from_glib_none(ret)
33 }
34 }
35
36 fn parent_uri(&self) -> Option<String> {
37 unsafe {
38 let type_data = Self::type_data();
39 let parent_iface = type_data.as_ref().parent_interface::<URIHandler>()
40 as *const ffi::GstURIHandlerInterface;
41
42 let func = (*parent_iface)
43 .get_uri
44 .expect("no parent \"uri\" implementation");
45 let ret = func(self.obj().unsafe_cast_ref::<URIHandler>().to_glib_none().0);
46 from_glib_full(ret)
47 }
48 }
49
50 fn parent_set_uri(&self, uri: &str) -> Result<(), glib::Error> {
51 unsafe {
52 let type_data = Self::type_data();
53 let parent_iface = type_data.as_ref().parent_interface::<URIHandler>()
54 as *const ffi::GstURIHandlerInterface;
55
56 let func = (*parent_iface)
57 .set_uri
58 .expect("no parent \"set_uri\" implementation");
59
60 let mut err = ptr::null_mut();
61 func(
62 self.obj().unsafe_cast_ref::<URIHandler>().to_glib_none().0,
63 uri.to_glib_none().0,
64 &mut err,
65 );
66
67 if !err.is_null() {
68 Err(from_glib_full(err))
69 } else {
70 Ok(())
71 }
72 }
73 }
74}
75
76impl<T: URIHandlerImpl> URIHandlerImplExt for T {}
77
78unsafe impl<T: URIHandlerImpl> IsImplementable<T> for URIHandler {
79 fn interface_init(iface: &mut glib::Interface<Self>) {
80 let iface: &mut GstURIHandlerInterface = iface.as_mut();
81
82 // Store the protocols in the interface data for later use
83 unsafe {
84 let mut data: NonNull = T::type_data();
85 let protocols: &[&str] = T::protocols();
86 let data: &mut TypeData = data.as_mut();
87 data.set_class_data(Self::static_type(), data:glib::StrV::from(protocols));
88 }
89
90 iface.get_type = Some(uri_handler_get_type::<T>);
91 iface.get_protocols = Some(uri_handler_get_protocols::<T>);
92 iface.get_uri = Some(uri_handler_get_uri::<T>);
93 iface.set_uri = Some(uri_handler_set_uri::<T>);
94 }
95}
96
97unsafe extern "C" fn uri_handler_get_type<T: URIHandlerImpl>(
98 _type_: glib::ffi::GType,
99) -> ffi::GstURIType {
100 <T as URIHandlerImpl>::URI_TYPE.into_glib()
101}
102
103unsafe extern "C" fn uri_handler_get_protocols<T: URIHandlerImpl>(
104 _type_: glib::ffi::GType,
105) -> *const *const libc::c_char {
106 let data: NonNull = <T as ObjectSubclassType>::type_data();
107 data.as_ref()
108 .class_data::<glib::StrV>(URIHandler::static_type())
109 .map(|p| p.as_ptr() as *const *const _)
110 .unwrap_or(default:ptr::null())
111}
112
113unsafe extern "C" fn uri_handler_get_uri<T: URIHandlerImpl>(
114 uri_handler: *mut ffi::GstURIHandler,
115) -> *mut libc::c_char {
116 let instance: &::Instance = &*(uri_handler as *mut T::Instance);
117 let imp: &T = instance.imp();
118
119 imp.uri().to_glib_full()
120}
121
122unsafe extern "C" fn uri_handler_set_uri<T: URIHandlerImpl>(
123 uri_handler: *mut ffi::GstURIHandler,
124 uri: *const libc::c_char,
125 err: *mut *mut glib::ffi::GError,
126) -> glib::ffi::gboolean {
127 let instance: &::Instance = &*(uri_handler as *mut T::Instance);
128 let imp: &T = instance.imp();
129
130 match imp.set_uri(glib::GString::from_glib_borrow(_ptr:uri).as_str()) {
131 Ok(()) => true.into_glib(),
132 Err(error: Error) => {
133 if !err.is_null() {
134 *err = error.into_glib_ptr();
135 }
136 false.into_glib()
137 }
138 }
139}
140