gstreamer_editing_services/subclass/
formatter.rs1use crate::{ffi, prelude::*, Formatter};
4use glib::{subclass::prelude::*, translate::*};
5
6pub trait FormatterImpl: ObjectImpl + ObjectSubclass<Type: IsA<Formatter>> + Send + Sync {
7 fn can_load_uri(&self, uri: &str) -> Result<(), glib::Error> {
8 self.parent_can_load_uri(uri)
9 }
10
11 fn load_from_uri(&self, timeline: &crate::Timeline, uri: &str) -> Result<(), glib::Error> {
12 self.parent_load_from_uri(timeline, uri)
13 }
14
15 fn save_to_uri(
16 &self,
17 timeline: &crate::Timeline,
18 uri: &str,
19 overwrite: bool,
20 ) -> Result<(), glib::Error> {
21 self.parent_save_to_uri(timeline, uri, overwrite)
22 }
23}
24
25pub trait FormatterImplExt: FormatterImpl {
26 fn parent_can_load_uri(&self, uri: &str) -> Result<(), glib::Error> {
27 unsafe {
28 let data = Self::type_data();
29 let parent_class = data.as_ref().parent_class() as *mut ffi::GESFormatterClass;
30
31 let f = (*parent_class)
32 .can_load_uri
33 .expect("Missing parent function `can_load_uri`");
34
35 let mut error = std::ptr::null_mut();
36 let res = f(
37 self.obj()
38 .unsafe_cast_ref::<crate::Formatter>()
39 .to_glib_none()
40 .0,
41 uri.to_glib_none().0,
42 &mut error,
43 );
44
45 if res == glib::ffi::GFALSE {
46 if error.is_null() {
47 Err(glib::Error::new(
48 gst::CoreError::Failed,
49 "Can load uri failed",
50 ))
51 } else {
52 Err(from_glib_full(error))
53 }
54 } else {
55 Ok(())
56 }
57 }
58 }
59
60 fn parent_load_from_uri(
61 &self,
62 timeline: &crate::Timeline,
63 uri: &str,
64 ) -> Result<(), glib::Error> {
65 unsafe {
66 let data = Self::type_data();
67 let parent_class = data.as_ref().parent_class() as *mut ffi::GESFormatterClass;
68
69 let f = (*parent_class)
70 .load_from_uri
71 .expect("Missing parent function `load_from_uri`");
72
73 let mut error = std::ptr::null_mut();
74 let res = f(
75 self.obj()
76 .unsafe_cast_ref::<crate::Formatter>()
77 .to_glib_none()
78 .0,
79 timeline
80 .unsafe_cast_ref::<crate::Timeline>()
81 .to_glib_none()
82 .0,
83 uri.to_glib_none().0,
84 &mut error,
85 );
86
87 if res == glib::ffi::GFALSE {
88 if error.is_null() {
89 Err(glib::Error::new(
90 gst::CoreError::Failed,
91 "Load from uri failed",
92 ))
93 } else {
94 Err(from_glib_full(error))
95 }
96 } else {
97 Ok(())
98 }
99 }
100 }
101 fn parent_save_to_uri(
102 &self,
103 timeline: &crate::Timeline,
104 uri: &str,
105 overwrite: bool,
106 ) -> Result<(), glib::Error> {
107 unsafe {
108 let data = Self::type_data();
109 let parent_class = data.as_ref().parent_class() as *mut ffi::GESFormatterClass;
110
111 let f = (*parent_class)
112 .save_to_uri
113 .expect("Missing parent function `save_to_uri`");
114
115 let mut error = std::ptr::null_mut();
116 let res = f(
117 self.obj()
118 .unsafe_cast_ref::<crate::Formatter>()
119 .to_glib_none()
120 .0,
121 timeline
122 .unsafe_cast_ref::<crate::Timeline>()
123 .to_glib_none()
124 .0,
125 uri.to_glib_none().0,
126 overwrite.into_glib(),
127 &mut error,
128 );
129
130 if res == glib::ffi::GFALSE {
131 if error.is_null() {
132 Err(glib::Error::new(
133 gst::CoreError::Failed,
134 "Save to uri failed",
135 ))
136 } else {
137 Err(from_glib_full(error))
138 }
139 } else {
140 Ok(())
141 }
142 }
143 }
144}
145
146impl<T: FormatterImpl> FormatterImplExt for T {}
147
148unsafe impl<T: FormatterImpl> IsSubclassable<T> for Formatter {
149 fn class_init(klass: &mut glib::Class<Self>) {
150 Self::parent_class_init::<T>(klass);
151 let klass = klass.as_mut();
152 klass.can_load_uri = Some(formatter_can_load_uri::<T>);
153 klass.load_from_uri = Some(formatter_load_from_uri::<T>);
154 klass.save_to_uri = Some(formatter_save_to_uri::<T>);
155 }
156}
157
158unsafe extern "C" fn formatter_can_load_uri<T: FormatterImpl>(
159 ptr: *mut ffi::GESFormatter,
160 uri: *const libc::c_char,
161 error: *mut *mut glib::ffi::GError,
162) -> glib::ffi::gboolean {
163 let instance = &*(ptr as *mut T::Instance);
164 let imp = instance.imp();
165
166 match imp.can_load_uri(glib::GString::from_glib_borrow(uri).as_str()) {
167 Err(err) => {
168 if !error.is_null() {
169 *error = err.into_glib_ptr();
170 }
171
172 glib::ffi::GFALSE
173 }
174 Ok(_) => glib::ffi::GTRUE,
175 }
176}
177
178unsafe extern "C" fn formatter_load_from_uri<T: FormatterImpl>(
179 ptr: *mut ffi::GESFormatter,
180 timeline: *mut ffi::GESTimeline,
181 uri: *const libc::c_char,
182 error: *mut *mut glib::ffi::GError,
183) -> glib::ffi::gboolean {
184 let instance = &*(ptr as *mut T::Instance);
185 let imp = instance.imp();
186 let timeline = from_glib_borrow(timeline);
187
188 match imp.load_from_uri(&timeline, glib::GString::from_glib_borrow(uri).as_str()) {
189 Err(err) => {
190 if !error.is_null() {
191 *error = err.into_glib_ptr();
192 }
193
194 glib::ffi::GFALSE
195 }
196 Ok(_) => glib::ffi::GTRUE,
197 }
198}
199
200unsafe extern "C" fn formatter_save_to_uri<T: FormatterImpl>(
201 ptr: *mut ffi::GESFormatter,
202 timeline: *mut ffi::GESTimeline,
203 uri: *const libc::c_char,
204 overwrite: glib::ffi::gboolean,
205 error: *mut *mut glib::ffi::GError,
206) -> glib::ffi::gboolean {
207 let instance = &*(ptr as *mut T::Instance);
208 let imp = instance.imp();
209 let timeline = from_glib_borrow(timeline);
210
211 match imp.save_to_uri(
212 &timeline,
213 glib::GString::from_glib_borrow(uri).as_str(),
214 from_glib(overwrite),
215 ) {
216 Err(err) => {
217 if !error.is_null() {
218 *error = err.into_glib_ptr();
219 }
220
221 glib::ffi::GFALSE
222 }
223 Ok(_) => glib::ffi::GTRUE,
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230 use crate::Formatter;
231
232 pub mod imp {
233 use super::*;
234
235 #[derive(Default)]
236 pub struct SimpleFormatter;
237
238 #[glib::object_subclass]
239 impl ObjectSubclass for SimpleFormatter {
240 const NAME: &'static str = "SimpleFormatter";
241 type Type = super::SimpleFormatter;
242 type ParentType = Formatter;
243 }
244 impl ObjectImpl for SimpleFormatter {}
245 impl FormatterImpl for SimpleFormatter {
246 fn can_load_uri(&self, uri: &str) -> Result<(), glib::Error> {
247 if uri.starts_with("ges:test") {
248 Ok(())
249 } else {
250 self.parent_can_load_uri(uri)
251 }
252 }
253
254 fn load_from_uri(
255 &self,
256 timeline: &crate::Timeline,
257 _uri: &str,
258 ) -> Result<(), glib::Error> {
259 timeline.append_layer();
260
261 Ok(())
262 }
263
264 fn save_to_uri(
265 &self,
266 timeline: &crate::Timeline,
267 uri: &str,
268 _overwrite: bool,
269 ) -> Result<(), glib::Error> {
270 unsafe { timeline.set_data("saved", uri.to_string()) };
271
272 Ok(())
273 }
274 }
275 }
276
277 glib::wrapper! {
278 pub struct SimpleFormatter(ObjectSubclass<imp::SimpleFormatter>) @extends Formatter, gst::Object;
279 }
280
281 impl SimpleFormatter {
282 pub fn new() -> Self {
283 glib::Object::builder().build()
284 }
285 }
286
287 impl Default for SimpleFormatter {
288 fn default() -> Self {
289 Self::new()
290 }
291 }
292
293 #[test]
294 fn test_formatter_subclass() {
295 crate::init().unwrap();
296
297 let formatter = SimpleFormatter::new();
298 formatter
299 .can_load_uri("ges:test:")
300 .expect("We can load anything...");
301
302 assert!(formatter.can_load_uri("nottest").is_err());
303
304 let timeline = crate::Timeline::new();
305 assert_eq!(timeline.layers().len(), 0);
306 #[allow(deprecated)]
307 formatter
308 .load_from_uri(&timeline, "test")
309 .expect("We can load anything...");
310 assert_eq!(timeline.layers().len(), 1);
311
312 unsafe {
313 assert_eq!(timeline.data::<Option<String>>("saved"), None);
314 }
315 #[allow(deprecated)]
316 formatter
317 .save_to_uri(&timeline, "test", false)
318 .expect("We can save anything...");
319 unsafe {
320 assert_eq!(
321 timeline.data::<String>("saved").unwrap().as_ref(),
322 &"test".to_string()
323 );
324 }
325
326 Formatter::register(
327 SimpleFormatter::static_type(),
328 "SimpleFormatter",
329 None,
330 None,
331 None,
332 1.0,
333 gst::Rank::PRIMARY,
334 );
335
336 let proj = crate::Project::new(Some("ges:test:"));
337 let timeline = proj
338 .extract()
339 .unwrap()
340 .downcast::<crate::Timeline>()
341 .unwrap();
342 assert_eq!(timeline.layers().len(), 1);
343
344 let proj = crate::Project::new(Some("ges:notest:"));
345 assert!(proj.extract().is_err());
346 }
347}