1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ptr;
4
5use glib::translate::*;
6use gst::subclass::prelude::*;
7
8use crate::{prelude::*, AudioEncoder, AudioInfo};
9
10pub trait AudioEncoderImpl: AudioEncoderImplExt + ElementImpl {
11 fn open(&self) -> Result<(), gst::ErrorMessage> {
12 self.parent_open()
13 }
14
15 fn close(&self) -> Result<(), gst::ErrorMessage> {
16 self.parent_close()
17 }
18
19 fn start(&self) -> Result<(), gst::ErrorMessage> {
20 self.parent_start()
21 }
22
23 fn stop(&self) -> Result<(), gst::ErrorMessage> {
24 self.parent_stop()
25 }
26
27 fn set_format(&self, info: &AudioInfo) -> Result<(), gst::LoggableError> {
28 self.parent_set_format(info)
29 }
30
31 fn handle_frame(
32 &self,
33 buffer: Option<&gst::Buffer>,
34 ) -> Result<gst::FlowSuccess, gst::FlowError> {
35 self.parent_handle_frame(buffer)
36 }
37
38 fn pre_push(&self, buffer: gst::Buffer) -> Result<Option<gst::Buffer>, gst::FlowError> {
39 self.parent_pre_push(buffer)
40 }
41
42 fn flush(&self) {
43 self.parent_flush()
44 }
45
46 fn negotiate(&self) -> Result<(), gst::LoggableError> {
47 self.parent_negotiate()
48 }
49
50 fn caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
51 self.parent_caps(filter)
52 }
53
54 fn sink_event(&self, event: gst::Event) -> bool {
55 self.parent_sink_event(event)
56 }
57
58 fn sink_query(&self, query: &mut gst::QueryRef) -> bool {
59 self.parent_sink_query(query)
60 }
61
62 fn src_event(&self, event: gst::Event) -> bool {
63 self.parent_src_event(event)
64 }
65
66 fn src_query(&self, query: &mut gst::QueryRef) -> bool {
67 self.parent_src_query(query)
68 }
69
70 fn propose_allocation(
71 &self,
72 query: &mut gst::query::Allocation,
73 ) -> Result<(), gst::LoggableError> {
74 self.parent_propose_allocation(query)
75 }
76
77 fn decide_allocation(
78 &self,
79 query: &mut gst::query::Allocation,
80 ) -> Result<(), gst::LoggableError> {
81 self.parent_decide_allocation(query)
82 }
83}
84
85mod sealed {
86 pub trait Sealed {}
87 impl<T: super::AudioEncoderImplExt> Sealed for T {}
88}
89
90pub trait AudioEncoderImplExt: sealed::Sealed + ObjectSubclass {
91 fn parent_open(&self) -> Result<(), gst::ErrorMessage> {
92 unsafe {
93 let data = Self::type_data();
94 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
95 (*parent_class)
96 .open
97 .map(|f| {
98 if from_glib(f(self
99 .obj()
100 .unsafe_cast_ref::<AudioEncoder>()
101 .to_glib_none()
102 .0))
103 {
104 Ok(())
105 } else {
106 Err(gst::error_msg!(
107 gst::CoreError::StateChange,
108 ["Parent function `open` failed"]
109 ))
110 }
111 })
112 .unwrap_or(Ok(()))
113 }
114 }
115
116 fn parent_close(&self) -> Result<(), gst::ErrorMessage> {
117 unsafe {
118 let data = Self::type_data();
119 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
120 (*parent_class)
121 .close
122 .map(|f| {
123 if from_glib(f(self
124 .obj()
125 .unsafe_cast_ref::<AudioEncoder>()
126 .to_glib_none()
127 .0))
128 {
129 Ok(())
130 } else {
131 Err(gst::error_msg!(
132 gst::CoreError::StateChange,
133 ["Parent function `close` failed"]
134 ))
135 }
136 })
137 .unwrap_or(Ok(()))
138 }
139 }
140
141 fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
142 unsafe {
143 let data = Self::type_data();
144 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
145 (*parent_class)
146 .start
147 .map(|f| {
148 if from_glib(f(self
149 .obj()
150 .unsafe_cast_ref::<AudioEncoder>()
151 .to_glib_none()
152 .0))
153 {
154 Ok(())
155 } else {
156 Err(gst::error_msg!(
157 gst::CoreError::StateChange,
158 ["Parent function `start` failed"]
159 ))
160 }
161 })
162 .unwrap_or(Ok(()))
163 }
164 }
165
166 fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
167 unsafe {
168 let data = Self::type_data();
169 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
170 (*parent_class)
171 .stop
172 .map(|f| {
173 if from_glib(f(self
174 .obj()
175 .unsafe_cast_ref::<AudioEncoder>()
176 .to_glib_none()
177 .0))
178 {
179 Ok(())
180 } else {
181 Err(gst::error_msg!(
182 gst::CoreError::StateChange,
183 ["Parent function `stop` failed"]
184 ))
185 }
186 })
187 .unwrap_or(Ok(()))
188 }
189 }
190
191 fn parent_set_format(&self, info: &AudioInfo) -> Result<(), gst::LoggableError> {
192 unsafe {
193 let data = Self::type_data();
194 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
195 (*parent_class)
196 .set_format
197 .map(|f| {
198 gst::result_from_gboolean!(
199 f(
200 self.obj()
201 .unsafe_cast_ref::<AudioEncoder>()
202 .to_glib_none()
203 .0,
204 info.to_glib_none().0 as *mut _
205 ),
206 gst::CAT_RUST,
207 "parent function `set_format` failed"
208 )
209 })
210 .unwrap_or(Ok(()))
211 }
212 }
213
214 fn parent_handle_frame(
215 &self,
216 buffer: Option<&gst::Buffer>,
217 ) -> Result<gst::FlowSuccess, gst::FlowError> {
218 unsafe {
219 let data = Self::type_data();
220 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
221 (*parent_class)
222 .handle_frame
223 .map(|f| {
224 try_from_glib(f(
225 self.obj()
226 .unsafe_cast_ref::<AudioEncoder>()
227 .to_glib_none()
228 .0,
229 buffer
230 .map(|buffer| buffer.as_mut_ptr() as *mut *mut gst::ffi::GstBuffer)
231 .unwrap_or(ptr::null_mut()),
232 ))
233 })
234 .unwrap_or(Err(gst::FlowError::Error))
235 }
236 }
237
238 fn parent_pre_push(&self, buffer: gst::Buffer) -> Result<Option<gst::Buffer>, gst::FlowError> {
239 unsafe {
240 let data = Self::type_data();
241 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
242 if let Some(f) = (*parent_class).pre_push {
243 let mut buffer = buffer.into_glib_ptr();
244 gst::FlowSuccess::try_from_glib(f(
245 self.obj()
246 .unsafe_cast_ref::<AudioEncoder>()
247 .to_glib_none()
248 .0,
249 &mut buffer,
250 ))
251 .map(|_| from_glib_full(buffer))
252 } else {
253 Ok(Some(buffer))
254 }
255 }
256 }
257
258 fn parent_flush(&self) {
259 unsafe {
260 let data = Self::type_data();
261 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
262 (*parent_class)
263 .flush
264 .map(|f| {
265 f(self
266 .obj()
267 .unsafe_cast_ref::<AudioEncoder>()
268 .to_glib_none()
269 .0)
270 })
271 .unwrap_or(())
272 }
273 }
274
275 fn parent_negotiate(&self) -> Result<(), gst::LoggableError> {
276 unsafe {
277 let data = Self::type_data();
278 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
279 (*parent_class)
280 .negotiate
281 .map(|f| {
282 gst::result_from_gboolean!(
283 f(self
284 .obj()
285 .unsafe_cast_ref::<AudioEncoder>()
286 .to_glib_none()
287 .0),
288 gst::CAT_RUST,
289 "Parent function `negotiate` failed"
290 )
291 })
292 .unwrap_or(Ok(()))
293 }
294 }
295
296 fn parent_caps(&self, filter: Option<&gst::Caps>) -> gst::Caps {
297 unsafe {
298 let data = Self::type_data();
299 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
300 (*parent_class)
301 .getcaps
302 .map(|f| {
303 from_glib_full(f(
304 self.obj()
305 .unsafe_cast_ref::<AudioEncoder>()
306 .to_glib_none()
307 .0,
308 filter.to_glib_none().0,
309 ))
310 })
311 .unwrap_or_else(|| {
312 self.obj()
313 .unsafe_cast_ref::<AudioEncoder>()
314 .proxy_getcaps(None, filter)
315 })
316 }
317 }
318
319 fn parent_sink_event(&self, event: gst::Event) -> bool {
320 unsafe {
321 let data = Self::type_data();
322 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
323 let f = (*parent_class)
324 .sink_event
325 .expect("Missing parent function `sink_event`");
326 from_glib(f(
327 self.obj()
328 .unsafe_cast_ref::<AudioEncoder>()
329 .to_glib_none()
330 .0,
331 event.into_glib_ptr(),
332 ))
333 }
334 }
335
336 fn parent_sink_query(&self, query: &mut gst::QueryRef) -> bool {
337 unsafe {
338 let data = Self::type_data();
339 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
340 let f = (*parent_class)
341 .sink_query
342 .expect("Missing parent function `sink_query`");
343 from_glib(f(
344 self.obj()
345 .unsafe_cast_ref::<AudioEncoder>()
346 .to_glib_none()
347 .0,
348 query.as_mut_ptr(),
349 ))
350 }
351 }
352
353 fn parent_src_event(&self, event: gst::Event) -> bool {
354 unsafe {
355 let data = Self::type_data();
356 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
357 let f = (*parent_class)
358 .src_event
359 .expect("Missing parent function `src_event`");
360 from_glib(f(
361 self.obj()
362 .unsafe_cast_ref::<AudioEncoder>()
363 .to_glib_none()
364 .0,
365 event.into_glib_ptr(),
366 ))
367 }
368 }
369
370 fn parent_src_query(&self, query: &mut gst::QueryRef) -> bool {
371 unsafe {
372 let data = Self::type_data();
373 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
374 let f = (*parent_class)
375 .src_query
376 .expect("Missing parent function `src_query`");
377 from_glib(f(
378 self.obj()
379 .unsafe_cast_ref::<AudioEncoder>()
380 .to_glib_none()
381 .0,
382 query.as_mut_ptr(),
383 ))
384 }
385 }
386
387 fn parent_propose_allocation(
388 &self,
389 query: &mut gst::query::Allocation,
390 ) -> Result<(), gst::LoggableError> {
391 unsafe {
392 let data = Self::type_data();
393 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
394 (*parent_class)
395 .propose_allocation
396 .map(|f| {
397 gst::result_from_gboolean!(
398 f(
399 self.obj()
400 .unsafe_cast_ref::<AudioEncoder>()
401 .to_glib_none()
402 .0,
403 query.as_mut_ptr(),
404 ),
405 gst::CAT_RUST,
406 "Parent function `propose_allocation` failed",
407 )
408 })
409 .unwrap_or(Ok(()))
410 }
411 }
412
413 fn parent_decide_allocation(
414 &self,
415 query: &mut gst::query::Allocation,
416 ) -> Result<(), gst::LoggableError> {
417 unsafe {
418 let data = Self::type_data();
419 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioEncoderClass;
420 (*parent_class)
421 .decide_allocation
422 .map(|f| {
423 gst::result_from_gboolean!(
424 f(
425 self.obj()
426 .unsafe_cast_ref::<AudioEncoder>()
427 .to_glib_none()
428 .0,
429 query.as_mut_ptr(),
430 ),
431 gst::CAT_RUST,
432 "Parent function `decide_allocation` failed",
433 )
434 })
435 .unwrap_or(Ok(()))
436 }
437 }
438}
439
440impl<T: AudioEncoderImpl> AudioEncoderImplExt for T {}
441
442unsafe impl<T: AudioEncoderImpl> IsSubclassable<T> for AudioEncoder {
443 fn class_init(klass: &mut glib::Class<Self>) {
444 Self::parent_class_init::<T>(class:klass);
445 let klass: &mut GstAudioEncoderClass = klass.as_mut();
446 klass.open = Some(audio_encoder_open::<T>);
447 klass.close = Some(audio_encoder_close::<T>);
448 klass.start = Some(audio_encoder_start::<T>);
449 klass.stop = Some(audio_encoder_stop::<T>);
450 klass.set_format = Some(audio_encoder_set_format::<T>);
451 klass.handle_frame = Some(audio_encoder_handle_frame::<T>);
452 klass.pre_push = Some(audio_encoder_pre_push::<T>);
453 klass.flush = Some(audio_encoder_flush::<T>);
454 klass.negotiate = Some(audio_encoder_negotiate::<T>);
455 klass.getcaps = Some(audio_encoder_getcaps::<T>);
456 klass.sink_event = Some(audio_encoder_sink_event::<T>);
457 klass.src_event = Some(audio_encoder_src_event::<T>);
458 klass.sink_query = Some(audio_encoder_sink_query::<T>);
459 klass.src_query = Some(audio_encoder_src_query::<T>);
460 klass.propose_allocation = Some(audio_encoder_propose_allocation::<T>);
461 klass.decide_allocation = Some(audio_encoder_decide_allocation::<T>);
462 }
463}
464
465unsafe extern "C" fn audio_encoder_open<T: AudioEncoderImpl>(
466 ptr: *mut ffi::GstAudioEncoder,
467) -> glib::ffi::gboolean {
468 let instance: &::Instance = &*(ptr as *mut T::Instance);
469 let imp: &T = instance.imp();
470
471 gstbool::panic_to_error!(imp, false, {
472 match imp.open() {
473 Ok(()) => true,
474 Err(err) => {
475 imp.post_error_message(err);
476 false
477 }
478 }
479 })
480 .into_glib()
481}
482
483unsafe extern "C" fn audio_encoder_close<T: AudioEncoderImpl>(
484 ptr: *mut ffi::GstAudioEncoder,
485) -> glib::ffi::gboolean {
486 let instance: &::Instance = &*(ptr as *mut T::Instance);
487 let imp: &T = instance.imp();
488
489 gstbool::panic_to_error!(imp, false, {
490 match imp.close() {
491 Ok(()) => true,
492 Err(err) => {
493 imp.post_error_message(err);
494 false
495 }
496 }
497 })
498 .into_glib()
499}
500
501unsafe extern "C" fn audio_encoder_start<T: AudioEncoderImpl>(
502 ptr: *mut ffi::GstAudioEncoder,
503) -> glib::ffi::gboolean {
504 let instance: &::Instance = &*(ptr as *mut T::Instance);
505 let imp: &T = instance.imp();
506
507 gstbool::panic_to_error!(imp, false, {
508 match imp.start() {
509 Ok(()) => true,
510 Err(err) => {
511 imp.post_error_message(err);
512 false
513 }
514 }
515 })
516 .into_glib()
517}
518
519unsafe extern "C" fn audio_encoder_stop<T: AudioEncoderImpl>(
520 ptr: *mut ffi::GstAudioEncoder,
521) -> glib::ffi::gboolean {
522 let instance: &::Instance = &*(ptr as *mut T::Instance);
523 let imp: &T = instance.imp();
524
525 gstbool::panic_to_error!(imp, false, {
526 match imp.stop() {
527 Ok(()) => true,
528 Err(err) => {
529 imp.post_error_message(err);
530 false
531 }
532 }
533 })
534 .into_glib()
535}
536
537unsafe extern "C" fn audio_encoder_set_format<T: AudioEncoderImpl>(
538 ptr: *mut ffi::GstAudioEncoder,
539 info: *mut ffi::GstAudioInfo,
540) -> glib::ffi::gboolean {
541 let instance: &::Instance = &*(ptr as *mut T::Instance);
542 let imp: &T = instance.imp();
543
544 gstbool::panic_to_error!(imp, false, {
545 match imp.set_format(&from_glib_none(info)) {
546 Ok(()) => true,
547 Err(err) => {
548 err.log_with_imp(imp);
549 false
550 }
551 }
552 })
553 .into_glib()
554}
555
556unsafe extern "C" fn audio_encoder_handle_frame<T: AudioEncoderImpl>(
557 ptr: *mut ffi::GstAudioEncoder,
558 buffer: *mut *mut gst::ffi::GstBuffer,
559) -> gst::ffi::GstFlowReturn {
560 // FIXME: Misgenerated in gstreamer-audio-sys
561 let buffer: *mut GstBuffer = buffer as *mut gst::ffi::GstBuffer;
562 let instance: &::Instance = &*(ptr as *mut T::Instance);
563 let imp: &T = instance.imp();
564
565 gstFlowReturn::panic_to_error!(imp, gst::FlowReturn::Error, {
566 imp.handle_frame(Option::<gst::Buffer>::from_glib_none(buffer).as_ref())
567 .into()
568 })
569 .into_glib()
570}
571
572unsafe extern "C" fn audio_encoder_pre_push<T: AudioEncoderImpl>(
573 ptr: *mut ffi::GstAudioEncoder,
574 buffer: *mut *mut gst::ffi::GstBuffer,
575) -> gst::ffi::GstFlowReturn {
576 let instance: &::Instance = &*(ptr as *mut T::Instance);
577 let imp: &T = instance.imp();
578
579 gstFlowReturn::panic_to_error!(imp, gst::FlowReturn::Error, {
580 match imp.pre_push(from_glib_full(*buffer)) {
581 Ok(Some(new_buffer)) => {
582 *buffer = new_buffer.into_glib_ptr();
583 Ok(gst::FlowSuccess::Ok)
584 }
585 Ok(None) => {
586 *buffer = ptr::null_mut();
587 Ok(gst::FlowSuccess::Ok)
588 }
589 Err(err) => Err(err),
590 }
591 .into()
592 })
593 .into_glib()
594}
595
596unsafe extern "C" fn audio_encoder_flush<T: AudioEncoderImpl>(ptr: *mut ffi::GstAudioEncoder) {
597 let instance: &::Instance = &*(ptr as *mut T::Instance);
598 let imp: &T = instance.imp();
599
600 gst::panic_to_error!(imp, (), { AudioEncoderImpl::flush(imp,) })
601}
602
603unsafe extern "C" fn audio_encoder_negotiate<T: AudioEncoderImpl>(
604 ptr: *mut ffi::GstAudioEncoder,
605) -> glib::ffi::gboolean {
606 let instance: &::Instance = &*(ptr as *mut T::Instance);
607 let imp: &T = instance.imp();
608
609 gstbool::panic_to_error!(imp, false, {
610 match imp.negotiate() {
611 Ok(()) => true,
612 Err(err) => {
613 err.log_with_imp(imp);
614 false
615 }
616 }
617 })
618 .into_glib()
619}
620
621unsafe extern "C" fn audio_encoder_getcaps<T: AudioEncoderImpl>(
622 ptr: *mut ffi::GstAudioEncoder,
623 filter: *mut gst::ffi::GstCaps,
624) -> *mut gst::ffi::GstCaps {
625 let instance: &::Instance = &*(ptr as *mut T::Instance);
626 let imp: &T = instance.imp();
627
628 gstCaps::panic_to_error!(imp, gst::Caps::new_empty(), {
629 AudioEncoderImpl::caps(
630 imp,
631 Option::<gst::Caps>::from_glib_borrow(filter)
632 .as_ref()
633 .as_ref(),
634 )
635 })
636 .into_glib_ptr()
637}
638
639unsafe extern "C" fn audio_encoder_sink_event<T: AudioEncoderImpl>(
640 ptr: *mut ffi::GstAudioEncoder,
641 event: *mut gst::ffi::GstEvent,
642) -> glib::ffi::gboolean {
643 let instance: &::Instance = &*(ptr as *mut T::Instance);
644 let imp: &T = instance.imp();
645
646 gst::panic_to_error!(imp, false, { imp.sink_event(from_glib_full(event)) }).into_glib()
647}
648
649unsafe extern "C" fn audio_encoder_sink_query<T: AudioEncoderImpl>(
650 ptr: *mut ffi::GstAudioEncoder,
651 query: *mut gst::ffi::GstQuery,
652) -> glib::ffi::gboolean {
653 let instance: &::Instance = &*(ptr as *mut T::Instance);
654 let imp: &T = instance.imp();
655
656 gstbool::panic_to_error!(imp, false, {
657 imp.sink_query(gst::QueryRef::from_mut_ptr(query))
658 })
659 .into_glib()
660}
661
662unsafe extern "C" fn audio_encoder_src_event<T: AudioEncoderImpl>(
663 ptr: *mut ffi::GstAudioEncoder,
664 event: *mut gst::ffi::GstEvent,
665) -> glib::ffi::gboolean {
666 let instance: &::Instance = &*(ptr as *mut T::Instance);
667 let imp: &T = instance.imp();
668
669 gst::panic_to_error!(imp, false, { imp.src_event(from_glib_full(event)) }).into_glib()
670}
671
672unsafe extern "C" fn audio_encoder_src_query<T: AudioEncoderImpl>(
673 ptr: *mut ffi::GstAudioEncoder,
674 query: *mut gst::ffi::GstQuery,
675) -> glib::ffi::gboolean {
676 let instance: &::Instance = &*(ptr as *mut T::Instance);
677 let imp: &T = instance.imp();
678
679 gstbool::panic_to_error!(imp, false, {
680 imp.src_query(gst::QueryRef::from_mut_ptr(query))
681 })
682 .into_glib()
683}
684
685unsafe extern "C" fn audio_encoder_propose_allocation<T: AudioEncoderImpl>(
686 ptr: *mut ffi::GstAudioEncoder,
687 query: *mut gst::ffi::GstQuery,
688) -> glib::ffi::gboolean {
689 let instance: &::Instance = &*(ptr as *mut T::Instance);
690 let imp: &T = instance.imp();
691 let query: &mut Allocation = match gst::QueryRef::from_mut_ptr(query).view_mut() {
692 gst::QueryViewMut::Allocation(allocation: &mut Allocation) => allocation,
693 _ => unreachable!(),
694 };
695
696 gstbool::panic_to_error!(imp, false, {
697 match imp.propose_allocation(query) {
698 Ok(()) => true,
699 Err(err) => {
700 err.log_with_imp(imp);
701 false
702 }
703 }
704 })
705 .into_glib()
706}
707
708unsafe extern "C" fn audio_encoder_decide_allocation<T: AudioEncoderImpl>(
709 ptr: *mut ffi::GstAudioEncoder,
710 query: *mut gst::ffi::GstQuery,
711) -> glib::ffi::gboolean {
712 let instance: &::Instance = &*(ptr as *mut T::Instance);
713 let imp: &T = instance.imp();
714 let query: &mut Allocation = match gst::QueryRef::from_mut_ptr(query).view_mut() {
715 gst::QueryViewMut::Allocation(allocation: &mut Allocation) => allocation,
716 _ => unreachable!(),
717 };
718
719 gstbool::panic_to_error!(imp, false, {
720 match imp.decide_allocation(query) {
721 Ok(()) => true,
722 Err(err) => {
723 err.log_with_imp(imp);
724 false
725 }
726 }
727 })
728 .into_glib()
729}
730