1use std::mem;
10use std::ptr;
11
12use glib_ffi;
13use gobject_ffi;
14use gst_base_ffi;
15use gst_ffi;
16
17use glib;
18use glib::translate::*;
19use gst;
20use gst::prelude::*;
21use gst_base;
22
23use gobject_subclass::anyimpl::*;
24use gobject_subclass::object::*;
25
26use element::*;
27use object::*;
28
29pub trait BaseSinkImpl<T: BaseSinkBase>:
30 AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static
31where
32 T::InstanceStructType: PanicPoison,
33{
34 fn start(&self, _element: &T) -> bool {
35 true
36 }
37
38 fn stop(&self, _element: &T) -> bool {
39 true
40 }
41
42 fn render(&self, element: &T, buffer: &gst::BufferRef) -> gst::FlowReturn;
43
44 fn prepare(&self, _element: &T, _buffer: &gst::BufferRef) -> gst::FlowReturn {
45 gst::FlowReturn::Ok
46 }
47
48 fn render_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
49 for buffer in list.iter() {
50 let ret = self.render(element, buffer);
51 if ret != gst::FlowReturn::Ok {
52 return ret;
53 }
54 }
55
56 gst::FlowReturn::Ok
57 }
58
59 fn prepare_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
60 for buffer in list.iter() {
61 let ret = self.prepare(element, buffer);
62 if ret != gst::FlowReturn::Ok {
63 return ret;
64 }
65 }
66
67 gst::FlowReturn::Ok
68 }
69
70 fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
71 element.parent_query(query)
72 }
73
74 fn event(&self, element: &T, event: gst::Event) -> bool {
75 element.parent_event(event)
76 }
77
78 fn get_caps(&self, element: &T, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
79 element.parent_get_caps(filter)
80 }
81
82 fn set_caps(&self, element: &T, caps: &gst::CapsRef) -> bool {
83 element.parent_set_caps(caps)
84 }
85
86 fn fixate(&self, element: &T, caps: gst::Caps) -> gst::Caps {
87 element.parent_fixate(caps)
88 }
89
90 fn unlock(&self, _element: &T) -> bool {
91 true
92 }
93
94 fn unlock_stop(&self, _element: &T) -> bool {
95 true
96 }
97}
98
99any_impl!(BaseSinkBase, BaseSinkImpl, PanicPoison);
100
101pub unsafe trait BaseSinkBase:
102 IsA<gst::Element> + IsA<gst_base::BaseSink> + ObjectType
103{
104 fn parent_query(&self, query: &mut gst::QueryRef) -> bool {
105 unsafe {
106 let klass = self.get_class();
107 let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
108 (*parent_klass)
109 .query
110 .map(|f| from_glib(f(self.to_glib_none().0, query.as_mut_ptr())))
111 .unwrap_or(false)
112 }
113 }
114
115 fn parent_event(&self, event: gst::Event) -> bool {
116 unsafe {
117 let klass = self.get_class();
118 let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
119 (*parent_klass)
120 .event
121 .map(|f| from_glib(f(self.to_glib_none().0, event.into_ptr())))
122 .unwrap_or(false)
123 }
124 }
125
126 fn parent_get_caps(&self, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
127 unsafe {
128 let klass = self.get_class();
129 let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
130 let filter_ptr = if let Some(filter) = filter {
131 filter.as_mut_ptr()
132 } else {
133 ptr::null_mut()
134 };
135
136 (*parent_klass)
137 .get_caps
138 .map(|f| from_glib_full(f(self.to_glib_none().0, filter_ptr)))
139 .unwrap_or(None)
140 }
141 }
142
143 fn parent_set_caps(&self, caps: &gst::CapsRef) -> bool {
144 unsafe {
145 let klass = self.get_class();
146 let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
147 (*parent_klass)
148 .set_caps
149 .map(|f| from_glib(f(self.to_glib_none().0, caps.as_mut_ptr())))
150 .unwrap_or(true)
151 }
152 }
153
154 fn parent_fixate(&self, caps: gst::Caps) -> gst::Caps {
155 unsafe {
156 let klass = self.get_class();
157 let parent_klass = (*klass).get_parent_class() as *const gst_base_ffi::GstBaseSinkClass;
158
159 match (*parent_klass).fixate {
160 Some(fixate) => from_glib_full(fixate(self.to_glib_none().0, caps.into_ptr())),
161 None => caps,
162 }
163 }
164 }
165}
166
167pub unsafe trait BaseSinkClassExt<T: BaseSinkBase>
168where
169 T::ImplType: BaseSinkImpl<T>,
170 T::InstanceStructType: PanicPoison,
171{
172 fn override_vfuncs(&mut self, _: &ClassInitToken) {
173 unsafe {
174 let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstBaseSinkClass);
175 klass.start = Some(base_sink_start::<T>);
176 klass.stop = Some(base_sink_stop::<T>);
177 klass.render = Some(base_sink_render::<T>);
178 klass.render_list = Some(base_sink_render_list::<T>);
179 klass.prepare = Some(base_sink_prepare::<T>);
180 klass.prepare_list = Some(base_sink_prepare_list::<T>);
181 klass.query = Some(base_sink_query::<T>);
182 klass.event = Some(base_sink_event::<T>);
183 klass.get_caps = Some(base_sink_get_caps::<T>);
184 klass.set_caps = Some(base_sink_set_caps::<T>);
185 klass.fixate = Some(base_sink_fixate::<T>);
186 klass.unlock = Some(base_sink_unlock::<T>);
187 klass.unlock_stop = Some(base_sink_unlock_stop::<T>);
188 }
189 }
190}
191
192glib_wrapper! {
193 pub struct BaseSink(Object<ElementInstanceStruct<BaseSink>>):
194 [gst_base::BaseSink => gst_base_ffi::GstBaseSink,
195 gst::Element => gst_ffi::GstElement,
196 gst::Object => gst_ffi::GstObject];
197
198 match fn {
199 get_type => || get_type::<BaseSink>(),
200 }
201}
202
203unsafe impl<T: IsA<gst::Element> + IsA<gst_base::BaseSink> + ObjectType> BaseSinkBase for T {}
204pub type BaseSinkClass = ClassStruct<BaseSink>;
205
206unsafe impl BaseSinkClassExt<BaseSink> for BaseSinkClass {}
208unsafe impl ElementClassExt<BaseSink> for BaseSinkClass {}
209unsafe impl ObjectClassExt<BaseSink> for BaseSinkClass {}
210
211unsafe impl Send for BaseSink {}
212unsafe impl Sync for BaseSink {}
213
214#[macro_export]
215macro_rules! box_base_sink_impl(
216 ($name:ident) => {
217 box_element_impl!($name);
218
219 impl<T: BaseSinkBase> BaseSinkImpl<T> for Box<$name<T>>
220 where
221 T::InstanceStructType: PanicPoison
222 {
223 fn start(&self, element: &T) -> bool {
224 let imp: &$name<T> = self.as_ref();
225 imp.start(element)
226 }
227
228 fn stop(&self, element: &T) -> bool {
229 let imp: &$name<T> = self.as_ref();
230 imp.stop(element)
231 }
232
233 fn render(&self, element: &T, buffer: &gst::BufferRef) -> gst::FlowReturn {
234 let imp: &$name<T> = self.as_ref();
235 imp.render(element, buffer)
236 }
237
238 fn prepare(&self, element: &T, buffer: &gst::BufferRef) -> gst::FlowReturn {
239 let imp: &$name<T> = self.as_ref();
240 imp.prepare(element, buffer)
241 }
242
243 fn render_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
244 let imp: &$name<T> = self.as_ref();
245 imp.render_list(element, list)
246 }
247
248 fn prepare_list(&self, element: &T, list: &gst::BufferListRef) -> gst::FlowReturn {
249 let imp: &$name<T> = self.as_ref();
250 imp.prepare_list(element, list)
251 }
252
253 fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
254 let imp: &$name<T> = self.as_ref();
255 BaseSinkImpl::query(imp, element, query)
256 }
257
258 fn event(&self, element: &T, event: gst::Event) -> bool {
259 let imp: &$name<T> = self.as_ref();
260 imp.event(element, event)
261 }
262
263 fn get_caps(&self, element: &T, filter: Option<&gst::CapsRef>) -> Option<gst::Caps> {
264 let imp: &$name<T> = self.as_ref();
265 imp.get_caps(element, filter)
266 }
267
268 fn set_caps(&self, element: &T, caps: &gst::CapsRef) -> bool {
269 let imp: &$name<T> = self.as_ref();
270 imp.set_caps(element, caps)
271 }
272
273 fn fixate(&self, element: &T, caps: gst::Caps) -> gst::Caps {
274 let imp: &$name<T> = self.as_ref();
275 imp.fixate(element, caps)
276 }
277
278 fn unlock(&self, element: &T) -> bool {
279 let imp: &$name<T> = self.as_ref();
280 imp.unlock(element)
281 }
282
283 fn unlock_stop(&self, element: &T) -> bool {
284 let imp: &$name<T> = self.as_ref();
285 imp.unlock_stop(element)
286 }
287 }
288 };
289);
290
291box_base_sink_impl!(BaseSinkImpl);
292
293impl ObjectType for BaseSink {
294 const NAME: &'static str = "RsBaseSink";
295 type ParentType = gst_base::BaseSink;
296 type ImplType = Box<BaseSinkImpl<Self>>;
297 type InstanceStructType = ElementInstanceStruct<Self>;
298
299 fn class_init(token: &ClassInitToken, klass: &mut BaseSinkClass) {
300 ObjectClassExt::override_vfuncs(klass, token);
301 ElementClassExt::override_vfuncs(klass, token);
302 BaseSinkClassExt::override_vfuncs(klass, token);
303 }
304
305 object_type_fns!();
306}
307
308unsafe extern "C" fn base_sink_start<T: BaseSinkBase>(
309 ptr: *mut gst_base_ffi::GstBaseSink,
310) -> glib_ffi::gboolean
311where
312 T::ImplType: BaseSinkImpl<T>,
313 T::InstanceStructType: PanicPoison,
314{
315 floating_reference_guard!(ptr);
316 let element = &*(ptr as *mut T::InstanceStructType);
317 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
318 let imp = element.get_impl();
319
320 panic_to_error!(&wrap, &element.panicked(), false, { imp.start(&wrap) }).to_glib()
321}
322
323unsafe extern "C" fn base_sink_stop<T: BaseSinkBase>(
324 ptr: *mut gst_base_ffi::GstBaseSink,
325) -> glib_ffi::gboolean
326where
327 T::ImplType: BaseSinkImpl<T>,
328 T::InstanceStructType: PanicPoison,
329{
330 floating_reference_guard!(ptr);
331 let element = &*(ptr as *mut T::InstanceStructType);
332 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
333 let imp = element.get_impl();
334
335 panic_to_error!(&wrap, &element.panicked(), false, { imp.stop(&wrap) }).to_glib()
336}
337
338unsafe extern "C" fn base_sink_render<T: BaseSinkBase>(
339 ptr: *mut gst_base_ffi::GstBaseSink,
340 buffer: *mut gst_ffi::GstBuffer,
341) -> gst_ffi::GstFlowReturn
342where
343 T::ImplType: BaseSinkImpl<T>,
344 T::InstanceStructType: PanicPoison,
345{
346 floating_reference_guard!(ptr);
347 let element = &*(ptr as *mut T::InstanceStructType);
348 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
349 let imp = element.get_impl();
350 let buffer = gst::BufferRef::from_ptr(buffer);
351
352 panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
353 imp.render(&wrap, buffer)
354 })
355 .to_glib()
356}
357
358unsafe extern "C" fn base_sink_prepare<T: BaseSinkBase>(
359 ptr: *mut gst_base_ffi::GstBaseSink,
360 buffer: *mut gst_ffi::GstBuffer,
361) -> gst_ffi::GstFlowReturn
362where
363 T::ImplType: BaseSinkImpl<T>,
364 T::InstanceStructType: PanicPoison,
365{
366 floating_reference_guard!(ptr);
367 let element = &*(ptr as *mut T::InstanceStructType);
368 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
369 let imp = element.get_impl();
370 let buffer = gst::BufferRef::from_ptr(buffer);
371
372 panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
373 imp.prepare(&wrap, buffer)
374 })
375 .to_glib()
376}
377
378unsafe extern "C" fn base_sink_render_list<T: BaseSinkBase>(
379 ptr: *mut gst_base_ffi::GstBaseSink,
380 list: *mut gst_ffi::GstBufferList,
381) -> gst_ffi::GstFlowReturn
382where
383 T::ImplType: BaseSinkImpl<T>,
384 T::InstanceStructType: PanicPoison,
385{
386 floating_reference_guard!(ptr);
387 let element = &*(ptr as *mut T::InstanceStructType);
388 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
389 let imp = element.get_impl();
390 let list = gst::BufferListRef::from_ptr(list);
391
392 panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
393 imp.render_list(&wrap, list)
394 })
395 .to_glib()
396}
397
398unsafe extern "C" fn base_sink_prepare_list<T: BaseSinkBase>(
399 ptr: *mut gst_base_ffi::GstBaseSink,
400 list: *mut gst_ffi::GstBufferList,
401) -> gst_ffi::GstFlowReturn
402where
403 T::ImplType: BaseSinkImpl<T>,
404 T::InstanceStructType: PanicPoison,
405{
406 floating_reference_guard!(ptr);
407 let element = &*(ptr as *mut T::InstanceStructType);
408 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
409 let imp = element.get_impl();
410 let list = gst::BufferListRef::from_ptr(list);
411
412 panic_to_error!(&wrap, &element.panicked(), gst::FlowReturn::Error, {
413 imp.prepare_list(&wrap, list)
414 })
415 .to_glib()
416}
417
418unsafe extern "C" fn base_sink_query<T: BaseSinkBase>(
419 ptr: *mut gst_base_ffi::GstBaseSink,
420 query_ptr: *mut gst_ffi::GstQuery,
421) -> glib_ffi::gboolean
422where
423 T::ImplType: BaseSinkImpl<T>,
424 T::InstanceStructType: PanicPoison,
425{
426 floating_reference_guard!(ptr);
427 let element = &*(ptr as *mut T::InstanceStructType);
428 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
429 let imp = element.get_impl();
430 let query = gst::QueryRef::from_mut_ptr(query_ptr);
431
432 panic_to_error!(&wrap, &element.panicked(), false, {
433 BaseSinkImpl::query(imp, &wrap, query)
434 })
435 .to_glib()
436}
437
438unsafe extern "C" fn base_sink_event<T: BaseSinkBase>(
439 ptr: *mut gst_base_ffi::GstBaseSink,
440 event_ptr: *mut gst_ffi::GstEvent,
441) -> glib_ffi::gboolean
442where
443 T::ImplType: BaseSinkImpl<T>,
444 T::InstanceStructType: PanicPoison,
445{
446 floating_reference_guard!(ptr);
447 let element = &*(ptr as *mut T::InstanceStructType);
448 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
449 let imp = element.get_impl();
450
451 panic_to_error!(&wrap, &element.panicked(), false, {
452 imp.event(&wrap, from_glib_full(event_ptr))
453 })
454 .to_glib()
455}
456
457unsafe extern "C" fn base_sink_get_caps<T: BaseSinkBase>(
458 ptr: *mut gst_base_ffi::GstBaseSink,
459 filter: *mut gst_ffi::GstCaps,
460) -> *mut gst_ffi::GstCaps
461where
462 T::ImplType: BaseSinkImpl<T>,
463 T::InstanceStructType: PanicPoison,
464{
465 floating_reference_guard!(ptr);
466 let element = &*(ptr as *mut T::InstanceStructType);
467 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
468 let imp = element.get_impl();
469 let filter = if filter.is_null() {
470 None
471 } else {
472 Some(gst::CapsRef::from_ptr(filter))
473 };
474
475 panic_to_error!(&wrap, &element.panicked(), None, {
476 imp.get_caps(&wrap, filter)
477 })
478 .map(|caps| caps.into_ptr())
479 .unwrap_or(ptr::null_mut())
480}
481
482unsafe extern "C" fn base_sink_set_caps<T: BaseSinkBase>(
483 ptr: *mut gst_base_ffi::GstBaseSink,
484 caps: *mut gst_ffi::GstCaps,
485) -> glib_ffi::gboolean
486where
487 T::ImplType: BaseSinkImpl<T>,
488 T::InstanceStructType: PanicPoison,
489{
490 floating_reference_guard!(ptr);
491 let element = &*(ptr as *mut T::InstanceStructType);
492 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
493 let imp = element.get_impl();
494 let caps = gst::CapsRef::from_ptr(caps);
495
496 panic_to_error!(&wrap, &element.panicked(), false, {
497 imp.set_caps(&wrap, caps)
498 })
499 .to_glib()
500}
501
502unsafe extern "C" fn base_sink_fixate<T: BaseSinkBase>(
503 ptr: *mut gst_base_ffi::GstBaseSink,
504 caps: *mut gst_ffi::GstCaps,
505) -> *mut gst_ffi::GstCaps
506where
507 T::ImplType: BaseSinkImpl<T>,
508 T::InstanceStructType: PanicPoison,
509{
510 floating_reference_guard!(ptr);
511 let element = &*(ptr as *mut T::InstanceStructType);
512 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
513 let imp = element.get_impl();
514 let caps = from_glib_full(caps);
515
516 panic_to_error!(&wrap, &element.panicked(), gst::Caps::new_empty(), {
517 imp.fixate(&wrap, caps)
518 })
519 .into_ptr()
520}
521
522unsafe extern "C" fn base_sink_unlock<T: BaseSinkBase>(
523 ptr: *mut gst_base_ffi::GstBaseSink,
524) -> glib_ffi::gboolean
525where
526 T::ImplType: BaseSinkImpl<T>,
527 T::InstanceStructType: PanicPoison,
528{
529 floating_reference_guard!(ptr);
530 let element = &*(ptr as *mut T::InstanceStructType);
531 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
532 let imp = element.get_impl();
533
534 panic_to_error!(&wrap, &element.panicked(), false, { imp.unlock(&wrap) }).to_glib()
535}
536
537unsafe extern "C" fn base_sink_unlock_stop<T: BaseSinkBase>(
538 ptr: *mut gst_base_ffi::GstBaseSink,
539) -> glib_ffi::gboolean
540where
541 T::ImplType: BaseSinkImpl<T>,
542 T::InstanceStructType: PanicPoison,
543{
544 floating_reference_guard!(ptr);
545 let element = &*(ptr as *mut T::InstanceStructType);
546 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
547 let imp = element.get_impl();
548
549 panic_to_error!(&wrap, &element.panicked(), false, {
550 imp.unlock_stop(&wrap)
551 })
552 .to_glib()
553}