gstreamer-rs/gstreamer-audio/src/subclass/audio_sink.rs
Bilal Elmoussaoui 4ebec84f5e Adapt to no longer renamed ffi crates
Allows us to set all the crates in the main workspace file, so changing
their versions or branch is much simpler and reduce the amount of noise
in the diff

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1450>
2024-06-02 11:20:55 +02:00

288 lines
8.6 KiB
Rust

// Take a look at the license at the top of the repository in the LICENSE file.
use glib::{prelude::*, translate::*};
use gst::LoggableError;
use gst_base::subclass::prelude::*;
use super::prelude::*;
use crate::{ffi, AudioRingBufferSpec, AudioSink};
pub trait AudioSinkImpl: AudioSinkImplExt + AudioBaseSinkImpl {
fn close(&self) -> Result<(), LoggableError> {
self.parent_close()
}
fn delay(&self) -> u32 {
self.parent_delay()
}
fn open(&self) -> Result<(), LoggableError> {
self.parent_open()
}
fn prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
AudioSinkImplExt::parent_prepare(self, spec)
}
fn unprepare(&self) -> Result<(), LoggableError> {
self.parent_unprepare()
}
fn write(&self, audio_data: &[u8]) -> Result<i32, LoggableError> {
self.parent_write(audio_data)
}
fn reset(&self) {
self.parent_reset()
}
}
mod sealed {
pub trait Sealed {}
impl<T: super::AudioSinkImplExt> Sealed for T {}
}
pub trait AudioSinkImplExt: sealed::Sealed + ObjectSubclass {
fn parent_close(&self) -> Result<(), LoggableError> {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
let f = match (*parent_class).close {
None => return Ok(()),
Some(f) => f,
};
gst::result_from_gboolean!(
f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0),
gst::CAT_RUST,
"Failed to close element using the parent function"
)
}
}
fn parent_delay(&self) -> u32 {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
let f = match (*parent_class).delay {
Some(f) => f,
None => return 0,
};
f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0)
}
}
fn parent_open(&self) -> Result<(), LoggableError> {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
let f = match (*parent_class).open {
Some(f) => f,
None => return Ok(()),
};
gst::result_from_gboolean!(
f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0),
gst::CAT_RUST,
"Failed to open element using the parent function"
)
}
}
fn parent_prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
let f = match (*parent_class).prepare {
Some(f) => f,
None => return Ok(()),
};
gst::result_from_gboolean!(
f(
self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0,
&mut spec.0
),
gst::CAT_RUST,
"Failed to prepare element using the parent function"
)
}
}
fn parent_unprepare(&self) -> Result<(), LoggableError> {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
let f = match (*parent_class).unprepare {
Some(f) => f,
None => {
return Err(gst::loggable_error!(
gst::CAT_RUST,
"Unprepare is not implemented!"
))
}
};
gst::result_from_gboolean!(
f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0),
gst::CAT_RUST,
"Failed to unprepare element using the parent function"
)
}
}
fn parent_write(&self, buffer: &[u8]) -> Result<i32, LoggableError> {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
let f = match (*parent_class).write {
Some(f) => f,
None => return Ok(-1),
};
let buffer_ptr = buffer.as_ptr() as glib::ffi::gpointer;
let ret = f(
self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0,
buffer_ptr,
buffer.len() as u32,
);
if ret > 0 {
Ok(ret)
} else {
Err(gst::loggable_error!(
gst::CAT_RUST,
"Failed to write using the parent function"
))
}
}
}
fn parent_reset(&self) {
unsafe {
let data = Self::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
if let Some(f) = (*parent_class).reset {
f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0)
}
}
}
}
impl<T: AudioSinkImpl> AudioSinkImplExt for T {}
unsafe impl<T: AudioSinkImpl> IsSubclassable<T> for AudioSink {
fn class_init(klass: &mut glib::Class<Self>) {
Self::parent_class_init::<T>(klass);
let klass = klass.as_mut();
klass.close = Some(audiosink_close::<T>);
klass.delay = Some(audiosink_delay::<T>);
klass.open = Some(audiosink_open::<T>);
klass.prepare = Some(audiosink_prepare::<T>);
klass.unprepare = Some(audiosink_unprepare::<T>);
klass.write = Some(audiosink_write::<T>);
klass.reset = Some(audiosink_reset::<T>);
}
}
unsafe extern "C" fn audiosink_close<T: AudioSinkImpl>(
ptr: *mut ffi::GstAudioSink,
) -> glib::ffi::gboolean {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();
gst::panic_to_error!(imp, false, {
match imp.close() {
Ok(()) => true,
Err(err) => {
err.log_with_imp(imp);
false
}
}
})
.into_glib()
}
unsafe extern "C" fn audiosink_delay<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) -> u32 {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();
gst::panic_to_error!(imp, 0, { imp.delay() })
}
unsafe extern "C" fn audiosink_open<T: AudioSinkImpl>(
ptr: *mut ffi::GstAudioSink,
) -> glib::ffi::gboolean {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();
gst::panic_to_error!(imp, false, {
match imp.open() {
Ok(()) => true,
Err(err) => {
err.log_with_imp(imp);
false
}
}
})
.into_glib()
}
unsafe extern "C" fn audiosink_prepare<T: AudioSinkImpl>(
ptr: *mut ffi::GstAudioSink,
spec: *mut ffi::GstAudioRingBufferSpec,
) -> glib::ffi::gboolean {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();
let spec = &mut *(spec as *mut AudioRingBufferSpec);
gst::panic_to_error!(imp, false, {
match AudioSinkImpl::prepare(imp, spec) {
Ok(()) => true,
Err(err) => {
err.log_with_imp(imp);
false
}
}
})
.into_glib()
}
unsafe extern "C" fn audiosink_unprepare<T: AudioSinkImpl>(
ptr: *mut ffi::GstAudioSink,
) -> glib::ffi::gboolean {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();
gst::panic_to_error!(imp, false, {
match imp.unprepare() {
Ok(()) => true,
Err(err) => {
err.log_with_imp(imp);
false
}
}
})
.into_glib()
}
unsafe extern "C" fn audiosink_write<T: AudioSinkImpl>(
ptr: *mut ffi::GstAudioSink,
data: glib::ffi::gpointer,
length: u32,
) -> i32 {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();
let data_slice = if length == 0 {
&[]
} else {
std::slice::from_raw_parts(data as *const u8, length as usize)
};
gst::panic_to_error!(imp, -1, { imp.write(data_slice).unwrap_or(-1) })
}
unsafe extern "C" fn audiosink_reset<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();
gst::panic_to_error!(imp, (), {
imp.reset();
});
}