Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2021-01-21 21:21:29 +0300
committerSebastian Dröge <sebastian@centricular.com>2021-01-25 15:43:05 +0300
commitd4ce1a33f2257ea19f873711c78b7b57d5cb7e5f (patch)
tree7a4ff75e550640afd69786a2d8a41f07b6b6c593 /tutorial
parent875c3efb916f2400df355f8517f1daeff6f7ae85 (diff)
Update for glib/gstreamer bindings API changes
Diffstat (limited to 'tutorial')
-rw-r--r--tutorial/src/identity/imp.rs94
-rw-r--r--tutorial/src/progressbin/imp.rs149
-rw-r--r--tutorial/src/rgb2gray/imp.rs284
-rw-r--r--tutorial/src/sinesrc/imp.rs260
4 files changed, 400 insertions, 387 deletions
diff --git a/tutorial/src/identity/imp.rs b/tutorial/src/identity/imp.rs
index d94ec448d..7a256e60c 100644
--- a/tutorial/src/identity/imp.rs
+++ b/tutorial/src/identity/imp.rs
@@ -118,6 +118,7 @@ impl ObjectSubclass for Identity {
const NAME: &'static str = "RsIdentity";
type Type = super::Identity;
type ParentType = gst::Element;
+ type Interfaces = ();
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -185,50 +186,6 @@ impl ObjectSubclass for Identity {
// into the debug logs
Self { srcpad, sinkpad }
}
-
- // Called exactly once when registering the type. Used for
- // setting up metadata for all instances, e.g. the name and
- // classification and the pad templates with their caps.
- //
- // Actual instances can create pads based on those pad templates
- // with a subset of the caps given here.
- fn class_init(klass: &mut Self::Class) {
- // Set the element specific metadata. This information is what
- // is visible from gst-inspect-1.0 and can also be programatically
- // retrieved from the gst::Registry after initial registration
- // without having to load the plugin in memory.
- klass.set_metadata(
- "Identity",
- "Generic",
- "Does nothing with the data",
- "Sebastian Dröge <sebastian@centricular.com>",
- );
-
- // Create and add pad templates for our sink and source pad. These
- // are later used for actually creating the pads and beforehand
- // already provide information to GStreamer about all possible
- // pads that could exist for this type.
-
- // Our element can accept any possible caps on both pads
- let caps = gst::Caps::new_any();
- 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);
- }
}
// Implementation of glib::Object virtual methods
@@ -247,6 +204,55 @@ impl ObjectImpl for Identity {
// Implementation of gst::Element virtual methods
impl ElementImpl for Identity {
+ // Set the element specific metadata. This information is what
+ // is visible from gst-inspect-1.0 and can also be programatically
+ // retrieved from the gst::Registry after initial registration
+ // without having to load the plugin in memory.
+ fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
+ static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| {
+ gst::subclass::ElementMetadata::new(
+ "Identity",
+ "Generic",
+ "Does nothing with the data",
+ "Sebastian Dröge <sebastian@centricular.com>",
+ )
+ });
+
+ Some(&*ELEMENT_METADATA)
+ }
+
+ // Create and add pad templates for our sink and source pad. These
+ // are later used for actually creating the pads and beforehand
+ // already provide information to GStreamer about all possible
+ // pads that could exist for this type.
+ //
+ // Actual instances can create pads based on those pad templates
+ fn pad_templates() -> &'static [gst::PadTemplate] {
+ static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
+ // Our element can accept any possible caps on both pads
+ let caps = gst::Caps::new_any();
+ 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()
+ }
+
// Called whenever the state of the element should be changed. This allows for
// starting up the element, allocating/deallocating resources or shutting down
// the element again.
diff --git a/tutorial/src/progressbin/imp.rs b/tutorial/src/progressbin/imp.rs
index 9a1e5c7cf..7410bc2b3 100644
--- a/tutorial/src/progressbin/imp.rs
+++ b/tutorial/src/progressbin/imp.rs
@@ -41,18 +41,6 @@ pub struct ProgressBin {
output_type: Mutex<ProgressBinOutput>,
}
-// Metadata for the element's properties
-static PROPERTIES: [subclass::Property; 1] = [subclass::Property("output", |name| {
- glib::ParamSpec::enum_(
- name,
- "Output",
- "Defines the output type of the progressbin",
- ProgressBinOutput::static_type(),
- DEFAULT_OUTPUT_TYPE as i32,
- glib::ParamFlags::READWRITE,
- )
-})];
-
// This trait registers our type with the GObject object system and
// provides the entry points for creating a new instance and setting
// up the class data
@@ -60,6 +48,7 @@ impl ObjectSubclass for ProgressBin {
const NAME: &'static str = "RsProgressBin";
type Type = super::ProgressBin;
type ParentType = gst::Bin;
+ type Interfaces = ();
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -92,64 +81,37 @@ impl ObjectSubclass for ProgressBin {
output_type: Mutex::new(ProgressBinOutput::Println),
}
}
-
- // Called exactly once when registering the type. Used for
- // setting up metadata for all instances, e.g. the name and
- // classification and the pad templates with their caps.
- //
- // Actual instances can create pads based on those pad templates
- // with a subset of the caps given here.
- fn class_init(klass: &mut Self::Class) {
- // Set the element specific metadata. This information is what
- // is visible from gst-inspect-1.0 and can also be programatically
- // retrieved from the gst::Registry after initial registration
- // without having to load the plugin in memory.
- klass.set_metadata(
- "ProgressBin",
- "Generic",
- "Prints progress information to stdout",
- "Sebastian Dröge <sebastian@centricular.com>",
- );
-
- // Create and add pad templates for our sink and source pad. These
- // are later used for actually creating the pads and beforehand
- // already provide information to GStreamer about all possible
- // pads that could exist for this type.
-
- // Our element can accept any possible caps on both pads
- let caps = gst::Caps::new_any();
- 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);
-
- // Install all our properties
- klass.install_properties(&PROPERTIES);
- }
}
// Implementation of glib::Object virtual methods
impl ObjectImpl for ProgressBin {
+ // Metadata for the element's properties
+ fn properties() -> &'static [glib::ParamSpec] {
+ static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
+ vec![glib::ParamSpec::enum_(
+ "output",
+ "Output",
+ "Defines the output type of the progressbin",
+ ProgressBinOutput::static_type(),
+ DEFAULT_OUTPUT_TYPE as i32,
+ glib::ParamFlags::READWRITE,
+ )]
+ });
+
+ PROPERTIES.as_ref()
+ }
+
// Called whenever a value of a property is changed. It can be called
// at any time from any thread.
- fn set_property(&self, obj: &Self::Type, id: usize, value: &glib::Value) {
- let prop = &PROPERTIES[id];
-
- match *prop {
- subclass::Property("output", ..) => {
+ fn set_property(
+ &self,
+ obj: &Self::Type,
+ _id: usize,
+ value: &glib::Value,
+ pspec: &glib::ParamSpec,
+ ) {
+ match pspec.get_name() {
+ "output" => {
let mut output_type = self.output_type.lock().unwrap();
let new_output_type = value
.get_some::<ProgressBinOutput>()
@@ -169,11 +131,9 @@ impl ObjectImpl for ProgressBin {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
- fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value {
- let prop = &PROPERTIES[id];
-
- match *prop {
- subclass::Property("output", ..) => {
+ fn get_property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
+ match pspec.get_name() {
+ "output" => {
let output_type = self.output_type.lock().unwrap();
output_type.to_value()
}
@@ -207,7 +167,56 @@ impl ObjectImpl for ProgressBin {
}
// Implementation of gst::Element virtual methods
-impl ElementImpl for ProgressBin {}
+impl ElementImpl for ProgressBin {
+ // Set the element specific metadata. This information is what
+ // is visible from gst-inspect-1.0 and can also be programatically
+ // retrieved from the gst::Registry after initial registration
+ // without having to load the plugin in memory.
+ fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
+ static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| {
+ gst::subclass::ElementMetadata::new(
+ "ProgressBin",
+ "Generic",
+ "Prints progress information to stdout",
+ "Sebastian Dröge <sebastian@centricular.com>",
+ )
+ });
+
+ Some(&*ELEMENT_METADATA)
+ }
+ // Create and add pad templates for our sink and source pad. These
+ // are later used for actually creating the pads and beforehand
+ // already provide information to GStreamer about all possible
+ // pads that could exist for this type.
+ //
+ // Actual instances can create pads based on those pad templates
+ // with a subset of the caps given here.
+ fn pad_templates() -> &'static [gst::PadTemplate] {
+ static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
+ // Our element can accept any possible caps on both pads
+ let caps = gst::Caps::new_any();
+ 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()
+ }
+}
// Implementation of gst::Bin virtual methods
impl BinImpl for ProgressBin {
diff --git a/tutorial/src/rgb2gray/imp.rs b/tutorial/src/rgb2gray/imp.rs
index f330e467b..019e48d33 100644
--- a/tutorial/src/rgb2gray/imp.rs
+++ b/tutorial/src/rgb2gray/imp.rs
@@ -48,30 +48,6 @@ impl Default for Settings {
}
}
-// Metadata for the properties
-static PROPERTIES: [subclass::Property; 2] = [
- subclass::Property("invert", |name| {
- glib::ParamSpec::boolean(
- name,
- "Invert",
- "Invert grayscale output",
- DEFAULT_INVERT,
- glib::ParamFlags::READWRITE,
- )
- }),
- subclass::Property("shift", |name| {
- glib::ParamSpec::uint(
- name,
- "Shift",
- "Shift grayscale output (wrapping around)",
- 0,
- 255,
- DEFAULT_SHIFT,
- glib::ParamFlags::READWRITE,
- )
- }),
-];
-
// Stream-specific state, i.e. video format configuration
struct State {
in_info: gst_video::VideoInfo,
@@ -118,6 +94,7 @@ impl ObjectSubclass for Rgb2Gray {
const NAME: &'static str = "RsRgb2Gray";
type Type = super::Rgb2Gray;
type ParentType = gst_base::BaseTransform;
+ type Interfaces = ();
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -132,122 +109,47 @@ impl ObjectSubclass for Rgb2Gray {
state: Mutex::new(None),
}
}
+}
- // Called exactly once when registering the type. Used for
- // setting up metadata for all instances, e.g. the name and
- // classification and the pad templates with their caps.
- //
- // Actual instances can create pads based on those pad templates
- // with a subset of the caps given here. In case of basetransform,
- // a "src" and "sink" pad template are required here and the base class
- // will automatically instantiate pads for them.
- //
- // Our element here can convert BGRx to BGRx or GRAY8, both being grayscale.
- fn class_init(klass: &mut Self::Class) {
- // Set the element specific metadata. This information is what
- // is visible from gst-inspect-1.0 and can also be programatically
- // retrieved from the gst::Registry after initial registration
- // without having to load the plugin in memory.
- klass.set_metadata(
- "RGB-GRAY Converter",
- "Filter/Effect/Converter/Video",
- "Converts RGB to GRAY or grayscale RGB",
- "Sebastian Dröge <sebastian@centricular.com>",
- );
-
- // Create and add pad templates for our sink and source pad. These
- // are later used for actually creating the pads and beforehand
- // already provide information to GStreamer about all possible
- // pads that could exist for this type.
-
- // On the src pad, we can produce BGRx and GRAY8 of any
- // width/height and with any framerate
- let caps = gst::Caps::new_simple(
- "video/x-raw",
- &[
- (
- "format",
- &gst::List::new(&[
- &gst_video::VideoFormat::Bgrx.to_str(),
- &gst_video::VideoFormat::Gray8.to_str(),
- ]),
- ),
- ("width", &gst::IntRange::<i32>::new(0, i32::MAX)),
- ("height", &gst::IntRange::<i32>::new(0, i32::MAX)),
- (
- "framerate",
- &gst::FractionRange::new(
- gst::Fraction::new(0, 1),
- gst::Fraction::new(i32::MAX, 1),
- ),
+// Implementation of glib::Object virtual methods
+impl ObjectImpl for Rgb2Gray {
+ fn properties() -> &'static [glib::ParamSpec] {
+ // Metadata for the properties
+ static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
+ vec![
+ glib::ParamSpec::boolean(
+ "invert",
+ "Invert",
+ "Invert grayscale output",
+ DEFAULT_INVERT,
+ glib::ParamFlags::READWRITE,
),
- ],
- );
- // The src pad template must be named "src" for basetransform
- // and specific a pad that is always there
- let src_pad_template = gst::PadTemplate::new(
- "src",
- gst::PadDirection::Src,
- gst::PadPresence::Always,
- &caps,
- )
- .unwrap();
- klass.add_pad_template(src_pad_template);
-
- // On the sink pad, we can accept BGRx of any
- // width/height and with any framerate
- let caps = gst::Caps::new_simple(
- "video/x-raw",
- &[
- ("format", &gst_video::VideoFormat::Bgrx.to_str()),
- ("width", &gst::IntRange::<i32>::new(0, i32::MAX)),
- ("height", &gst::IntRange::<i32>::new(0, i32::MAX)),
- (
- "framerate",
- &gst::FractionRange::new(
- gst::Fraction::new(0, 1),
- gst::Fraction::new(i32::MAX, 1),
- ),
+ glib::ParamSpec::uint(
+ "shift",
+ "Shift",
+ "Shift grayscale output (wrapping around)",
+ 0,
+ 255,
+ DEFAULT_SHIFT,
+ glib::ParamFlags::READWRITE,
),
- ],
- );
- // The sink pad template must be named "sink" for basetransform
- // and specific a pad that is always there
- let sink_pad_template = gst::PadTemplate::new(
- "sink",
- gst::PadDirection::Sink,
- gst::PadPresence::Always,
- &caps,
- )
- .unwrap();
- klass.add_pad_template(sink_pad_template);
-
- // Install all our properties
- klass.install_properties(&PROPERTIES);
-
- // Configure basetransform so that we are never running in-place,
- // don't passthrough on same caps and also never call transform_ip
- // in passthrough mode (which does not matter for us here).
- //
- // We could work in-place for BGRx->BGRx but don't do here for simplicity
- // for now.
- klass.configure(
- gst_base::subclass::BaseTransformMode::NeverInPlace,
- false,
- false,
- );
+ ]
+ });
+
+ PROPERTIES.as_ref()
}
-}
-// Implementation of glib::Object virtual methods
-impl ObjectImpl for Rgb2Gray {
// Called whenever a value of a property is changed. It can be called
// at any time from any thread.
- fn set_property(&self, obj: &Self::Type, id: usize, value: &glib::Value) {
- let prop = &PROPERTIES[id];
-
- match *prop {
- subclass::Property("invert", ..) => {
+ fn set_property(
+ &self,
+ obj: &Self::Type,
+ _id: usize,
+ value: &glib::Value,
+ pspec: &glib::ParamSpec,
+ ) {
+ match pspec.get_name() {
+ "invert" => {
let mut settings = self.settings.lock().unwrap();
let invert = value.get_some().expect("type checked upstream");
gst_info!(
@@ -259,7 +161,7 @@ impl ObjectImpl for Rgb2Gray {
);
settings.invert = invert;
}
- subclass::Property("shift", ..) => {
+ "shift" => {
let mut settings = self.settings.lock().unwrap();
let shift = value.get_some().expect("type checked upstream");
gst_info!(
@@ -277,15 +179,13 @@ impl ObjectImpl for Rgb2Gray {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
- fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value {
- let prop = &PROPERTIES[id];
-
- match *prop {
- subclass::Property("invert", ..) => {
+ fn get_property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
+ match pspec.get_name() {
+ "invert" => {
let settings = self.settings.lock().unwrap();
settings.invert.to_value()
}
- subclass::Property("shift", ..) => {
+ "shift" => {
let settings = self.settings.lock().unwrap();
settings.shift.to_value()
}
@@ -295,10 +195,112 @@ impl ObjectImpl for Rgb2Gray {
}
// Implementation of gst::Element virtual methods
-impl ElementImpl for Rgb2Gray {}
+impl ElementImpl for Rgb2Gray {
+ // Set the element specific metadata. This information is what
+ // is visible from gst-inspect-1.0 and can also be programatically
+ // retrieved from the gst::Registry after initial registration
+ // without having to load the plugin in memory.
+ fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
+ static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| {
+ gst::subclass::ElementMetadata::new(
+ "RGB-GRAY Converter",
+ "Filter/Effect/Converter/Video",
+ "Converts RGB to GRAY or grayscale RGB",
+ "Sebastian Dröge <sebastian@centricular.com>",
+ )
+ });
+
+ Some(&*ELEMENT_METADATA)
+ }
+
+ // Create and add pad templates for our sink and source pad. These
+ // are later used for actually creating the pads and beforehand
+ // already provide information to GStreamer about all possible
+ // pads that could exist for this type.
+ //
+ // Our element here can convert BGRx to BGRx or GRAY8, both being grayscale.
+ fn pad_templates() -> &'static [gst::PadTemplate] {
+ static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
+ // On the src pad, we can produce BGRx and GRAY8 of any
+ // width/height and with any framerate
+ let caps = gst::Caps::new_simple(
+ "video/x-raw",
+ &[
+ (
+ "format",
+ &gst::List::new(&[
+ &gst_video::VideoFormat::Bgrx.to_str(),
+ &gst_video::VideoFormat::Gray8.to_str(),
+ ]),
+ ),
+ ("width", &gst::IntRange::<i32>::new(0, i32::MAX)),
+ ("height", &gst::IntRange::<i32>::new(0, i32::MAX)),
+ (
+ "framerate",
+ &gst::FractionRange::new(
+ gst::Fraction::new(0, 1),
+ gst::Fraction::new(i32::MAX, 1),
+ ),
+ ),
+ ],
+ );
+ // The src pad template must be named "src" for basetransform
+ // and specific a pad that is always there
+ let src_pad_template = gst::PadTemplate::new(
+ "src",
+ gst::PadDirection::Src,
+ gst::PadPresence::Always,
+ &caps,
+ )
+ .unwrap();
+
+ // On the sink pad, we can accept BGRx of any
+ // width/height and with any framerate
+ let caps = gst::Caps::new_simple(
+ "video/x-raw",
+ &[
+ ("format", &gst_video::VideoFormat::Bgrx.to_str()),
+ ("width", &gst::IntRange::<i32>::new(0, i32::MAX)),
+ ("height", &gst::IntRange::<i32>::new(0, i32::MAX)),
+ (
+ "framerate",
+ &gst::FractionRange::new(
+ gst::Fraction::new(0, 1),
+ gst::Fraction::new(i32::MAX, 1),
+ ),
+ ),
+ ],
+ );
+ // The sink pad template must be named "sink" for basetransform
+ // and specific a pad that is always there
+ 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()
+ }
+}
// Implementation of gst_base::BaseTransform virtual methods
impl BaseTransformImpl for Rgb2Gray {
+ // Configure basetransform so that we are never running in-place,
+ // don't passthrough on same caps and also never call transform_ip
+ // in passthrough mode (which does not matter for us here).
+ //
+ // We could work in-place for BGRx->BGRx but don't do here for simplicity
+ // for now.
+ 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;
+
// Called for converting caps from one pad to another to account for any
// changes in the media format this element is performing.
//
diff --git a/tutorial/src/sinesrc/imp.rs b/tutorial/src/sinesrc/imp.rs
index 951dc4b4e..558aaf58a 100644
--- a/tutorial/src/sinesrc/imp.rs
+++ b/tutorial/src/sinesrc/imp.rs
@@ -64,61 +64,6 @@ impl Default for Settings {
}
}
-// Metadata for the properties
-static PROPERTIES: [subclass::Property; 5] = [
- subclass::Property("samples-per-buffer", |name| {
- glib::ParamSpec::uint(
- name,
- "Samples Per Buffer",
- "Number of samples per output buffer",
- 1,
- u32::MAX,
- DEFAULT_SAMPLES_PER_BUFFER,
- glib::ParamFlags::READWRITE,
- )
- }),
- subclass::Property("freq", |name| {
- glib::ParamSpec::uint(
- name,
- "Frequency",
- "Frequency",
- 1,
- u32::MAX,
- DEFAULT_FREQ,
- glib::ParamFlags::READWRITE,
- )
- }),
- subclass::Property("volume", |name| {
- glib::ParamSpec::double(
- name,
- "Volume",
- "Output volume",
- 0.0,
- 10.0,
- DEFAULT_VOLUME,
- glib::ParamFlags::READWRITE,
- )
- }),
- subclass::Property("mute", |name| {
- glib::ParamSpec::boolean(
- name,
- "Mute",
- "Mute",
- DEFAULT_MUTE,
- glib::ParamFlags::READWRITE,
- )
- }),
- subclass::Property("is-live", |name| {
- glib::ParamSpec::boolean(
- name,
- "Is Live",
- "(Pseudo) live output",
- DEFAULT_IS_LIVE,
- glib::ParamFlags::READWRITE,
- )
- }),
-];
-
// Stream-specific state, i.e. audio format configuration
// and sample offset
struct State {
@@ -203,6 +148,7 @@ impl ObjectSubclass for SineSrc {
const NAME: &'static str = "RsSineSrc";
type Type = super::SineSrc;
type ParentType = gst_base::PushSrc;
+ type Interfaces = ();
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -221,69 +167,61 @@ impl ObjectSubclass for SineSrc {
}),
}
}
-
- // Called exactly once when registering the type. Used for
- // setting up metadata for all instances, e.g. the name and
- // classification and the pad templates with their caps.
- //
- // Actual instances can create pads based on those pad templates
- // with a subset of the caps given here. In case of basesrc,
- // a "src" and "sink" pad template are required here and the base class
- // will automatically instantiate pads for them.
- //
- // Our element here can output f32 and f64
- fn class_init(klass: &mut Self::Class) {
- // Set the element specific metadata. This information is what
- // is visible from gst-inspect-1.0 and can also be programatically
- // retrieved from the gst::Registry after initial registration
- // without having to load the plugin in memory.
- klass.set_metadata(
- "Sine Wave Source",
- "Source/Audio",
- "Creates a sine wave",
- "Sebastian Dröge <sebastian@centricular.com>",
- );
-
- // Create and add pad templates for our sink and source pad. These
- // are later used for actually creating the pads and beforehand
- // already provide information to GStreamer about all possible
- // pads that could exist for this type.
-
- // On the src pad, we can produce F32/F64 with any sample rate
- // and any number of channels
- 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(),
- ]),
- ),
- ("layout", &"interleaved"),
- ("rate", &gst::IntRange::<i32>::new(1, i32::MAX)),
- ("channels", &gst::IntRange::<i32>::new(1, i32::MAX)),
- ],
- );
- // The src pad template must be named "src" for basesrc
- // and specific a pad that is always there
- let src_pad_template = gst::PadTemplate::new(
- "src",
- gst::PadDirection::Src,
- gst::PadPresence::Always,
- &caps,
- )
- .unwrap();
- klass.add_pad_template(src_pad_template);
-
- // Install all our properties
- klass.install_properties(&PROPERTIES);
- }
}
// Implementation of glib::Object virtual methods
impl ObjectImpl for SineSrc {
+ // Metadata for the properties
+ fn properties() -> &'static [glib::ParamSpec] {
+ static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
+ vec![
+ glib::ParamSpec::uint(
+ "samples-per-buffer",
+ "Samples Per Buffer",
+ "Number of samples per output buffer",
+ 1,
+ u32::MAX,
+ DEFAULT_SAMPLES_PER_BUFFER,
+ glib::ParamFlags::READWRITE,
+ ),
+ glib::ParamSpec::uint(
+ "freq",
+ "Frequency",
+ "Frequency",
+ 1,
+ u32::MAX,
+ DEFAULT_FREQ,
+ glib::ParamFlags::READWRITE,
+ ),
+ glib::ParamSpec::double(
+ "volume",
+ "Volume",
+ "Output volume",
+ 0.0,
+ 10.0,
+ DEFAULT_VOLUME,
+ glib::ParamFlags::READWRITE,
+ ),
+ glib::ParamSpec::boolean(
+ "mute",
+ "Mute",
+ "Mute",
+ DEFAULT_MUTE,
+ glib::ParamFlags::READWRITE,
+ ),
+ glib::ParamSpec::boolean(
+ "is-live",
+ "Is Live",
+ "(Pseudo) live output",
+ DEFAULT_IS_LIVE,
+ glib::ParamFlags::READWRITE,
+ ),
+ ]
+ });
+
+ PROPERTIES.as_ref()
+ }
+
// Called right after construction of a new instance
fn constructed(&self, obj: &Self::Type) {
// Call the parent class' ::constructed() implementation first
@@ -297,11 +235,15 @@ impl ObjectImpl for SineSrc {
// Called whenever a value of a property is changed. It can be called
// at any time from any thread.
- fn set_property(&self, obj: &Self::Type, id: usize, value: &glib::Value) {
- let prop = &PROPERTIES[id];
-
- match *prop {
- subclass::Property("samples-per-buffer", ..) => {
+ fn set_property(
+ &self,
+ obj: &Self::Type,
+ _id: usize,
+ value: &glib::Value,
+ pspec: &glib::ParamSpec,
+ ) {
+ match pspec.get_name() {
+ "samples-per-buffer" => {
let mut settings = self.settings.lock().unwrap();
let samples_per_buffer = value.get_some().expect("type checked upstream");
gst_info!(
@@ -316,7 +258,7 @@ impl ObjectImpl for SineSrc {
let _ = obj.post_message(gst::message::Latency::builder().src(obj).build());
}
- subclass::Property("freq", ..) => {
+ "freq" => {
let mut settings = self.settings.lock().unwrap();
let freq = value.get_some().expect("type checked upstream");
gst_info!(
@@ -328,7 +270,7 @@ impl ObjectImpl for SineSrc {
);
settings.freq = freq;
}
- subclass::Property("volume", ..) => {
+ "volume" => {
let mut settings = self.settings.lock().unwrap();
let volume = value.get_some().expect("type checked upstream");
gst_info!(
@@ -340,7 +282,7 @@ impl ObjectImpl for SineSrc {
);
settings.volume = volume;
}
- subclass::Property("mute", ..) => {
+ "mute" => {
let mut settings = self.settings.lock().unwrap();
let mute = value.get_some().expect("type checked upstream");
gst_info!(
@@ -352,7 +294,7 @@ impl ObjectImpl for SineSrc {
);
settings.mute = mute;
}
- subclass::Property("is-live", ..) => {
+ "is-live" => {
let mut settings = self.settings.lock().unwrap();
let is_live = value.get_some().expect("type checked upstream");
gst_info!(
@@ -370,27 +312,25 @@ impl ObjectImpl for SineSrc {
// Called whenever a value of a property is read. It can be called
// at any time from any thread.
- fn get_property(&self, _obj: &Self::Type, id: usize) -> glib::Value {
- let prop = &PROPERTIES[id];
-
- match *prop {
- subclass::Property("samples-per-buffer", ..) => {
+ fn get_property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
+ match pspec.get_name() {
+ "samples-per-buffer" => {
let settings = self.settings.lock().unwrap();
settings.samples_per_buffer.to_value()
}
- subclass::Property("freq", ..) => {
+ "freq" => {
let settings = self.settings.lock().unwrap();
settings.freq.to_value()
}
- subclass::Property("volume", ..) => {
+ "volume" => {
let settings = self.settings.lock().unwrap();
settings.volume.to_value()
}
- subclass::Property("mute", ..) => {
+ "mute" => {
let settings = self.settings.lock().unwrap();
settings.mute.to_value()
}
- subclass::Property("is-live", ..) => {
+ "is-live" => {
let settings = self.settings.lock().unwrap();
settings.is_live.to_value()
}
@@ -401,6 +341,62 @@ impl ObjectImpl for SineSrc {
// Implementation of gst::Element virtual methods
impl ElementImpl for SineSrc {
+ // Set the element specific metadata. This information is what
+ // is visible from gst-inspect-1.0 and can also be programatically
+ // retrieved from the gst::Registry after initial registration
+ // without having to load the plugin in memory.
+ fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
+ static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| {
+ gst::subclass::ElementMetadata::new(
+ "Sine Wave Source",
+ "Source/Audio",
+ "Creates a sine wave",
+ "Sebastian Dröge <sebastian@centricular.com>",
+ )
+ });
+
+ Some(&*ELEMENT_METADATA)
+ }
+
+ // Create and add pad templates for our sink and source pad. These
+ // are later used for actually creating the pads and beforehand
+ // already provide information to GStreamer about all possible
+ // pads that could exist for this type.
+ fn pad_templates() -> &'static [gst::PadTemplate] {
+ static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
+ // On the src pad, we can produce F32/F64 with any sample rate
+ // and any number of channels
+ 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(),
+ ]),
+ ),
+ ("layout", &"interleaved"),
+ ("rate", &gst::IntRange::<i32>::new(1, i32::MAX)),
+ ("channels", &gst::IntRange::<i32>::new(1, i32::MAX)),
+ ],
+ );
+ // The src pad template must be named "src" for basesrc
+ // and specific a pad that is always there
+ let src_pad_template = gst::PadTemplate::new(
+ "src",
+ gst::PadDirection::Src,
+ gst::PadPresence::Always,
+ &caps,
+ )
+ .unwrap();
+
+ vec![src_pad_template]
+ });
+
+ PAD_TEMPLATES.as_ref()
+ }
+
// Called whenever the state of the element should be changed. This allows for
// starting up the element, allocating/deallocating resources or shutting down
// the element again.