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