From aa3581cee970573e80759015a9c179990cbb9a60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 3 Jul 2017 13:56:26 +0300 Subject: [PATCH] Add initial Message/MiniObject bindings --- Gir_Gst.toml | 16 ++- gstreamer/src/auto/bus.rs | 114 ++++++++------- gstreamer/src/auto/element.rs | 19 +-- gstreamer/src/auto/flags.rs | 61 ++++++++ gstreamer/src/auto/mod.rs | 41 ++++++ gstreamer/src/lib.rs | 5 + gstreamer/src/message.rs | 73 ++++++++++ gstreamer/src/miniobject.rs | 258 ++++++++++++++++++++++++++++++++++ 8 files changed, 531 insertions(+), 56 deletions(-) create mode 100644 gstreamer/src/message.rs create mode 100644 gstreamer/src/miniobject.rs diff --git a/Gir_Gst.toml b/Gir_Gst.toml index f1dbf7acb..e264ac953 100644 --- a/Gir_Gst.toml +++ b/Gir_Gst.toml @@ -28,11 +28,12 @@ generate = [ "Gst.ElementFactory", "Gst.ElementFactoryListType", "Gst.Format", + "Gst.MessageType", ] manual = [ "GLib.Error", - #"Gst.Message", + "Gst.Message", ] [[object]] @@ -66,6 +67,19 @@ status = "generate" # Needs manual bindings and GSource support in glib-rs ignore = true + [[object.function]] + name = "timed_pop_filtered" + # Uses enum as flags + ignore = true + [[object.function]] + name = "pop_filtered" + # Uses enum as flags + ignore = true + [[object.function]] + name = "poll" + # Uses enum as flags + ignore = true + [[object]] name = "Gst.Clock" status = "generate" diff --git a/gstreamer/src/auto/bus.rs b/gstreamer/src/auto/bus.rs index 7adec9dbd..95ce98683 100644 --- a/gstreamer/src/auto/bus.rs +++ b/gstreamer/src/auto/bus.rs @@ -1,10 +1,18 @@ // This file was generated by gir (33e9567) from gir-files (???) // DO NOT EDIT +use ClockTime; +use Message; use Object; use ffi; +use glib; +use glib::object::Downcast; use glib::object::IsA; +use glib::signal::connect; use glib::translate::*; +use glib_ffi; +use std::boxed::Box as Box_; +use std::mem::transmute; glib_wrapper! { pub struct Bus(Object): Object; @@ -34,7 +42,7 @@ pub trait BusExt { //fn add_watch_full>>(&self, priority: i32, func: /*Unknown conversion*//*Unimplemented*/BusFunc, user_data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify) -> u32; - //fn async_signal_func>>(&self, message: /*Ignored*/&mut Message, data: P) -> bool; + //fn async_signal_func>>(&self, message: &mut Message, data: P) -> bool; //fn create_watch(&self) -> /*Ignored*/Option; @@ -44,15 +52,11 @@ pub trait BusExt { fn have_pending(&self) -> bool; - //fn peek(&self) -> /*Ignored*/Option; + fn peek(&self) -> Option; - //fn poll(&self, events: /*Ignored*/MessageType, timeout: ClockTime) -> /*Ignored*/Option; + fn pop(&self) -> Option; - //fn pop(&self) -> /*Ignored*/Option; - - //fn pop_filtered(&self, types: /*Ignored*/MessageType) -> /*Ignored*/Option; - - //fn post(&self, message: /*Ignored*/&mut Message) -> bool; + fn post(&self, message: &mut Message) -> bool; fn remove_signal_watch(&self); @@ -60,18 +64,16 @@ pub trait BusExt { //fn set_sync_handler<'a, P: Into>, Q: Into>>(&self, func: P, user_data: Q, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify); - //fn sync_signal_handler>>(&self, message: /*Ignored*/&mut Message, data: P) -> /*Ignored*/BusSyncReply; + //fn sync_signal_handler>>(&self, message: &mut Message, data: P) -> /*Ignored*/BusSyncReply; - //fn timed_pop(&self, timeout: ClockTime) -> /*Ignored*/Option; + fn timed_pop(&self, timeout: ClockTime) -> Option; - //fn timed_pop_filtered(&self, timeout: ClockTime, types: /*Ignored*/MessageType) -> /*Ignored*/Option; + fn connect_message(&self, f: F) -> u64; - //fn connect_message(&self, f: F) -> u64; - - //fn connect_sync_message(&self, f: F) -> u64; + fn connect_sync_message(&self, f: F) -> u64; } -impl> BusExt for O { +impl + IsA> BusExt for O { fn add_signal_watch(&self) { unsafe { ffi::gst_bus_add_signal_watch(self.to_glib_none().0); @@ -92,7 +94,7 @@ impl> BusExt for O { // unsafe { TODO: call ffi::gst_bus_add_watch_full() } //} - //fn async_signal_func>>(&self, message: /*Ignored*/&mut Message, data: P) -> bool { + //fn async_signal_func>>(&self, message: &mut Message, data: P) -> bool { // unsafe { TODO: call ffi::gst_bus_async_signal_func() } //} @@ -118,25 +120,23 @@ impl> BusExt for O { } } - //fn peek(&self) -> /*Ignored*/Option { - // unsafe { TODO: call ffi::gst_bus_peek() } - //} + fn peek(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_bus_peek(self.to_glib_none().0)) + } + } - //fn poll(&self, events: /*Ignored*/MessageType, timeout: ClockTime) -> /*Ignored*/Option { - // unsafe { TODO: call ffi::gst_bus_poll() } - //} + fn pop(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_bus_pop(self.to_glib_none().0)) + } + } - //fn pop(&self) -> /*Ignored*/Option { - // unsafe { TODO: call ffi::gst_bus_pop() } - //} - - //fn pop_filtered(&self, types: /*Ignored*/MessageType) -> /*Ignored*/Option { - // unsafe { TODO: call ffi::gst_bus_pop_filtered() } - //} - - //fn post(&self, message: /*Ignored*/&mut Message) -> bool { - // unsafe { TODO: call ffi::gst_bus_post() } - //} + fn post(&self, message: &mut Message) -> bool { + unsafe { + from_glib(ffi::gst_bus_post(self.to_glib_none().0, message.to_glib_full())) + } + } fn remove_signal_watch(&self) { unsafe { @@ -154,23 +154,43 @@ impl> BusExt for O { // unsafe { TODO: call ffi::gst_bus_set_sync_handler() } //} - //fn sync_signal_handler>>(&self, message: /*Ignored*/&mut Message, data: P) -> /*Ignored*/BusSyncReply { + //fn sync_signal_handler>>(&self, message: &mut Message, data: P) -> /*Ignored*/BusSyncReply { // unsafe { TODO: call ffi::gst_bus_sync_signal_handler() } //} - //fn timed_pop(&self, timeout: ClockTime) -> /*Ignored*/Option { - // unsafe { TODO: call ffi::gst_bus_timed_pop() } - //} + fn timed_pop(&self, timeout: ClockTime) -> Option { + unsafe { + from_glib_full(ffi::gst_bus_timed_pop(self.to_glib_none().0, timeout)) + } + } - //fn timed_pop_filtered(&self, timeout: ClockTime, types: /*Ignored*/MessageType) -> /*Ignored*/Option { - // unsafe { TODO: call ffi::gst_bus_timed_pop_filtered() } - //} + fn connect_message(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "message", + transmute(message_trampoline:: as usize), Box_::into_raw(f) as *mut _) + } + } - //fn connect_message(&self, f: F) -> u64 { - // Ignored message: Gst.Message - //} - - //fn connect_sync_message(&self, f: F) -> u64 { - // Ignored message: Gst.Message - //} + fn connect_sync_message(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "sync-message", + transmute(sync_message_trampoline:: as usize), Box_::into_raw(f) as *mut _) + } + } +} + +unsafe extern "C" fn message_trampoline

(this: *mut ffi::GstBus, message: *mut ffi::GstMessage, f: glib_ffi::gpointer) +where P: IsA { + callback_guard!(); + let f: &Box_ = transmute(f); + f(&Bus::from_glib_none(this).downcast_unchecked(), &from_glib_none(message)) +} + +unsafe extern "C" fn sync_message_trampoline

(this: *mut ffi::GstBus, message: *mut ffi::GstMessage, f: glib_ffi::gpointer) +where P: IsA { + callback_guard!(); + let f: &Box_ = transmute(f); + f(&Bus::from_glib_none(this).downcast_unchecked(), &from_glib_none(message)) } diff --git a/gstreamer/src/auto/element.rs b/gstreamer/src/auto/element.rs index 1086bc6c8..2dbcf26d4 100644 --- a/gstreamer/src/auto/element.rs +++ b/gstreamer/src/auto/element.rs @@ -7,6 +7,7 @@ use ClockTime; use ElementFactory; use Error; use Format; +use Message; use Object; use Pad; use PadTemplate; @@ -140,14 +141,14 @@ pub trait ElementExt { fn lost_state(&self); - //fn message_full<'a, 'b, P: Into>, Q: Into>>(&self, type_: /*Ignored*/MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32); + //fn message_full<'a, 'b, P: Into>, Q: Into>>(&self, type_: 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>, Q: Into>>(&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>, Q: Into>>(&self, type_: MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32, structure: /*Ignored*/&mut Structure); fn no_more_pads(&self); - //fn post_message(&self, message: /*Ignored*/&mut Message) -> bool; + fn post_message(&self, message: &mut Message) -> bool; fn provide_clock(&self) -> Option; @@ -389,12 +390,12 @@ impl + IsA> ElementExt for O { } } - //fn message_full<'a, 'b, P: Into>, Q: Into>>(&self, type_: /*Ignored*/MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32) { + //fn message_full<'a, 'b, P: Into>, Q: Into>>(&self, type_: MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32) { // unsafe { TODO: call ffi::gst_element_message_full() } //} //#[cfg(feature = "v1_10")] - //fn message_full_with_details<'a, 'b, P: Into>, Q: Into>>(&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>, Q: Into>>(&self, type_: MessageType, domain: /*Ignored*/glib::Quark, code: i32, text: P, debug: Q, file: &str, function: &str, line: i32, structure: /*Ignored*/&mut Structure) { // unsafe { TODO: call ffi::gst_element_message_full_with_details() } //} @@ -404,9 +405,11 @@ impl + IsA> ElementExt for O { } } - //fn post_message(&self, message: /*Ignored*/&mut Message) -> bool { - // unsafe { TODO: call ffi::gst_element_post_message() } - //} + fn post_message(&self, message: &mut Message) -> bool { + unsafe { + from_glib(ffi::gst_element_post_message(self.to_glib_none().0, message.to_glib_full())) + } + } fn provide_clock(&self) -> Option { unsafe { diff --git a/gstreamer/src/auto/flags.rs b/gstreamer/src/auto/flags.rs index e79a0220d..e978fc075 100644 --- a/gstreamer/src/auto/flags.rs +++ b/gstreamer/src/auto/flags.rs @@ -4,6 +4,67 @@ use ffi; use glib::translate::*; +bitflags! { + pub struct MessageType: u32 { + const MESSAGE_UNKNOWN = 0; + const MESSAGE_EOS = 1; + const MESSAGE_ERROR = 2; + const MESSAGE_WARNING = 4; + const MESSAGE_INFO = 8; + const MESSAGE_TAG = 16; + const MESSAGE_BUFFERING = 32; + const MESSAGE_STATE_CHANGED = 64; + const MESSAGE_STATE_DIRTY = 128; + const MESSAGE_STEP_DONE = 256; + const MESSAGE_CLOCK_PROVIDE = 512; + const MESSAGE_CLOCK_LOST = 1024; + const MESSAGE_NEW_CLOCK = 2048; + const MESSAGE_STRUCTURE_CHANGE = 4096; + const MESSAGE_STREAM_STATUS = 8192; + const MESSAGE_APPLICATION = 16384; + const MESSAGE_ELEMENT = 32768; + const MESSAGE_SEGMENT_START = 65536; + const MESSAGE_SEGMENT_DONE = 131072; + const MESSAGE_DURATION_CHANGED = 262144; + const MESSAGE_LATENCY = 524288; + const MESSAGE_ASYNC_START = 1048576; + const MESSAGE_ASYNC_DONE = 2097152; + const MESSAGE_REQUEST_STATE = 4194304; + const MESSAGE_STEP_START = 8388608; + const MESSAGE_QOS = 16777216; + const MESSAGE_PROGRESS = 33554432; + const MESSAGE_TOC = 67108864; + const MESSAGE_RESET_TIME = 134217728; + const MESSAGE_STREAM_START = 268435456; + const MESSAGE_NEED_CONTEXT = 536870912; + const MESSAGE_HAVE_CONTEXT = 1073741824; + const MESSAGE_EXTENDED = 2147483648; + const MESSAGE_DEVICE_ADDED = 2147483649; + const MESSAGE_DEVICE_REMOVED = 2147483650; + const MESSAGE_PROPERTY_NOTIFY = 2147483651; + const MESSAGE_STREAM_COLLECTION = 2147483652; + const MESSAGE_STREAMS_SELECTED = 2147483653; + const MESSAGE_REDIRECT = 2147483654; + const MESSAGE_ANY = 4294967295; + } +} + +#[doc(hidden)] +impl ToGlib for MessageType { + type GlibType = ffi::GstMessageType; + + fn to_glib(&self) -> ffi::GstMessageType { + ffi::GstMessageType::from_bits_truncate(self.bits()) + } +} + +#[doc(hidden)] +impl FromGlib for MessageType { + fn from_glib(value: ffi::GstMessageType) -> MessageType { + MessageType::from_bits_truncate(value.bits()) + } +} + bitflags! { pub struct SeekFlags: u32 { const SEEK_FLAG_NONE = 0; diff --git a/gstreamer/src/auto/mod.rs b/gstreamer/src/auto/mod.rs index 008198c43..469335723 100644 --- a/gstreamer/src/auto/mod.rs +++ b/gstreamer/src/auto/mod.rs @@ -52,6 +52,47 @@ pub use self::enums::StateChangeReturn; pub use self::enums::URIType; mod flags; +pub use self::flags::MessageType; +pub use self::flags::MESSAGE_UNKNOWN; +pub use self::flags::MESSAGE_EOS; +pub use self::flags::MESSAGE_ERROR; +pub use self::flags::MESSAGE_WARNING; +pub use self::flags::MESSAGE_INFO; +pub use self::flags::MESSAGE_TAG; +pub use self::flags::MESSAGE_BUFFERING; +pub use self::flags::MESSAGE_STATE_CHANGED; +pub use self::flags::MESSAGE_STATE_DIRTY; +pub use self::flags::MESSAGE_STEP_DONE; +pub use self::flags::MESSAGE_CLOCK_PROVIDE; +pub use self::flags::MESSAGE_CLOCK_LOST; +pub use self::flags::MESSAGE_NEW_CLOCK; +pub use self::flags::MESSAGE_STRUCTURE_CHANGE; +pub use self::flags::MESSAGE_STREAM_STATUS; +pub use self::flags::MESSAGE_APPLICATION; +pub use self::flags::MESSAGE_ELEMENT; +pub use self::flags::MESSAGE_SEGMENT_START; +pub use self::flags::MESSAGE_SEGMENT_DONE; +pub use self::flags::MESSAGE_DURATION_CHANGED; +pub use self::flags::MESSAGE_LATENCY; +pub use self::flags::MESSAGE_ASYNC_START; +pub use self::flags::MESSAGE_ASYNC_DONE; +pub use self::flags::MESSAGE_REQUEST_STATE; +pub use self::flags::MESSAGE_STEP_START; +pub use self::flags::MESSAGE_QOS; +pub use self::flags::MESSAGE_PROGRESS; +pub use self::flags::MESSAGE_TOC; +pub use self::flags::MESSAGE_RESET_TIME; +pub use self::flags::MESSAGE_STREAM_START; +pub use self::flags::MESSAGE_NEED_CONTEXT; +pub use self::flags::MESSAGE_HAVE_CONTEXT; +pub use self::flags::MESSAGE_EXTENDED; +pub use self::flags::MESSAGE_DEVICE_ADDED; +pub use self::flags::MESSAGE_DEVICE_REMOVED; +pub use self::flags::MESSAGE_PROPERTY_NOTIFY; +pub use self::flags::MESSAGE_STREAM_COLLECTION; +pub use self::flags::MESSAGE_STREAMS_SELECTED; +pub use self::flags::MESSAGE_REDIRECT; +pub use self::flags::MESSAGE_ANY; pub use self::flags::SeekFlags; pub use self::flags::SEEK_FLAG_NONE; pub use self::flags::SEEK_FLAG_FLUSH; diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index c0c3ed147..9ffa6ce74 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -32,6 +32,11 @@ pub use glib::{ pub use auto::*; mod auto; +pub mod miniobject; +pub use miniobject::GstRc; +pub mod message; +pub use message::Message; + use std::ptr; pub fn init() -> Result<(), glib::Error> { diff --git a/gstreamer/src/message.rs b/gstreamer/src/message.rs new file mode 100644 index 000000000..8b39c9414 --- /dev/null +++ b/gstreamer/src/message.rs @@ -0,0 +1,73 @@ +// Copyright (C) 2016-2017 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi; +use Object; +use MessageType; +use miniobject::*; +use std::ffi::CStr; + +use glib; +use glib::translate::{from_glib, from_glib_none, from_glib_full, ToGlibPtr, ToGlib}; + +#[repr(C)] +pub struct MessageImpl(ffi::GstMessage); + +pub type Message = GstRc; + +unsafe impl MiniObject for MessageImpl { + type GstType = ffi::GstMessage; +} + +impl MessageImpl { + pub fn new_eos(src: &Object) -> GstRc { + unsafe { + from_glib_full(ffi::gst_message_new_eos(src.to_glib_none().0)) + } + } + + pub fn get_src(&self) -> Object { + unsafe { + from_glib_none((*self.as_ptr()).src) + } + } + + pub fn get_message_type(&self) -> MessageType { + unsafe { + from_glib((*self.as_ptr()).type_) + } + } + + pub fn get_message_type_name(&self) -> &'static str { + unsafe { + CStr::from_ptr(ffi::gst_message_type_get_name(self.get_message_type().to_glib())).to_str().unwrap() + } + } + + pub fn get_seqnum(&self) -> u32 { + unsafe { + ffi::gst_message_get_seqnum(self.as_mut_ptr()) + } + } + + pub fn set_seqnum(&mut self, seqnum: u32) { + unsafe { + ffi::gst_message_set_seqnum(self.as_mut_ptr(), seqnum) + } + } + + // TODO get_structure(), get_mut_structure() +} + +impl glib::types::StaticType for GstRc { + fn static_type() -> glib::types::Type { + unsafe { + from_glib(ffi::gst_message_get_type()) + } + } +} diff --git a/gstreamer/src/miniobject.rs b/gstreamer/src/miniobject.rs new file mode 100644 index 000000000..0e8978596 --- /dev/null +++ b/gstreamer/src/miniobject.rs @@ -0,0 +1,258 @@ +// Copyright (C) 2016-2017 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::{fmt, ops, borrow}; +use std::mem; +use std::marker::PhantomData; + +use ffi; +use glib; +use glib::translate::{from_glib, Stash, StashMut, ToGlibPtr, ToGlibPtrMut, FromGlibPtrNone, FromGlibPtrFull, FromGlibPtrBorrow}; + +#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct GstRc { + obj: *mut T, + borrowed: bool, + phantom: PhantomData, +} + +impl GstRc { + pub unsafe fn from_glib_none(ptr: *const T::GstType) -> Self { + assert!(!ptr.is_null()); + + ffi::gst_mini_object_ref(ptr as *mut ffi::GstMiniObject); + + GstRc { + obj: T::from_mut_ptr(ptr as *mut T::GstType) as *mut T, + borrowed: false, + phantom: PhantomData, + } + } + + pub unsafe fn from_glib_full(ptr: *const T::GstType) -> Self { + assert!(!ptr.is_null()); + + GstRc { + obj: T::from_mut_ptr(ptr as *mut T::GstType) as *mut T, + borrowed: false, + phantom: PhantomData, + } + } + + pub unsafe fn from_glib_borrow(ptr: *const T::GstType) -> Self { + assert!(!ptr.is_null()); + + GstRc { + obj: T::from_mut_ptr(ptr as *mut T::GstType) as *mut T, + borrowed: true, + phantom: PhantomData, + } + } + + pub fn make_mut(&mut self) -> &mut T { + unsafe { + if self.is_writable() { + return &mut *self.obj; + } + + self.obj = T::from_mut_ptr( + ffi::gst_mini_object_make_writable( + self.as_mut_ptr() as *mut ffi::GstMiniObject + ) as *mut T::GstType + ); + assert!(self.is_writable()); + + &mut *self.obj + } + } + + pub fn get_mut(&mut self) -> Option<&mut T> { + if self.is_writable() { + Some(unsafe { &mut *self.obj }) + } else { + None + } + } + + pub fn copy(&self) -> Self { + unsafe { + GstRc::from_glib_full( + ffi::gst_mini_object_copy( + self.as_ptr() as *const ffi::GstMiniObject + ) as *const T::GstType + ) + } + } + + pub fn is_writable(&self) -> bool { + unsafe { + from_glib(ffi::gst_mini_object_is_writable(self.as_ptr() as *const ffi::GstMiniObject)) + } + } + + pub unsafe fn into_ptr(self) -> *mut T::GstType { + let ptr = self.as_mut_ptr(); + mem::forget(self); + + ptr + } +} + +impl ops::Deref for GstRc { + type Target = T; + fn deref(&self) -> &T { + self.as_ref() + } +} + +impl AsRef for GstRc { + fn as_ref(&self) -> &T { + unsafe { &*self.obj } + } +} + +impl borrow::Borrow for GstRc { + fn borrow(&self) -> &T { + self.as_ref() + } +} + +// FIXME: Not generally possible because neither T nor ToOwned are defined here... +//impl ToOwned for T { +// type Owned = GstRc; +// +// fn to_owned(&self) -> GstRc { +// unsafe { GstRc::from_unowned_ptr(self.as_ptr()) } +// } +//} + +impl Clone for GstRc { + fn clone(&self) -> GstRc { + unsafe { GstRc::from_glib_none(self.as_ptr()) } + } +} + +impl Drop for GstRc { + fn drop(&mut self) { + if !self.borrowed { + unsafe { + ffi::gst_mini_object_unref(self.as_mut_ptr() as *mut ffi::GstMiniObject); + } + } + } +} + +unsafe impl Sync for GstRc {} +unsafe impl Send for GstRc {} + +impl fmt::Display for GstRc { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (unsafe { &*self.obj }).fmt(f) + } +} + +pub unsafe trait MiniObject +where + Self: Sized, +{ + type GstType; + + unsafe fn as_ptr(&self) -> *const Self::GstType { + self as *const Self as *const Self::GstType + } + + unsafe fn as_mut_ptr(&self) -> *mut Self::GstType { + self as *const Self as *mut Self::GstType + } + + unsafe fn from_ptr<'a>(ptr: *const Self::GstType) -> &'a Self { + assert!(!ptr.is_null()); + &*(ptr as *const Self) + } + + unsafe fn from_mut_ptr<'a>(ptr: *mut Self::GstType) -> &'a mut Self { + assert!(!ptr.is_null()); + &mut *(ptr as *mut Self) + } +} + +impl<'a, T: MiniObject + 'static> ToGlibPtr<'a, *const T::GstType> for GstRc { + type Storage = &'a Self; + + fn to_glib_none(&'a self) -> Stash<'a, *const T::GstType, Self> { + Stash(unsafe { self.as_ptr() }, self) + } + + fn to_glib_full(&self) -> *const T::GstType { + unsafe { + ffi::gst_mini_object_ref(self.as_mut_ptr() as *mut ffi::GstMiniObject); + self.as_ptr() + } + } +} + +impl<'a, T: MiniObject + 'static> ToGlibPtr<'a, *mut T::GstType> for GstRc { + type Storage = &'a Self; + + fn to_glib_none(&'a self) -> Stash<'a, *mut T::GstType, Self> { + Stash(unsafe { self.as_mut_ptr() }, self) + } + + fn to_glib_full(&self) -> *mut T::GstType { + unsafe { + ffi::gst_mini_object_ref(self.as_mut_ptr() as *mut ffi::GstMiniObject); + self.as_mut_ptr() + } + } +} + +impl<'a, T: MiniObject + 'static> ToGlibPtrMut<'a, *mut T::GstType> for GstRc { + type Storage = &'a mut Self; + + fn to_glib_none_mut(&'a mut self) -> StashMut<*mut T::GstType, Self> { + self.make_mut(); + StashMut(unsafe { self.as_mut_ptr() }, self) + } +} + +impl FromGlibPtrNone<*const T::GstType> for GstRc { + unsafe fn from_glib_none(ptr: *const T::GstType) -> Self { + Self::from_glib_none(ptr) + } +} + +impl FromGlibPtrNone<*mut T::GstType> for GstRc { + unsafe fn from_glib_none(ptr: *mut T::GstType) -> Self { + Self::from_glib_none(ptr) + } +} + +impl FromGlibPtrFull<*const T::GstType> for GstRc { + unsafe fn from_glib_full(ptr: *const T::GstType) -> Self { + Self::from_glib_full(ptr) + } +} + +impl FromGlibPtrFull<*mut T::GstType> for GstRc { + unsafe fn from_glib_full(ptr: *mut T::GstType) -> Self { + Self::from_glib_full(ptr) + } +} + +impl FromGlibPtrBorrow<*const T::GstType> for GstRc { + unsafe fn from_glib_borrow(ptr: *const T::GstType) -> Self { + Self::from_glib_borrow(ptr) + } +} + +impl FromGlibPtrBorrow<*mut T::GstType> for GstRc { + unsafe fn from_glib_borrow(ptr: *mut T::GstType) -> Self { + Self::from_glib_borrow(ptr) + } +} +