diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2021-01-21 21:21:29 +0300 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2021-01-25 15:43:05 +0300 |
commit | d4ce1a33f2257ea19f873711c78b7b57d5cb7e5f (patch) | |
tree | 7a4ff75e550640afd69786a2d8a41f07b6b6c593 /audio | |
parent | 875c3efb916f2400df355f8517f1daeff6f7ae85 (diff) |
Update for glib/gstreamer bindings API changes
Diffstat (limited to 'audio')
-rw-r--r-- | audio/audiofx/src/audioecho/imp.rs | 229 | ||||
-rw-r--r-- | audio/audiofx/src/audioloudnorm/imp.rs | 209 | ||||
-rw-r--r-- | audio/audiofx/src/audiornnoise/imp.rs | 97 | ||||
-rw-r--r-- | audio/claxon/Cargo.toml | 1 | ||||
-rw-r--r-- | audio/claxon/src/claxondec/imp.rs | 141 | ||||
-rw-r--r-- | audio/csound/src/filter/imp.rs | 213 | ||||
-rw-r--r-- | audio/lewton/src/lewtondec/imp.rs | 85 |
7 files changed, 519 insertions, 456 deletions
diff --git a/audio/audiofx/src/audioecho/imp.rs b/audio/audiofx/src/audioecho/imp.rs index 88204141e..19fa2deca 100644 --- a/audio/audiofx/src/audioecho/imp.rs +++ b/audio/audiofx/src/audioecho/imp.rs @@ -65,51 +65,6 @@ pub struct AudioEcho { state: Mutex<Option<State>>, } -static PROPERTIES: [subclass::Property; 4] = [ - subclass::Property("max-delay", |name| { - glib::ParamSpec::uint64(name, - "Maximum Delay", - "Maximum delay of the echo in nanoseconds (can't be changed in PLAYING or PAUSED state)", - 0, u64::MAX, - DEFAULT_MAX_DELAY, - glib::ParamFlags::READWRITE, - ) - }), - subclass::Property("delay", |name| { - glib::ParamSpec::uint64( - name, - "Delay", - "Delay of the echo in nanoseconds", - 0, - u64::MAX, - DEFAULT_DELAY, - glib::ParamFlags::READWRITE, - ) - }), - subclass::Property("intensity", |name| { - glib::ParamSpec::double( - name, - "Intensity", - "Intensity of the echo", - 0.0, - 1.0, - DEFAULT_INTENSITY, - glib::ParamFlags::READWRITE, - ) - }), - subclass::Property("feedback", |name| { - glib::ParamSpec::double( - name, - "Feedback", - "Amount of feedback", - 0.0, - 1.0, - DEFAULT_FEEDBACK, - glib::ParamFlags::READWRITE, - ) - }), -]; - impl AudioEcho { fn process<F: Float + ToPrimitive + FromPrimitive>( data: &mut [F], @@ -134,6 +89,7 @@ impl ObjectSubclass for AudioEcho { const NAME: &'static str = "RsAudioEcho"; type Type = super::AudioEcho; type ParentType = gst_base::BaseTransform; + type Interfaces = (); type Instance = gst::subclass::ElementInstanceStruct<Self>; type Class = subclass::simple::ClassStruct<Self>; @@ -145,78 +101,75 @@ impl ObjectSubclass for AudioEcho { state: Mutex::new(None), } } - - fn class_init(klass: &mut Self::Class) { - klass.set_metadata( - "Audio echo", - "Filter/Effect/Audio", - "Adds an echo or reverb effect to an audio stream", - "Sebastian Dröge <sebastian@centricular.com>", - ); - - let caps = gst::Caps::new_simple( - "audio/x-raw", - &[ - ( - "format", - &gst::List::new(&[ - &gst_audio::AUDIO_FORMAT_F32.to_str(), - &gst_audio::AUDIO_FORMAT_F64.to_str(), - ]), - ), - ("rate", &gst::IntRange::<i32>::new(0, i32::MAX)), - ("channels", &gst::IntRange::<i32>::new(0, i32::MAX)), - ("layout", &"interleaved"), - ], - ); - let src_pad_template = gst::PadTemplate::new( - "src", - gst::PadDirection::Src, - gst::PadPresence::Always, - &caps, - ) - .unwrap(); - klass.add_pad_template(src_pad_template); - - let sink_pad_template = gst::PadTemplate::new( - "sink", - gst::PadDirection::Sink, - gst::PadPresence::Always, - &caps, - ) - .unwrap(); - klass.add_pad_template(sink_pad_template); - - klass.install_properties(&PROPERTIES); - - klass.configure( - gst_base::subclass::BaseTransformMode::AlwaysInPlace, - false, - false, - ); - } } impl ObjectImpl for AudioEcho { - fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) { - let prop = &PROPERTIES[id]; + fn properties() -> &'static [glib::ParamSpec] { + static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| { + vec![ + glib::ParamSpec::uint64("max-delay", + "Maximum Delay", + "Maximum delay of the echo in nanoseconds (can't be changed in PLAYING or PAUSED state)", + 0, u64::MAX, + DEFAULT_MAX_DELAY, + glib::ParamFlags::READWRITE, + ), + glib::ParamSpec::uint64( + "delay", + "Delay", + "Delay of the echo in nanoseconds", + 0, + u64::MAX, + DEFAULT_DELAY, + glib::ParamFlags::READWRITE, + ), + glib::ParamSpec::double( + "intensity", + "Intensity", + "Intensity of the echo", + 0.0, + 1.0, + DEFAULT_INTENSITY, + glib::ParamFlags::READWRITE, + ), + glib::ParamSpec::double( + "feedback", + "Feedback", + "Amount of feedback", + 0.0, + 1.0, + DEFAULT_FEEDBACK, + glib::ParamFlags::READWRITE, + ), + ] + }); - match *prop { - subclass::Property("max-delay", ..) => { + PROPERTIES.as_ref() + } + + fn set_property( + &self, + _obj: &Self::Type, + _id: usize, + value: &glib::Value, + pspec: &glib::ParamSpec, + ) { + match pspec.get_name() { + "max-delay" => { let mut settings = self.settings.lock().unwrap(); if self.state.lock().unwrap().is_none() { settings.max_delay = value.get_some().expect("type checked upstream"); } } - subclass::Property("delay", ..) => { + "delay" => { let mut settings = self.settings.lock().unwrap(); settings.delay = value.get_some().expect("type checked upstream"); } - subclass::Property("intensity", ..) => { + "intensity" => { let mut settings = self.settings.lock().unwrap(); settings.intensity = value.get_some().expect("type checked upstream"); } - subclass::Property("feedback", ..) => { + "feedback" => { let mut settings = self.settings.lock().unwrap(); settings.feedback = value.get_some().expect("type checked upstream"); } @@ -224,23 +177,21 @@ impl ObjectImpl for AudioEcho { } } - fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value { - let prop = &PROPERTIES[id]; - - match *prop { - subclass::Property("max-delay", ..) => { + fn get_property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { + match pspec.get_name() { + "max-delay" => { let settings = self.settings.lock().unwrap(); settings.max_delay.to_value() } - subclass::Property("delay", ..) => { + "delay" => { let settings = self.settings.lock().unwrap(); settings.delay.to_value() } - subclass::Property("intensity", ..) => { + "intensity" => { let settings = self.settings.lock().unwrap(); settings.intensity.to_value() } - subclass::Property("feedback", ..) => { + "feedback" => { let settings = self.settings.lock().unwrap(); settings.feedback.to_value() } @@ -249,9 +200,65 @@ impl ObjectImpl for AudioEcho { } } -impl ElementImpl for AudioEcho {} +impl ElementImpl for AudioEcho { + fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { + static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| { + gst::subclass::ElementMetadata::new( + "Audio echo", + "Filter/Effect/Audio", + "Adds an echo or reverb effect to an audio stream", + "Sebastian Dröge <sebastian@centricular.com>", + ) + }); + + Some(&*ELEMENT_METADATA) + } + + fn pad_templates() -> &'static [gst::PadTemplate] { + static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| { + let caps = gst::Caps::new_simple( + "audio/x-raw", + &[ + ( + "format", + &gst::List::new(&[ + &gst_audio::AUDIO_FORMAT_F32.to_str(), + &gst_audio::AUDIO_FORMAT_F64.to_str(), + ]), + ), + ("rate", &gst::IntRange::<i32>::new(0, i32::MAX)), + ("channels", &gst::IntRange::<i32>::new(0, i32::MAX)), + ("layout", &"interleaved"), + ], + ); + let src_pad_template = gst::PadTemplate::new( + "src", + gst::PadDirection::Src, + gst::PadPresence::Always, + &caps, + ) + .unwrap(); + + let sink_pad_template = gst::PadTemplate::new( + "sink", + gst::PadDirection::Sink, + gst::PadPresence::Always, + &caps, + ) + .unwrap(); + vec![src_pad_template, sink_pad_template] + }); + + PAD_TEMPLATES.as_ref() + } +} impl BaseTransformImpl for AudioEcho { + const MODE: gst_base::subclass::BaseTransformMode = + gst_base::subclass::BaseTransformMode::AlwaysInPlace; + const PASSTHROUGH_ON_SAME_CAPS: bool = false; + const TRANSFORM_IP_ON_PASSTHROUGH: bool = false; + fn transform_ip( &self, _element: &Self::Type, diff --git a/audio/audiofx/src/audioloudnorm/imp.rs b/audio/audiofx/src/audioloudnorm/imp.rs index 76e227e44..102894e55 100644 --- a/audio/audiofx/src/audioloudnorm/imp.rs +++ b/audio/audiofx/src/audioloudnorm/imp.rs @@ -210,53 +210,6 @@ pub struct AudioLoudNorm { state: Mutex<Option<State>>, } -static PROPERTIES: [subclass::Property; 4] = [ - subclass::Property("loudness-target", |name| { - glib::ParamSpec::double( - name, - "Loudness Target", - "Loudness target in LUFS", - -70.0, - -5.0, - DEFAULT_LOUDNESS_TARGET, - glib::ParamFlags::READWRITE, - ) - }), - subclass::Property("loudness-range-target", |name| { - glib::ParamSpec::double( - name, - "Loudness Range Target", - "Loudness range target in LU", - 1.0, - 20.0, - DEFAULT_LOUDNESS_RANGE_TARGET, - glib::ParamFlags::READWRITE, - ) - }), - subclass::Property("max-true-peak", |name| { - glib::ParamSpec::double( - name, - "Maximum True Peak", - "Maximum True Peak in dbTP", - -9.0, - 0.0, - DEFAULT_MAX_TRUE_PEAK, - glib::ParamFlags::READWRITE, - ) - }), - subclass::Property("offset", |name| { - glib::ParamSpec::double( - name, - "Offset Gain", - "Offset Gain in LU", - -99.0, - 99.0, - DEFAULT_OFFSET, - glib::ParamFlags::READWRITE, - ) - }), -]; - // Gain analysis parameters const GAIN_LOOKAHEAD: usize = 3 * 192_000; // 3s const FRAME_SIZE: usize = 19_200; // 100ms @@ -1752,6 +1705,7 @@ impl ObjectSubclass for AudioLoudNorm { const NAME: &'static str = "RsAudioLoudNorm"; type Type = super::AudioLoudNorm; type ParentType = gst::Element; + type Interfaces = (); type Instance = gst::subclass::ElementInstanceStruct<Self>; type Class = subclass::simple::ClassStruct<Self>; @@ -1796,47 +1750,54 @@ impl ObjectSubclass for AudioLoudNorm { state: Mutex::new(None), } } +} - fn class_init(klass: &mut Self::Class) { - klass.set_metadata( - "Audio loudness normalizer", - "Filter/Effect/Audio", - "Normalizes perceived loudness of an audio stream", - "Sebastian Dröge <sebastian@centricular.com>", - ); - - let caps = gst::Caps::new_simple( - "audio/x-raw", - &[ - ("format", &gst_audio::AUDIO_FORMAT_F64.to_str()), - ("rate", &192_000i32), - ("channels", &gst::IntRange::<i32>::new(1, std::i32::MAX)), - ("layout", &"interleaved"), - ], - ); - let src_pad_template = gst::PadTemplate::new( - "src", - gst::PadDirection::Src, - gst::PadPresence::Always, - &caps, - ) - .unwrap(); - klass.add_pad_template(src_pad_template); - - let sink_pad_template = gst::PadTemplate::new( - "sink", - gst::PadDirection::Sink, - gst::PadPresence::Always, - &caps, - ) - .unwrap(); - klass.add_pad_template(sink_pad_template); +impl ObjectImpl for AudioLoudNorm { + fn properties() -> &'static [glib::ParamSpec] { + static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| { + vec![ + glib::ParamSpec::double( + "loudness-target", + "Loudness Target", + "Loudness target in LUFS", + -70.0, + -5.0, + DEFAULT_LOUDNESS_TARGET, + glib::ParamFlags::READWRITE, + ), + glib::ParamSpec::double( + "loudness-range-target", + "Loudness Range Target", + "Loudness range target in LU", + 1.0, + 20.0, + DEFAULT_LOUDNESS_RANGE_TARGET, + glib::ParamFlags::READWRITE, + ), + glib::ParamSpec::double( + "max-true-peak", + "Maximum True Peak", + "Maximum True Peak in dbTP", + -9.0, + 0.0, + DEFAULT_MAX_TRUE_PEAK, + glib::ParamFlags::READWRITE, + ), + glib::ParamSpec::double( + "offset", + "Offset Gain", + "Offset Gain in LU", + -99.0, + 99.0, + DEFAULT_OFFSET, + glib::ParamFlags::READWRITE, + ), + ] + }); - klass.install_properties(&PROPERTIES); + PROPERTIES.as_ref() } -} -impl ObjectImpl for AudioLoudNorm { fn constructed(&self, obj: &Self::Type) { self.parent_constructed(obj); @@ -1844,23 +1805,27 @@ impl ObjectImpl for AudioLoudNorm { obj.add_pad(&self.srcpad).unwrap(); } - fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) { - let prop = &PROPERTIES[id]; - - match *prop { - subclass::Property("loudness-target", ..) => { + fn set_property( + &self, + _obj: &Self::Type, + _id: usize, + value: &glib::Value, + pspec: &glib::ParamSpec, + ) { + match pspec.get_name() { + "loudness-target" => { let mut settings = self.settings.lock().unwrap(); settings.loudness_target = value.get_some().expect("type checked upstream"); } - subclass::Property("loudness-range-target", ..) => { + "loudness-range-target" => { let mut settings = self.settings.lock().unwrap(); settings.loudness_range_target = value.get_some().expect("type checked upstream"); } - subclass::Property("max-true-peak", ..) => { + "max-true-peak" => { let mut settings = self.settings.lock().unwrap(); settings.max_true_peak = value.get_some().expect("type checked upstream"); } - subclass::Property("offset", ..) => { + "offset" => { let mut settings = self.settings.lock().unwrap(); settings.offset = value.get_some().expect("type checked upstream"); } @@ -1868,23 +1833,21 @@ impl ObjectImpl for AudioLoudNorm { } } - fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value { - let prop = &PROPERTIES[id]; - - match *prop { - subclass::Property("loudness-target", ..) => { + fn get_property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { + match pspec.get_name() { + "loudness-target" => { let settings = self.settings.lock().unwrap(); settings.loudness_target.to_value() } - subclass::Property("loudness-range-target", ..) => { + "loudness-range-target" => { let settings = self.settings.lock().unwrap(); settings.loudness_range_target.to_value() } - subclass::Property("max-true-peak", ..) => { + "max-true-peak" => { let settings = self.settings.lock().unwrap(); settings.max_true_peak.to_value() } - subclass::Property("offset", ..) => { + "offset" => { let settings = self.settings.lock().unwrap(); settings.offset.to_value() } @@ -1894,6 +1857,52 @@ impl ObjectImpl for AudioLoudNorm { } impl ElementImpl for AudioLoudNorm { + fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { + static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| { + gst::subclass::ElementMetadata::new( + "Audio loudness normalizer", + "Filter/Effect/Audio", + "Normalizes perceived loudness of an audio stream", + "Sebastian Dröge <sebastian@centricular.com>", + ) + }); + + Some(&*ELEMENT_METADATA) + } + + fn pad_templates() -> &'static [gst::PadTemplate] { + static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| { + let caps = gst::Caps::new_simple( + "audio/x-raw", + &[ + ("format", &gst_audio::AUDIO_FORMAT_F64.to_str()), + ("rate", &192_000i32), + ("channels", &gst::IntRange::<i32>::new(1, std::i32::MAX)), + ("layout", &"interleaved"), + ], + ); + let src_pad_template = gst::PadTemplate::new( + "src", + gst::PadDirection::Src, + gst::PadPresence::Always, + &caps, + ) + .unwrap(); + + let sink_pad_template = gst::PadTemplate::new( + "sink", + gst::PadDirection::Sink, + gst::PadPresence::Always, + &caps, + ) + .unwrap(); + + vec![src_pad_template, sink_pad_template] + }); + + PAD_TEMPLATES.as_ref() + } + fn change_state( &self, element: &Self::Type, diff --git a/audio/audiofx/src/audiornnoise/imp.rs b/audio/audiofx/src/audiornnoise/imp.rs index 71a75f695..02a23a755 100644 --- a/audio/audiofx/src/audiornnoise/imp.rs +++ b/audio/audiofx/src/audiornnoise/imp.rs @@ -193,6 +193,7 @@ impl ObjectSubclass for AudioRNNoise { const NAME: &'static str = "AudioRNNoise"; type Type = super::AudioRNNoise; type ParentType = gst_base::BaseTransform; + type Interfaces = (); type Instance = gst::subclass::ElementInstanceStruct<Self>; type Class = subclass::simple::ClassStruct<Self>; @@ -203,54 +204,64 @@ impl ObjectSubclass for AudioRNNoise { state: Mutex::new(None), } } - - fn class_init(klass: &mut Self::Class) { - klass.set_metadata( - "Audio denoise", - "Filter/Effect/Audio", - "Removes noise from an audio stream", - "Philippe Normand <philn@igalia.com>", - ); - - let caps = gst::Caps::new_simple( - "audio/x-raw", - &[ - ("format", &gst_audio::AUDIO_FORMAT_F32.to_str()), - ("rate", &48000), - ("channels", &gst::IntRange::<i32>::new(1, std::i32::MAX)), - ("layout", &"interleaved"), - ], - ); - let src_pad_template = gst::PadTemplate::new( - "src", - gst::PadDirection::Src, - gst::PadPresence::Always, - &caps, - ) - .unwrap(); - klass.add_pad_template(src_pad_template); - - let sink_pad_template = gst::PadTemplate::new( - "sink", - gst::PadDirection::Sink, - gst::PadPresence::Always, - &caps, - ) - .unwrap(); - klass.add_pad_template(sink_pad_template); - - klass.configure( - gst_base::subclass::BaseTransformMode::NeverInPlace, - false, - false, - ); - } } impl ObjectImpl for AudioRNNoise {} -impl ElementImpl for AudioRNNoise {} + +impl ElementImpl for AudioRNNoise { + fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { + static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| { + gst::subclass::ElementMetadata::new( + "Audio denoise", + "Filter/Effect/Audio", + "Removes noise from an audio stream", + "Philippe Normand <philn@igalia.com>", + ) + }); + + Some(&*ELEMENT_METADATA) + } + + fn pad_templates() -> &'static [gst::PadTemplate] { + static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| { + let caps = gst::Caps::new_simple( + "audio/x-raw", + &[ + ("format", &gst_audio::AUDIO_FORMAT_F32.to_str()), + ("rate", &48000), + ("channels", &gst::IntRange::<i32>::new(1, std::i32::MAX)), + ("layout", &"interleaved"), + ], + ); + let src_pad_template = gst::PadTemplate::new( + "src", + gst::PadDirection::Src, + gst::PadPresence::Always, + &caps, + ) + .unwrap(); + + let sink_pad_template = gst::PadTemplate::new( + "sink", + gst::PadDirection::Sink, + gst::PadPresence::Always, + &caps, + ) + .unwrap(); + + vec![src_pad_template, sink_pad_template] + }); + + PAD_TEMPLATES.as_ref() + } +} impl BaseTransformImpl for AudioRNNoise { + const MODE: gst_base::subclass::BaseTransformMode = + gst_base::subclass::BaseTransformMode::NeverInPlace; + const PASSTHROUGH_ON_SAME_CAPS: bool = false; + const TRANSFORM_IP_ON_PASSTHROUGH: bool = false; + fn set_caps( &self, element: &Self::Type, diff --git a/audio/claxon/Cargo.toml b/audio/claxon/Cargo.toml index 531f49623..322471fa5 100644 --- a/audio/claxon/Cargo.toml +++ b/audio/claxon/Cargo.toml @@ -14,6 +14,7 @@ gst-audio = { package = "gstreamer-audio", git = "https://gitlab.freedesktop.org claxon = { version = "0.4" } byte-slice-cast = "1.0" atomic_refcell = "0.1" +once_cell = "1" [dev-dependencies] gst-check = { package = "gstreamer-check", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } diff --git a/audio/claxon/src/claxondec/imp.rs b/audio/claxon/src/claxondec/imp.rs index ce8d2761b..bbec688d9 100644 --- a/audio/claxon/src/claxondec/imp.rs +++ b/audio/claxon/src/claxondec/imp.rs @@ -19,13 +19,22 @@ use atomic_refcell::AtomicRefCell; use byte_slice_cast::*; +use once_cell::sync::Lazy; + +static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| { + gst::DebugCategory::new( + "claxondec", + gst::DebugColorFlags::empty(), + Some("Claxon FLAC decoder"), + ) +}); + struct State { streaminfo: Option<claxon::metadata::StreamInfo>, audio_info: Option<gst_audio::AudioInfo>, } pub struct ClaxonDec { - cat: gst::DebugCategory, state: AtomicRefCell<Option<State>>, } @@ -33,6 +42,7 @@ impl ObjectSubclass for ClaxonDec { const NAME: &'static str = "ClaxonDec"; type Type = super::ClaxonDec; type ParentType = gst_audio::AudioDecoder; + type Interfaces = (); type Instance = gst::subclass::ElementInstanceStruct<Self>; type Class = subclass::simple::ClassStruct<Self>; @@ -40,64 +50,69 @@ impl ObjectSubclass for ClaxonDec { fn new() -> Self { Self { - cat: gst::DebugCategory::new( - "claxondec", - gst::DebugColorFlags::empty(), - Some("Claxon FLAC decoder"), - ), state: AtomicRefCell::new(None), } } +} - fn class_init(klass: &mut Self::Class) { - klass.set_metadata( - "Claxon FLAC decoder", - "Decoder/Audio", - "Claxon FLAC decoder", - "Ruben Gonzalez <rgonzalez@fluendo.com>", - ); +impl ObjectImpl for ClaxonDec {} - let sink_caps = gst::Caps::new_simple("audio/x-flac", &[("framed", &true)]); - let sink_pad_template = gst::PadTemplate::new( - "sink", - gst::PadDirection::Sink, - gst::PadPresence::Always, - &sink_caps, - ) - .unwrap(); - klass.add_pad_template(sink_pad_template); - - let src_caps = gst::Caps::new_simple( - "audio/x-raw", - &[ - ( - "format", - &gst::List::new(&[ - &gst_audio::AudioFormat::S8.to_str(), - &gst_audio::AUDIO_FORMAT_S16.to_str(), - &gst_audio::AUDIO_FORMAT_S2432.to_str(), - &gst_audio::AUDIO_FORMAT_S32.to_str(), - ]), - ), - ("rate", &gst::IntRange::<i32>::new(1, 655_350)), - ("channels", &gst::IntRange::<i32>::new(1, 8)), - ("layout", &"interleaved"), - ], - ); - let src_pad_template = gst::PadTemplate::new( - "src", - gst::PadDirection::Src, - gst::PadPresence::Always, - &src_caps, - ) - .unwrap(); - klass.add_pad_template(src_pad_template); +impl ElementImpl for ClaxonDec { + fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { + static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| { + gst::subclass::ElementMetadata::new( + "Claxon FLAC decoder", + "Decoder/Audio", + "Claxon FLAC decoder", + "Ruben Gonzalez <rgonzalez@fluendo.com>", + ) + }); + + Some(&*ELEMENT_METADATA) } -} -impl ObjectImpl for ClaxonDec {} + fn pad_templates() -> &'static [gst::PadTemplate] { + static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| { + let sink_caps = gst::Caps::new_simple("audio/x-flac", &[("framed", &true)]); + let sink_pad_template = gst::PadTemplate::new( + "sink", + gst::PadDirection::Sink, + gst::PadPresence::Always, + &sink_caps, + ) + .unwrap(); + + let src_caps = gst::Caps::new_simple( + "audio/x-raw", + &[ + ( + "format", + &gst::List::new(&[ + &gst_audio::AudioFormat::S8.to_str(), + &gst_audio::AUDIO_FORMAT_S16.to_str(), + &gst_audio::AUDIO_FORMAT_S2432.to_str(), + &gst_audio::AUDIO_FORMAT_S32.to_str(), + ]), + ), + ("rate", &gst::IntRange::<i32>::new(1, 655_350)), + ("channels", &gst::IntRange::<i32>::new(1, 8)), + ("layout", &"interleaved"), + ], + ); + let src_pad_template = gst::PadTemplate::new( + "src", + gst::PadDirection::Src, + gst::PadPresence::Always, + &src_caps, + ) + .unwrap(); + + vec![sink_pad_template, src_pad_template] + }); -impl ElementImpl for ClaxonDec {} + PAD_TEMPLATES.as_ref() + } +} impl AudioDecoderImpl for ClaxonDec { fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> { @@ -116,7 +131,7 @@ impl AudioDecoderImpl for ClaxonDec { } fn set_format(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> { - gst_debug!(self.cat, obj: element, "Setting format {:?}", caps); + gst_debug!(CAT, obj: element, "Setting format {:?}", caps); let mut streaminfo: Option<claxon::metadata::StreamInfo> = None; let mut audio_info: Option<gst_audio::AudioInfo> = None; @@ -127,18 +142,18 @@ impl AudioDecoderImpl for ClaxonDec { if streamheaders.len() < 2 { gst_debug!( - self.cat, + CAT, obj: element, "Not enough streamheaders, trying in-band" ); } else { let ident_buf = streamheaders[0].get::<gst::Buffer>(); if let Ok(Some(ident_buf)) = ident_buf { - gst_debug!(self.cat, obj: element, "Got streamheader buffers"); + gst_debug!(CAT, obj: element, "Got streamheader buffers"); let inmap = ident_buf.map_readable().unwrap(); if inmap[0..7] != [0x7f, b'F', b'L', b'A', b'C', 0x01, 0x00] { - gst_debug!(self.cat, obj: element, "Unknown streamheader format"); + gst_debug!(CAT, obj: element, "Unknown streamheader format"); } else if let Ok(tstreaminfo) = get_claxon_streaminfo(&inmap[13..]) { if let Ok(taudio_info) = get_gstaudioinfo(tstreaminfo) { // To speed up negotiation @@ -146,7 +161,7 @@ impl AudioDecoderImpl for ClaxonDec { || element.negotiate().is_err() { gst_debug!( - self.cat, + CAT, obj: element, "Error to negotiate output from based on in-caps streaminfo" ); @@ -175,7 +190,7 @@ impl AudioDecoderImpl for ClaxonDec { element: &Self::Type, inbuf: Option<&gst::Buffer>, ) -> Result<gst::FlowSuccess, gst::FlowError> { - gst_debug!(self.cat, obj: element, "Handling buffer {:?}", inbuf); + gst_debug!(CAT, obj: element, "Handling buffer {:?}", inbuf); let inbuf = match inbuf { None => return Ok(gst::FlowSuccess::Ok), @@ -183,7 +198,7 @@ impl AudioDecoderImpl for ClaxonDec { }; let inmap = inbuf.map_readable().map_err(|_| { - gst_error!(self.cat, obj: element, "Failed to buffer readable"); + gst_error!(CAT, obj: element, "Failed to buffer readable"); gst::FlowError::Error })?; @@ -191,17 +206,17 @@ impl AudioDecoderImpl for ClaxonDec { let state = state_guard.as_mut().ok_or(gst::FlowError::NotNegotiated)?; if inmap.as_slice() == b"fLaC" { - gst_debug!(self.cat, obj: element, "fLaC buffer received"); + gst_debug!(CAT, obj: element, "fLaC buffer received"); } else if inmap[0] & 0x7F == 0x00 { - gst_debug!(self.cat, obj: element, "Streaminfo header buffer received"); + gst_debug!(CAT, obj: element, "Streaminfo header buffer received"); return self.handle_streaminfo_header(element, state, inmap.as_ref()); } else if inmap[0] == 0b1111_1111 && inmap[1] & 0b1111_1100 == 0b1111_1000 { - gst_debug!(self.cat, obj: element, "Data buffer received"); + gst_debug!(CAT, obj: element, "Data buffer received"); return self.handle_data(element, state, inmap.as_ref()); } else { // info about other headers in flacparse and https://xiph.org/flac/format.html gst_debug!( - self.cat, + CAT, obj: element, "Other header buffer received {:?}", inmap[0] & 0x7F @@ -230,7 +245,7 @@ impl ClaxonDec { })?; gst_debug!( - self.cat, + CAT, obj: element, "Successfully parsed headers: {:?}", audio_info diff --git a/audio/csound/src/filter/imp.rs b/audio/csound/src/filter/imp.rs index 6fdda3aff..9967587e4 100644 --- a/audio/csound/src/filter/imp.rs +++ b/audio/csound/src/filter/imp.rs @@ -80,49 +80,6 @@ pub struct CsoundFilter { compiled: AtomicBool, } -static PROPERTIES: [subclass::Property; 4] = [ - subclass::Property("loop", |name| { - glib::ParamSpec::boolean( - name, - "Loop", - "loop over the score (can be changed in PLAYING or PAUSED state)", - DEFAULT_LOOP, - glib::ParamFlags::READWRITE, - ) - }), - subclass::Property("location", |name| { - glib::ParamSpec::string( - name, - "Location", - "Location of the csd file to be used by csound. - Use either location or CSD-text but not both at the same time, if so and error would be triggered", - None, - glib::ParamFlags::READWRITE, - ) - }), - subclass::Property("csd-text", |name| { - glib::ParamSpec::string( - name, - "CSD-text", - "The content of a csd file passed as a String. - Use either location or csd-text but not both at the same time, if so and error would be triggered", - None, - glib::ParamFlags::READWRITE, - ) - }), - subclass::Property("score_offset", |name| { - glib::ParamSpec::double( - name, - "Score Offset", - "Score offset in seconds to start the performance", - 0.0, - f64::MAX, - SCORE_OFFSET_DEFAULT, - glib::ParamFlags::READWRITE, - ) - }), -]; - impl State { // Considering an input of size: input_size and the user's ksmps, // calculates the equivalent output_size @@ -361,6 +318,7 @@ impl ObjectSubclass for CsoundFilter { const NAME: &'static str = "CsoundFilter"; type Type = super::CsoundFilter; type ParentType = gst_base::BaseTransform; + type Interfaces = (); type Instance = gst::subclass::ElementInstanceStruct<Self>; type Class = subclass::simple::ClassStruct<Self>; @@ -383,61 +341,63 @@ impl ObjectSubclass for CsoundFilter { compiled: AtomicBool::new(false), } } +} - fn class_init(klass: &mut Self::Class) { - klass.set_metadata( - "Audio filter", - "Filter/Effect/Audio", - "Implement an audio filter/effects using Csound", - "Natanael Mojica <neithanmo@gmail.com>", - ); +impl ObjectImpl for CsoundFilter { + fn properties() -> &'static [glib::ParamSpec] { + static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| { + vec![ + glib::ParamSpec::boolean( + "loop", + "Loop", + "loop over the score (can be changed in PLAYING or PAUSED state)", + DEFAULT_LOOP, + glib::ParamFlags::READWRITE, + ), + glib::ParamSpec::string( + "location", + "Location", + "Location of the csd file to be used by csound. + Use either location or CSD-text but not both at the same time, if so and error would be triggered", + None, + glib::ParamFlags::READWRITE, + ), + glib::ParamSpec::string( + "csd-text", + "CSD-text", + "The content of a csd file passed as a String. + Use either location or csd-text but not both at the same time, if so and error would be triggered", + None, + glib::ParamFlags::READWRITE, + ), + glib::ParamSpec::double( + "score-offset", + "Score Offset", + "Score offset in seconds to start the performance", + 0.0, + f64::MAX, + SCORE_OFFSET_DEFAULT, + glib::ParamFlags::READWRITE, + ), + ] + }); - let caps = gst::Caps::new_simple( - "audio/x-raw", - &[ - ("format", &gst_audio::AUDIO_FORMAT_F64.to_str()), - ("rate", &gst::IntRange::<i32>::new(1, i32::MAX)), - ("channels", &gst::IntRange::<i32>::new(1, i32::MAX)), - ("layout", &"interleaved"), - ], - ); - let src_pad_template = gst::PadTemplate::new( - "src", - gst::PadDirection::Src, - gst::PadPresence::Always, - &caps, - ) - .unwrap(); - klass.add_pad_template(src_pad_template); - - let sink_pad_template = gst::PadTemplate::new( - "sink", - gst::PadDirection::Sink, - gst::PadPresence::Always, - &caps, - ) - .unwrap(); - klass.add_pad_template(sink_pad_template); - - klass.install_properties(&PROPERTIES); - - klass.configure( - gst_base::subclass::BaseTransformMode::NeverInPlace, - false, - false, - ); + PROPERTIES.as_ref() } -} -impl ObjectImpl for CsoundFilter { - fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) { - let prop = &PROPERTIES[id]; - match *prop { - subclass::Property("loop", ..) => { + fn set_property( + &self, + _obj: &Self::Type, + _id: usize, + value: &glib::Value, + pspec: &glib::ParamSpec, + ) { + match pspec.get_name() { + "loop" => { let mut settings = self.settings.lock().unwrap(); settings.loop_ = value.get_some().expect("type checked upstream"); } - subclass::Property("location", ..) => { + "location" => { let mut settings = self.settings.lock().unwrap(); if self.state.lock().unwrap().is_none() { settings.location = match value.get::<String>() { @@ -446,7 +406,7 @@ impl ObjectImpl for CsoundFilter { }; } } - subclass::Property("csd-text", ..) => { + "csd-text" => { let mut settings = self.settings.lock().unwrap(); if self.state.lock().unwrap().is_none() { settings.csd_text = match value.get::<String>() { @@ -455,7 +415,7 @@ impl ObjectImpl for CsoundFilter { }; } } - subclass::Property("score_offset", ..) => { + "score_offset" => { let mut settings = self.settings.lock().unwrap(); settings.offset = value.get_some().expect("type checked upstream"); } @@ -463,23 +423,21 @@ impl ObjectImpl for CsoundFilter { } } - fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value { - let prop = &PROPERTIES[id]; - - match *prop { - subclass::Property("loop", ..) => { + fn get_property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { + match pspec.get_name() { + "loop" => { let settings = self.settings.lock().unwrap(); settings.loop_.to_value() } - subclass::Property("location", ..) => { + "location" => { let settings = self.settings.lock().unwrap(); settings.location.to_value() } - subclass::Property("csd-text", ..) => { + "csd-text" => { let settings = self.settings.lock().unwrap(); settings.csd_text.to_value() } - subclass::Property("score_offset", ..) => { + "score_offset" => { let settings = self.settings.lock().unwrap(); settings.offset.to_value() } @@ -488,9 +446,60 @@ impl ObjectImpl for CsoundFilter { } } -impl ElementImpl for CsoundFilter {} +impl ElementImpl for CsoundFilter { + fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { + static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| { + gst::subclass::ElementMetadata::new( + "Audio filter", + "Filter/Effect/Audio", + "Implement an audio filter/effects using Csound", + "Natanael Mojica <neithanmo@gmail.com>", + ) + }); + + Some(&*ELEMENT_METADATA) + } + + fn pad_templates() -> &'static [gst::PadTemplate] { + static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| { + let caps = gst::Caps::new_simple( + "audio/x-raw", + &[ + ("format", &gst_audio::AUDIO_FORMAT_F64.to_str()), + ("rate", &gst::IntRange::<i32>::new(1, i32::MAX)), + ("channels", &gst::IntRange::<i32>::new(1, i32::MAX)), + ("layout", &"interleaved"), + ], + ); + let src_pad_template = gst::PadTemplate::new( + "src", + gst::PadDirection::Src, + gst::PadPresence::Always, + &caps, + ) + .unwrap(); + + let sink_pad_template = gst::PadTemplate::new( + "sink", + gst::PadDirection::Sink, + gst::PadPresence::Always, + &caps, + ) + .unwrap(); + + vec![src_pad_template, sink_pad_template] + }); + + PAD_TEMPLATES.as_ref() + } +} impl BaseTransformImpl for CsoundFilter { + const MODE: gst_base::subclass::BaseTransformMode = + gst_base::subclass::BaseTransformMode::NeverInPlace; + const PASSTHROUGH_ON_SAME_CAPS: bool = false; + const TRANSFORM_IP_ON_PASSTHROUGH: bool = false; + fn start(&self, _element: &Self::Type) -> std::result::Result<(), gst::ErrorMessage> { self.compile_score()?; diff --git a/audio/lewton/src/lewtondec/imp.rs b/audio/lewton/src/lewtondec/imp.rs index 3573a55e7..c08167752 100644 --- a/audio/lewton/src/lewtondec/imp.rs +++ b/audio/lewton/src/lewtondec/imp.rs @@ -47,6 +47,7 @@ impl ObjectSubclass for LewtonDec { const NAME: &'static str = "LewtonDec"; type Type = super::LewtonDec; type ParentType = gst_audio::AudioDecoder; + type Interfaces = (); type Instance = gst::subclass::ElementInstanceStruct<Self>; type Class = subclass::simple::ClassStruct<Self>; @@ -57,48 +58,58 @@ impl ObjectSubclass for LewtonDec { state: AtomicRefCell::new(None), } } +} - fn class_init(klass: &mut Self::Class) { - klass.set_metadata( - "lewton Vorbis decoder", - "Decoder/Audio", - "lewton Vorbis decoder", - "Sebastian Dröge <sebastian@centricular.com>", - ); +impl ObjectImpl for LewtonDec {} - let sink_caps = gst::Caps::new_simple("audio/x-vorbis", &[]); - let sink_pad_template = gst::PadTemplate::new( - "sink", - gst::PadDirection::Sink, - gst::PadPresence::Always, - &sink_caps, - ) - .unwrap(); - klass.add_pad_template(sink_pad_template); - - let src_caps = gst::Caps::new_simple( - "audio/x-raw", - &[ - ("format", &gst_audio::AUDIO_FORMAT_F32.to_str()), - ("rate", &gst::IntRange::<i32>::new(1, std::i32::MAX)), - ("channels", &gst::IntRange::<i32>::new(1, 255)), - ("layout", &"interleaved"), - ], - ); - let src_pad_template = gst::PadTemplate::new( - "src", - gst::PadDirection::Src, - gst::PadPresence::Always, - &src_caps, - ) - .unwrap(); - klass.add_pad_template(src_pad_template); +impl ElementImpl for LewtonDec { + fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { + static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| { + gst::subclass::ElementMetadata::new( + "lewton Vorbis decoder", + "Decoder/Audio", + "lewton Vorbis decoder", + "Sebastian Dröge <sebastian@centricular.com>", + ) + }); + + Some(&*ELEMENT_METADATA) } -} -impl ObjectImpl for LewtonDec {} + fn pad_templates() -> &'static [gst::PadTemplate] { + static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| { + let sink_caps = gst::Caps::new_simple("audio/x-vorbis", &[]); + let sink_pad_template = gst::PadTemplate::new( + "sink", + gst::PadDirection::Sink, + gst::PadPresence::Always, + &sink_caps, + ) + .unwrap(); + + let src_caps = gst::Caps::new_simple( + "audio/x-raw", + &[ + ("format", &gst_audio::AUDIO_FORMAT_F32.to_str()), + ("rate", &gst::IntRange::<i32>::new(1, std::i32::MAX)), + ("channels", &gst::IntRange::<i32>::new(1, 255)), + ("layout", &"interleaved"), + ], + ); + let src_pad_template = gst::PadTemplate::new( + "src", + gst::PadDirection::Src, + gst::PadPresence::Always, + &src_caps, + ) + .unwrap(); + + vec![sink_pad_template, src_pad_template] + }); -impl ElementImpl for LewtonDec {} + PAD_TEMPLATES.as_ref() + } +} impl AudioDecoderImpl for LewtonDec { fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> { |