mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-12-23 08:36:31 +00:00
pbutils: Add bindings for the AudioVisualizer base class
This commit is contained in:
parent
44d899a0eb
commit
6163914605
9 changed files with 545 additions and 0 deletions
|
@ -19,6 +19,8 @@ libc = "0.2"
|
||||||
ffi = { package = "gstreamer-pbutils-sys", path = "sys" }
|
ffi = { package = "gstreamer-pbutils-sys", path = "sys" }
|
||||||
glib = { git = "https://github.com/gtk-rs/gtk-rs-core" }
|
glib = { git = "https://github.com/gtk-rs/gtk-rs-core" }
|
||||||
gst = { package = "gstreamer", path = "../gstreamer" }
|
gst = { package = "gstreamer", path = "../gstreamer" }
|
||||||
|
gst-video = { package = "gstreamer-video", path = "../gstreamer-video" }
|
||||||
|
gst-audio = { package = "gstreamer-audio", path = "../gstreamer-audio" }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1.0", optional = true }
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ external_libraries = [
|
||||||
]
|
]
|
||||||
|
|
||||||
generate = [
|
generate = [
|
||||||
|
"GstPbutils.AudioVisualizer",
|
||||||
|
"GstPbutils.AudioVisualizerShader",
|
||||||
"GstPbutils.DiscovererResult",
|
"GstPbutils.DiscovererResult",
|
||||||
"GstPbutils.PbUtilsCapsDescriptionFlags",
|
"GstPbutils.PbUtilsCapsDescriptionFlags",
|
||||||
]
|
]
|
||||||
|
|
72
gstreamer-pbutils/src/audio_visualizer.rs
Normal file
72
gstreamer-pbutils/src/audio_visualizer.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||||
|
|
||||||
|
use crate::auto::AudioVisualizer;
|
||||||
|
use crate::subclass::AudioVisualizerSetupToken;
|
||||||
|
use glib::object::IsA;
|
||||||
|
use gst::prelude::*;
|
||||||
|
|
||||||
|
pub trait AudioVisualizerExtManual: 'static {
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Returns the number of samples per frame required before calling the render method
|
||||||
|
fn req_spf(&self) -> u32;
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// Modify the request of samples per frame required to be present in buffer before calling
|
||||||
|
/// the render method
|
||||||
|
fn set_req_spf(&self, spf: u32, token: &AudioVisualizerSetupToken);
|
||||||
|
|
||||||
|
fn audio_info(&self) -> gst_audio::AudioInfo;
|
||||||
|
|
||||||
|
fn video_info(&self) -> gst_video::VideoInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O: IsA<AudioVisualizer> + ElementExt> AudioVisualizerExtManual for O {
|
||||||
|
fn req_spf(&self) -> u32 {
|
||||||
|
let sinkpad = self.static_pad("sink").expect("sink pad presence");
|
||||||
|
let _stream_lock = sinkpad.stream_lock();
|
||||||
|
|
||||||
|
let ptr = self.as_ptr() as *mut ffi::GstAudioVisualizer;
|
||||||
|
unsafe { (*ptr).req_spf }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_req_spf(&self, spf: u32, token: &AudioVisualizerSetupToken) {
|
||||||
|
assert_eq!(
|
||||||
|
self.as_ptr() as *mut ffi::GstAudioVisualizer,
|
||||||
|
token.0.as_ptr() as *mut ffi::GstAudioVisualizer
|
||||||
|
);
|
||||||
|
|
||||||
|
let sinkpad = self.static_pad("sink").expect("sink pad presence");
|
||||||
|
let _stream_lock = sinkpad.stream_lock();
|
||||||
|
|
||||||
|
let mut ptr = self.as_ptr() as *mut ffi::GstAudioVisualizer;
|
||||||
|
unsafe {
|
||||||
|
(*ptr).req_spf = spf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn audio_info(&self) -> gst_audio::AudioInfo {
|
||||||
|
let sinkpad = self.static_pad("sink").expect("sink pad presence");
|
||||||
|
let _stream_lock = sinkpad.stream_lock();
|
||||||
|
|
||||||
|
let ptr = self.as_ptr() as *mut ffi::GstAudioVisualizer;
|
||||||
|
unsafe {
|
||||||
|
let info = &(*ptr).ainfo;
|
||||||
|
glib::translate::from_glib_none(glib::translate::mut_override(
|
||||||
|
info as *const gst_audio::ffi::GstAudioInfo,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn video_info(&self) -> gst_video::VideoInfo {
|
||||||
|
let srcpad = self.static_pad("src").expect("src pad presence");
|
||||||
|
let _stream_lock = srcpad.stream_lock();
|
||||||
|
|
||||||
|
let ptr = self.as_ptr() as *mut ffi::GstAudioVisualizer;
|
||||||
|
unsafe {
|
||||||
|
let info = &(*ptr).vinfo;
|
||||||
|
glib::translate::from_glib_none(glib::translate::mut_override(
|
||||||
|
info as *const gst_video::ffi::GstVideoInfo,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
123
gstreamer-pbutils/src/auto/audio_visualizer.rs
Normal file
123
gstreamer-pbutils/src/auto/audio_visualizer.rs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
// This file was generated by gir (https://github.com/gtk-rs/gir)
|
||||||
|
// from gir-files (https://github.com/gtk-rs/gir-files)
|
||||||
|
// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
|
||||||
|
// DO NOT EDIT
|
||||||
|
|
||||||
|
use crate::AudioVisualizerShader;
|
||||||
|
use glib::object::Cast;
|
||||||
|
use glib::object::IsA;
|
||||||
|
use glib::signal::connect_raw;
|
||||||
|
use glib::signal::SignalHandlerId;
|
||||||
|
use glib::translate::*;
|
||||||
|
use glib::StaticType;
|
||||||
|
use glib::ToValue;
|
||||||
|
use std::boxed::Box as Box_;
|
||||||
|
use std::mem::transmute;
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
#[doc(alias = "GstAudioVisualizer")]
|
||||||
|
pub struct AudioVisualizer(Object<ffi::GstAudioVisualizer, ffi::GstAudioVisualizerClass>) @extends gst::Element, gst::Object;
|
||||||
|
|
||||||
|
match fn {
|
||||||
|
type_ => || ffi::gst_audio_visualizer_get_type(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AudioVisualizer {
|
||||||
|
pub const NONE: Option<&'static AudioVisualizer> = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for AudioVisualizer {}
|
||||||
|
unsafe impl Sync for AudioVisualizer {}
|
||||||
|
|
||||||
|
pub trait AudioVisualizerExt: 'static {
|
||||||
|
#[doc(alias = "shade-amount")]
|
||||||
|
fn shade_amount(&self) -> u32;
|
||||||
|
|
||||||
|
#[doc(alias = "shade-amount")]
|
||||||
|
fn set_shade_amount(&self, shade_amount: u32);
|
||||||
|
|
||||||
|
fn shader(&self) -> AudioVisualizerShader;
|
||||||
|
|
||||||
|
fn set_shader(&self, shader: AudioVisualizerShader);
|
||||||
|
|
||||||
|
#[doc(alias = "shade-amount")]
|
||||||
|
fn connect_shade_amount_notify<F: Fn(&Self) + Send + Sync + 'static>(
|
||||||
|
&self,
|
||||||
|
f: F,
|
||||||
|
) -> SignalHandlerId;
|
||||||
|
|
||||||
|
#[doc(alias = "shader")]
|
||||||
|
fn connect_shader_notify<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O: IsA<AudioVisualizer>> AudioVisualizerExt for O {
|
||||||
|
fn shade_amount(&self) -> u32 {
|
||||||
|
glib::ObjectExt::property(self.as_ref(), "shade-amount")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_shade_amount(&self, shade_amount: u32) {
|
||||||
|
glib::ObjectExt::set_property(self.as_ref(), "shade-amount", &shade_amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shader(&self) -> AudioVisualizerShader {
|
||||||
|
glib::ObjectExt::property(self.as_ref(), "shader")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_shader(&self, shader: AudioVisualizerShader) {
|
||||||
|
glib::ObjectExt::set_property(self.as_ref(), "shader", &shader)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect_shade_amount_notify<F: Fn(&Self) + Send + Sync + 'static>(
|
||||||
|
&self,
|
||||||
|
f: F,
|
||||||
|
) -> SignalHandlerId {
|
||||||
|
unsafe extern "C" fn notify_shade_amount_trampoline<
|
||||||
|
P: IsA<AudioVisualizer>,
|
||||||
|
F: Fn(&P) + Send + Sync + 'static,
|
||||||
|
>(
|
||||||
|
this: *mut ffi::GstAudioVisualizer,
|
||||||
|
_param_spec: glib::ffi::gpointer,
|
||||||
|
f: glib::ffi::gpointer,
|
||||||
|
) {
|
||||||
|
let f: &F = &*(f as *const F);
|
||||||
|
f(AudioVisualizer::from_glib_borrow(this).unsafe_cast_ref())
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
let f: Box_<F> = Box_::new(f);
|
||||||
|
connect_raw(
|
||||||
|
self.as_ptr() as *mut _,
|
||||||
|
b"notify::shade-amount\0".as_ptr() as *const _,
|
||||||
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
|
notify_shade_amount_trampoline::<Self, F> as *const (),
|
||||||
|
)),
|
||||||
|
Box_::into_raw(f),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect_shader_notify<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId {
|
||||||
|
unsafe extern "C" fn notify_shader_trampoline<
|
||||||
|
P: IsA<AudioVisualizer>,
|
||||||
|
F: Fn(&P) + Send + Sync + 'static,
|
||||||
|
>(
|
||||||
|
this: *mut ffi::GstAudioVisualizer,
|
||||||
|
_param_spec: glib::ffi::gpointer,
|
||||||
|
f: glib::ffi::gpointer,
|
||||||
|
) {
|
||||||
|
let f: &F = &*(f as *const F);
|
||||||
|
f(AudioVisualizer::from_glib_borrow(this).unsafe_cast_ref())
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
let f: Box_<F> = Box_::new(f);
|
||||||
|
connect_raw(
|
||||||
|
self.as_ptr() as *mut _,
|
||||||
|
b"notify::shader\0".as_ptr() as *const _,
|
||||||
|
Some(transmute::<_, unsafe extern "C" fn()>(
|
||||||
|
notify_shader_trampoline::<Self, F> as *const (),
|
||||||
|
)),
|
||||||
|
Box_::into_raw(f),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,108 @@ use glib::value::ToValue;
|
||||||
use glib::StaticType;
|
use glib::StaticType;
|
||||||
use glib::Type;
|
use glib::Type;
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[doc(alias = "GstAudioVisualizerShader")]
|
||||||
|
pub enum AudioVisualizerShader {
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_NONE")]
|
||||||
|
None,
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_FADE")]
|
||||||
|
Fade,
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_UP")]
|
||||||
|
FadeAndMoveUp,
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN")]
|
||||||
|
FadeAndMoveDown,
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_LEFT")]
|
||||||
|
FadeAndMoveLeft,
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_RIGHT")]
|
||||||
|
FadeAndMoveRight,
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT")]
|
||||||
|
FadeAndMoveHorizOut,
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_IN")]
|
||||||
|
FadeAndMoveHorizIn,
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_OUT")]
|
||||||
|
FadeAndMoveVertOut,
|
||||||
|
#[doc(alias = "GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_IN")]
|
||||||
|
FadeAndMoveVertIn,
|
||||||
|
#[doc(hidden)]
|
||||||
|
__Unknown(i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl IntoGlib for AudioVisualizerShader {
|
||||||
|
type GlibType = ffi::GstAudioVisualizerShader;
|
||||||
|
|
||||||
|
fn into_glib(self) -> ffi::GstAudioVisualizerShader {
|
||||||
|
match self {
|
||||||
|
Self::None => ffi::GST_AUDIO_VISUALIZER_SHADER_NONE,
|
||||||
|
Self::Fade => ffi::GST_AUDIO_VISUALIZER_SHADER_FADE,
|
||||||
|
Self::FadeAndMoveUp => ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_UP,
|
||||||
|
Self::FadeAndMoveDown => ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN,
|
||||||
|
Self::FadeAndMoveLeft => ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_LEFT,
|
||||||
|
Self::FadeAndMoveRight => ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_RIGHT,
|
||||||
|
Self::FadeAndMoveHorizOut => ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT,
|
||||||
|
Self::FadeAndMoveHorizIn => ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_IN,
|
||||||
|
Self::FadeAndMoveVertOut => ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_OUT,
|
||||||
|
Self::FadeAndMoveVertIn => ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_IN,
|
||||||
|
Self::__Unknown(value) => value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl FromGlib<ffi::GstAudioVisualizerShader> for AudioVisualizerShader {
|
||||||
|
unsafe fn from_glib(value: ffi::GstAudioVisualizerShader) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
match value {
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_NONE => Self::None,
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_FADE => Self::Fade,
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_UP => Self::FadeAndMoveUp,
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN => Self::FadeAndMoveDown,
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_LEFT => Self::FadeAndMoveLeft,
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_RIGHT => Self::FadeAndMoveRight,
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT => Self::FadeAndMoveHorizOut,
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_IN => Self::FadeAndMoveHorizIn,
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_OUT => Self::FadeAndMoveVertOut,
|
||||||
|
ffi::GST_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_IN => Self::FadeAndMoveVertIn,
|
||||||
|
value => Self::__Unknown(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StaticType for AudioVisualizerShader {
|
||||||
|
fn static_type() -> Type {
|
||||||
|
unsafe { from_glib(ffi::gst_audio_visualizer_shader_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl glib::value::ValueType for AudioVisualizerShader {
|
||||||
|
type Type = Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a> FromValue<'a> for AudioVisualizerShader {
|
||||||
|
type Checker = glib::value::GenericValueTypeChecker<Self>;
|
||||||
|
|
||||||
|
unsafe fn from_value(value: &'a glib::Value) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
from_glib(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToValue for AudioVisualizerShader {
|
||||||
|
fn to_value(&self) -> glib::Value {
|
||||||
|
let mut value = glib::Value::for_value_type::<Self>();
|
||||||
|
unsafe {
|
||||||
|
glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, self.into_glib());
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_type(&self) -> glib::Type {
|
||||||
|
Self::static_type()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[doc(alias = "GstDiscovererResult")]
|
#[doc(alias = "GstDiscovererResult")]
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
|
// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
|
||||||
// DO NOT EDIT
|
// DO NOT EDIT
|
||||||
|
|
||||||
|
mod audio_visualizer;
|
||||||
|
pub use self::audio_visualizer::AudioVisualizer;
|
||||||
|
|
||||||
mod discoverer;
|
mod discoverer;
|
||||||
pub use self::discoverer::Discoverer;
|
pub use self::discoverer::Discoverer;
|
||||||
|
|
||||||
|
@ -40,6 +43,7 @@ mod encoding_video_profile;
|
||||||
pub use self::encoding_video_profile::EncodingVideoProfile;
|
pub use self::encoding_video_profile::EncodingVideoProfile;
|
||||||
|
|
||||||
mod enums;
|
mod enums;
|
||||||
|
pub use self::enums::AudioVisualizerShader;
|
||||||
pub use self::enums::DiscovererResult;
|
pub use self::enums::DiscovererResult;
|
||||||
|
|
||||||
mod flags;
|
mod flags;
|
||||||
|
@ -52,6 +56,7 @@ pub mod functions;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod traits {
|
pub mod traits {
|
||||||
|
pub use super::audio_visualizer::AudioVisualizerExt;
|
||||||
pub use super::discoverer_stream_info::DiscovererStreamInfoExt;
|
pub use super::discoverer_stream_info::DiscovererStreamInfoExt;
|
||||||
pub use super::encoding_profile::EncodingProfileExt;
|
pub use super::encoding_profile::EncodingProfileExt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,12 +57,17 @@ pub mod encoding_profile;
|
||||||
pub mod functions;
|
pub mod functions;
|
||||||
pub use crate::functions::*;
|
pub use crate::functions::*;
|
||||||
|
|
||||||
|
pub mod subclass;
|
||||||
|
|
||||||
|
pub mod audio_visualizer;
|
||||||
|
|
||||||
// Re-export all the traits in a prelude module, so that applications
|
// Re-export all the traits in a prelude module, so that applications
|
||||||
// can always "use gst_pbutils::prelude::*" without getting conflicts
|
// can always "use gst_pbutils::prelude::*" without getting conflicts
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use gst::prelude::*;
|
pub use gst::prelude::*;
|
||||||
|
|
||||||
|
pub use crate::audio_visualizer::*;
|
||||||
pub use crate::auto::traits::*;
|
pub use crate::auto::traits::*;
|
||||||
pub use crate::encoding_profile::{
|
pub use crate::encoding_profile::{
|
||||||
EncodingProfileBuilder, EncodingProfileHasRestrictionGetter,
|
EncodingProfileBuilder, EncodingProfileHasRestrictionGetter,
|
||||||
|
|
226
gstreamer-pbutils/src/subclass/audio_visualizer.rs
Normal file
226
gstreamer-pbutils/src/subclass/audio_visualizer.rs
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||||
|
|
||||||
|
use glib::prelude::*;
|
||||||
|
use glib::translate::*;
|
||||||
|
use gst::subclass::prelude::*;
|
||||||
|
use gst::{result_from_gboolean, LoggableError, CAT_RUST};
|
||||||
|
|
||||||
|
use crate::AudioVisualizer;
|
||||||
|
|
||||||
|
pub struct AudioVisualizerSetupToken<'a>(pub(crate) &'a AudioVisualizer);
|
||||||
|
|
||||||
|
pub trait AudioVisualizerImpl: AudioVisualizerImplExt + ElementImpl {
|
||||||
|
fn setup(
|
||||||
|
&self,
|
||||||
|
element: &Self::Type,
|
||||||
|
token: &AudioVisualizerSetupToken,
|
||||||
|
) -> Result<(), LoggableError> {
|
||||||
|
self.parent_setup(element, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(
|
||||||
|
&self,
|
||||||
|
element: &Self::Type,
|
||||||
|
audio_buffer: &gst::BufferRef,
|
||||||
|
video_frame: &mut gst_video::VideoFrameRef<&mut gst::BufferRef>,
|
||||||
|
) -> Result<(), LoggableError> {
|
||||||
|
self.parent_render(element, audio_buffer, video_frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decide_allocation(
|
||||||
|
&self,
|
||||||
|
element: &Self::Type,
|
||||||
|
query: &mut gst::query::Allocation,
|
||||||
|
) -> Result<(), gst::LoggableError> {
|
||||||
|
self.parent_decide_allocation(element, query)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AudioVisualizerImplExt: ObjectSubclass {
|
||||||
|
fn parent_setup(
|
||||||
|
&self,
|
||||||
|
element: &Self::Type,
|
||||||
|
token: &AudioVisualizerSetupToken,
|
||||||
|
) -> Result<(), LoggableError>;
|
||||||
|
|
||||||
|
fn parent_render(
|
||||||
|
&self,
|
||||||
|
element: &Self::Type,
|
||||||
|
audio_buffer: &gst::BufferRef,
|
||||||
|
video_frame: &mut gst_video::VideoFrameRef<&mut gst::BufferRef>,
|
||||||
|
) -> Result<(), LoggableError>;
|
||||||
|
|
||||||
|
fn parent_decide_allocation(
|
||||||
|
&self,
|
||||||
|
element: &Self::Type,
|
||||||
|
query: &mut gst::query::Allocation,
|
||||||
|
) -> Result<(), gst::LoggableError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AudioVisualizerImpl> AudioVisualizerImplExt for T {
|
||||||
|
fn parent_setup(
|
||||||
|
&self,
|
||||||
|
element: &Self::Type,
|
||||||
|
token: &AudioVisualizerSetupToken,
|
||||||
|
) -> Result<(), LoggableError> {
|
||||||
|
assert_eq!(
|
||||||
|
element.as_ptr() as *mut ffi::GstAudioVisualizer,
|
||||||
|
token.0.as_ptr() as *mut ffi::GstAudioVisualizer
|
||||||
|
);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let data = Self::type_data();
|
||||||
|
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioVisualizerClass;
|
||||||
|
(*parent_class)
|
||||||
|
.setup
|
||||||
|
.map(|f| {
|
||||||
|
result_from_gboolean!(
|
||||||
|
f(element
|
||||||
|
.unsafe_cast_ref::<AudioVisualizer>()
|
||||||
|
.to_glib_none()
|
||||||
|
.0,),
|
||||||
|
CAT_RUST,
|
||||||
|
"Parent function `setup` failed",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or(Ok(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent_render(
|
||||||
|
&self,
|
||||||
|
element: &Self::Type,
|
||||||
|
audio_buffer: &gst::BufferRef,
|
||||||
|
video_frame: &mut gst_video::VideoFrameRef<&mut gst::BufferRef>,
|
||||||
|
) -> Result<(), LoggableError> {
|
||||||
|
unsafe {
|
||||||
|
let data = Self::type_data();
|
||||||
|
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioVisualizerClass;
|
||||||
|
(*parent_class)
|
||||||
|
.render
|
||||||
|
.map(|f| {
|
||||||
|
result_from_gboolean!(
|
||||||
|
f(
|
||||||
|
element
|
||||||
|
.unsafe_cast_ref::<AudioVisualizer>()
|
||||||
|
.to_glib_none()
|
||||||
|
.0,
|
||||||
|
audio_buffer.as_mut_ptr(),
|
||||||
|
video_frame.as_mut_ptr(),
|
||||||
|
),
|
||||||
|
CAT_RUST,
|
||||||
|
"Parent function `render` failed",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or(Ok(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent_decide_allocation(
|
||||||
|
&self,
|
||||||
|
element: &Self::Type,
|
||||||
|
query: &mut gst::query::Allocation,
|
||||||
|
) -> Result<(), gst::LoggableError> {
|
||||||
|
unsafe {
|
||||||
|
let data = Self::type_data();
|
||||||
|
let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioVisualizerClass;
|
||||||
|
(*parent_class)
|
||||||
|
.decide_allocation
|
||||||
|
.map(|f| {
|
||||||
|
gst::result_from_gboolean!(
|
||||||
|
f(
|
||||||
|
element
|
||||||
|
.unsafe_cast_ref::<AudioVisualizer>()
|
||||||
|
.to_glib_none()
|
||||||
|
.0,
|
||||||
|
query.as_mut_ptr(),
|
||||||
|
),
|
||||||
|
gst::CAT_RUST,
|
||||||
|
"Parent function `decide_allocation` failed",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or(Ok(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: AudioVisualizerImpl> IsSubclassable<T> for AudioVisualizer {
|
||||||
|
fn class_init(klass: &mut glib::Class<Self>) {
|
||||||
|
Self::parent_class_init::<T>(klass);
|
||||||
|
let klass = klass.as_mut();
|
||||||
|
klass.setup = Some(audio_visualizer_setup::<T>);
|
||||||
|
klass.render = Some(audio_visualizer_render::<T>);
|
||||||
|
klass.decide_allocation = Some(audio_visualizer_decide_allocation::<T>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn audio_visualizer_setup<T: AudioVisualizerImpl>(
|
||||||
|
ptr: *mut ffi::GstAudioVisualizer,
|
||||||
|
) -> gst::ffi::GstFlowReturn {
|
||||||
|
let instance = &*(ptr as *mut T::Instance);
|
||||||
|
let imp = instance.imp();
|
||||||
|
let wrap: Borrowed<AudioVisualizer> = from_glib_borrow(ptr);
|
||||||
|
|
||||||
|
gst::panic_to_error!(&wrap, imp.panicked(), false, {
|
||||||
|
let token = AudioVisualizerSetupToken(&*wrap);
|
||||||
|
|
||||||
|
match imp.setup(wrap.unsafe_cast_ref(), &token) {
|
||||||
|
Ok(()) => true,
|
||||||
|
Err(err) => {
|
||||||
|
err.log_with_object(&*wrap);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into_glib()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn audio_visualizer_render<T: AudioVisualizerImpl>(
|
||||||
|
ptr: *mut ffi::GstAudioVisualizer,
|
||||||
|
audio_buffer: *mut gst::ffi::GstBuffer,
|
||||||
|
video_frame: *mut gst_video::ffi::GstVideoFrame,
|
||||||
|
) -> gst::ffi::GstFlowReturn {
|
||||||
|
let instance = &*(ptr as *mut T::Instance);
|
||||||
|
let imp = instance.imp();
|
||||||
|
let wrap: Borrowed<AudioVisualizer> = from_glib_borrow(ptr);
|
||||||
|
let buffer = gst::BufferRef::from_ptr(audio_buffer);
|
||||||
|
|
||||||
|
gst::panic_to_error!(&wrap, imp.panicked(), false, {
|
||||||
|
match imp.render(
|
||||||
|
wrap.unsafe_cast_ref(),
|
||||||
|
buffer,
|
||||||
|
&mut gst_video::VideoFrameRef::from_glib_borrow_mut(video_frame),
|
||||||
|
) {
|
||||||
|
Ok(()) => true,
|
||||||
|
Err(err) => {
|
||||||
|
err.log_with_object(&*wrap);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into_glib()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn audio_visualizer_decide_allocation<T: AudioVisualizerImpl>(
|
||||||
|
ptr: *mut ffi::GstAudioVisualizer,
|
||||||
|
query: *mut gst::ffi::GstQuery,
|
||||||
|
) -> gst::ffi::GstFlowReturn {
|
||||||
|
let instance = &*(ptr as *mut T::Instance);
|
||||||
|
let imp = instance.imp();
|
||||||
|
let wrap: Borrowed<AudioVisualizer> = from_glib_borrow(ptr);
|
||||||
|
let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
|
||||||
|
gst::QueryViewMut::Allocation(allocation) => allocation,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
gst::panic_to_error!(&wrap, imp.panicked(), false, {
|
||||||
|
match imp.decide_allocation(wrap.unsafe_cast_ref(), query) {
|
||||||
|
Ok(()) => true,
|
||||||
|
Err(err) => {
|
||||||
|
err.log_with_object(&*wrap);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into_glib()
|
||||||
|
}
|
8
gstreamer-pbutils/src/subclass/mod.rs
Normal file
8
gstreamer-pbutils/src/subclass/mod.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||||
|
|
||||||
|
mod audio_visualizer;
|
||||||
|
pub use audio_visualizer::AudioVisualizerSetupToken;
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub use super::audio_visualizer::{AudioVisualizerImpl, AudioVisualizerImplExt};
|
||||||
|
}
|
Loading…
Reference in a new issue