Port everything else over to glib/gobject/gstreamer-sys

This commit is contained in:
Sebastian Dröge 2017-04-10 00:29:07 +03:00
parent e4ababa98f
commit 24a10bb614
19 changed files with 509 additions and 751 deletions

View file

@ -14,9 +14,9 @@ slog = { version = "1.3", features = ["max_level_trace"] }
lazy_static = "0.2" lazy_static = "0.2"
byteorder = "1.0" byteorder = "1.0"
num-rational = { version = "0.1", default-features = false, features = [] } num-rational = { version = "0.1", default-features = false, features = [] }
glib-sys = "0.3" glib-sys = { git = "https://github.com/gtk-rs/sys.git" }
gobject-sys = "0.3" gobject-sys = { git = "https://github.com/gtk-rs/sys.git" }
gstreamer-sys = { git = "https://github.com/sdroege/gstreamer-sys.git" } gstreamer-sys = { git = "https://github.com/sdroege/gstreamer-sys.git", features = ["v1_10"] }
derivative = "1.0" derivative = "1.0"
[build-dependencies] [build-dependencies]

View file

@ -14,7 +14,7 @@ fn main() {
let gstbase = pkg_config::probe_library("gstreamer-base-1.0").unwrap(); let gstbase = pkg_config::probe_library("gstreamer-base-1.0").unwrap();
let includes = [gstreamer.include_paths, gstbase.include_paths]; let includes = [gstreamer.include_paths, gstbase.include_paths];
let files = ["src/error.c", "src/log.c", "src/source.c", "src/sink.c", "src/demuxer.c"]; let files = ["src/source.c", "src/sink.c", "src/demuxer.c"];
let mut config = gcc::Config::new(); let mut config = gcc::Config::new();
config.include("src"); config.include("src");

View file

@ -179,7 +179,10 @@ impl Adapter {
trace!(LOGGER, "Get buffer of {} bytes, copy into new buffer", size); trace!(LOGGER, "Get buffer of {} bytes, copy into new buffer", size);
let mut new = Buffer::new_with_size(size).unwrap(); let mut new = Buffer::new_with_size(size).unwrap();
{ {
let mut map = new.get_mut().unwrap().map_readwrite().unwrap(); let mut map = new.get_mut()
.unwrap()
.map_readwrite()
.unwrap();
let data = map.as_mut_slice(); let data = map.as_mut_slice();
Self::copy_data(&self.deque, self.skip, data, size); Self::copy_data(&self.deque, self.skip, data, size);
} }
@ -204,7 +207,10 @@ impl Adapter {
let mut left = size; let mut left = size;
while left > 0 { while left > 0 {
let front_size = self.deque.front().unwrap().get_size() - self.skip; let front_size = self.deque
.front()
.unwrap()
.get_size() - self.skip;
if front_size <= left { if front_size <= left {
trace!(LOGGER, trace!(LOGGER,
@ -234,15 +240,11 @@ impl Adapter {
mod tests { mod tests {
use super::*; use super::*;
use std::ptr; use std::ptr;
use std::os::raw::c_void; use gst;
fn init() { fn init() {
extern "C" {
fn gst_init(argc: *mut c_void, argv: *mut c_void);
}
unsafe { unsafe {
gst_init(ptr::null_mut(), ptr::null_mut()); gst::gst_init(ptr::null_mut(), ptr::null_mut());
} }
} }

View file

@ -8,7 +8,6 @@
use std::ptr; use std::ptr;
use std::mem; use std::mem;
use std::os::raw::c_void;
use std::slice; use std::slice;
use std::u64; use std::u64;
use std::usize; use std::usize;
@ -54,22 +53,24 @@ pub struct ReadWriteMappedBuffer {
} }
unsafe impl MiniObject for Buffer { unsafe impl MiniObject for Buffer {
unsafe fn as_ptr(&self) -> *mut c_void { type PtrType = gst::GstBuffer;
self.0 as *mut c_void
unsafe fn as_ptr(&self) -> *mut gst::GstBuffer {
self.0
} }
unsafe fn replace_ptr(&mut self, ptr: *mut c_void) { unsafe fn replace_ptr(&mut self, ptr: *mut gst::GstBuffer) {
self.0 = ptr as *mut gst::GstBuffer self.0 = ptr
} }
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self { unsafe fn new_from_ptr(ptr: *mut gst::GstBuffer) -> Self {
Buffer(ptr as *mut gst::GstBuffer) Buffer(ptr)
} }
} }
impl Buffer { impl Buffer {
pub fn new() -> GstRc<Buffer> { pub fn new() -> GstRc<Buffer> {
unsafe { GstRc::new_from_owned_ptr(gst::gst_buffer_new() as *mut c_void) } unsafe { GstRc::new_from_owned_ptr(gst::gst_buffer_new()) }
} }
pub fn new_with_size(size: usize) -> Option<GstRc<Buffer>> { pub fn new_with_size(size: usize) -> Option<GstRc<Buffer>> {
@ -77,7 +78,7 @@ impl Buffer {
if raw.is_null() { if raw.is_null() {
None None
} else { } else {
Some(unsafe { GstRc::new_from_owned_ptr(raw as *mut c_void) }) Some(unsafe { GstRc::new_from_owned_ptr(raw) })
} }
} }
@ -105,17 +106,13 @@ impl Buffer {
if raw.is_null() { if raw.is_null() {
None None
} else { } else {
Some(unsafe { GstRc::new_from_owned_ptr(raw as *mut c_void) }) Some(unsafe { GstRc::new_from_owned_ptr(raw) })
} }
} }
pub fn map_read(&self) -> Option<ReadBufferMap> { pub fn map_read(&self) -> Option<ReadBufferMap> {
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() }; let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
let res = unsafe { let res = unsafe { gst::gst_buffer_map(self.0, &mut map_info, gst::GST_MAP_READ) };
gst::gst_buffer_map(self.0,
&mut map_info as *mut gst::GstMapInfo,
gst::GST_MAP_READ)
};
if res == glib::GTRUE { if res == glib::GTRUE {
Some(ReadBufferMap { Some(ReadBufferMap {
buffer: self, buffer: self,
@ -128,11 +125,7 @@ impl Buffer {
pub fn map_readwrite(&mut self) -> Option<ReadWriteBufferMap> { pub fn map_readwrite(&mut self) -> Option<ReadWriteBufferMap> {
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() }; let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
let res = unsafe { let res = unsafe { gst::gst_buffer_map(self.0, &mut map_info, gst::GST_MAP_READWRITE) };
gst::gst_buffer_map(self.0,
&mut map_info as *mut gst::GstMapInfo,
gst::GST_MAP_READWRITE)
};
if res == glib::GTRUE { if res == glib::GTRUE {
Some(ReadWriteBufferMap { Some(ReadWriteBufferMap {
buffer: self, buffer: self,
@ -145,11 +138,7 @@ impl Buffer {
pub fn into_read_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadMappedBuffer> { pub fn into_read_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadMappedBuffer> {
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() }; let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
let res = unsafe { let res = unsafe { gst::gst_buffer_map(buffer.0, &mut map_info, gst::GST_MAP_READ) };
gst::gst_buffer_map(buffer.0,
&mut map_info as *mut gst::GstMapInfo,
gst::GST_MAP_READ)
};
if res == glib::GTRUE { if res == glib::GTRUE {
Some(ReadMappedBuffer { Some(ReadMappedBuffer {
buffer: buffer, buffer: buffer,
@ -162,11 +151,7 @@ impl Buffer {
pub fn into_readwrite_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadWriteMappedBuffer> { pub fn into_readwrite_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadWriteMappedBuffer> {
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() }; let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
let res = unsafe { let res = unsafe { gst::gst_buffer_map(buffer.0, &mut map_info, gst::GST_MAP_READWRITE) };
gst::gst_buffer_map(buffer.0,
&mut map_info as *mut gst::GstMapInfo,
gst::GST_MAP_READWRITE)
};
if res == glib::GTRUE { if res == glib::GTRUE {
Some(ReadWriteMappedBuffer { Some(ReadWriteMappedBuffer {
buffer: buffer, buffer: buffer,
@ -182,8 +167,7 @@ impl Buffer {
GstRc::new_from_owned_ptr(gst::gst_buffer_append(buffer.into_ptr() as GstRc::new_from_owned_ptr(gst::gst_buffer_append(buffer.into_ptr() as
*mut gst::GstBuffer, *mut gst::GstBuffer,
other.into_ptr() as other.into_ptr() as
*mut gst::GstBuffer) as *mut gst::GstBuffer))
*mut c_void)
} }
} }
@ -197,7 +181,7 @@ impl Buffer {
if raw.is_null() { if raw.is_null() {
None None
} else { } else {
Some(unsafe { GstRc::new_from_owned_ptr(raw as *mut c_void) }) Some(unsafe { GstRc::new_from_owned_ptr(raw) })
} }
} }
@ -386,7 +370,7 @@ impl<'a> ReadBufferMap<'a> {
impl<'a> Drop for ReadBufferMap<'a> { impl<'a> Drop for ReadBufferMap<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut gst::GstMapInfo); gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info);
} }
} }
} }
@ -412,7 +396,7 @@ impl<'a> ReadWriteBufferMap<'a> {
impl<'a> Drop for ReadWriteBufferMap<'a> { impl<'a> Drop for ReadWriteBufferMap<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut gst::GstMapInfo); gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info);
} }
} }
} }
@ -435,7 +419,7 @@ impl Drop for ReadMappedBuffer {
fn drop(&mut self) { fn drop(&mut self) {
if !self.buffer.0.is_null() { if !self.buffer.0.is_null() {
unsafe { unsafe {
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut gst::GstMapInfo); gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info);
} }
} }
} }
@ -466,7 +450,7 @@ impl Drop for ReadWriteMappedBuffer {
fn drop(&mut self) { fn drop(&mut self) {
if !self.buffer.0.is_null() { if !self.buffer.0.is_null() {
unsafe { unsafe {
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut gst::GstMapInfo); gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info);
} }
} }
} }

View file

@ -6,62 +6,52 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use libc::c_char;
use std::os::raw::c_void;
use std::ffi::CString; use std::ffi::CString;
use std::ffi::CStr; use std::ffi::CStr;
use std::fmt; use std::fmt;
use value::*; use value::*;
use utils::*;
use miniobject::*; use miniobject::*;
use glib;
use gobject;
use gst;
#[derive(Eq)] #[derive(Eq)]
pub struct Caps(*mut c_void); pub struct Caps(*mut gst::GstCaps);
unsafe impl MiniObject for Caps { unsafe impl MiniObject for Caps {
unsafe fn as_ptr(&self) -> *mut c_void { type PtrType = gst::GstCaps;
unsafe fn as_ptr(&self) -> *mut gst::GstCaps {
self.0 self.0
} }
unsafe fn replace_ptr(&mut self, ptr: *mut c_void) { unsafe fn replace_ptr(&mut self, ptr: *mut gst::GstCaps) {
self.0 = ptr self.0 = ptr
} }
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self { unsafe fn new_from_ptr(ptr: *mut gst::GstCaps) -> Self {
Caps(ptr) Caps(ptr)
} }
} }
impl Caps { impl Caps {
pub fn new_empty() -> GstRc<Self> { pub fn new_empty() -> GstRc<Self> {
extern "C" { unsafe { GstRc::new_from_owned_ptr(gst::gst_caps_new_empty()) }
fn gst_caps_new_empty() -> *mut c_void;
}
unsafe { GstRc::new_from_owned_ptr(gst_caps_new_empty()) }
} }
pub fn new_any() -> GstRc<Self> { pub fn new_any() -> GstRc<Self> {
extern "C" { unsafe { GstRc::new_from_owned_ptr(gst::gst_caps_new_any()) }
fn gst_caps_new_any() -> *mut c_void;
}
unsafe { GstRc::new_from_owned_ptr(gst_caps_new_any()) }
} }
pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> GstRc<Self> { pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> GstRc<Self> {
extern "C" {
fn gst_caps_append_structure(caps: *mut c_void, structure: *mut c_void);
fn gst_structure_new_empty(name: *const c_char) -> *mut c_void;
}
let mut caps = Caps::new_empty(); let mut caps = Caps::new_empty();
let name_cstr = CString::new(name).unwrap(); let name_cstr = CString::new(name).unwrap();
let structure = unsafe { gst_structure_new_empty(name_cstr.as_ptr()) }; let structure = unsafe { gst::gst_structure_new_empty(name_cstr.as_ptr()) };
unsafe { unsafe {
gst_caps_append_structure(caps.as_ptr(), structure); gst::gst_caps_append_structure((*caps).0, structure);
} }
caps.get_mut().unwrap().set_simple(values); caps.get_mut().unwrap().set_simple(values);
@ -70,14 +60,10 @@ impl Caps {
} }
pub fn from_string(value: &str) -> Option<GstRc<Self>> { pub fn from_string(value: &str) -> Option<GstRc<Self>> {
extern "C" {
fn gst_caps_from_string(value: *const c_char) -> *mut c_void;
}
let value_cstr = CString::new(value).unwrap(); let value_cstr = CString::new(value).unwrap();
unsafe { unsafe {
let caps_ptr = gst_caps_from_string(value_cstr.as_ptr()); let caps_ptr = gst::gst_caps_from_string(value_cstr.as_ptr());
if caps_ptr.is_null() { if caps_ptr.is_null() {
None None
@ -88,30 +74,21 @@ impl Caps {
} }
pub fn set_simple(&mut self, values: &[(&str, &Value)]) { pub fn set_simple(&mut self, values: &[(&str, &Value)]) {
extern "C" {
fn gst_caps_set_value(caps: *mut c_void, name: *const c_char, value: *const GValue);
}
for value in values { for value in values {
let name_cstr = CString::new(value.0).unwrap(); let name_cstr = CString::new(value.0).unwrap();
let mut gvalue = value.1.to_gvalue();
unsafe { unsafe {
gst_caps_set_value(self.0, name_cstr.as_ptr(), &mut gvalue as *mut GValue); let mut gvalue = value.1.to_gvalue();
gst::gst_caps_set_value(self.0, name_cstr.as_ptr(), &mut gvalue);
gobject::g_value_unset(&mut gvalue);
} }
} }
} }
pub fn to_string(&self) -> String { pub fn to_string(&self) -> String {
extern "C" {
fn gst_caps_to_string(caps: *mut c_void) -> *mut c_char;
fn g_free(ptr: *mut c_char);
}
unsafe { unsafe {
let ptr = gst_caps_to_string(self.0); let ptr = gst::gst_caps_to_string(self.0);
let s = CStr::from_ptr(ptr).to_str().unwrap().into(); let s = CStr::from_ptr(ptr).to_str().unwrap().into();
g_free(ptr); glib::g_free(ptr as glib::gpointer);
s s
} }
@ -126,11 +103,7 @@ impl fmt::Debug for Caps {
impl PartialEq for Caps { impl PartialEq for Caps {
fn eq(&self, other: &Caps) -> bool { fn eq(&self, other: &Caps) -> bool {
extern "C" { (unsafe { gst::gst_caps_is_equal(self.0, other.0) } == glib::GTRUE)
fn gst_caps_is_equal(a: *const c_void, b: *const c_void) -> GBoolean;
}
unsafe { gst_caps_is_equal(self.0, other.0).to_bool() }
} }
} }
@ -141,15 +114,10 @@ unsafe impl Send for Caps {}
mod tests { mod tests {
use super::*; use super::*;
use std::ptr; use std::ptr;
use std::os::raw::c_void;
fn init() { fn init() {
extern "C" {
fn gst_init(argc: *mut c_void, argv: *mut c_void);
}
unsafe { unsafe {
gst_init(ptr::null_mut(), ptr::null_mut()); gst::gst_init(ptr::null_mut(), ptr::null_mut());
} }
} }

View file

@ -28,6 +28,9 @@ use log::*;
use caps::Caps; use caps::Caps;
use plugin::Plugin; use plugin::Plugin;
use glib;
use gst;
pub type StreamIndex = u32; pub type StreamIndex = u32;
#[derive(Debug)] #[derive(Debug)]
@ -89,14 +92,14 @@ impl Stream {
} }
pub struct DemuxerWrapper { pub struct DemuxerWrapper {
raw: *mut c_void, raw: *mut gst::GstElement,
logger: Logger, logger: Logger,
demuxer: Mutex<Box<Demuxer>>, demuxer: Mutex<Box<Demuxer>>,
panicked: AtomicBool, panicked: AtomicBool,
} }
impl DemuxerWrapper { impl DemuxerWrapper {
fn new(raw: *mut c_void, demuxer: Box<Demuxer>) -> DemuxerWrapper { fn new(raw: *mut gst::GstElement, demuxer: Box<Demuxer>) -> DemuxerWrapper {
DemuxerWrapper { DemuxerWrapper {
raw: raw, raw: raw,
logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }), logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }),
@ -164,44 +167,44 @@ impl DemuxerWrapper {
} }
fn get_position(&self, position: &mut u64) -> GBoolean { fn get_position(&self, position: &mut u64) -> glib::gboolean {
let demuxer = &self.demuxer.lock().unwrap(); let demuxer = &self.demuxer.lock().unwrap();
match demuxer.get_position() { match demuxer.get_position() {
None => { None => {
trace!(self.logger, "Got no position"); trace!(self.logger, "Got no position");
*position = u64::MAX; *position = u64::MAX;
GBoolean::False glib::GFALSE
} }
Some(pos) => { Some(pos) => {
trace!(self.logger, "Returning position {}", pos); trace!(self.logger, "Returning position {}", pos);
*position = pos; *position = pos;
GBoolean::True glib::GTRUE
} }
} }
} }
fn get_duration(&self, duration: &mut u64) -> GBoolean { fn get_duration(&self, duration: &mut u64) -> glib::gboolean {
let demuxer = &self.demuxer.lock().unwrap(); let demuxer = &self.demuxer.lock().unwrap();
match demuxer.get_duration() { match demuxer.get_duration() {
None => { None => {
trace!(self.logger, "Got no duration"); trace!(self.logger, "Got no duration");
*duration = u64::MAX; *duration = u64::MAX;
GBoolean::False glib::GFALSE
} }
Some(dur) => { Some(dur) => {
trace!(self.logger, "Returning duration {}", dur); trace!(self.logger, "Returning duration {}", dur);
*duration = dur; *duration = dur;
GBoolean::True glib::GTRUE
} }
} }
} }
fn seek(&self, start: u64, stop: u64, offset: &mut u64) -> bool { fn seek(&self, start: u64, stop: u64, offset: &mut u64) -> bool {
extern "C" { extern "C" {
fn gst_rs_demuxer_stream_eos(raw: *mut c_void, index: u32); fn gst_rs_demuxer_stream_eos(raw: *mut gst::GstElement, index: u32);
}; };
let stop = if stop == u64::MAX { None } else { Some(stop) }; let stop = if stop == u64::MAX { None } else { Some(stop) };
@ -246,19 +249,19 @@ impl DemuxerWrapper {
fn handle_buffer(&self, buffer: GstRc<Buffer>) -> GstFlowReturn { fn handle_buffer(&self, buffer: GstRc<Buffer>) -> GstFlowReturn {
extern "C" { extern "C" {
fn gst_rs_demuxer_stream_eos(raw: *mut c_void, index: u32); fn gst_rs_demuxer_stream_eos(raw: *mut gst::GstElement, index: u32);
fn gst_rs_demuxer_add_stream(raw: *mut c_void, fn gst_rs_demuxer_add_stream(raw: *mut gst::GstElement,
index: u32, index: u32,
caps: *const c_void, caps: *const gst::GstCaps,
stream_id: *const c_char); stream_id: *const c_char);
fn gst_rs_demuxer_added_all_streams(raw: *mut c_void); fn gst_rs_demuxer_added_all_streams(raw: *mut gst::GstElement);
// fn gst_rs_demuxer_remove_all_streams(raw: *mut c_void); // fn gst_rs_demuxer_remove_all_streams(raw: *mut gst::GstElement);
fn gst_rs_demuxer_stream_format_changed(raw: *mut c_void, fn gst_rs_demuxer_stream_format_changed(raw: *mut gst::GstElement,
index: u32, index: u32,
caps: *const c_void); caps: *const gst::GstCaps);
fn gst_rs_demuxer_stream_push_buffer(raw: *mut c_void, fn gst_rs_demuxer_stream_push_buffer(raw: *mut gst::GstElement,
index: u32, index: u32,
buffer: *mut c_void) buffer: *mut gst::GstBuffer)
-> GstFlowReturn; -> GstFlowReturn;
}; };
@ -379,7 +382,7 @@ impl DemuxerWrapper {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn demuxer_new(demuxer: *mut c_void, pub unsafe extern "C" fn demuxer_new(demuxer: *mut gst::GstElement,
create_instance: fn(Element) -> Box<Demuxer>) create_instance: fn(Element) -> Box<Demuxer>)
-> *mut DemuxerWrapper { -> *mut DemuxerWrapper {
let instance = create_instance(Element::new(demuxer)); let instance = create_instance(Element::new(demuxer));
@ -394,40 +397,52 @@ pub unsafe extern "C" fn demuxer_drop(ptr: *mut DemuxerWrapper) {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn demuxer_start(ptr: *const DemuxerWrapper, pub unsafe extern "C" fn demuxer_start(ptr: *const DemuxerWrapper,
upstream_size: u64, upstream_size: u64,
random_access: GBoolean) random_access: glib::gboolean)
-> GBoolean { -> glib::gboolean {
let wrap: &DemuxerWrapper = &*ptr; let wrap: &DemuxerWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
GBoolean::from_bool(wrap.start(upstream_size, random_access.to_bool())) if wrap.start(upstream_size, random_access != glib::GFALSE) {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn demuxer_stop(ptr: *const DemuxerWrapper) -> GBoolean { pub unsafe extern "C" fn demuxer_stop(ptr: *const DemuxerWrapper) -> glib::gboolean {
let wrap: &DemuxerWrapper = &*ptr; let wrap: &DemuxerWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::True, { panic_to_error!(wrap, glib::GTRUE, {
GBoolean::from_bool(wrap.stop()) if wrap.stop() {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn demuxer_is_seekable(ptr: *const DemuxerWrapper) -> GBoolean { pub unsafe extern "C" fn demuxer_is_seekable(ptr: *const DemuxerWrapper) -> glib::gboolean {
let wrap: &DemuxerWrapper = &*ptr; let wrap: &DemuxerWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
GBoolean::from_bool(wrap.is_seekable()) if wrap.is_seekable() {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn demuxer_get_position(ptr: *const DemuxerWrapper, pub unsafe extern "C" fn demuxer_get_position(ptr: *const DemuxerWrapper,
position: *mut u64) position: *mut u64)
-> GBoolean { -> glib::gboolean {
let wrap: &DemuxerWrapper = &*ptr; let wrap: &DemuxerWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
let position = &mut *position; let position = &mut *position;
wrap.get_position(position) wrap.get_position(position)
}) })
@ -436,10 +451,10 @@ pub unsafe extern "C" fn demuxer_get_position(ptr: *const DemuxerWrapper,
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn demuxer_get_duration(ptr: *const DemuxerWrapper, pub unsafe extern "C" fn demuxer_get_duration(ptr: *const DemuxerWrapper,
duration: *mut u64) duration: *mut u64)
-> GBoolean { -> glib::gboolean {
let wrap: &DemuxerWrapper = &*ptr; let wrap: &DemuxerWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
let duration = &mut *duration; let duration = &mut *duration;
wrap.get_duration(duration) wrap.get_duration(duration)
}) })
@ -450,20 +465,24 @@ pub unsafe extern "C" fn demuxer_seek(ptr: *mut DemuxerWrapper,
start: u64, start: u64,
stop: u64, stop: u64,
offset: *mut u64) offset: *mut u64)
-> GBoolean { -> glib::gboolean {
let wrap: &mut DemuxerWrapper = &mut *ptr; let wrap: &mut DemuxerWrapper = &mut *ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
let offset = &mut *offset; let offset = &mut *offset;
GBoolean::from_bool(wrap.seek(start, stop, offset)) if wrap.seek(start, stop, offset) {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn demuxer_handle_buffer(ptr: *mut DemuxerWrapper, pub unsafe extern "C" fn demuxer_handle_buffer(ptr: *mut DemuxerWrapper,
buffer: *mut c_void) buffer: *mut gst::GstBuffer)
-> GstFlowReturn { -> GstFlowReturn {
let wrap: &mut DemuxerWrapper = &mut *ptr; let wrap: &mut DemuxerWrapper = &mut *ptr;
@ -496,7 +515,7 @@ pub struct DemuxerInfo<'a> {
pub fn demuxer_register(plugin: &Plugin, demuxer_info: &DemuxerInfo) { pub fn demuxer_register(plugin: &Plugin, demuxer_info: &DemuxerInfo) {
extern "C" { extern "C" {
fn gst_rs_demuxer_register(plugin: *const c_void, fn gst_rs_demuxer_register(plugin: *const gst::GstPlugin,
name: *const c_char, name: *const c_char,
long_name: *const c_char, long_name: *const c_char,
description: *const c_char, description: *const c_char,
@ -504,9 +523,9 @@ pub fn demuxer_register(plugin: &Plugin, demuxer_info: &DemuxerInfo) {
author: *const c_char, author: *const c_char,
rank: i32, rank: i32,
create_instance: *const c_void, create_instance: *const c_void,
input_caps: *const c_void, input_caps: *const gst::GstCaps,
output_caps: *const c_void) output_caps: *const gst::GstCaps)
-> GBoolean; -> glib::gboolean;
} }
let cname = CString::new(demuxer_info.name).unwrap(); let cname = CString::new(demuxer_info.name).unwrap();

View file

@ -1,19 +0,0 @@
/* 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.
*/
#include <gst/gst.h>
void
gst_rs_element_error (GstElement * element, GQuark error_domain,
gint error_code, const gchar * message, const gchar * debug,
const gchar * file, const gchar * function, guint line)
{
gst_element_message_full (element, GST_MESSAGE_ERROR, error_domain,
error_code, g_strdup (message), g_strdup (debug), file, function, line);
}

View file

@ -6,8 +6,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use libc::c_char;
use std::os::raw::c_void;
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr;
use std::error::Error; use std::error::Error;
@ -19,6 +17,9 @@ use url::Url;
use utils::*; use utils::*;
use glib;
use gst;
#[macro_export] #[macro_export]
macro_rules! error_msg( macro_rules! error_msg(
// Plain strings // Plain strings
@ -61,20 +62,12 @@ pub trait ToGError {
fn to_gerror(&self) -> (u32, i32); fn to_gerror(&self) -> (u32, i32);
} }
pub fn gst_library_error_domain() -> u32 { pub fn gst_library_error_domain() -> glib::GQuark {
extern "C" { unsafe { gst::gst_library_error_quark() }
fn gst_library_error_quark() -> u32;
}
unsafe { gst_library_error_quark() }
} }
pub fn gst_resource_error_domain() -> u32 { pub fn gst_resource_error_domain() -> glib::GQuark {
extern "C" { unsafe { gst::gst_resource_error_quark() }
fn gst_resource_error_quark() -> u32;
}
unsafe { gst_resource_error_quark() }
} }
#[derive(Debug)] #[derive(Debug)]
@ -110,18 +103,7 @@ impl ErrorMessage {
} }
pub unsafe fn post(&self, element: *mut c_void) { pub unsafe fn post(&self, element: *mut gst::GstElement) {
extern "C" {
fn gst_rs_element_error(sink: *mut c_void,
error_domain: u32,
error_code: i32,
message: *const c_char,
debug: *const c_char,
filename: *const c_char,
function: *const c_char,
line: u32);
}
let ErrorMessage { error_domain, let ErrorMessage { error_domain,
error_code, error_code,
ref message, ref message,
@ -142,14 +124,15 @@ impl ErrorMessage {
let function_cstr = CString::new(function.as_bytes()).unwrap(); let function_cstr = CString::new(function.as_bytes()).unwrap();
let function_ptr = function_cstr.as_ptr(); let function_ptr = function_cstr.as_ptr();
gst_rs_element_error(element, gst::gst_element_message_full(element,
error_domain, gst::GST_MESSAGE_ERROR,
error_code, error_domain,
message_ptr, error_code,
debug_ptr, glib::g_strdup(message_ptr),
file_ptr, glib::g_strdup(debug_ptr),
function_ptr, file_ptr,
line); function_ptr,
line as i32);
} }
} }
@ -233,27 +216,18 @@ impl UriError {
&self.error_kind &self.error_kind
} }
pub unsafe fn into_gerror(self, err: *mut c_void) { pub unsafe fn into_gerror(self, err: *mut *mut glib::GError) {
extern "C" {
fn g_set_error_literal(err: *mut c_void,
domain: u32,
code: i32,
message: *const c_char);
fn gst_uri_error_quark() -> u32;
}
if let Some(msg) = self.message { if let Some(msg) = self.message {
let cmsg = CString::new(msg.as_str()).unwrap(); let cmsg = CString::new(msg.as_str()).unwrap();
g_set_error_literal(err, glib::g_set_error_literal(err,
gst_uri_error_quark(), gst::gst_uri_error_quark(),
self.error_kind as i32, self.error_kind as i32,
cmsg.as_ptr()); cmsg.as_ptr());
} else { } else {
g_set_error_literal(err, glib::g_set_error_literal(err,
gst_uri_error_quark(), gst::gst_uri_error_quark(),
self.error_kind as i32, self.error_kind as i32,
ptr::null()); ptr::null());
} }
} }
} }

View file

@ -19,9 +19,9 @@ extern crate byteorder;
extern crate num_rational; extern crate num_rational;
#[macro_use] #[macro_use]
extern crate derivative; extern crate derivative;
extern crate gobject_sys as gobject; pub extern crate gobject_sys as gobject;
extern crate glib_sys as glib; pub extern crate glib_sys as glib;
extern crate gstreamer_sys as gst; pub extern crate gstreamer_sys as gst;
#[macro_use] #[macro_use]
pub mod utils; pub mod utils;
@ -41,3 +41,9 @@ pub mod bytes;
pub mod tags; pub mod tags;
pub mod streams; pub mod streams;
pub mod miniobject; pub mod miniobject;
pub mod ffi {
pub use glib;
pub use gobject;
pub use gst;
}

View file

@ -1,19 +0,0 @@
/* 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.
*/
#include <gst/gst.h>
void
gst_rs_debug_log (GstDebugCategory * category,
GstDebugLevel level,
const gchar * file,
const gchar * function, gint line, GObject * object, const gchar * message)
{
gst_debug_log (category, level, file, function, line, object, "%s", message);
}

View file

@ -6,19 +6,21 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::os::raw::c_void;
use libc::c_char; use libc::c_char;
use std::ffi::CString; use std::ffi::CString;
use slog::{Drain, Record, OwnedKeyValueList, Never, Level}; use slog::{Drain, Record, OwnedKeyValueList, Never, Level};
use std::fmt; use std::fmt;
use std::ptr; use std::ptr;
use std::mem;
use utils::Element; use utils::Element;
#[derive(Debug)] use gobject;
use gst;
pub struct GstDebugDrain { pub struct GstDebugDrain {
category: *const c_void, category: *mut gst::GstDebugCategory,
element: *const c_void, element: gobject::GWeakRef,
} }
impl GstDebugDrain { impl GstDebugDrain {
@ -31,7 +33,7 @@ impl GstDebugDrain {
fn _gst_debug_category_new(name: *const c_char, fn _gst_debug_category_new(name: *const c_char,
color: u32, color: u32,
description: *const c_char) description: *const c_char)
-> *const c_void; -> *mut gst::GstDebugCategory;
} }
let name_cstr = CString::new(name.as_bytes()).unwrap(); let name_cstr = CString::new(name.as_bytes()).unwrap();
@ -47,18 +49,14 @@ impl GstDebugDrain {
None => ptr::null(), None => ptr::null(),
}; };
let drain = GstDebugDrain { let mut drain = GstDebugDrain {
category: category, category: category,
element: ptr::null(), element: unsafe { mem::zeroed() },
}; };
extern "C" {
fn g_weak_ref_set(weak_ref: &*const c_void, obj: *const c_void);
}
if !element.is_null() { if !element.is_null() {
unsafe { unsafe {
g_weak_ref_set(&drain.element, element); gobject::g_weak_ref_set(&mut drain.element, element as *mut gobject::GObject);
} }
} }
@ -68,14 +66,8 @@ impl GstDebugDrain {
impl Drop for GstDebugDrain { impl Drop for GstDebugDrain {
fn drop(&mut self) { fn drop(&mut self) {
extern "C" { unsafe {
fn g_weak_ref_clear(weak_ref: &*const c_void); gobject::g_weak_ref_clear(&mut self.element);
}
if !self.element.is_null() {
unsafe {
g_weak_ref_clear(&self.element);
}
} }
} }
} }
@ -84,30 +76,17 @@ impl Drain for GstDebugDrain {
type Error = Never; type Error = Never;
fn log(&self, record: &Record, _: &OwnedKeyValueList) -> Result<(), Never> { fn log(&self, record: &Record, _: &OwnedKeyValueList) -> Result<(), Never> {
extern "C" {
fn gst_rs_debug_log(category: *const c_void,
level: u32,
file: *const c_char,
function: *const c_char,
line: u32,
object: *const c_void,
message: *const c_char);
fn gst_debug_category_get_threshold(category: *const c_void) -> u32;
fn g_weak_ref_get(weak_ref: &*const c_void) -> *const c_void;
fn gst_object_unref(obj: *const c_void);
}
let level = match record.level() { let level = match record.level() {
Level::Critical | Level::Error => 1, Level::Critical | Level::Error => gst::GST_LEVEL_ERROR,
Level::Warning => 2, Level::Warning => gst::GST_LEVEL_WARNING,
Level::Info => 4, Level::Info => gst::GST_LEVEL_INFO,
Level::Debug => 5, Level::Debug => gst::GST_LEVEL_DEBUG,
Level::Trace => 7, Level::Trace => gst::GST_LEVEL_TRACE,
}; };
let threshold = unsafe { gst_debug_category_get_threshold(self.category) }; let threshold = unsafe { gst::gst_debug_category_get_threshold(self.category) };
if level > threshold { if level as u32 > threshold as u32 {
return Ok(()); return Ok(());
} }
@ -119,22 +98,19 @@ impl Drain for GstDebugDrain {
let message_cstr = CString::new(fmt::format(record.msg()).as_bytes()).unwrap(); let message_cstr = CString::new(fmt::format(record.msg()).as_bytes()).unwrap();
unsafe { unsafe {
let element = if self.element.is_null() { let element = gobject::g_weak_ref_get(&self.element as *const gobject::GWeakRef as
ptr::null() *mut gobject::GWeakRef);
} else {
g_weak_ref_get(&self.element)
};
gst_rs_debug_log(self.category, gst::gst_debug_log(self.category,
level, level,
file_cstr.as_ptr(), file_cstr.as_ptr(),
function_cstr.as_ptr(), function_cstr.as_ptr(),
record.line(), record.line() as i32,
element, element as *mut gobject::GObject,
message_cstr.as_ptr()); message_cstr.as_ptr());
if !element.is_null() { if !element.is_null() {
gst_object_unref(element); gst::gst_object_unref(element as *mut gst::GstObject);
} }
} }

View file

@ -6,10 +6,11 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::os::raw::c_void;
use std::{fmt, ops, borrow, ptr}; use std::{fmt, ops, borrow, ptr};
use std::marker::PhantomData; use std::marker::PhantomData;
use utils::*;
use glib;
use gst;
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct GstRc<T: MiniObject> { pub struct GstRc<T: MiniObject> {
@ -18,31 +19,24 @@ pub struct GstRc<T: MiniObject> {
impl<T: MiniObject> GstRc<T> { impl<T: MiniObject> GstRc<T> {
unsafe fn new(obj: T, owned: bool) -> Self { unsafe fn new(obj: T, owned: bool) -> Self {
extern "C" {
fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void;
}
assert!(!obj.as_ptr().is_null()); assert!(!obj.as_ptr().is_null());
if !owned { if !owned {
gst_mini_object_ref(obj.as_ptr()); gst::gst_mini_object_ref(obj.as_ptr() as *mut gst::GstMiniObject);
} }
GstRc { obj: obj } GstRc { obj: obj }
} }
pub unsafe fn new_from_owned_ptr(ptr: *mut c_void) -> Self { pub unsafe fn new_from_owned_ptr(ptr: *mut T::PtrType) -> Self {
Self::new(T::new_from_ptr(ptr), true) Self::new(T::new_from_ptr(ptr), true)
} }
pub unsafe fn new_from_unowned_ptr(ptr: *mut c_void) -> Self { pub unsafe fn new_from_unowned_ptr(ptr: *mut T::PtrType) -> Self {
Self::new(T::new_from_ptr(ptr), false) Self::new(T::new_from_ptr(ptr), false)
} }
pub fn make_mut(&mut self) -> &mut T { pub fn make_mut(&mut self) -> &mut T {
extern "C" {
fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void;
}
unsafe { unsafe {
let ptr = self.obj.as_ptr(); let ptr = self.obj.as_ptr();
@ -50,7 +44,9 @@ impl<T: MiniObject> GstRc<T> {
return &mut self.obj; return &mut self.obj;
} }
self.obj.replace_ptr(gst_mini_object_make_writable(ptr)); self.obj.replace_ptr(gst::gst_mini_object_make_writable(ptr as
*mut gst::GstMiniObject) as
*mut T::PtrType);
assert!(self.is_writable()); assert!(self.is_writable());
&mut self.obj &mut self.obj
@ -66,20 +62,20 @@ impl<T: MiniObject> GstRc<T> {
} }
pub fn copy(&self) -> Self { pub fn copy(&self) -> Self {
extern "C" { unsafe {
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void; GstRc::new_from_owned_ptr(gst::gst_mini_object_copy(self.obj.as_ptr() as
*const gst::GstMiniObject) as
*mut T::PtrType)
} }
unsafe { GstRc::new_from_owned_ptr(gst_mini_object_copy(self.obj.as_ptr())) }
} }
fn is_writable(&self) -> bool { fn is_writable(&self) -> bool {
extern "C" { (unsafe {
fn gst_mini_object_is_writable(obj: *mut c_void) -> GBoolean; gst::gst_mini_object_is_writable(self.as_ptr() as *const gst::GstMiniObject)
} } == glib::GTRUE)
unsafe { gst_mini_object_is_writable(self.as_ptr()).to_bool() }
} }
pub unsafe fn into_ptr(mut self) -> *mut c_void { pub unsafe fn into_ptr(mut self) -> *mut T::PtrType {
self.obj.swap_ptr(ptr::null_mut()) self.obj.swap_ptr(ptr::null_mut())
} }
} }
@ -111,13 +107,9 @@ impl<T: MiniObject> Clone for GstRc<T> {
impl<T: MiniObject> Drop for GstRc<T> { impl<T: MiniObject> Drop for GstRc<T> {
fn drop(&mut self) { fn drop(&mut self) {
extern "C" {
fn gst_mini_object_unref(obj: *mut c_void) -> *mut c_void;
}
unsafe { unsafe {
if !self.obj.as_ptr().is_null() { if !self.obj.as_ptr().is_null() {
gst_mini_object_unref(self.obj.as_ptr()); gst::gst_mini_object_unref(self.obj.as_ptr() as *mut gst::GstMiniObject);
} }
} }
} }
@ -134,16 +126,18 @@ impl<T: MiniObject + fmt::Display> fmt::Display for GstRc<T> {
// NOTE: Reference counting must not happen in here // NOTE: Reference counting must not happen in here
pub unsafe trait MiniObject { pub unsafe trait MiniObject {
unsafe fn as_ptr(&self) -> *mut c_void; type PtrType;
unsafe fn replace_ptr(&mut self, ptr: *mut c_void);
unsafe fn swap_ptr(&mut self, new_ptr: *mut c_void) -> *mut c_void { unsafe fn as_ptr(&self) -> *mut Self::PtrType;
unsafe fn replace_ptr(&mut self, ptr: *mut Self::PtrType);
unsafe fn swap_ptr(&mut self, new_ptr: *mut Self::PtrType) -> *mut Self::PtrType {
let ptr = self.as_ptr(); let ptr = self.as_ptr();
self.replace_ptr(new_ptr); self.replace_ptr(new_ptr);
ptr ptr
} }
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self; unsafe fn new_from_ptr(ptr: *mut Self::PtrType) -> Self;
} }
impl<'a, T: MiniObject> From<&'a T> for GstRc<T> { impl<'a, T: MiniObject> From<&'a T> for GstRc<T> {
@ -159,19 +153,19 @@ impl<'a, T: MiniObject> From<&'a mut T> for GstRc<T> {
} }
#[repr(C)] #[repr(C)]
pub struct GstRefPtr(*mut c_void); pub struct GstRefPtr<T: MiniObject>(*mut T::PtrType);
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct GstRef<'a, T: MiniObject> { pub struct GstRef<'a, T: 'a + MiniObject> {
obj: T, obj: T,
#[allow(dead_code)] #[allow(dead_code)]
phantom: PhantomData<&'a GstRefPtr>, phantom: PhantomData<&'a GstRefPtr<T>>,
} }
impl<'a, T: MiniObject> GstRef<'a, T> { impl<'a, T: MiniObject> GstRef<'a, T> {
pub unsafe fn new(ptr: &'a GstRefPtr) -> GstRef<'a, T> { pub unsafe fn new(ptr: &'a GstRefPtr<T>) -> GstRef<'a, T> {
GstRef { GstRef {
obj: T::new_from_ptr(ptr.0), obj: T::new_from_ptr(ptr.0 as *mut T::PtrType),
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -185,20 +179,20 @@ impl<'a, T: MiniObject> GstRef<'a, T> {
} }
pub fn copy(&self) -> GstRc<T> { pub fn copy(&self) -> GstRc<T> {
extern "C" { unsafe {
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void; GstRc::new_from_owned_ptr(gst::gst_mini_object_copy(self.obj.as_ptr() as
*const gst::GstMiniObject) as
*mut T::PtrType)
} }
unsafe { GstRc::new_from_owned_ptr(gst_mini_object_copy(self.obj.as_ptr())) }
} }
fn is_writable(&self) -> bool { fn is_writable(&self) -> bool {
extern "C" { (unsafe {
fn gst_mini_object_is_writable(obj: *mut c_void) -> GBoolean; gst::gst_mini_object_is_writable(self.as_ptr() as *const gst::GstMiniObject)
} } == glib::GTRUE)
unsafe { gst_mini_object_is_writable(self.as_ptr()).to_bool() }
} }
pub unsafe fn into_ptr(mut self) -> *mut c_void { pub unsafe fn into_ptr(mut self) -> *mut T::PtrType {
self.obj.swap_ptr(ptr::null_mut()) self.obj.swap_ptr(ptr::null_mut())
} }
} }

View file

@ -6,16 +6,16 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::os::raw::c_void; use gst;
pub struct Plugin(*const c_void); pub struct Plugin(*mut gst::GstPlugin);
impl Plugin { impl Plugin {
pub unsafe fn new(plugin: *const c_void) -> Plugin { pub unsafe fn new(plugin: *mut gst::GstPlugin) -> Plugin {
Plugin(plugin) Plugin(plugin)
} }
pub unsafe fn as_ptr(&self) -> *const c_void { pub unsafe fn as_ptr(&self) -> *mut gst::GstPlugin {
self.0 self.0
} }
} }
@ -26,47 +26,41 @@ macro_rules! plugin_define(
$version:expr, $license:expr, $source:expr, $version:expr, $license:expr, $source:expr,
$package:expr, $origin:expr, $release_datetime:expr) => { $package:expr, $origin:expr, $release_datetime:expr) => {
pub mod plugin_desc { pub mod plugin_desc {
use std::os::raw::c_void;
use $crate::utils::GBoolean;
use $crate::plugin::Plugin; use $crate::plugin::Plugin;
use $crate::ffi::gst;
use $crate::ffi::glib;
// Not using c_char here because it requires the libc crate
#[allow(non_camel_case_types)]
type c_char = i8;
#[repr(C)] #[repr(C)]
pub struct GstPluginDesc { pub struct GstPluginDesc(gst::GstPluginDesc);
major_version: i32,
minor_version: i32,
name: *const u8,
description: *const u8,
plugin_init: unsafe extern "C" fn(plugin: *const c_void) -> GBoolean,
version: *const u8,
license: *const u8,
source: *const u8,
package: *const u8,
origin: *const u8,
release_datetime: *const u8,
_gst_reserved: [usize; 4],
}
unsafe impl Sync for GstPluginDesc {} unsafe impl Sync for GstPluginDesc {}
#[no_mangle] #[no_mangle]
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
pub static gst_plugin_desc: GstPluginDesc = GstPluginDesc { pub static gst_plugin_desc: GstPluginDesc = GstPluginDesc(gst::GstPluginDesc {
major_version: 1, major_version: 1,
minor_version: 10, minor_version: 10,
name: $name as *const u8, name: $name as *const u8 as *const c_char,
description: $description as *const u8, description: $description as *const u8 as *const c_char,
plugin_init: plugin_init_trampoline, plugin_init: Some(plugin_init_trampoline),
version: $version as *const u8, version: $version as *const u8 as *const c_char,
license: $license as *const u8, license: $license as *const u8 as *const c_char,
source: $source as *const u8, source: $source as *const u8 as *const c_char,
package: $package as *const u8, package: $package as *const u8 as *const c_char,
origin: $origin as *const u8, origin: $origin as *const u8 as *const c_char,
release_datetime: $release_datetime as *const u8, release_datetime: $release_datetime as *const u8 as *const c_char,
_gst_reserved: [0, 0, 0, 0], _gst_reserved: [0 as glib::gpointer; 4],
}; });
unsafe extern "C" fn plugin_init_trampoline(plugin: *const c_void) -> GBoolean { unsafe extern "C" fn plugin_init_trampoline(plugin: *mut gst::GstPlugin) -> glib::gboolean {
GBoolean::from_bool(super::$plugin_init(&Plugin::new(plugin))) if super::$plugin_init(&Plugin::new(plugin)) {
glib::GTRUE
} else {
glib::GFALSE
}
} }
} }
}; };

View file

@ -28,6 +28,9 @@ use miniobject::*;
use log::*; use log::*;
use plugin::Plugin; use plugin::Plugin;
use glib;
use gst;
#[derive(Debug)] #[derive(Debug)]
pub enum SinkError { pub enum SinkError {
Failure, Failure,
@ -50,7 +53,7 @@ impl ToGError for SinkError {
} }
pub struct SinkWrapper { pub struct SinkWrapper {
raw: *mut c_void, raw: *mut gst::GstElement,
logger: Logger, logger: Logger,
uri: Mutex<(Option<Url>, bool)>, uri: Mutex<(Option<Url>, bool)>,
uri_validator: Box<UriValidator>, uri_validator: Box<UriValidator>,
@ -68,7 +71,7 @@ pub trait Sink {
} }
impl SinkWrapper { impl SinkWrapper {
fn new(raw: *mut c_void, sink: Box<Sink>) -> SinkWrapper { fn new(raw: *mut gst::GstElement, sink: Box<Sink>) -> SinkWrapper {
SinkWrapper { SinkWrapper {
raw: raw, raw: raw,
logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }), logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }),
@ -141,7 +144,10 @@ impl SinkWrapper {
Err(ref msg) => { Err(ref msg) => {
error!(self.logger, "Failed to start: {:?}", msg); error!(self.logger, "Failed to start: {:?}", msg);
self.uri.lock().unwrap().1 = false; self.uri
.lock()
.unwrap()
.1 = false;
self.post_message(msg); self.post_message(msg);
false false
} }
@ -156,7 +162,10 @@ impl SinkWrapper {
match sink.stop() { match sink.stop() {
Ok(..) => { Ok(..) => {
trace!(self.logger, "Stopped successfully"); trace!(self.logger, "Stopped successfully");
self.uri.lock().unwrap().1 = false; self.uri
.lock()
.unwrap()
.1 = false;
true true
} }
Err(ref msg) => { Err(ref msg) => {
@ -195,7 +204,7 @@ impl SinkWrapper {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sink_new(sink: *mut c_void, pub unsafe extern "C" fn sink_new(sink: *mut gst::GstElement,
create_instance: fn(Element) -> Box<Sink>) create_instance: fn(Element) -> Box<Sink>)
-> *mut SinkWrapper { -> *mut SinkWrapper {
let instance = create_instance(Element::new(sink)); let instance = create_instance(Element::new(sink));
@ -210,11 +219,11 @@ pub unsafe extern "C" fn sink_drop(ptr: *mut SinkWrapper) {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sink_set_uri(ptr: *const SinkWrapper, pub unsafe extern "C" fn sink_set_uri(ptr: *const SinkWrapper,
uri_ptr: *const c_char, uri_ptr: *const c_char,
cerr: *mut c_void) cerr: *mut *mut glib::GError)
-> GBoolean { -> glib::gboolean {
let wrap: &SinkWrapper = &*ptr; let wrap: &SinkWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
let uri_str = if uri_ptr.is_null() { let uri_str = if uri_ptr.is_null() {
None None
} else { } else {
@ -225,9 +234,9 @@ pub unsafe extern "C" fn sink_set_uri(ptr: *const SinkWrapper,
Err(err) => { Err(err) => {
error!(wrap.logger, "Failed to set URI {:?}", err); error!(wrap.logger, "Failed to set URI {:?}", err);
err.into_gerror(cerr); err.into_gerror(cerr);
GBoolean::False glib::GFALSE
} }
Ok(_) => GBoolean::True, Ok(_) => glib::GTRUE,
} }
}) })
} }
@ -245,24 +254,34 @@ pub unsafe extern "C" fn sink_get_uri(ptr: *const SinkWrapper) -> *mut c_char {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sink_start(ptr: *const SinkWrapper) -> GBoolean { pub unsafe extern "C" fn sink_start(ptr: *const SinkWrapper) -> glib::gboolean {
let wrap: &SinkWrapper = &*ptr; let wrap: &SinkWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
GBoolean::from_bool(wrap.start()) if wrap.start() {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sink_stop(ptr: *const SinkWrapper) -> GBoolean { pub unsafe extern "C" fn sink_stop(ptr: *const SinkWrapper) -> glib::gboolean {
let wrap: &SinkWrapper = &*ptr; let wrap: &SinkWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::True, { panic_to_error!(wrap, glib::GTRUE, {
GBoolean::from_bool(wrap.stop()) if wrap.stop() {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper, buffer: GstRefPtr) -> GstFlowReturn { pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper,
buffer: GstRefPtr<Buffer>)
-> GstFlowReturn {
let wrap: &SinkWrapper = &*ptr; let wrap: &SinkWrapper = &*ptr;
panic_to_error!(wrap, GstFlowReturn::Error, { panic_to_error!(wrap, GstFlowReturn::Error, {
let buffer: GstRef<Buffer> = GstRef::new(&buffer); let buffer: GstRef<Buffer> = GstRef::new(&buffer);
@ -283,7 +302,7 @@ pub struct SinkInfo<'a> {
pub fn sink_register(plugin: &Plugin, sink_info: &SinkInfo) { pub fn sink_register(plugin: &Plugin, sink_info: &SinkInfo) {
extern "C" { extern "C" {
fn gst_rs_sink_register(plugin: *const c_void, fn gst_rs_sink_register(plugin: *const gst::GstPlugin,
name: *const c_char, name: *const c_char,
long_name: *const c_char, long_name: *const c_char,
description: *const c_char, description: *const c_char,
@ -292,7 +311,7 @@ pub fn sink_register(plugin: &Plugin, sink_info: &SinkInfo) {
rank: i32, rank: i32,
create_instance: *const c_void, create_instance: *const c_void,
protocols: *const c_char) protocols: *const c_char)
-> GBoolean; -> glib::gboolean;
} }
let cname = CString::new(sink_info.name).unwrap(); let cname = CString::new(sink_info.name).unwrap();

View file

@ -28,6 +28,9 @@ use buffer::*;
use miniobject::*; use miniobject::*;
use log::*; use log::*;
use glib;
use gst;
#[derive(Debug)] #[derive(Debug)]
pub enum SourceError { pub enum SourceError {
Failure, Failure,
@ -50,7 +53,7 @@ impl ToGError for SourceError {
} }
pub struct SourceWrapper { pub struct SourceWrapper {
raw: *mut c_void, raw: *mut gst::GstElement,
logger: Logger, logger: Logger,
uri: Mutex<(Option<Url>, bool)>, uri: Mutex<(Option<Url>, bool)>,
uri_validator: Box<UriValidator>, uri_validator: Box<UriValidator>,
@ -71,7 +74,7 @@ pub trait Source {
} }
impl SourceWrapper { impl SourceWrapper {
fn new(raw: *mut c_void, source: Box<Source>) -> SourceWrapper { fn new(raw: *mut gst::GstElement, source: Box<Source>) -> SourceWrapper {
SourceWrapper { SourceWrapper {
raw: raw, raw: raw,
logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }), logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }),
@ -154,7 +157,10 @@ impl SourceWrapper {
Err(ref msg) => { Err(ref msg) => {
error!(self.logger, "Failed to start: {:?}", msg); error!(self.logger, "Failed to start: {:?}", msg);
self.uri.lock().unwrap().1 = false; self.uri
.lock()
.unwrap()
.1 = false;
self.post_message(msg); self.post_message(msg);
false false
} }
@ -169,7 +175,10 @@ impl SourceWrapper {
match source.stop() { match source.stop() {
Ok(..) => { Ok(..) => {
trace!(self.logger, "Stopped successfully"); trace!(self.logger, "Stopped successfully");
self.uri.lock().unwrap().1 = false; self.uri
.lock()
.unwrap()
.1 = false;
true true
} }
Err(ref msg) => { Err(ref msg) => {
@ -227,7 +236,7 @@ impl SourceWrapper {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn source_new(source: *mut c_void, pub unsafe extern "C" fn source_new(source: *mut gst::GstElement,
create_instance: fn(Element) -> Box<Source>) create_instance: fn(Element) -> Box<Source>)
-> *mut SourceWrapper { -> *mut SourceWrapper {
let instance = create_instance(Element::new(source)); let instance = create_instance(Element::new(source));
@ -243,11 +252,11 @@ pub unsafe extern "C" fn source_drop(ptr: *mut SourceWrapper) {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn source_set_uri(ptr: *const SourceWrapper, pub unsafe extern "C" fn source_set_uri(ptr: *const SourceWrapper,
uri_ptr: *const c_char, uri_ptr: *const c_char,
cerr: *mut c_void) cerr: *mut *mut glib::GError)
-> GBoolean { -> glib::gboolean {
let wrap: &SourceWrapper = &*ptr; let wrap: &SourceWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
let uri_str = if uri_ptr.is_null() { let uri_str = if uri_ptr.is_null() {
None None
} else { } else {
@ -258,9 +267,9 @@ pub unsafe extern "C" fn source_set_uri(ptr: *const SourceWrapper,
Err(err) => { Err(err) => {
error!(wrap.logger, "Failed to set URI {:?}", err); error!(wrap.logger, "Failed to set URI {:?}", err);
err.into_gerror(cerr); err.into_gerror(cerr);
GBoolean::False glib::GFALSE
} }
Ok(_) => GBoolean::True, Ok(_) => glib::GTRUE,
} }
}) })
} }
@ -277,11 +286,15 @@ pub unsafe extern "C" fn source_get_uri(ptr: *const SourceWrapper) -> *mut c_cha
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn source_is_seekable(ptr: *const SourceWrapper) -> GBoolean { pub unsafe extern "C" fn source_is_seekable(ptr: *const SourceWrapper) -> glib::gboolean {
let wrap: &SourceWrapper = &*ptr; let wrap: &SourceWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
GBoolean::from_bool(wrap.is_seekable()) if wrap.is_seekable() {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
@ -294,20 +307,28 @@ pub unsafe extern "C" fn source_get_size(ptr: *const SourceWrapper) -> u64 {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn source_start(ptr: *const SourceWrapper) -> GBoolean { pub unsafe extern "C" fn source_start(ptr: *const SourceWrapper) -> glib::gboolean {
let wrap: &SourceWrapper = &*ptr; let wrap: &SourceWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
GBoolean::from_bool(wrap.start()) if wrap.start() {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> GBoolean { pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> glib::gboolean {
let wrap: &SourceWrapper = &*ptr; let wrap: &SourceWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::True, { panic_to_error!(wrap, glib::GTRUE, {
GBoolean::from_bool(wrap.stop()) if wrap.stop() {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
@ -315,7 +336,7 @@ pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> GBoolean {
pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper, pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper,
offset: u64, offset: u64,
length: u32, length: u32,
buffer: GstRefPtr) buffer: GstRefPtr<Buffer>)
-> GstFlowReturn { -> GstFlowReturn {
let wrap: &SourceWrapper = &*ptr; let wrap: &SourceWrapper = &*ptr;
@ -326,11 +347,18 @@ pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper,
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn source_seek(ptr: *const SourceWrapper, start: u64, stop: u64) -> GBoolean { pub unsafe extern "C" fn source_seek(ptr: *const SourceWrapper,
start: u64,
stop: u64)
-> glib::gboolean {
let wrap: &SourceWrapper = &*ptr; let wrap: &SourceWrapper = &*ptr;
panic_to_error!(wrap, GBoolean::False, { panic_to_error!(wrap, glib::GFALSE, {
GBoolean::from_bool(wrap.seek(start, if stop == u64::MAX { None } else { Some(stop) })) if wrap.seek(start, if stop == u64::MAX { None } else { Some(stop) }) {
glib::GTRUE
} else {
glib::GFALSE
}
}) })
} }
@ -349,7 +377,7 @@ pub struct SourceInfo<'a> {
pub fn source_register(plugin: &Plugin, source_info: &SourceInfo) { pub fn source_register(plugin: &Plugin, source_info: &SourceInfo) {
extern "C" { extern "C" {
fn gst_rs_source_register(plugin: *const c_void, fn gst_rs_source_register(plugin: *const gst::GstPlugin,
name: *const c_char, name: *const c_char,
long_name: *const c_char, long_name: *const c_char,
description: *const c_char, description: *const c_char,
@ -358,8 +386,8 @@ pub fn source_register(plugin: &Plugin, source_info: &SourceInfo) {
rank: i32, rank: i32,
create_instance: *const c_void, create_instance: *const c_void,
protocols: *const c_char, protocols: *const c_char,
push_only: GBoolean) push_only: glib::gboolean)
-> GBoolean; -> glib::gboolean;
} }
let cname = CString::new(source_info.name).unwrap(); let cname = CString::new(source_info.name).unwrap();
@ -379,6 +407,10 @@ pub fn source_register(plugin: &Plugin, source_info: &SourceInfo) {
source_info.rank, source_info.rank,
source_info.create_instance as *const c_void, source_info.create_instance as *const c_void,
cprotocols.as_ptr(), cprotocols.as_ptr(),
GBoolean::from_bool(source_info.push_only)); if source_info.push_only {
glib::GTRUE
} else {
glib::GFALSE
});
} }
} }

View file

@ -6,16 +6,17 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::os::raw::c_void;
use std::ptr; use std::ptr;
use libc::c_char; use std::mem;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use caps::Caps; use caps::Caps;
use miniobject::*; use miniobject::*;
use tags::TagList; use tags::TagList;
pub struct Stream(*mut c_void); use gst;
pub struct StreamCollection(*mut c_void);
pub struct Stream(*mut gst::GstStream);
pub struct StreamCollection(*mut gst::GstStreamCollection);
bitflags! { bitflags! {
#[repr(C)] #[repr(C)]
@ -43,30 +44,23 @@ impl Stream {
t: StreamType, t: StreamType,
flags: StreamFlags) flags: StreamFlags)
-> Self { -> Self {
extern "C" {
fn gst_stream_new(stream_id: *const c_char,
caps: *const c_void,
t: StreamType,
flags: StreamFlags)
-> *mut c_void;
}
let stream_id_cstr = CString::new(stream_id).unwrap(); let stream_id_cstr = CString::new(stream_id).unwrap();
let caps = caps.map(|caps| unsafe { caps.as_ptr() }).unwrap_or(ptr::null_mut()); let caps = caps.map(|caps| unsafe { caps.as_ptr() }).unwrap_or(ptr::null_mut());
Stream(unsafe { gst_stream_new(stream_id_cstr.as_ptr(), caps, t, flags) }) Stream(unsafe {
gst::gst_stream_new(stream_id_cstr.as_ptr(),
caps,
mem::transmute(t.bits()),
mem::transmute(flags.bits()))
})
} }
pub unsafe fn as_ptr(&self) -> *const c_void { pub unsafe fn as_ptr(&self) -> *const gst::GstStream {
self.0 self.0
} }
pub fn get_caps(&self) -> Option<GstRc<Caps>> { pub fn get_caps(&self) -> Option<GstRc<Caps>> {
extern "C" { let ptr = unsafe { gst::gst_stream_get_caps(self.0) };
fn gst_stream_get_caps(stream: *mut c_void) -> *mut c_void;
}
let ptr = unsafe { gst_stream_get_caps(self.0) };
if ptr.is_null() { if ptr.is_null() {
return None; return None;
@ -76,36 +70,20 @@ impl Stream {
} }
pub fn get_stream_flags(&self) -> StreamFlags { pub fn get_stream_flags(&self) -> StreamFlags {
extern "C" { StreamFlags::from_bits_truncate(unsafe { gst::gst_stream_get_stream_flags(self.0).bits() })
fn gst_stream_get_stream_flags(stream: *mut c_void) -> u32;
}
StreamFlags::from_bits_truncate(unsafe { gst_stream_get_stream_flags(self.0) })
} }
pub fn get_stream_type(&self) -> StreamType { pub fn get_stream_type(&self) -> StreamType {
extern "C" { StreamType::from_bits_truncate(unsafe { gst::gst_stream_get_stream_type(self.0).bits() })
fn gst_stream_get_stream_type(stream: *mut c_void) -> u32;
}
StreamType::from_bits_truncate(unsafe { gst_stream_get_stream_type(self.0) })
} }
pub fn get_stream_id(&self) -> &str { pub fn get_stream_id(&self) -> &str {
extern "C" { let cstr = unsafe { CStr::from_ptr(gst::gst_stream_get_stream_id(self.0)) };
fn gst_stream_get_stream_id(collection: *mut c_void) -> *mut c_char;
}
let cstr = unsafe { CStr::from_ptr(gst_stream_get_stream_id(self.0)) };
cstr.to_str().unwrap() cstr.to_str().unwrap()
} }
pub fn get_tags(&self) -> Option<TagList> { pub fn get_tags(&self) -> Option<TagList> {
extern "C" { let ptr = unsafe { gst::gst_stream_get_tags(self.0) };
fn gst_stream_get_tags(stream: *mut c_void) -> *mut c_void;
}
let ptr = unsafe { gst_stream_get_tags(self.0) };
if ptr.is_null() { if ptr.is_null() {
return None; return None;
@ -115,75 +93,46 @@ impl Stream {
} }
pub fn set_caps(&self, caps: Option<GstRc<Caps>>) { pub fn set_caps(&self, caps: Option<GstRc<Caps>>) {
extern "C" {
fn gst_stream_set_caps(stream: *mut c_void, caps: *mut c_void);
}
let ptr = caps.map(|caps| unsafe { caps.as_ptr() }).unwrap_or(ptr::null_mut()); let ptr = caps.map(|caps| unsafe { caps.as_ptr() }).unwrap_or(ptr::null_mut());
unsafe { gst_stream_set_caps(self.0, ptr as *mut c_void) } unsafe { gst::gst_stream_set_caps(self.0, ptr) }
} }
pub fn set_stream_flags(&self, flags: StreamFlags) { pub fn set_stream_flags(&self, flags: StreamFlags) {
extern "C" { unsafe { gst::gst_stream_set_stream_flags(self.0, mem::transmute(flags.bits())) }
fn gst_stream_set_stream_flags(stream: *mut c_void, flags: u32);
}
unsafe { gst_stream_set_stream_flags(self.0, flags.bits()) }
} }
pub fn set_stream_type(&self, t: StreamType) { pub fn set_stream_type(&self, t: StreamType) {
extern "C" { unsafe { gst::gst_stream_set_stream_type(self.0, mem::transmute(t.bits())) }
fn gst_stream_set_stream_type(stream: *mut c_void, t: u32);
}
unsafe { gst_stream_set_stream_type(self.0, t.bits()) }
} }
pub fn set_tags(&self, tags: Option<TagList>) { pub fn set_tags(&self, tags: Option<TagList>) {
extern "C" {
fn gst_stream_set_tags(stream: *mut c_void, tags: *mut c_void);
}
let ptr = tags.map(|tags| unsafe { tags.as_ptr() }).unwrap_or(ptr::null_mut()); let ptr = tags.map(|tags| unsafe { tags.as_ptr() }).unwrap_or(ptr::null_mut());
unsafe { gst_stream_set_tags(self.0, ptr as *mut c_void) } unsafe { gst::gst_stream_set_tags(self.0, ptr) }
} }
} }
impl Clone for Stream { impl Clone for Stream {
fn clone(&self) -> Self { fn clone(&self) -> Self {
extern "C" { unsafe { Stream(gst::gst_object_ref(self.0 as *mut gst::GstObject) as *mut gst::GstStream) }
fn gst_object_ref(object: *mut c_void) -> *mut c_void;
}
unsafe { Stream(gst_object_ref(self.0)) }
} }
} }
impl Drop for Stream { impl Drop for Stream {
fn drop(&mut self) { fn drop(&mut self) {
extern "C" { unsafe { gst::gst_object_unref(self.0 as *mut gst::GstObject) }
fn gst_object_unref(object: *mut c_void);
}
unsafe { gst_object_unref(self.0) }
} }
} }
impl StreamCollection { impl StreamCollection {
pub fn new(upstream_id: &str, streams: &[Stream]) -> Self { pub fn new(upstream_id: &str, streams: &[Stream]) -> Self {
extern "C" {
fn gst_stream_collection_new(upstream_id: *const c_char) -> *mut c_void;
fn gst_stream_collection_add_stream(collection: *mut c_void, stream: *mut c_void);
}
let upstream_id_cstr = CString::new(upstream_id).unwrap(); let upstream_id_cstr = CString::new(upstream_id).unwrap();
let collection = let collection =
StreamCollection(unsafe { gst_stream_collection_new(upstream_id_cstr.as_ptr()) }); StreamCollection(unsafe { gst::gst_stream_collection_new(upstream_id_cstr.as_ptr()) });
for stream in streams { for stream in streams {
unsafe { gst_stream_collection_add_stream(collection.0, stream.clone().0) } unsafe { gst::gst_stream_collection_add_stream(collection.0, stream.clone().0) };
} }
collection collection
@ -194,11 +143,7 @@ impl StreamCollection {
} }
pub fn len(&self) -> u32 { pub fn len(&self) -> u32 {
extern "C" { unsafe { gst::gst_stream_collection_get_size(self.0) }
fn gst_stream_collection_get_size(collection: *mut c_void) -> u32;
}
unsafe { gst_stream_collection_get_size(self.0) }
} }
pub fn empty(&self) -> bool { pub fn empty(&self) -> bool {
@ -206,15 +151,11 @@ impl StreamCollection {
} }
pub fn get_upstream_id(&self) -> &str { pub fn get_upstream_id(&self) -> &str {
extern "C" { let cstr = unsafe { CStr::from_ptr(gst::gst_stream_collection_get_upstream_id(self.0)) };
fn gst_stream_collection_get_upstream_id(collection: *mut c_void) -> *mut c_char;
}
let cstr = unsafe { CStr::from_ptr(gst_stream_collection_get_upstream_id(self.0)) };
cstr.to_str().unwrap() cstr.to_str().unwrap()
} }
pub unsafe fn as_ptr(&self) -> *const c_void { pub unsafe fn as_ptr(&self) -> *const gst::GstStreamCollection {
self.0 self.0
} }
} }
@ -239,44 +180,35 @@ impl<'a> Iterator for StreamCollectionIterator<'a> {
type Item = Stream; type Item = Stream;
fn next(&mut self) -> Option<Stream> { fn next(&mut self) -> Option<Stream> {
extern "C" {
fn gst_stream_collection_get_stream(collection: *mut c_void,
index: u32)
-> *mut c_void;
fn gst_object_ref(object: *mut c_void) -> *mut c_void;
}
if self.position == self.length { if self.position == self.length {
return None; return None;
} }
let stream = unsafe { gst_stream_collection_get_stream(self.collection.0, self.position) }; let stream =
unsafe { gst::gst_stream_collection_get_stream(self.collection.0, self.position) };
if stream.is_null() { if stream.is_null() {
self.position = self.length; self.position = self.length;
return None; return None;
} }
self.position += 1; self.position += 1;
Some(unsafe { Stream(gst_object_ref(stream)) }) Some(unsafe {
Stream(gst::gst_object_ref(stream as *mut gst::GstObject) as *mut gst::GstStream)
})
} }
} }
impl Clone for StreamCollection { impl Clone for StreamCollection {
fn clone(&self) -> Self { fn clone(&self) -> Self {
extern "C" { unsafe {
fn gst_object_ref(object: *mut c_void) -> *mut c_void; StreamCollection(gst::gst_object_ref(self.0 as *mut gst::GstObject) as
*mut gst::GstStreamCollection)
} }
unsafe { StreamCollection(gst_object_ref(self.0)) }
} }
} }
impl Drop for StreamCollection { impl Drop for StreamCollection {
fn drop(&mut self) { fn drop(&mut self) {
extern "C" { unsafe { gst::gst_object_unref(self.0 as *mut gst::GstObject) }
fn gst_object_unref(object: *mut c_void);
}
unsafe { gst_object_unref(self.0) }
} }
} }

View file

@ -6,14 +6,16 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::os::raw::c_void;
use std::fmt; use std::fmt;
use libc::c_char; use std::mem;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use utils::*;
use value::*; use value::*;
use miniobject::*; use miniobject::*;
use glib;
use gobject;
use gst;
pub trait Tag { pub trait Tag {
type TagType: ValueType; type TagType: ValueType;
fn tag_name() -> &'static str; fn tag_name() -> &'static str;
@ -44,9 +46,8 @@ impl_tag!(LanguageCode, String, "language-code");
impl_tag!(Duration, u64, "duration"); impl_tag!(Duration, u64, "duration");
impl_tag!(NominalBitrate, u32, "nominal-bitrate"); impl_tag!(NominalBitrate, u32, "nominal-bitrate");
#[repr(C)]
pub enum MergeMode { pub enum MergeMode {
ReplaceAll = 1, ReplaceAll,
Replace, Replace,
Append, Append,
Prepend, Prepend,
@ -54,91 +55,86 @@ pub enum MergeMode {
KeepAll, KeepAll,
} }
impl MergeMode {
fn to_ffi(&self) -> gst::GstTagMergeMode {
match *self {
MergeMode::ReplaceAll => gst::GST_TAG_MERGE_REPLACE_ALL,
MergeMode::Replace => gst::GST_TAG_MERGE_REPLACE,
MergeMode::Append => gst::GST_TAG_MERGE_APPEND,
MergeMode::Prepend => gst::GST_TAG_MERGE_PREPEND,
MergeMode::Keep => gst::GST_TAG_MERGE_KEEP,
MergeMode::KeepAll => gst::GST_TAG_MERGE_KEEP_ALL,
}
}
}
#[derive(Eq)] #[derive(Eq)]
pub struct TagList(*mut c_void); pub struct TagList(*mut gst::GstTagList);
unsafe impl MiniObject for TagList { unsafe impl MiniObject for TagList {
unsafe fn as_ptr(&self) -> *mut c_void { type PtrType = gst::GstTagList;
unsafe fn as_ptr(&self) -> *mut gst::GstTagList {
self.0 self.0
} }
unsafe fn replace_ptr(&mut self, ptr: *mut c_void) { unsafe fn replace_ptr(&mut self, ptr: *mut gst::GstTagList) {
self.0 = ptr self.0 = ptr
} }
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self { unsafe fn new_from_ptr(ptr: *mut gst::GstTagList) -> Self {
TagList(ptr) TagList(ptr)
} }
} }
impl TagList { impl TagList {
pub fn new() -> GstRc<Self> { pub fn new() -> GstRc<Self> {
extern "C" { unsafe { GstRc::new_from_owned_ptr(gst::gst_tag_list_new_empty()) }
fn gst_tag_list_new_empty() -> *mut c_void;
}
unsafe { GstRc::new_from_owned_ptr(gst_tag_list_new_empty()) }
} }
pub fn add<T: Tag>(&mut self, value: T::TagType, mode: MergeMode) pub fn add<T: Tag>(&mut self, value: T::TagType, mode: MergeMode)
where Value: From<<T as Tag>::TagType> where Value: From<<T as Tag>::TagType>
{ {
extern "C" {
fn gst_tag_list_add_value(list: *mut c_void,
mode: u32,
tag: *const c_char,
value: *const GValue);
}
let v = Value::from(value);
let gvalue = v.to_gvalue();
let tag_name = CString::new(T::tag_name()).unwrap();
unsafe { unsafe {
gst_tag_list_add_value(self.0, let v = Value::from(value);
mode as u32, let mut gvalue = v.to_gvalue();
tag_name.as_ptr(), let tag_name = CString::new(T::tag_name()).unwrap();
&gvalue as *const GValue);
gst::gst_tag_list_add_value(self.0, mode.to_ffi(), tag_name.as_ptr(), &gvalue);
gobject::g_value_unset(&mut gvalue);
} }
} }
pub fn get<T: Tag>(&self) -> Option<TypedValue<T::TagType>> pub fn get<T: Tag>(&self) -> Option<TypedValue<T::TagType>>
where Value: From<<T as Tag>::TagType> where Value: From<<T as Tag>::TagType>
{ {
extern "C" { unsafe {
fn gst_tag_list_copy_value(value: *mut GValue, let mut gvalue = mem::zeroed();
list: *mut c_void, let tag_name = CString::new(T::tag_name()).unwrap();
tag: *const c_char)
-> GBoolean;
}
let mut gvalue = GValue::new(); let found = gst::gst_tag_list_copy_value(&mut gvalue, self.0, tag_name.as_ptr());
let tag_name = CString::new(T::tag_name()).unwrap();
let found = unsafe { if found == glib::GFALSE {
gst_tag_list_copy_value(&mut gvalue as *mut GValue, self.0, tag_name.as_ptr()) return None;
}; }
if !found.to_bool() { let res = match Value::from_gvalue(&gvalue) {
return None; Some(value) => Some(TypedValue::new(value)),
} None => None,
};
match Value::from_gvalue(&gvalue) { gobject::g_value_unset(&mut gvalue);
Some(value) => Some(TypedValue::new(value)),
None => None, res
} }
} }
pub fn to_string(&self) -> String { pub fn to_string(&self) -> String {
extern "C" {
fn gst_tag_list_to_string(tag_list: *mut c_void) -> *mut c_char;
fn g_free(ptr: *mut c_char);
}
unsafe { unsafe {
let ptr = gst_tag_list_to_string(self.0); let ptr = gst::gst_tag_list_to_string(self.0);
let s = CStr::from_ptr(ptr).to_str().unwrap().into(); let s = CStr::from_ptr(ptr).to_str().unwrap().into();
g_free(ptr); glib::g_free(ptr as glib::gpointer);
s s
} }
@ -153,11 +149,7 @@ impl fmt::Debug for TagList {
impl PartialEq for TagList { impl PartialEq for TagList {
fn eq(&self, other: &TagList) -> bool { fn eq(&self, other: &TagList) -> bool {
extern "C" { (unsafe { gst::gst_tag_list_is_equal(self.0, other.0) } == glib::GTRUE)
fn gst_tag_list_is_equal(a: *const c_void, b: *const c_void) -> GBoolean;
}
unsafe { gst_tag_list_is_equal(self.0, other.0).to_bool() }
} }
} }
@ -168,15 +160,10 @@ unsafe impl Send for TagList {}
mod tests { mod tests {
use super::*; use super::*;
use std::ptr; use std::ptr;
use std::os::raw::c_void;
fn init() { fn init() {
extern "C" {
fn gst_init(argc: *mut c_void, argv: *mut c_void);
}
unsafe { unsafe {
gst_init(ptr::null_mut(), ptr::null_mut()); gst::gst_init(ptr::null_mut(), ptr::null_mut());
} }
} }

View file

@ -7,11 +7,12 @@
// except according to those terms. // except according to those terms.
use libc::c_char; use libc::c_char;
use std::os::raw::c_void;
use std::ffi::CString; use std::ffi::CString;
use std::i32; use std::i32;
use num_rational::Rational32; use num_rational::Rational32;
use gst;
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum GstFlowReturn { pub enum GstFlowReturn {
@ -23,53 +24,28 @@ pub enum GstFlowReturn {
Error = -5, Error = -5,
} }
#[repr(C)] pub struct Element(*mut gst::GstElement);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum GBoolean {
False = 0,
True = 1,
}
impl GBoolean {
pub fn from_bool(v: bool) -> GBoolean {
if v { GBoolean::True } else { GBoolean::False }
}
pub fn to_bool(&self) -> bool {
!(*self == GBoolean::False)
}
}
pub struct Element(*const c_void);
impl Element { impl Element {
pub unsafe fn new(element: *const c_void) -> Element { pub unsafe fn new(element: *mut gst::GstElement) -> Element {
extern "C" {
fn gst_object_ref(object: *const c_void) -> *const c_void;
}
if element.is_null() { if element.is_null() {
panic!("NULL not allowed"); panic!("NULL not allowed");
} }
gst_object_ref(element); gst::gst_object_ref(element as *mut gst::GstObject);
Element(element) Element(element)
} }
pub unsafe fn as_ptr(&self) -> *const c_void { pub unsafe fn as_ptr(&self) -> *mut gst::GstElement {
self.0 self.0
} }
} }
impl Drop for Element { impl Drop for Element {
fn drop(&mut self) { fn drop(&mut self) {
extern "C" {
fn gst_object_unref(object: *const c_void);
}
unsafe { unsafe {
gst_object_unref(self.0); gst::gst_object_unref(self.0 as *mut gst::GstObject);
} }
} }
} }

View file

@ -6,8 +6,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use libc::c_char;
use std::os::raw::c_void;
use std::ffi::{CString, CStr}; use std::ffi::{CString, CStr};
use std::mem; use std::mem;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -18,6 +16,10 @@ pub use num_rational::Rational32;
use buffer::*; use buffer::*;
use miniobject::*; use miniobject::*;
use glib;
use gobject;
use gst;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum Value { pub enum Value {
Bool(bool), Bool(bool),
@ -58,145 +60,76 @@ impl_value_type!(Rational32, Fraction);
impl_value_type!(GstRc<Buffer>, Buffer); impl_value_type!(GstRc<Buffer>, Buffer);
impl_value_type!(Vec<Value>, Array); impl_value_type!(Vec<Value>, Array);
#[repr(C)]
pub struct GValue {
typ: usize,
data: [u64; 2],
}
impl GValue {
pub fn new() -> GValue {
unsafe { mem::zeroed() }
}
}
impl Drop for GValue {
fn drop(&mut self) {
extern "C" {
fn g_value_unset(value: *mut GValue);
}
if self.typ != 0 {
unsafe { g_value_unset(self as *mut GValue) }
}
}
}
// See gtype.h
const TYPE_BOOLEAN: usize = (5 << 2);
const TYPE_INT: usize = (6 << 2);
const TYPE_UINT: usize = (7 << 2);
const TYPE_INT64: usize = (10 << 2);
const TYPE_UINT64: usize = (11 << 2);
const TYPE_STRING: usize = (16 << 2);
extern "C" {
fn gst_buffer_get_type() -> usize;
fn gst_fraction_get_type() -> usize;
fn gst_value_array_get_type() -> usize;
}
lazy_static! { lazy_static! {
static ref TYPE_BUFFER: usize = unsafe { gst_buffer_get_type() }; static ref TYPE_BUFFER: glib::GType = unsafe { gst::gst_buffer_get_type() };
static ref TYPE_FRACTION: usize = unsafe { gst_fraction_get_type() }; static ref TYPE_FRACTION: glib::GType = unsafe { gst::gst_fraction_get_type() };
static ref TYPE_GST_VALUE_ARRAY: usize = unsafe { gst_value_array_get_type() }; static ref TYPE_GST_VALUE_ARRAY: glib::GType = unsafe { gst::gst_value_array_get_type() };
} }
impl Value { impl Value {
pub fn to_gvalue(&self) -> GValue { pub unsafe fn to_gvalue(&self) -> gobject::GValue {
extern "C" { let mut gvalue = mem::zeroed();
fn g_value_init(value: *mut GValue, gtype: usize);
fn g_value_set_boolean(value: *mut GValue, value: i32);
fn g_value_set_int(value: *mut GValue, value: i32);
fn g_value_set_uint(value: *mut GValue, value: u32);
fn g_value_set_int64(value: *mut GValue, value: i64);
fn g_value_set_uint64(value: *mut GValue, value: u64);
fn g_value_set_string(value: *mut GValue, value: *const c_char);
fn gst_value_set_fraction(value: *mut GValue, value_n: i32, value_d: i32);
fn g_value_set_boxed(value: *mut GValue, boxed: *const c_void);
fn gst_value_array_append_and_take_value(value: *mut GValue, element: *mut GValue);
}
let mut gvalue = GValue::new();
match *self { match *self {
Value::Bool(v) => unsafe { Value::Bool(v) => {
g_value_init(&mut gvalue as *mut GValue, TYPE_BOOLEAN); gobject::g_value_init(&mut gvalue, gobject::G_TYPE_BOOLEAN);
g_value_set_boolean(&mut gvalue as *mut GValue, if v { 1 } else { 0 }); gobject::g_value_set_boolean(&mut gvalue,
}, if v { glib::GTRUE } else { glib::GFALSE });
Value::Int(v) => unsafe { }
g_value_init(&mut gvalue as *mut GValue, TYPE_INT); Value::Int(v) => {
g_value_set_int(&mut gvalue as *mut GValue, v); gobject::g_value_init(&mut gvalue, gobject::G_TYPE_INT);
}, gobject::g_value_set_int(&mut gvalue, v);
Value::UInt(v) => unsafe { }
g_value_init(&mut gvalue as *mut GValue, TYPE_UINT); Value::UInt(v) => {
g_value_set_uint(&mut gvalue as *mut GValue, v); gobject::g_value_init(&mut gvalue, gobject::G_TYPE_UINT);
}, gobject::g_value_set_uint(&mut gvalue, v);
Value::Int64(v) => unsafe { }
g_value_init(&mut gvalue as *mut GValue, TYPE_INT64); Value::Int64(v) => {
g_value_set_int64(&mut gvalue as *mut GValue, v); gobject::g_value_init(&mut gvalue, gobject::G_TYPE_INT64);
}, gobject::g_value_set_int64(&mut gvalue, v);
Value::UInt64(v) => unsafe { }
g_value_init(&mut gvalue as *mut GValue, TYPE_UINT64); Value::UInt64(v) => {
g_value_set_uint64(&mut gvalue as *mut GValue, v); gobject::g_value_init(&mut gvalue, gobject::G_TYPE_UINT64);
}, gobject::g_value_set_uint64(&mut gvalue, v);
Value::String(ref v) => unsafe { }
Value::String(ref v) => {
let v_cstr = CString::new(String::from(v.clone())).unwrap(); let v_cstr = CString::new(String::from(v.clone())).unwrap();
g_value_init(&mut gvalue as *mut GValue, TYPE_STRING); gobject::g_value_init(&mut gvalue, gobject::G_TYPE_STRING);
g_value_set_string(&mut gvalue as *mut GValue, v_cstr.as_ptr()); gobject::g_value_set_string(&mut gvalue, v_cstr.as_ptr());
}, }
Value::Fraction(ref v) => unsafe { Value::Fraction(ref v) => {
g_value_init(&mut gvalue as *mut GValue, *TYPE_FRACTION); gobject::g_value_init(&mut gvalue, *TYPE_FRACTION);
gst_value_set_fraction(&mut gvalue as *mut GValue, *v.numer(), *v.denom()); gst::gst_value_set_fraction(&mut gvalue, *v.numer(), *v.denom());
}, }
Value::Buffer(ref buffer) => unsafe { Value::Buffer(ref buffer) => {
g_value_init(&mut gvalue as *mut GValue, *TYPE_BUFFER); gobject::g_value_init(&mut gvalue, *TYPE_BUFFER);
g_value_set_boxed(&mut gvalue as *mut GValue, buffer.as_ptr()); gobject::g_value_set_boxed(&mut gvalue, buffer.as_ptr() as glib::gconstpointer);
}, }
Value::Array(ref array) => unsafe { Value::Array(ref array) => {
g_value_init(&mut gvalue as *mut GValue, *TYPE_GST_VALUE_ARRAY); gobject::g_value_init(&mut gvalue, *TYPE_GST_VALUE_ARRAY);
for e in array { for e in array {
let mut e_value = e.to_gvalue(); let mut e_value = e.to_gvalue();
gst_value_array_append_and_take_value(&mut gvalue as *mut GValue, gst::gst_value_array_append_and_take_value(&mut gvalue, &mut e_value);
&mut e_value as *mut GValue);
// Takes ownership, invalidate GValue
e_value.typ = 0;
} }
}, }
} }
gvalue gvalue
} }
pub fn from_gvalue(gvalue: &GValue) -> Option<Self> { pub unsafe fn from_gvalue(gvalue: &gobject::GValue) -> Option<Self> {
extern "C" { match gvalue.g_type {
fn g_value_get_boolean(value: *const GValue) -> i32; gobject::G_TYPE_BOOLEAN => {
fn g_value_get_int(value: *const GValue) -> i32; Some(Value::Bool(!(gobject::g_value_get_boolean(gvalue) == 0)))
fn g_value_get_uint(value: *const GValue) -> u32; }
fn g_value_get_int64(value: *const GValue) -> i64; gobject::G_TYPE_INT => Some(Value::Int(gobject::g_value_get_int(gvalue))),
fn g_value_get_uint64(value: *const GValue) -> u64; gobject::G_TYPE_UINT => Some(Value::UInt(gobject::g_value_get_uint(gvalue))),
fn g_value_get_string(value: *const GValue) -> *const c_char; gobject::G_TYPE_INT64 => Some(Value::Int64(gobject::g_value_get_int64(gvalue))),
fn gst_value_get_fraction_numerator(value: *const GValue) -> i32; gobject::G_TYPE_UINT64 => Some(Value::UInt64(gobject::g_value_get_uint64(gvalue))),
fn gst_value_get_fraction_denominator(value: *const GValue) -> i32; gobject::G_TYPE_STRING => {
fn g_value_get_boxed(value: *const GValue) -> *mut c_void; let s = gobject::g_value_get_string(gvalue);
fn gst_value_array_get_size(value: *const GValue) -> u32;
fn gst_value_array_get_value(value: *const GValue, index: u32) -> *const GValue;
}
match gvalue.typ {
TYPE_BOOLEAN => unsafe {
Some(Value::Bool(!(g_value_get_boolean(gvalue as *const GValue) == 0)))
},
TYPE_INT => unsafe { Some(Value::Int(g_value_get_int(gvalue as *const GValue))) },
TYPE_UINT => unsafe { Some(Value::UInt(g_value_get_uint(gvalue as *const GValue))) },
TYPE_INT64 => unsafe { Some(Value::Int64(g_value_get_int64(gvalue as *const GValue))) },
TYPE_UINT64 => unsafe {
Some(Value::UInt64(g_value_get_uint64(gvalue as *const GValue)))
},
TYPE_STRING => unsafe {
let s = g_value_get_string(gvalue as *const GValue);
if s.is_null() { if s.is_null() {
return None; return None;
} }
@ -206,29 +139,29 @@ impl Value {
Err(_) => None, Err(_) => None,
Ok(s) => Some(Value::String(s.into())), Ok(s) => Some(Value::String(s.into())),
} }
}, }
typ if typ == *TYPE_FRACTION => unsafe { typ if typ == *TYPE_FRACTION => {
let n = gst_value_get_fraction_numerator(gvalue as *const GValue); let n = gst::gst_value_get_fraction_numerator(gvalue);
let d = gst_value_get_fraction_denominator(gvalue as *const GValue); let d = gst::gst_value_get_fraction_denominator(gvalue);
Some(Value::Fraction(Rational32::new(n, d))) Some(Value::Fraction(Rational32::new(n, d)))
}, }
typ if typ == *TYPE_BUFFER => unsafe { typ if typ == *TYPE_BUFFER => {
let b = g_value_get_boxed(gvalue as *const GValue); let b = gobject::g_value_get_boxed(gvalue);
if b.is_null() { if b.is_null() {
return None; return None;
} }
Some(Value::Buffer(GstRc::new_from_unowned_ptr(b))) Some(Value::Buffer(GstRc::new_from_unowned_ptr(b as *mut gst::GstBuffer)))
}, }
typ if typ == *TYPE_GST_VALUE_ARRAY => unsafe { typ if typ == *TYPE_GST_VALUE_ARRAY => {
let n = gst_value_array_get_size(gvalue as *const GValue); let n = gst::gst_value_array_get_size(gvalue);
let mut vec = Vec::with_capacity(n as usize); let mut vec = Vec::with_capacity(n as usize);
for i in 0..n { for i in 0..n {
let val = gst_value_array_get_value(gvalue as *const GValue, i); let val = gst::gst_value_array_get_value(gvalue, i);
if val.is_null() { if val.is_null() {
return None; return None;
@ -242,7 +175,7 @@ impl Value {
} }
Some(Value::Array(vec)) Some(Value::Array(vec))
}, }
_ => None, _ => None,
} }
} }