mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-06-03 05:49:31 +00:00
Add infrastructure for installing various kinds of properties
From both the subclass and the implementation
This commit is contained in:
parent
1c997c171d
commit
4ee8b12e66
|
@ -25,7 +25,9 @@ use gst_base::prelude::*;
|
||||||
use object::*;
|
use object::*;
|
||||||
use element::*;
|
use element::*;
|
||||||
|
|
||||||
pub trait BaseSrcImpl: mopa::Any + ElementImpl + Send + Sync + 'static {}
|
pub trait BaseSrcImpl
|
||||||
|
: mopa::Any + ObjectImpl + ElementImpl + Send + Sync + 'static {
|
||||||
|
}
|
||||||
|
|
||||||
mopafy!(BaseSrcImpl);
|
mopafy!(BaseSrcImpl);
|
||||||
|
|
||||||
|
@ -56,6 +58,7 @@ unsafe impl BaseSrcClass<RsBaseSrc> for gst_base_ffi::GstBaseSrcClass {}
|
||||||
unsafe impl BaseSrcClass<RsBaseSrc> for RsBaseSrcClass {}
|
unsafe impl BaseSrcClass<RsBaseSrc> for RsBaseSrcClass {}
|
||||||
unsafe impl ElementClass<RsBaseSrc> for gst_base_ffi::GstBaseSrcClass {}
|
unsafe impl ElementClass<RsBaseSrc> for gst_base_ffi::GstBaseSrcClass {}
|
||||||
unsafe impl ElementClass<RsBaseSrc> for RsBaseSrcClass {}
|
unsafe impl ElementClass<RsBaseSrc> for RsBaseSrcClass {}
|
||||||
|
unsafe impl ObjectClassStruct for gst_base_ffi::GstBaseSrcClass {}
|
||||||
|
|
||||||
// FIXME: Boilerplate
|
// FIXME: Boilerplate
|
||||||
impl BaseSrcImpl for Box<BaseSrcImpl> {}
|
impl BaseSrcImpl for Box<BaseSrcImpl> {}
|
||||||
|
@ -72,6 +75,8 @@ impl ElementImpl for Box<BaseSrcImpl> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for Box<BaseSrcImpl> {}
|
||||||
|
|
||||||
impl ObjectType for RsBaseSrc {
|
impl ObjectType for RsBaseSrc {
|
||||||
const NAME: &'static str = "RsBaseSrc";
|
const NAME: &'static str = "RsBaseSrc";
|
||||||
type GlibType = gst_base_ffi::GstBaseSrc;
|
type GlibType = gst_base_ffi::GstBaseSrc;
|
||||||
|
|
|
@ -13,7 +13,7 @@ use std::u64;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use error::*;
|
use error::*;
|
||||||
use object::{register_type, ImplTypeStatic};
|
use object::*;
|
||||||
use element::*;
|
use element::*;
|
||||||
|
|
||||||
use glib;
|
use glib;
|
||||||
|
@ -638,6 +638,8 @@ impl Demuxer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for Demuxer {}
|
||||||
|
|
||||||
impl ElementImpl for Demuxer {
|
impl ElementImpl for Demuxer {
|
||||||
fn change_state(
|
fn change_state(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -21,7 +21,7 @@ use gst::prelude::*;
|
||||||
|
|
||||||
use object::*;
|
use object::*;
|
||||||
|
|
||||||
pub trait ElementImpl: mopa::Any + Send + Sync + 'static {
|
pub trait ElementImpl: ObjectImpl + mopa::Any + Send + Sync + 'static {
|
||||||
fn change_state(
|
fn change_state(
|
||||||
&self,
|
&self,
|
||||||
element: &gst::Element,
|
element: &gst::Element,
|
||||||
|
@ -114,10 +114,15 @@ impl RsElement {
|
||||||
|
|
||||||
unsafe impl<T: IsA<gst::Element>> Element for T {}
|
unsafe impl<T: IsA<gst::Element>> Element for T {}
|
||||||
pub type RsElementClass = ClassStruct<RsElement>;
|
pub type RsElementClass = ClassStruct<RsElement>;
|
||||||
unsafe impl ElementClass<RsElement> for RsElementClass {}
|
|
||||||
unsafe impl ElementClass<RsElement> for gst_ffi::GstElementClass {}
|
|
||||||
|
|
||||||
// FIXME: Boilerplate
|
// FIXME: Boilerplate
|
||||||
|
unsafe impl ElementClass<RsElement> for RsElementClass {}
|
||||||
|
unsafe impl ElementClass<RsElement> for gst_ffi::GstElementClass {}
|
||||||
|
unsafe impl ObjectClassStruct for gst_ffi::GstElementClass {}
|
||||||
|
|
||||||
|
// FIXME: Boilerplate
|
||||||
|
impl ObjectImpl for Box<ElementImpl> {}
|
||||||
|
|
||||||
impl ElementImpl for Box<ElementImpl> {
|
impl ElementImpl for Box<ElementImpl> {
|
||||||
fn change_state(
|
fn change_state(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -17,6 +17,30 @@ use gobject_ffi;
|
||||||
use glib;
|
use glib;
|
||||||
use glib::translate::*;
|
use glib::translate::*;
|
||||||
|
|
||||||
|
pub trait ObjectImpl: Send + Sync + 'static {
|
||||||
|
fn set_property(&self, _obj: &glib::Object, _id: u32, _value: &glib::Value) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_property(&self, _obj: &glib::Object, _id: u32, _value: &mut glib::Value) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn notify(&self, obj: &glib::Object, id: u32) {
|
||||||
|
unsafe {
|
||||||
|
let stash = obj.to_glib_none();
|
||||||
|
let ptr: *mut gobject_ffi::GObject = stash.0;
|
||||||
|
let klass = *(ptr as *const *const gobject_ffi::GObjectClass);
|
||||||
|
let mut n_pspecs = 0;
|
||||||
|
let pspecs =
|
||||||
|
gobject_ffi::g_object_class_list_properties(klass as *mut _, &mut n_pspecs);
|
||||||
|
|
||||||
|
assert!(n_pspecs > id);
|
||||||
|
gobject_ffi::g_object_notify_by_pspec(ptr, *pspecs.offset(id as isize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ImplTypeStatic<T: ObjectType>: Send + Sync + 'static {
|
pub trait ImplTypeStatic<T: ObjectType>: Send + Sync + 'static {
|
||||||
fn get_name(&self) -> &str;
|
fn get_name(&self) -> &str;
|
||||||
fn new(&self, &T::RsType) -> T::ImplType;
|
fn new(&self, &T::RsType) -> T::ImplType;
|
||||||
|
@ -31,11 +55,19 @@ where
|
||||||
type GlibType;
|
type GlibType;
|
||||||
type GlibClassType;
|
type GlibClassType;
|
||||||
type RsType: FromGlibPtrBorrow<*mut InstanceStruct<Self>>;
|
type RsType: FromGlibPtrBorrow<*mut InstanceStruct<Self>>;
|
||||||
type ImplType: 'static;
|
type ImplType: ObjectImpl;
|
||||||
|
|
||||||
fn glib_type() -> glib::Type;
|
fn glib_type() -> glib::Type;
|
||||||
|
|
||||||
fn class_init(klass: &mut Self::GlibClassType);
|
fn class_init(klass: &mut Self::GlibClassType);
|
||||||
|
|
||||||
|
fn set_property(_obj: &Self::RsType, _id: u32, _value: &glib::Value) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_property(_obj: &Self::RsType, _id: u32, _value: &mut glib::Value) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -57,6 +89,215 @@ pub struct ClassStruct<T: ObjectType> {
|
||||||
pub imp_static: *const Box<ImplTypeStatic<T>>,
|
pub imp_static: *const Box<ImplTypeStatic<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe trait ObjectClassStruct {
|
||||||
|
fn install_properties(&mut self, properties: &[Property]) {
|
||||||
|
if properties.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut pspecs = Vec::with_capacity(properties.len());
|
||||||
|
|
||||||
|
pspecs.push(ptr::null_mut());
|
||||||
|
|
||||||
|
for property in properties {
|
||||||
|
match *property {
|
||||||
|
Property::Boolean(name, nick, description, default, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_boolean(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
default.to_glib(),
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Property::Int(name, nick, description, (min, max), default, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_int(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
default,
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Property::Int64(name, nick, description, (min, max), default, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_int64(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
default,
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Property::UInt(name, nick, description, (min, max), default, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_uint(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
default,
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Property::UInt64(name, nick, description, (min, max), default, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_uint64(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
default,
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Property::Float(name, nick, description, (min, max), default, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_float(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
default,
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Property::Double(name, nick, description, (min, max), default, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_double(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
default,
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Property::String(name, nick, description, default, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_string(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
default.to_glib_none().0,
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Property::Boxed(name, nick, description, type_, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_boxed(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
type_.to_glib(),
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
Property::Object(name, nick, description, type_, mutability) => unsafe {
|
||||||
|
pspecs.push(gobject_ffi::g_param_spec_object(
|
||||||
|
name.to_glib_none().0,
|
||||||
|
nick.to_glib_none().0,
|
||||||
|
description.to_glib_none().0,
|
||||||
|
type_.to_glib(),
|
||||||
|
mutability.into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gobject_ffi::g_object_class_install_properties(
|
||||||
|
self as *mut _ as *mut gobject_ffi::GObjectClass,
|
||||||
|
pspecs.len() as u32,
|
||||||
|
pspecs.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: ObjectType> ObjectClassStruct for ClassStruct<T> {}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
pub enum PropertyMutability {
|
||||||
|
Readable,
|
||||||
|
Writable,
|
||||||
|
ReadWrite,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<gobject_ffi::GParamFlags> for PropertyMutability {
|
||||||
|
fn into(self) -> gobject_ffi::GParamFlags {
|
||||||
|
use self::PropertyMutability::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Readable => gobject_ffi::G_PARAM_READABLE,
|
||||||
|
Writable => gobject_ffi::G_PARAM_WRITABLE,
|
||||||
|
ReadWrite => gobject_ffi::G_PARAM_READWRITE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Property<'a> {
|
||||||
|
Boolean(&'a str, &'a str, &'a str, bool, PropertyMutability),
|
||||||
|
Int(
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
(i32, i32),
|
||||||
|
i32,
|
||||||
|
PropertyMutability,
|
||||||
|
),
|
||||||
|
Int64(
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
(i64, i64),
|
||||||
|
i64,
|
||||||
|
PropertyMutability,
|
||||||
|
),
|
||||||
|
UInt(
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
(u32, u32),
|
||||||
|
u32,
|
||||||
|
PropertyMutability,
|
||||||
|
),
|
||||||
|
UInt64(
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
(u64, u64),
|
||||||
|
u64,
|
||||||
|
PropertyMutability,
|
||||||
|
),
|
||||||
|
Float(
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
(f32, f32),
|
||||||
|
f32,
|
||||||
|
PropertyMutability,
|
||||||
|
),
|
||||||
|
Double(
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
(f64, f64),
|
||||||
|
f64,
|
||||||
|
PropertyMutability,
|
||||||
|
),
|
||||||
|
String(
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
&'a str,
|
||||||
|
Option<&'a str>,
|
||||||
|
PropertyMutability,
|
||||||
|
),
|
||||||
|
Boxed(&'a str, &'a str, &'a str, glib::Type, PropertyMutability),
|
||||||
|
Object(&'a str, &'a str, &'a str, glib::Type, PropertyMutability),
|
||||||
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn class_init<T: ObjectType>(
|
unsafe extern "C" fn class_init<T: ObjectType>(
|
||||||
klass: glib_ffi::gpointer,
|
klass: glib_ffi::gpointer,
|
||||||
_klass_data: glib_ffi::gpointer,
|
_klass_data: glib_ffi::gpointer,
|
||||||
|
@ -66,6 +307,8 @@ unsafe extern "C" fn class_init<T: ObjectType>(
|
||||||
let gobject_klass = &mut *(klass as *mut gobject_ffi::GObjectClass);
|
let gobject_klass = &mut *(klass as *mut gobject_ffi::GObjectClass);
|
||||||
|
|
||||||
gobject_klass.finalize = Some(finalize::<T>);
|
gobject_klass.finalize = Some(finalize::<T>);
|
||||||
|
gobject_klass.set_property = Some(set_property::<T>);
|
||||||
|
gobject_klass.get_property = Some(get_property::<T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
T::class_init(&mut *(klass as *mut T::GlibClassType));
|
T::class_init(&mut *(klass as *mut T::GlibClassType));
|
||||||
|
@ -85,6 +328,34 @@ unsafe extern "C" fn finalize<T: ObjectType>(obj: *mut gobject_ffi::GObject) {
|
||||||
parent_klass.finalize.map(|f| f(obj));
|
parent_klass.finalize.map(|f| f(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn get_property<T: ObjectType>(
|
||||||
|
obj: *mut gobject_ffi::GObject,
|
||||||
|
id: u32,
|
||||||
|
value: *mut gobject_ffi::GValue,
|
||||||
|
_pspec: *mut gobject_ffi::GParamSpec,
|
||||||
|
) {
|
||||||
|
callback_guard!();
|
||||||
|
T::get_property(
|
||||||
|
&from_glib_borrow(obj as *mut InstanceStruct<T>),
|
||||||
|
id,
|
||||||
|
&mut *(value as *mut glib::Value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn set_property<T: ObjectType>(
|
||||||
|
obj: *mut gobject_ffi::GObject,
|
||||||
|
id: u32,
|
||||||
|
value: *mut gobject_ffi::GValue,
|
||||||
|
_pspec: *mut gobject_ffi::GParamSpec,
|
||||||
|
) {
|
||||||
|
callback_guard!();
|
||||||
|
T::set_property(
|
||||||
|
&from_glib_borrow(obj as *mut InstanceStruct<T>),
|
||||||
|
id,
|
||||||
|
&*(value as *mut glib::Value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn get_type<T: ObjectType>() -> glib_ffi::GType {
|
pub unsafe fn get_type<T: ObjectType>() -> glib_ffi::GType {
|
||||||
use std::sync::{Once, ONCE_INIT};
|
use std::sync::{Once, ONCE_INIT};
|
||||||
|
|
||||||
|
@ -134,6 +405,12 @@ unsafe extern "C" fn sub_class_init<T: ObjectType>(
|
||||||
klass_data: glib_ffi::gpointer,
|
klass_data: glib_ffi::gpointer,
|
||||||
) {
|
) {
|
||||||
callback_guard!();
|
callback_guard!();
|
||||||
|
{
|
||||||
|
let gobject_klass = &mut *(klass as *mut gobject_ffi::GObjectClass);
|
||||||
|
|
||||||
|
gobject_klass.set_property = Some(sub_set_property::<T>);
|
||||||
|
gobject_klass.get_property = Some(sub_get_property::<T>);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
let klass = &mut *(klass as *mut ClassStruct<T>);
|
let klass = &mut *(klass as *mut ClassStruct<T>);
|
||||||
let imp_static = klass_data as *const Box<ImplTypeStatic<T>>;
|
let imp_static = klass_data as *const Box<ImplTypeStatic<T>>;
|
||||||
|
@ -143,6 +420,34 @@ unsafe extern "C" fn sub_class_init<T: ObjectType>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn sub_get_property<T: ObjectType>(
|
||||||
|
obj: *mut gobject_ffi::GObject,
|
||||||
|
id: u32,
|
||||||
|
value: *mut gobject_ffi::GValue,
|
||||||
|
_pspec: *mut gobject_ffi::GParamSpec,
|
||||||
|
) {
|
||||||
|
callback_guard!();
|
||||||
|
let instance = &*(obj as *mut InstanceStruct<T>);
|
||||||
|
let imp = instance.get_impl();
|
||||||
|
imp.get_property(
|
||||||
|
&from_glib_borrow(obj),
|
||||||
|
id,
|
||||||
|
&mut *(value as *mut glib::Value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn sub_set_property<T: ObjectType>(
|
||||||
|
obj: *mut gobject_ffi::GObject,
|
||||||
|
id: u32,
|
||||||
|
value: *mut gobject_ffi::GValue,
|
||||||
|
_pspec: *mut gobject_ffi::GParamSpec,
|
||||||
|
) {
|
||||||
|
callback_guard!();
|
||||||
|
let instance = &*(obj as *mut InstanceStruct<T>);
|
||||||
|
let imp = instance.get_impl();
|
||||||
|
imp.set_property(&from_glib_borrow(obj), id, &*(value as *mut glib::Value));
|
||||||
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn sub_init<T: ObjectType>(
|
unsafe extern "C" fn sub_init<T: ObjectType>(
|
||||||
obj: *mut gobject_ffi::GTypeInstance,
|
obj: *mut gobject_ffi::GTypeInstance,
|
||||||
_klass: glib_ffi::gpointer,
|
_klass: glib_ffi::gpointer,
|
||||||
|
|
Loading…
Reference in a new issue