Refactor Structure bindings and allow getting Structures from Caps

This commit is contained in:
Sebastian Dröge 2017-04-21 22:04:08 +01:00
parent df51424631
commit 2232af41b6
2 changed files with 156 additions and 35 deletions

View file

@ -11,6 +11,7 @@ use std::ffi::CStr;
use std::fmt; use std::fmt;
use value::*; use value::*;
use miniobject::*; use miniobject::*;
use structure::*;
use glib; use glib;
use gst; use gst;
@ -91,6 +92,22 @@ impl Caps {
s s
} }
} }
pub fn get_structure(&self, idx: u32) -> Option<&Structure> {
unsafe {
let structure = gst::gst_caps_get_structure(self.0, idx);
Structure::from_borrowed_ptr(structure as *mut gst::GstStructure)
}
}
pub fn get_mut_structure(&mut self, idx: u32) -> Option<&mut Structure> {
unsafe {
let structure = gst::gst_caps_get_structure(self.0, idx);
Structure::from_borrowed_mut_ptr(structure as *mut gst::GstStructure)
}
}
// TODO: All kinds of caps operations
} }
impl fmt::Debug for Caps { impl fmt::Debug for Caps {
@ -132,5 +149,15 @@ mod tests {
assert_eq!(caps.to_string(), assert_eq!(caps.to_string(),
"foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, \ "foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, \
fraction=(fraction)1/2, array=(int)< 1, 2 >"); fraction=(fraction)1/2, array=(int)< 1, 2 >");
let s = caps.get_structure(0).unwrap();
assert_eq!(s,
OwnedStructure::new("foo/bar",
&[("int", 12.into()),
("bool", true.into()),
("string", "bla".into()),
("fraction", (1, 2).into()),
("array", vec![1.into(), 2.into()].into())])
.as_ref());
} }
} }

View file

@ -9,6 +9,8 @@
use std::fmt; use std::fmt;
use std::ptr; use std::ptr;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::ops::{Deref, DerefMut};
use std::borrow::{Borrow, ToOwned, BorrowMut};
use value::*; use value::*;
@ -16,17 +18,19 @@ use glib;
use gobject; use gobject;
use gst; use gst;
#[repr(C)] pub struct OwnedStructure(&'static mut Structure);
pub struct Structure(*mut gst::GstStructure);
impl Structure { impl OwnedStructure {
pub fn new_empty(name: &str) -> Structure { pub fn new_empty(name: &str) -> OwnedStructure {
let name_cstr = CString::new(name).unwrap(); let name_cstr = CString::new(name).unwrap();
Structure(unsafe { gst::gst_structure_new_empty(name_cstr.as_ptr()) }) OwnedStructure(unsafe {
&mut *(gst::gst_structure_new_empty(name_cstr.as_ptr()) as
*mut Structure)
})
} }
pub fn new(name: &str, values: &[(&str, Value)]) -> Structure { pub fn new(name: &str, values: &[(&str, Value)]) -> OwnedStructure {
let mut structure = Structure::new_empty(name); let mut structure = OwnedStructure::new_empty(name);
for &(ref f, ref v) in values { for &(ref f, ref v) in values {
structure.set(f, v.clone()); structure.set(f, v.clone());
@ -35,21 +39,121 @@ impl Structure {
structure structure
} }
pub fn from_string(s: &str) -> Option<Structure> { pub fn from_string(s: &str) -> Option<OwnedStructure> {
unsafe { unsafe {
let cstr = CString::new(s).unwrap(); let cstr = CString::new(s).unwrap();
let structure = gst::gst_structure_from_string(cstr.as_ptr(), ptr::null_mut()); let structure = gst::gst_structure_from_string(cstr.as_ptr(), ptr::null_mut());
if structure.is_null() { if structure.is_null() {
None None
} else { } else {
Some(Structure(structure)) Some(OwnedStructure(&mut *(structure as *mut Structure)))
} }
} }
} }
}
impl Deref for OwnedStructure {
type Target = Structure;
fn deref(&self) -> &Structure {
self.0
}
}
impl DerefMut for OwnedStructure {
fn deref_mut(&mut self) -> &mut Structure {
self.0
}
}
impl AsRef<Structure> for OwnedStructure {
fn as_ref(&self) -> &Structure {
self.deref()
}
}
impl AsMut<Structure> for OwnedStructure {
fn as_mut(&mut self) -> &mut Structure {
self.deref_mut()
}
}
impl Clone for OwnedStructure {
fn clone(&self) -> Self {
OwnedStructure(unsafe { &mut *(gst::gst_structure_copy(&(self.0).0) as *mut Structure) })
}
}
impl Drop for OwnedStructure {
fn drop(&mut self) {
unsafe { gst::gst_structure_free(&mut (self.0).0) }
}
}
impl fmt::Debug for OwnedStructure {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.to_string())
}
}
impl PartialEq for OwnedStructure {
fn eq(&self, other: &OwnedStructure) -> bool {
self.as_ref().eq(other)
}
}
impl PartialEq<Structure> for OwnedStructure {
fn eq(&self, other: &Structure) -> bool {
self.as_ref().eq(other)
}
}
impl Eq for OwnedStructure {}
impl Borrow<Structure> for OwnedStructure {
fn borrow(&self) -> &Structure {
self.0
}
}
impl BorrowMut<Structure> for OwnedStructure {
fn borrow_mut(&mut self) -> &mut Structure {
self.0
}
}
impl ToOwned for Structure {
type Owned = OwnedStructure;
fn to_owned(&self) -> OwnedStructure {
OwnedStructure(unsafe { &mut *(gst::gst_structure_copy(&self.0) as *mut Structure) })
}
}
#[repr(C)]
pub struct Structure(gst::GstStructure);
impl Structure {
pub unsafe fn from_borrowed_ptr<'a>(ptr: *const gst::GstStructure) -> Option<&'a Structure> {
if ptr.is_null() {
return None;
}
Some(&*(ptr as *mut Structure))
}
pub unsafe fn from_borrowed_mut_ptr<'a>(ptr: *mut gst::GstStructure)
-> Option<&'a mut Structure> {
if ptr.is_null() {
return None;
}
Some(&mut *(ptr as *mut Structure))
}
pub fn to_string(&self) -> String { pub fn to_string(&self) -> String {
unsafe { unsafe {
let ptr = gst::gst_structure_to_string(self.0); let ptr = gst::gst_structure_to_string(&self.0);
let s = CStr::from_ptr(ptr).to_str().unwrap().into(); let s = CStr::from_ptr(ptr).to_str().unwrap().into();
glib::g_free(ptr as glib::gpointer); glib::g_free(ptr as glib::gpointer);
@ -66,7 +170,7 @@ impl Structure {
unsafe { unsafe {
let name_cstr = CString::new(name).unwrap(); let name_cstr = CString::new(name).unwrap();
let value = gst::gst_structure_get_value(self.0, name_cstr.as_ptr()); let value = gst::gst_structure_get_value(&self.0, name_cstr.as_ptr());
if value.is_null() { if value.is_null() {
return None; return None;
@ -81,14 +185,14 @@ impl Structure {
let name_cstr = CString::new(name).unwrap(); let name_cstr = CString::new(name).unwrap();
let mut gvalue = value.into().into_raw(); let mut gvalue = value.into().into_raw();
gst::gst_structure_take_value(self.0, name_cstr.as_ptr(), &mut gvalue); gst::gst_structure_take_value(&mut self.0, name_cstr.as_ptr(), &mut gvalue);
gvalue.g_type = gobject::G_TYPE_NONE; gvalue.g_type = gobject::G_TYPE_NONE;
} }
} }
pub fn get_name(&self) -> &str { pub fn get_name(&self) -> &str {
unsafe { unsafe {
let cstr = CStr::from_ptr(gst::gst_structure_get_name(self.0)); let cstr = CStr::from_ptr(gst::gst_structure_get_name(&self.0));
cstr.to_str().unwrap() cstr.to_str().unwrap()
} }
} }
@ -96,20 +200,20 @@ impl Structure {
pub fn has_field(&self, field: &str) -> bool { pub fn has_field(&self, field: &str) -> bool {
unsafe { unsafe {
let cstr = CString::new(field).unwrap(); let cstr = CString::new(field).unwrap();
gst::gst_structure_has_field(self.0, cstr.as_ptr()) == glib::GTRUE gst::gst_structure_has_field(&self.0, cstr.as_ptr()) == glib::GTRUE
} }
} }
pub fn remove_field(&mut self, field: &str) { pub fn remove_field(&mut self, field: &str) {
unsafe { unsafe {
let cstr = CString::new(field).unwrap(); let cstr = CString::new(field).unwrap();
gst::gst_structure_remove_field(self.0, cstr.as_ptr()); gst::gst_structure_remove_field(&mut self.0, cstr.as_ptr());
} }
} }
pub fn remove_all_fields(&mut self) { pub fn remove_all_fields(&mut self) {
unsafe { unsafe {
gst::gst_structure_remove_all_fields(self.0); gst::gst_structure_remove_all_fields(&mut self.0);
} }
} }
@ -123,7 +227,7 @@ impl Structure {
fn get_nth_field_name(&self, idx: u32) -> Option<&str> { fn get_nth_field_name(&self, idx: u32) -> Option<&str> {
unsafe { unsafe {
let field_name = gst::gst_structure_nth_field_name(self.0, idx); let field_name = gst::gst_structure_nth_field_name(&self.0, idx);
if field_name.is_null() { if field_name.is_null() {
return None; return None;
} }
@ -134,20 +238,10 @@ impl Structure {
} }
fn n_fields(&self) -> u32 { fn n_fields(&self) -> u32 {
unsafe { gst::gst_structure_n_fields(self.0) as u32 } unsafe { gst::gst_structure_n_fields(&self.0) as u32 }
} }
}
impl Clone for Structure { // TODO: Various operations
fn clone(&self) -> Self {
Structure(unsafe { gst::gst_structure_copy(self.0) })
}
}
impl Drop for Structure {
fn drop(&mut self) {
unsafe { gst::gst_structure_free(self.0) }
}
} }
impl fmt::Debug for Structure { impl fmt::Debug for Structure {
@ -158,7 +252,7 @@ impl fmt::Debug for Structure {
impl PartialEq for Structure { impl PartialEq for Structure {
fn eq(&self, other: &Structure) -> bool { fn eq(&self, other: &Structure) -> bool {
(unsafe { gst::gst_structure_is_equal(self.0, other.0) } == glib::GTRUE) (unsafe { gst::gst_structure_is_equal(&self.0, &other.0) } == glib::GTRUE)
} }
} }
@ -275,7 +369,7 @@ mod tests {
fn new_set_get() { fn new_set_get() {
unsafe { gst::gst_init(ptr::null_mut(), ptr::null_mut()) }; unsafe { gst::gst_init(ptr::null_mut(), ptr::null_mut()) };
let mut s = Structure::new_empty("test"); let mut s = OwnedStructure::new_empty("test");
assert_eq!(s.get_name(), "test"); assert_eq!(s.get_name(), "test");
s.set("f1", "abc"); s.set("f1", "abc");
@ -293,7 +387,7 @@ mod tests {
("f2", Value::new("bcd")), ("f2", Value::new("bcd")),
("f3", Value::new(123i32))]); ("f3", Value::new(123i32))]);
let s2 = Structure::new("test", let s2 = OwnedStructure::new("test",
&[("f1", "abc".into()), &[("f1", "abc".into()),
("f2", "bcd".into()), ("f2", "bcd".into()),
("f3", 123i32.into())]); ("f3", 123i32.into())]);