1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::ptr; |
4 | |
5 | use glib::{prelude::*, subclass::prelude::*, translate::*}; |
6 | |
7 | use crate::{URIHandler, URIType}; |
8 | |
9 | pub 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 | |
16 | mod sealed { |
17 | pub trait Sealed {} |
18 | impl<T: super::URIHandlerImplExt> Sealed for T {} |
19 | } |
20 | |
21 | pub 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 | |
76 | impl<T: URIHandlerImpl> URIHandlerImplExt for T {} |
77 | |
78 | unsafe 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 | |
97 | unsafe 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 | |
103 | unsafe 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 | |
113 | unsafe 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 | |
122 | unsafe 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 | |