Implement basic GstStructure bindings

This commit is contained in:
Sebastian Dröge 2017-07-07 16:04:54 +03:00
parent decf5da6d0
commit 992105b49f
8 changed files with 582 additions and 69 deletions

View file

@ -37,7 +37,6 @@ generate = [
"Gst.URIError",
"Gst.StructureChangeType",
"Gst.StreamStatusType",
"Gst.Device",
"Gst.DeviceMonitor",
"Gst.DeviceProvider",
"Gst.DeviceProviderFactory",
@ -52,6 +51,7 @@ generate = [
manual = [
"GLib.Error",
"Gst.Message",
"Gst.Structure",
]
[[object]]
@ -160,6 +160,20 @@ name = "Gst.ElementFactory"
status = "generate"
trait = false
[[object]]
name = "Gst.Device"
status = "generate"
[[object.function]]
name = "get_properties"
# Structure is not a GObject
ignore = true
[[object.property]]
name = "properties"
# Structure is not a GObject
ignore = true
[[object]]
name = "Gst.Object"
status = "generate"

View file

@ -35,8 +35,6 @@ pub trait DeviceExt {
fn get_display_name(&self) -> Option<String>;
//fn get_properties(&self) -> /*Ignored*/Option<Structure>;
fn has_classes(&self, classes: &str) -> bool;
fn has_classesv(&self, classes: &[&str]) -> bool;
@ -49,8 +47,6 @@ pub trait DeviceExt {
fn get_property_display_name(&self) -> Option<String>;
//fn get_property_properties(&self) -> /*Ignored*/Option<Structure>;
fn connect_removed<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> u64;
}
@ -79,10 +75,6 @@ impl<O: IsA<Device> + IsA<glib::object::Object>> DeviceExt for O {
}
}
//fn get_properties(&self) -> /*Ignored*/Option<Structure> {
// unsafe { TODO: call ffi::gst_device_get_properties() }
//}
fn has_classes(&self, classes: &str) -> bool {
unsafe {
from_glib(ffi::gst_device_has_classes(self.to_glib_none().0, classes.to_glib_none().0))
@ -125,14 +117,6 @@ impl<O: IsA<Device> + IsA<glib::object::Object>> DeviceExt for O {
value.get()
}
//fn get_property_properties(&self) -> /*Ignored*/Option<Structure> {
// let mut value = Value::from(None::<&/*Ignored*/Structure>);
// unsafe {
// gobject_ffi::g_object_get_property(self.to_glib_none().0, "properties".to_glib_none().0, value.to_glib_none_mut().0);
// }
// value.get()
//}
fn connect_removed<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> u64 {
unsafe {
let f: Box_<Box_<Fn(&Self) + Send + Sync + 'static>> = Box_::new(Box_::new(f));

View file

@ -146,7 +146,7 @@ pub trait ElementExt {
//fn message_full<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b str>>>(&self, type_: /*Ignored*/MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32);
//#[cfg(feature = "v1_10")]
//fn message_full_with_details<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b str>>>(&self, type_: /*Ignored*/MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32, structure: /*Ignored*/&mut Structure);
//fn message_full_with_details<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b str>>>(&self, type_: /*Ignored*/MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32, structure: &mut Structure);
fn no_more_pads(&self);
@ -394,7 +394,7 @@ impl<O: IsA<Element> + IsA<glib::object::Object>> ElementExt for O {
//}
//#[cfg(feature = "v1_10")]
//fn message_full_with_details<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b str>>>(&self, type_: /*Ignored*/MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32, structure: /*Ignored*/&mut Structure) {
//fn message_full_with_details<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b str>>>(&self, type_: /*Ignored*/MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32, structure: &mut Structure) {
// unsafe { TODO: call ffi::gst_element_message_full_with_details() }
//}

View file

@ -224,7 +224,7 @@ pub fn is_initialized() -> bool {
}
}
//pub fn make_element_message_details(name: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) -> /*Ignored*/Option<Structure> {
//pub fn make_element_message_details(name: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) -> Option<Structure> {
// unsafe { TODO: call ffi::gst_make_element_message_details() }
//}
@ -641,7 +641,7 @@ pub fn util_uint64_scale_round(val: u64, num: u64, denom: u64) -> u64 {
// unsafe { TODO: call ffi::gst_value_get_int_range_step() }
//}
//pub fn value_get_structure(value: /*Ignored*/&glib::Value) -> /*Ignored*/Option<Structure> {
//pub fn value_get_structure(value: /*Ignored*/&glib::Value) -> Option<Structure> {
// unsafe { TODO: call ffi::gst_value_get_structure() }
//}
@ -717,7 +717,7 @@ pub fn util_uint64_scale_round(val: u64, num: u64, denom: u64) -> u64 {
// unsafe { TODO: call ffi::gst_value_set_int_range_step() }
//}
//pub fn value_set_structure(value: /*Ignored*/&mut glib::Value, structure: /*Ignored*/&Structure) {
//pub fn value_set_structure(value: /*Ignored*/&mut glib::Value, structure: &Structure) {
// unsafe { TODO: call ffi::gst_value_set_structure() }
//}

View file

@ -3,6 +3,7 @@
use Error;
use Object;
use Structure;
use ffi;
use glib::translate::*;
use std::ptr;
@ -24,9 +25,11 @@ impl Plugin {
// unsafe { TODO: call ffi::gst_plugin_add_dependency_simple() }
//}
//pub fn get_cache_data(&self) -> /*Ignored*/Option<Structure> {
// unsafe { TODO: call ffi::gst_plugin_get_cache_data() }
//}
pub fn get_cache_data(&self) -> Option<Structure> {
unsafe {
from_glib_none(ffi::gst_plugin_get_cache_data(self.to_glib_none().0))
}
}
pub fn get_description(&self) -> Option<String> {
unsafe {
@ -88,9 +91,11 @@ impl Plugin {
}
}
//pub fn set_cache_data(&self, cache_data: /*Ignored*/&mut Structure) {
// unsafe { TODO: call ffi::gst_plugin_set_cache_data() }
//}
pub fn set_cache_data(&self, cache_data: &mut Structure) {
unsafe {
ffi::gst_plugin_set_cache_data(self.to_glib_none().0, cache_data.to_glib_full());
}
}
pub fn list_free(list: &[Plugin]) {
unsafe {

View file

@ -47,6 +47,8 @@ pub use miniobject::GstRc;
pub mod message;
pub use message::Message;
pub use message::MessageView;
pub mod structure;
pub use structure::Structure;
mod element;
mod bin;

View file

@ -723,9 +723,10 @@ macro_rules! message_builder_generic_impl {
}
}
pub fn build(self) -> Message {
pub fn build(mut self) -> Message {
unsafe {
let msg = $new_fn(&self, self.src.to_glib_none().0);
let src = self.src.to_glib_none().0;
let msg = $new_fn(&mut self, src);
if let Some(seqnum) = self.seqnum {
ffi::gst_message_set_seqnum(msg, seqnum);
}
@ -776,7 +777,7 @@ impl<'a> ErrorBuilder<'a> {
// TODO details
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_error(src, mut_override(s.error.to_glib_none().0), s.debug.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_error(src, mut_override(s.error.to_glib_none().0), s.debug.to_glib_none().0));
}
pub struct WarningBuilder<'a> {
@ -802,7 +803,7 @@ impl<'a> WarningBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_warning(src, mut_override(s.error.to_glib_none().0), s.debug.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_warning(src, mut_override(s.error.to_glib_none().0), s.debug.to_glib_none().0));
}
pub struct InfoBuilder<'a> {
@ -830,7 +831,7 @@ impl<'a> InfoBuilder<'a> {
// TODO details
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_warning(src, mut_override(s.error.to_glib_none().0), s.debug.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_warning(src, mut_override(s.error.to_glib_none().0), s.debug.to_glib_none().0));
}
pub struct TagBuilder<'a> {
@ -874,7 +875,7 @@ impl<'a> BufferingBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| {
message_builder_generic_impl!(|s: &mut Self, src| {
let msg = ffi::gst_message_new_buffering(src, s.percent);
if let Some((mode, avg_in, avg_out, buffering_left)) = s.stats {
@ -903,7 +904,7 @@ impl<'a> StateChangedBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_state_changed(src, s.old.to_glib(), s.new.to_glib(), s.pending.to_glib()));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_state_changed(src, s.old.to_glib(), s.new.to_glib(), s.pending.to_glib()));
}
pub struct StateDirtyBuilder<'a> {
@ -947,7 +948,7 @@ impl<'a> StepDoneBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_step_done(src, s.format.to_glib(), s.amount, s.rate, s.flush.to_glib(), s.intermediate.to_glib(), s.duration, s.eos.to_glib()));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_step_done(src, s.format.to_glib(), s.amount, s.rate, s.flush.to_glib(), s.intermediate.to_glib(), s.duration, s.eos.to_glib()));
}
pub struct ClockProvideBuilder<'a> {
@ -966,7 +967,7 @@ impl<'a> ClockProvideBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_clock_provide(src, s.clock.to_glib_none().0, s.ready.to_glib()));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_clock_provide(src, s.clock.to_glib_none().0, s.ready.to_glib()));
}
pub struct ClockLostBuilder<'a> {
@ -983,7 +984,7 @@ impl<'a> ClockLostBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_clock_lost(src, s.clock.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_clock_lost(src, s.clock.to_glib_none().0));
}
pub struct NewClockBuilder<'a> {
@ -1000,7 +1001,7 @@ impl<'a> NewClockBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_new_clock(src, s.clock.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_new_clock(src, s.clock.to_glib_none().0));
}
pub struct StructureChangeBuilder<'a> {
@ -1021,7 +1022,7 @@ impl<'a> StructureChangeBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_structure_change(src, s.type_.to_glib(), s.owner.to_glib_none().0, s.busy.to_glib()));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_structure_change(src, s.type_.to_glib(), s.owner.to_glib_none().0, s.busy.to_glib()));
}
pub struct StreamStatusBuilder<'a> {
@ -1049,7 +1050,7 @@ impl<'a> StreamStatusBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| {
message_builder_generic_impl!(|s: &mut Self, src| {
let msg = ffi::gst_message_new_stream_status(src, s.type_.to_glib(), s.owner.to_glib_none().0);
if let Some(status_object) = s.status_object {
ffi::gst_message_set_stream_status_object(msg, status_object.to_glib_none().0);
@ -1058,40 +1059,38 @@ impl<'a> StreamStatusBuilder<'a> {
});
}
// TODO Structure
pub struct ApplicationBuilder<'a> {
src: Option<&'a Object>,
seqnum: Option<u32>,
structure: (),
structure: Option<::Structure>,
}
impl<'a> ApplicationBuilder<'a> {
pub fn new(structure: () /* &'a Structure */) -> Self {
pub fn new(structure: ::Structure) -> Self {
Self {
src: None,
seqnum: None,
structure: structure,
structure: Some(structure),
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_application(src, ptr::null_mut() /*s.structure.to_glib_full()*/));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_application(src, s.structure.take().unwrap().into_ptr()));
}
// TODO Structure
pub struct ElementBuilder<'a> {
src: Option<&'a Object>,
seqnum: Option<u32>,
structure: (),
structure: Option<::Structure>,
}
impl<'a> ElementBuilder<'a> {
pub fn new(structure: () /* &'a Structure */) -> Self {
pub fn new(structure: ::Structure) -> Self {
Self {
src: None,
seqnum: None,
structure: structure,
structure: Some(structure),
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_element(src, ptr::null_mut() /*s.structure.to_glib_full()*/));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_element(src, s.structure.take().unwrap().into_ptr()));
}
pub struct SegmentStartBuilder<'a> {
@ -1110,7 +1109,7 @@ impl<'a> SegmentStartBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_segment_start(src, s.format.to_glib(), s.position));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_segment_start(src, s.format.to_glib(), s.position));
}
pub struct SegmentDoneBuilder<'a> {
@ -1129,7 +1128,7 @@ impl<'a> SegmentDoneBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_segment_done(src, s.format.to_glib(), s.position));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_segment_done(src, s.format.to_glib(), s.position));
}
pub struct DurationChangedBuilder<'a> {
@ -1191,7 +1190,7 @@ impl<'a> AsyncDoneBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_async_done(src, s.running_time));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_async_done(src, s.running_time));
}
pub struct RequestStateBuilder<'a> {
@ -1208,7 +1207,7 @@ impl<'a> RequestStateBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_request_state(src, s.state.to_glib()));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_request_state(src, s.state.to_glib()));
}
pub struct StepStartBuilder<'a> {
@ -1235,7 +1234,7 @@ impl<'a> StepStartBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_step_start(src, s.active.to_glib(), s.format.to_glib(), s.amount, s.rate, s.flush.to_glib(), s.intermediate.to_glib()));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_step_start(src, s.active.to_glib(), s.format.to_glib(), s.amount, s.rate, s.flush.to_glib(), s.intermediate.to_glib()));
}
pub struct QosBuilder<'a> {
@ -1278,7 +1277,7 @@ impl<'a> QosBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| {
message_builder_generic_impl!(|s: &mut Self, src| {
let msg = ffi::gst_message_new_qos(src, s.live.to_glib(), s.running_time, s.stream_time, s.timestamp, s.duration);
if let Some((jitter, proportion, quality)) = s.values {
ffi::gst_message_set_qos_values(msg, jitter, proportion, quality);
@ -1322,7 +1321,7 @@ impl<'a> ProgressBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_progress(src, s.type_.to_glib(), s.code.to_glib_none().0, s.text.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_progress(src, s.type_.to_glib(), s.code.to_glib_none().0, s.text.to_glib_none().0));
}
// TODO Toc
@ -1342,7 +1341,7 @@ impl<'a> TocBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_toc(src, ptr::null_mut() /*s.structure.to_glib_full()*/, s.updated.to_glib()));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_toc(src, ptr::null_mut() /*s.structure.to_glib_full()*/, s.updated.to_glib()));
}
pub struct ResetTimeBuilder<'a> {
@ -1359,7 +1358,7 @@ impl<'a> ResetTimeBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_reset_time(src, s.running_time));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_reset_time(src, s.running_time));
}
pub struct StreamStartBuilder<'a> {
@ -1383,7 +1382,7 @@ impl<'a> StreamStartBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| {
message_builder_generic_impl!(|s: &mut Self, src| {
let msg = ffi::gst_message_new_stream_start(src);
if let Some(group_id) = s.group_id {
ffi::gst_message_set_group_id(msg, group_id);
@ -1406,7 +1405,7 @@ impl<'a> NeedContextBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_need_context(src, s.context_type.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_need_context(src, s.context_type.to_glib_none().0));
}
// TODO Context
@ -1424,7 +1423,7 @@ impl<'a> HaveContextBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_have_context(src, ptr::null_mut() /*s.context.to_glib_full().0*/));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_have_context(src, ptr::null_mut() /*s.context.to_glib_full().0*/));
}
pub struct DeviceAddedBuilder<'a> {
@ -1441,7 +1440,7 @@ impl<'a> DeviceAddedBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_device_added(src, s.device.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_device_added(src, s.device.to_glib_none().0));
}
pub struct DeviceRemovedBuilder<'a> {
@ -1458,7 +1457,7 @@ impl<'a> DeviceRemovedBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_device_removed(src, s.device.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_device_removed(src, s.device.to_glib_none().0));
}
pub struct PropertyNotifyBuilder<'a> {
@ -1478,7 +1477,7 @@ impl<'a> PropertyNotifyBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_property_notify(src, s.property_name.to_glib_none().0, mut_override(s.value.to_glib_none().0)));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_property_notify(src, s.property_name.to_glib_none().0, mut_override(s.value.to_glib_none().0)));
}
pub struct StreamCollectionBuilder<'a> {
@ -1497,7 +1496,7 @@ impl<'a> StreamCollectionBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_message_new_stream_collection(src, s.collection.to_glib_none().0));
message_builder_generic_impl!(|s: &mut Self, src| ffi::gst_message_new_stream_collection(src, s.collection.to_glib_none().0));
}
pub struct StreamsSelectedBuilder<'a> {
@ -1526,7 +1525,7 @@ impl<'a> StreamsSelectedBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| {
message_builder_generic_impl!(|s: &mut Self, src| {
let msg = ffi::gst_message_new_streams_selected(src, s.collection.to_glib_none().0);
if let Some(streams) = s.streams {
for stream in streams {
@ -1566,7 +1565,7 @@ impl<'a> RedirectBuilder<'a> {
}
}
message_builder_generic_impl!(|s: &Self, src| {
message_builder_generic_impl!(|s: &mut Self, src| {
let msg = ffi::gst_message_new_redirect(src, s.location.to_glib_none().0, ptr::null_mut(), ptr::null_mut());
if let Some(entries) = s.entries {
for &(location, tag_list, entry_struct) in entries {

509
gstreamer/src/structure.rs Normal file
View file

@ -0,0 +1,509 @@
// Copyright (C) 2016-2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt;
use std::ptr;
use std::mem;
use std::ffi::{CStr, CString};
use std::ops::{Deref, DerefMut};
use std::borrow::{Borrow, ToOwned, BorrowMut};
use std::marker::PhantomData;
use glib;
use glib::translate::{from_glib, from_glib_full, from_glib_none, Stash, StashMut, ToGlibPtr, ToGlibPtrMut, FromGlibPtrNone, FromGlibPtrBorrow, FromGlibPtrFull};
use glib::value::{Value, ToValue, FromValueOptional};
use ffi;
use glib_ffi;
pub struct Structure(*mut StructureRef, PhantomData<StructureRef>, bool);
impl Structure {
pub fn new_empty(name: &str) -> Structure {
Structure(
unsafe { ffi::gst_structure_new_empty(name.to_glib_none().0) as *mut StructureRef },
PhantomData,
false,
)
}
pub fn new(name: &str, values: &[(&str, &Value)]) -> Structure {
let mut structure = Structure::new_empty(name);
for &(f, v) in values {
structure.set_value(f, v.clone());
}
structure
}
pub fn from_string(s: &str) -> Option<Structure> {
unsafe {
let structure = ffi::gst_structure_from_string(s.to_glib_none().0, ptr::null_mut());
if structure.is_null() {
None
} else {
Some(Structure(structure as *mut StructureRef, PhantomData, false))
}
}
}
pub unsafe fn into_ptr(self) -> *mut ffi::GstStructure {
let ptr = self.0 as *mut StructureRef as *mut ffi::GstStructure;
mem::forget(self);
ptr
}
}
impl Deref for Structure {
type Target = StructureRef;
fn deref(&self) -> &StructureRef {
unsafe { &*self.0 }
}
}
impl DerefMut for Structure {
fn deref_mut(&mut self) -> &mut StructureRef {
unsafe { &mut *self.0 }
}
}
impl AsRef<StructureRef> for Structure {
fn as_ref(&self) -> &StructureRef {
self.deref()
}
}
impl AsMut<StructureRef> for Structure {
fn as_mut(&mut self) -> &mut StructureRef {
self.deref_mut()
}
}
impl Clone for Structure {
fn clone(&self) -> Self {
Structure(
unsafe { ffi::gst_structure_copy(&(*self.0).0) as *mut StructureRef },
PhantomData,
false,
)
}
}
impl Drop for Structure {
fn drop(&mut self) {
if !self.2 {
unsafe { ffi::gst_structure_free(&mut (*self.0).0) }
}
}
}
impl fmt::Debug for Structure {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.to_string())
}
}
impl PartialEq for Structure {
fn eq(&self, other: &Structure) -> bool {
self.as_ref().eq(other)
}
}
impl PartialEq<StructureRef> for Structure {
fn eq(&self, other: &StructureRef) -> bool {
self.as_ref().eq(other)
}
}
impl Eq for Structure {}
impl Borrow<StructureRef> for Structure {
fn borrow(&self) -> &StructureRef {
unsafe { &*self.0 }
}
}
impl BorrowMut<StructureRef> for Structure {
fn borrow_mut(&mut self) -> &mut StructureRef {
unsafe { &mut *self.0 }
}
}
impl ToOwned for StructureRef {
type Owned = Structure;
fn to_owned(&self) -> Structure {
Structure(
unsafe { ffi::gst_structure_copy(&self.0) as *mut StructureRef },
PhantomData,
false,
)
}
}
impl<'a> ToGlibPtr<'a, *const ffi::GstStructure> for Structure {
type Storage = &'a Self;
fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstStructure, Self> {
Stash(unsafe { &(*self.0).0 }, self)
}
fn to_glib_full(&self) -> *const ffi::GstStructure {
unsafe {
ffi::gst_structure_copy(&(*self.0).0)
}
}
}
impl<'a> ToGlibPtr<'a, *mut ffi::GstStructure> for Structure {
type Storage = &'a Self;
fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GstStructure, Self> {
Stash(unsafe { &mut (*self.0).0 }, self)
}
fn to_glib_full(&self) -> *mut ffi::GstStructure {
unsafe {
ffi::gst_structure_copy(&(*self.0).0)
}
}
}
impl<'a> ToGlibPtrMut<'a, *mut ffi::GstStructure> for Structure {
type Storage = &'a mut Self;
fn to_glib_none_mut(&'a mut self) -> StashMut<*mut ffi::GstStructure, Self> {
StashMut(unsafe { &mut (*self.0).0 }, self)
}
}
impl FromGlibPtrNone<*const ffi::GstStructure> for Structure {
unsafe fn from_glib_none(ptr: *const ffi::GstStructure) -> Self {
Structure(
ffi::gst_structure_copy(ptr) as *mut StructureRef,
PhantomData,
false,
)
}
}
impl FromGlibPtrNone<*mut ffi::GstStructure> for Structure {
unsafe fn from_glib_none(ptr: *mut ffi::GstStructure) -> Self {
Structure(
ffi::gst_structure_copy(ptr) as *mut StructureRef,
PhantomData,
false,
)
}
}
impl FromGlibPtrFull<*const ffi::GstStructure> for Structure {
unsafe fn from_glib_full(ptr: *const ffi::GstStructure) -> Self {
Structure(
ptr as *mut StructureRef,
PhantomData,
false,
)
}
}
impl FromGlibPtrFull<*mut ffi::GstStructure> for Structure {
unsafe fn from_glib_full(ptr: *mut ffi::GstStructure) -> Self {
Structure(
ptr as *mut StructureRef,
PhantomData,
false,
)
}
}
impl FromGlibPtrBorrow<*const ffi::GstStructure> for Structure {
unsafe fn from_glib_borrow(ptr: *const ffi::GstStructure) -> Self {
Structure(
ptr as *mut StructureRef,
PhantomData,
true,
)
}
}
impl FromGlibPtrBorrow<*mut ffi::GstStructure> for Structure {
unsafe fn from_glib_borrow(ptr: *mut ffi::GstStructure) -> Self {
Structure(
ptr as *mut StructureRef,
PhantomData,
true,
)
}
}
#[repr(C)]
pub struct StructureRef(ffi::GstStructure);
impl StructureRef {
pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstStructure) -> &'a StructureRef {
assert!(!ptr.is_null());
&*(ptr as *mut StructureRef)
}
pub unsafe fn from_glib_borrow_mut<'a>(ptr: *mut ffi::GstStructure) -> &'a mut StructureRef {
assert!(!ptr.is_null());
&mut *(ptr as *mut StructureRef)
}
pub fn to_string(&self) -> String {
unsafe {
from_glib_full(ffi::gst_structure_to_string(&self.0))
}
}
pub fn get<'a, T: FromValueOptional<'a>>(&'a self, name: &str) -> Option<T> {
self.get_value(name).and_then(|v| v.get())
}
pub fn get_value<'a>(&'a self, name: &str) -> Option<&Value> {
unsafe {
let name_cstr = CString::new(name).unwrap();
let value = ffi::gst_structure_get_value(&self.0, name_cstr.as_ptr());
if value.is_null() {
return None;
}
Some(&*(value as *const Value))
}
}
pub fn set<T: ToValue>(&mut self, name: &str, value: T) {
let value = value.to_value();
self.set_value(name, value);
}
pub fn set_value(&mut self, name: &str, mut value: Value) {
unsafe {
let name_cstr = CString::new(name).unwrap();
ffi::gst_structure_take_value(&mut self.0, name_cstr.as_ptr(), value.to_glib_none_mut().0);
mem::forget(value);
}
}
pub fn get_name(&self) -> &str {
unsafe {
CStr::from_ptr(ffi::gst_structure_get_name(&self.0)).to_str().unwrap()
}
}
pub fn has_field(&self, field: &str) -> bool {
unsafe {
from_glib(ffi::gst_structure_has_field(&self.0, field.to_glib_none().0))
}
}
pub fn remove_field(&mut self, field: &str) {
unsafe {
ffi::gst_structure_remove_field(&mut self.0, field.to_glib_none().0);
}
}
pub fn remove_all_fields(&mut self) {
unsafe {
ffi::gst_structure_remove_all_fields(&mut self.0);
}
}
pub fn fields(&self) -> FieldIterator {
FieldIterator::new(self)
}
pub fn iter(&self) -> Iter {
Iter::new(self)
}
fn get_nth_field_name(&self, idx: u32) -> Option<&str> {
unsafe {
let field_name = ffi::gst_structure_nth_field_name(&self.0, idx);
if field_name.is_null() {
return None;
}
Some(CStr::from_ptr(field_name).to_str().unwrap())
}
}
fn n_fields(&self) -> u32 {
unsafe { ffi::gst_structure_n_fields(&self.0) as u32 }
}
// TODO: Various operations
}
impl fmt::Debug for StructureRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.to_string())
}
}
impl PartialEq for StructureRef {
fn eq(&self, other: &StructureRef) -> bool {
unsafe { from_glib(ffi::gst_structure_is_equal(&self.0, &other.0)) }
}
}
impl Eq for StructureRef {}
pub struct FieldIterator<'a> {
structure: &'a StructureRef,
idx: u32,
n_fields: u32,
}
impl<'a> FieldIterator<'a> {
pub fn new(structure: &'a StructureRef) -> FieldIterator<'a> {
let n_fields = structure.n_fields();
FieldIterator {
structure: structure,
idx: 0,
n_fields: n_fields,
}
}
}
impl<'a> Iterator for FieldIterator<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
if self.idx >= self.n_fields {
return None;
}
if let Some(field_name) = self.structure.get_nth_field_name(self.idx) {
self.idx += 1;
Some(field_name)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
if self.idx == self.n_fields {
return (0, Some(0));
}
let remaining = (self.n_fields - self.idx) as usize;
(remaining, Some(remaining))
}
}
impl<'a> DoubleEndedIterator for FieldIterator<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.idx == self.n_fields {
return None;
}
self.n_fields -= 1;
if let Some(field_name) = self.structure.get_nth_field_name(self.n_fields) {
Some(field_name)
} else {
None
}
}
}
impl<'a> ExactSizeIterator for FieldIterator<'a> {}
pub struct Iter<'a> {
iter: FieldIterator<'a>,
}
impl<'a> Iter<'a> {
pub fn new(structure: &'a StructureRef) -> Iter<'a> {
Iter { iter: FieldIterator::new(structure) }
}
}
impl<'a> Iterator for Iter<'a> {
type Item = (&'a str, &'a Value);
fn next(&mut self) -> Option<(&'a str, &'a Value)> {
if let Some(f) = self.iter.next() {
let v = self.iter.structure.get_value(f);
Some((f, v.unwrap()))
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> DoubleEndedIterator for Iter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if let Some(f) = self.iter.next_back() {
let v = self.iter.structure.get_value(f);
Some((f, v.unwrap()))
} else {
None
}
}
}
impl<'a> ExactSizeIterator for Iter<'a> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_set_get() {
::init().unwrap();
let mut s = Structure::new_empty("test");
assert_eq!(s.get_name(), "test");
s.set("f1", "abc");
s.set("f2", String::from("bcd"));
s.set("f3", 123i32);
assert_eq!(s.get::<&str>("f1").unwrap(), "abc");
assert_eq!(s.get::<&str>("f2").unwrap(), "bcd");
assert_eq!(s.get::<i32>("f3").unwrap(), 123i32);
assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f2", "f3"]);
/*
assert_eq!(
s.iter()
.map(|(f, v)| (f, v.clone()))
.collect::<Vec<_>>(),
vec![
("f1", "abc".into()),
("f2","bcd".into()),
("f3", 123i32.into()),
]
);
let s2 = Structure::new(
"test",
&[
("f1", "abc".into()),
("f2", "bcd".into()),
("f3", 123i32.into()),
],
);
assert_eq!(s, s2);
*/
}
}