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

github.com/sdroege/gst-plugin-rs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst-plugin-tutorial/README.md2
-rw-r--r--gst-plugin-tutorial/src/lib.rs1
-rw-r--r--gst-plugin-tutorial/src/progressbin.rs79
-rw-r--r--gst-plugin-tutorial/src/progressbin_output_enum.rs110
4 files changed, 190 insertions, 2 deletions
diff --git a/gst-plugin-tutorial/README.md b/gst-plugin-tutorial/README.md
index 62d70a6a..7592e26b 100644
--- a/gst-plugin-tutorial/README.md
+++ b/gst-plugin-tutorial/README.md
@@ -5,4 +5,4 @@ This tutorial is for the `gst-plugin-tutorial` plugin. This plugin provides 4 fe
1. [Part 1: `rgb2gray` - A Video Filter for converting RGB to grayscale](tutorial-1.md)
2. [Part 2: `sinesrc` - A raw audio sine wave source](tutorial-2.md)
3. Part 3: `identity`
-4. Part 4: `progressBin` - Prints progress information
+4. Part 4: `progressBin` - Prints progress information. Also showcases how to implement an enum-property on a plugin.
diff --git a/gst-plugin-tutorial/src/lib.rs b/gst-plugin-tutorial/src/lib.rs
index 5ec5e5e5..3d283bd0 100644
--- a/gst-plugin-tutorial/src/lib.rs
+++ b/gst-plugin-tutorial/src/lib.rs
@@ -21,6 +21,7 @@ extern crate lazy_static;
mod identity;
mod progressbin;
+mod progressbin_output_enum;
mod rgb2gray;
mod sinesrc;
diff --git a/gst-plugin-tutorial/src/progressbin.rs b/gst-plugin-tutorial/src/progressbin.rs
index 431f721c..a393be46 100644
--- a/gst-plugin-tutorial/src/progressbin.rs
+++ b/gst-plugin-tutorial/src/progressbin.rs
@@ -6,6 +6,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use crate::progressbin_output_enum::ProgressBinOutput;
use glib;
use glib::prelude::*;
use glib::subclass;
@@ -13,14 +14,41 @@ use glib::subclass::prelude::*;
use gst;
use gst::prelude::*;
use gst::subclass::prelude::*;
+use std::sync::Mutex;
+
+const DEFAULT_OUTPUT_TYPE: ProgressBinOutput = ProgressBinOutput::Println;
+
+lazy_static! {
+ static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
+ "progressbin",
+ gst::DebugColorFlags::empty(),
+ Some("Rust Progress Reporter"),
+ );
+}
// Struct containing all the element data
struct ProgressBin {
progress: gst::Element,
srcpad: gst::GhostPad,
sinkpad: gst::GhostPad,
+ // We put the output_type property behind a mutex, as we want
+ // change it in the set_property function, which can be called
+ // from any thread.
+ 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
@@ -56,6 +84,7 @@ impl ObjectSubclass for ProgressBin {
progress,
srcpad,
sinkpad,
+ output_type: Mutex::new(ProgressBinOutput::Println),
}
}
@@ -101,6 +130,9 @@ impl ObjectSubclass for ProgressBin {
)
.unwrap();
klass.add_pad_template(sink_pad_template);
+
+ // Install all our properties
+ klass.install_properties(&PROPERTIES);
}
}
@@ -109,6 +141,45 @@ impl ObjectImpl for ProgressBin {
// This macro provides some boilerplate
glib_object_impl!();
+ // Called whenever a value of a property is changed. It can be called
+ // at any time from any thread.
+ fn set_property(&self, obj: &glib::Object, id: usize, value: &glib::Value) {
+ let prop = &PROPERTIES[id];
+ let element = obj.downcast_ref::<gst_base::BaseTransform>().unwrap();
+
+ match *prop {
+ subclass::Property("output", ..) => {
+ let mut output_type = self.output_type.lock().unwrap();
+ let new_output_type = value
+ .get_some::<ProgressBinOutput>()
+ .expect("type checked upstream");
+ gst_info!(
+ CAT,
+ obj: element,
+ "Changing output from {:?} to {:?}",
+ output_type,
+ new_output_type
+ );
+ *output_type = new_output_type;
+ }
+ _ => unimplemented!(),
+ }
+ }
+
+ // Called whenever a value of a property is read. It can be called
+ // at any time from any thread.
+ fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
+ let prop = &PROPERTIES[id];
+
+ match *prop {
+ subclass::Property("output", ..) => {
+ let output_type = self.output_type.lock().unwrap();
+ Ok(output_type.to_value())
+ }
+ _ => unimplemented!(),
+ }
+ }
+
// Called right after construction of a new instance
fn constructed(&self, obj: &glib::Object) {
// Call the parent class' ::constructed() implementation first
@@ -157,7 +228,13 @@ impl BinImpl for ProgressBin {
{
let s = msg.get_structure().unwrap();
if let Ok(percent) = s.get_some::<f64>("percent-double") {
- println!("progress: {:5.1}%", percent);
+ let output_type = self.output_type.lock().unwrap();
+ match *output_type {
+ ProgressBinOutput::Println => println!("progress: {:5.1}%", percent),
+ ProgressBinOutput::DebugCategory => {
+ gst_info!(CAT, "progress: {:5.1}%", percent);
+ }
+ };
}
}
_ => self.parent_handle_message(bin, msg),
diff --git a/gst-plugin-tutorial/src/progressbin_output_enum.rs b/gst-plugin-tutorial/src/progressbin_output_enum.rs
new file mode 100644
index 00000000..737b9cb0
--- /dev/null
+++ b/gst-plugin-tutorial/src/progressbin_output_enum.rs
@@ -0,0 +1,110 @@
+use glib::{gobject_sys, StaticType, Type};
+
+// This enum may be used to control what type of output the progressbin should produce.
+// It also serves the secondary purpose of illustrating how to add enum-type properties
+// to a plugin written in rust.
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
+#[repr(u32)]
+pub(crate) enum ProgressBinOutput {
+ Println = 0,
+ DebugCategory = 1,
+}
+
+// This trait allows us to translate our custom enum type to a GLib type.
+impl glib::translate::ToGlib for ProgressBinOutput {
+ // We use i32 as the underlying representation for the enum.
+ type GlibType = i32;
+
+ fn to_glib(&self) -> Self::GlibType {
+ *self as Self::GlibType
+ }
+}
+
+// This trait allows us to translate from a GLib type back to our custom enum type.
+impl glib::translate::FromGlib<i32> for ProgressBinOutput {
+ fn from_glib(val: i32) -> Self {
+ match val {
+ 0 => ProgressBinOutput::Println,
+ 1 => ProgressBinOutput::DebugCategory,
+ _ => unreachable!(),
+ }
+ }
+}
+
+// This trait registers our enum with the GLib type system.
+impl StaticType for ProgressBinOutput {
+ fn static_type() -> Type {
+ progressbin_output_get_type()
+ }
+}
+
+impl<'a> glib::value::FromValueOptional<'a> for ProgressBinOutput {
+ unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> {
+ Some(glib::value::FromValue::from_value(value))
+ }
+}
+impl<'a> glib::value::FromValue<'a> for ProgressBinOutput {
+ unsafe fn from_value(value: &glib::Value) -> Self {
+ use glib::translate::ToGlibPtr;
+
+ glib::translate::from_glib(gobject_sys::g_value_get_enum(value.to_glib_none().0))
+ }
+}
+
+impl glib::value::SetValue for ProgressBinOutput {
+ unsafe fn set_value(value: &mut glib::Value, this: &Self) {
+ use glib::translate::{ToGlib, ToGlibPtrMut};
+
+ gobject_sys::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib())
+ }
+}
+
+// On the first call this function will register the enum type with GObject,
+// on all further calls it will simply return the registered type id.
+fn progressbin_output_get_type() -> glib::Type {
+ use std::sync::Once;
+ // We only want to register the enum once, and hence we use a Once struct to ensure that.
+ static ONCE: Once = Once::new();
+ static mut TYPE: glib::Type = glib::Type::Invalid;
+
+ // The first time anyone calls this function, we will call ONCE to complete the registration
+ // process, otherwise we'll just skip it
+ ONCE.call_once(|| {
+ use std::ffi;
+ use std::ptr;
+
+ // The descriptions in this array will be available to users of the plugin when using gst-inspect-1.0
+ static mut VALUES: [gobject_sys::GEnumValue; 3] = [
+ gobject_sys::GEnumValue {
+ value: ProgressBinOutput::Println as i32,
+ value_name: b"Println: Outputs the progress using a println! macro.\0".as_ptr() as *const _,
+ value_nick: b"println\0".as_ptr() as *const _,
+ },
+ gobject_sys::GEnumValue {
+ value: ProgressBinOutput::DebugCategory as i32,
+ value_name: b"Debug Category: Outputs the progress as info logs under the element's debug category.\0".as_ptr() as *const _,
+ value_nick: b"debug-category\0".as_ptr() as *const _,
+ },
+ // We use a struct with all null values to indicate the end of the array
+ gobject_sys::GEnumValue {
+ value: 0,
+ value_name: ptr::null(),
+ value_nick: ptr::null(),
+ },
+ ];
+
+ // Here we call the bindings to register the enum. We store the result in TYPE, so that we
+ // may re-use it later
+ let name = ffi::CString::new("GstProgressBinOutput").unwrap();
+ unsafe {
+ let type_ = gobject_sys::g_enum_register_static(name.as_ptr(), VALUES.as_ptr());
+ TYPE = glib::translate::from_glib(type_);
+ }
+ });
+
+ // Check that TYPE is not invalid and return it if so
+ unsafe {
+ assert_ne!(TYPE, glib::Type::Invalid);
+ TYPE
+ }
+}