Commit 77cb4da3 authored by Sebastian Dröge's avatar Sebastian Dröge 🍵

Add ClockId and related waiting API, and SystemClock

Fixes https://github.com/sdroege/gstreamer-rs/issues/23
parent d6c869b6
......@@ -15,6 +15,7 @@ external_libraries = [
generate = [
"Gst.ClockTime",
"Gst.ClockTimeDiff",
"Gst.Pipeline",
"Gst.State",
"Gst.StateChangeReturn",
......@@ -64,6 +65,8 @@ generate = [
"Gst.TocEntryType",
"Gst.TocLoopType",
"Gst.TocSetter",
"Gst.ClockType",
"Gst.ClockReturn",
]
manual = [
......@@ -193,6 +196,14 @@ status = "generate"
[object.function.return]
bool_return_is_error = "Timed out waiting for sync"
[[object]]
name = "Gst.SystemClock"
status = "generate"
[[object.function]]
name = "obtain"
[object.function.return]
nullable = false
[[object]]
name = "Gst.Element"
status = "generate"
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
#[allow(unused_imports)]
use auto::*;
pub type ClockTime = u64;
pub type ClockTimeDiff = i64;
pub type ElementFactoryListType = u64;
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use ChildProxy;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use ClockTime;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use ffi;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use ClockTime;
......@@ -46,11 +46,11 @@ impl Clock {
// unsafe { TODO: call ffi::gst_clock_id_unschedule() }
//}
//pub fn id_wait(id: /*Unimplemented*/ClockID) -> (/*Ignored*/ClockReturn, ClockTimeDiff) {
//pub fn id_wait(id: /*Unimplemented*/ClockID) -> (ClockReturn, ClockTimeDiff) {
// unsafe { TODO: call ffi::gst_clock_id_wait() }
//}
//pub fn id_wait_async<P: Into<Option</*Unimplemented*/Fundamental: Pointer>>>(id: /*Unimplemented*/ClockID, func: /*Unknown conversion*//*Unimplemented*/ClockCallback, user_data: P, destroy_data: /*Unknown conversion*//*Unimplemented*/DestroyNotify) -> /*Ignored*/ClockReturn {
//pub fn id_wait_async<P: Into<Option</*Unimplemented*/Fundamental: Pointer>>>(id: /*Unimplemented*/ClockID, func: /*Unknown conversion*//*Unimplemented*/ClockCallback, user_data: P, destroy_data: /*Unknown conversion*//*Unimplemented*/DestroyNotify) -> ClockReturn {
// unsafe { TODO: call ffi::gst_clock_id_wait_async() }
//}
}
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use ffi;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Caps;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Bus;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Bus;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use DeviceProvider;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Bus;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Caps;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use ffi;
......@@ -191,6 +191,141 @@ impl SetValue for CapsIntersectMode {
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum ClockReturn {
Ok,
Early,
Unscheduled,
Busy,
Badtime,
Error,
Unsupported,
Done,
#[doc(hidden)]
__Unknown(i32),
}
#[doc(hidden)]
impl ToGlib for ClockReturn {
type GlibType = ffi::GstClockReturn;
fn to_glib(&self) -> ffi::GstClockReturn {
match *self {
ClockReturn::Ok => ffi::GST_CLOCK_OK,
ClockReturn::Early => ffi::GST_CLOCK_EARLY,
ClockReturn::Unscheduled => ffi::GST_CLOCK_UNSCHEDULED,
ClockReturn::Busy => ffi::GST_CLOCK_BUSY,
ClockReturn::Badtime => ffi::GST_CLOCK_BADTIME,
ClockReturn::Error => ffi::GST_CLOCK_ERROR,
ClockReturn::Unsupported => ffi::GST_CLOCK_UNSUPPORTED,
ClockReturn::Done => ffi::GST_CLOCK_DONE,
ClockReturn::__Unknown(value) => unsafe{std::mem::transmute(value)}
}
}
}
#[doc(hidden)]
impl FromGlib<ffi::GstClockReturn> for ClockReturn {
fn from_glib(value: ffi::GstClockReturn) -> Self {
skip_assert_initialized!();
match value as i32 {
0 => ClockReturn::Ok,
1 => ClockReturn::Early,
2 => ClockReturn::Unscheduled,
3 => ClockReturn::Busy,
4 => ClockReturn::Badtime,
5 => ClockReturn::Error,
6 => ClockReturn::Unsupported,
7 => ClockReturn::Done,
value => ClockReturn::__Unknown(value),
}
}
}
impl StaticType for ClockReturn {
fn static_type() -> Type {
unsafe { from_glib(ffi::gst_clock_return_get_type()) }
}
}
impl<'a> FromValueOptional<'a> for ClockReturn {
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
Some(FromValue::from_value(value))
}
}
impl<'a> FromValue<'a> for ClockReturn {
unsafe fn from_value(value: &Value) -> Self {
from_glib(std::mem::transmute::<i32, ffi::GstClockReturn>(gobject_ffi::g_value_get_enum(value.to_glib_none().0)))
}
}
impl SetValue for ClockReturn {
unsafe fn set_value(value: &mut Value, this: &Self) {
gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib() as i32)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum ClockType {
Realtime,
Monotonic,
Other,
#[doc(hidden)]
__Unknown(i32),
}
#[doc(hidden)]
impl ToGlib for ClockType {
type GlibType = ffi::GstClockType;
fn to_glib(&self) -> ffi::GstClockType {
match *self {
ClockType::Realtime => ffi::GST_CLOCK_TYPE_REALTIME,
ClockType::Monotonic => ffi::GST_CLOCK_TYPE_MONOTONIC,
ClockType::Other => ffi::GST_CLOCK_TYPE_OTHER,
ClockType::__Unknown(value) => unsafe{std::mem::transmute(value)}
}
}
}
#[doc(hidden)]
impl FromGlib<ffi::GstClockType> for ClockType {
fn from_glib(value: ffi::GstClockType) -> Self {
skip_assert_initialized!();
match value as i32 {
0 => ClockType::Realtime,
1 => ClockType::Monotonic,
2 => ClockType::Other,
value => ClockType::__Unknown(value),
}
}
}
impl StaticType for ClockType {
fn static_type() -> Type {
unsafe { from_glib(ffi::gst_clock_type_get_type()) }
}
}
impl<'a> FromValueOptional<'a> for ClockType {
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
Some(FromValue::from_value(value))
}
}
impl<'a> FromValue<'a> for ClockType {
unsafe fn from_value(value: &Value) -> Self {
from_glib(std::mem::transmute::<i32, ffi::GstClockType>(gobject_ffi::g_value_get_enum(value.to_glib_none().0)))
}
}
impl SetValue for ClockType {
unsafe fn set_value(value: &mut Value, this: &Self) {
gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib() as i32)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum CoreError {
Failed,
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use ffi;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Bin;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Object;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
mod bin;
......@@ -84,6 +84,10 @@ pub use self::stream_collection::StreamCollection;
#[cfg(feature = "v1_10")]
pub use self::stream_collection::StreamCollectionExt;
mod system_clock;
pub use self::system_clock::SystemClock;
pub use self::system_clock::SystemClockExt;
mod tag_setter;
pub use self::tag_setter::TagSetter;
pub use self::tag_setter::TagSetterExt;
......@@ -103,6 +107,8 @@ mod enums;
pub use self::enums::BufferingMode;
pub use self::enums::BusSyncReply;
pub use self::enums::CapsIntersectMode;
pub use self::enums::ClockReturn;
pub use self::enums::ClockType;
pub use self::enums::CoreError;
pub use self::enums::EventType;
pub use self::enums::FlowReturn;
......@@ -210,6 +216,7 @@ pub use self::flags::STREAM_TYPE_TEXT;
mod alias;
pub use self::alias::ClockTime;
pub use self::alias::ClockTimeDiff;
pub use self::alias::ElementFactoryListType;
pub mod functions;
......@@ -235,6 +242,7 @@ pub mod traits {
pub use super::StreamExt;
#[cfg(feature = "v1_10")]
pub use super::StreamCollectionExt;
pub use super::SystemClockExt;
pub use super::TagSetterExt;
pub use super::TocSetterExt;
pub use super::URIHandlerExt;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use ClockTime;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Caps;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Caps;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Bin;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Error;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use ffi;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Iterator;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
#[cfg(feature = "v1_10")]
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Object;
......
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Clock;
use ClockType;
use Object;
use ffi;
use glib;
use glib::Value;
use glib::object::IsA;
use glib::translate::*;
use glib_ffi;
use gobject_ffi;
use std::mem;
use std::mem::transmute;
use std::ptr;
glib_wrapper! {
pub struct SystemClock(Object<ffi::GstSystemClock>): Clock, Object;
match fn {
get_type => || ffi::gst_system_clock_get_type(),
}
}
impl SystemClock {
pub fn obtain() -> Clock {
assert_initialized_main_thread!();
unsafe {
from_glib_full(ffi::gst_system_clock_obtain())
}
}
pub fn set_default<P: IsA<Clock>>(new_clock: &P) {
skip_assert_initialized!();
unsafe {
ffi::gst_system_clock_set_default(new_clock.to_glib_none().0);
}
}
}
unsafe impl Send for SystemClock {}
unsafe impl Sync for SystemClock {}
pub trait SystemClockExt {
fn get_property_clock_type(&self) -> ClockType;
fn set_property_clock_type(&self, clock_type: ClockType);
}
impl<O: IsA<SystemClock> + IsA<glib::object::Object>> SystemClockExt for O {
fn get_property_clock_type(&self) -> ClockType {
let mut value = Value::from(&0);
unsafe {
gobject_ffi::g_object_get_property(self.to_glib_none().0, "clock-type".to_glib_none().0, value.to_glib_none_mut().0);
from_glib(transmute(value.get::<i32>().unwrap()))
}
}
fn set_property_clock_type(&self, clock_type: ClockType) {
let clock_type = clock_type.to_glib() as i32;
unsafe {
gobject_ffi::g_object_set_property(self.to_glib_none().0, "clock-type".to_glib_none().0, Value::from(&clock_type).to_glib_none().0);
}
}
}
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Element;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Element;
......
// This file was generated by gir (3294959) from gir-files (???)
// This file was generated by gir (cf27827) from gir-files (???)
// DO NOT EDIT
use Error;
......
......@@ -26,13 +26,15 @@ unsafe extern "C" fn trampoline_watch(
func: gpointer,
) -> gboolean {
let _guard = CallbackGuard::new();
let func: &RefCell<Box<FnMut(&Bus, &Message) -> Continue + 'static>> = transmute(func);
let func: &RefCell<Box<FnMut(&Bus, &Message) -> Continue + Send + 'static>> = transmute(func);
(&mut *func.borrow_mut())(&from_glib_none(bus), &Message::from_glib_none(msg)).to_glib()
}
unsafe extern "C" fn destroy_closure_watch(ptr: gpointer) {
let _guard = CallbackGuard::new();
Box::<RefCell<Box<FnMut(&Bus, &Message) -> Continue + 'static>>>::from_raw(ptr as *mut _);
Box::<RefCell<Box<FnMut(&Bus, &Message) -> Continue + Send + 'static>>>::from_raw(
ptr as *mut _,
);
}
fn into_raw_watch<F: FnMut(&Bus, &Message) -> Continue + Send + 'static>(func: F) -> gpointer {
......@@ -47,17 +49,19 @@ unsafe extern "C" fn trampoline_sync(
func: gpointer,
) -> ffi::GstBusSyncReply {
let _guard = CallbackGuard::new();
let f: &&(Fn(&Bus, &Message) -> BusSyncReply + 'static) = transmute(func);
let f: &&(Fn(&Bus, &Message) -> BusSyncReply + Send + Sync + 'static) = transmute(func);
f(&from_glib_none(bus), &Message::from_glib_none(msg)).to_glib()
}
unsafe extern "C" fn destroy_closure_sync(ptr: gpointer) {
let _guard = CallbackGuard::new();
Box::<Box<Fn(&Bus, &Message) -> BusSyncReply + 'static>>::from_raw(ptr as *mut _);
Box::<Box<Fn(&Bus, &Message) -> BusSyncReply + Send + Sync + 'static>>::from_raw(ptr as *mut _);
}
fn into_raw_sync<F: Fn(&Bus, &Message) -> BusSyncReply + Send + 'static>(func: F) -> gpointer {
let func: Box<Box<Fn(&Bus, &Message) -> BusSyncReply + Send + 'static>> =
fn into_raw_sync<F: Fn(&Bus, &Message) -> BusSyncReply + Send + Sync + 'static>(
func: F,
) -> gpointer {
let func: Box<Box<Fn(&Bus, &Message) -> BusSyncReply + Send + Sync + 'static>> =
Box::new(Box::new(func));
Box::into_raw(func) as gpointer
}
......
// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use Clock;
use ClockTime;
use ClockTimeDiff;
use ClockReturn;
use std::mem;
use std::cmp;
use std::ptr;
use std::mem::transmute;
use ffi;
use glib;
use glib::IsA;
use glib::translate::*;
use glib::source::CallbackGuard;
use glib_ffi;
use glib_ffi::{gboolean, gpointer};
use libc::c_void;
glib_wrapper! {
pub struct ClockId(Shared<c_void>);
match fn {
ref => |ptr| ffi::gst_clock_id_ref(ptr),
unref => |ptr| ffi::gst_clock_id_unref(ptr),
}
}
unsafe extern "C" fn trampoline_wait_async(
clock: *mut ffi::GstClock,
time: ClockTime,
id: gpointer,
func: gpointer,
) -> gboolean {
let _guard = CallbackGuard::new();
let f: &&(Fn(&Clock, ClockTime, &ClockId) -> bool + Send + 'static) = transmute(func);
f(&from_glib_none(clock), time, &from_glib_none(id)).to_glib()
}
unsafe extern "C" fn destroy_closure_wait_async(ptr: gpointer) {
let _guard = CallbackGuard::new();
Box::<Box<Fn(&Clock, ClockTime, &ClockId) -> bool + Send + 'static>>::from_raw(ptr as *mut _);
}
fn into_raw_wait_async<F: Fn(&Clock, ClockTime, &ClockId) -> bool + Send + 'static>(
func: F,
) -> gpointer {
let func: Box<Box<Fn(&Clock, ClockTime, &ClockId) -> bool + Send + 'static>> =
Box::new(Box::new(func));
Box::into_raw(func) as gpointer
}
impl ClockId {
pub fn get_time(&self) -> ClockTime {
unsafe { ffi::gst_clock_id_get_time(self.to_glib_none().0) }
}
pub fn unschedule(&self) {
unsafe { ffi::gst_clock_id_unschedule(self.to_glib_none().0) }
}
pub fn wait(&self) -> (ClockReturn, ClockTimeDiff) {
unsafe {
let mut jitter = mem::uninitialized();
let res = ffi::gst_clock_id_wait(self.to_glib_none().0, &mut jitter);
(from_glib(res), jitter)
}
}
pub fn wait_async<F>(&self, func: F) -> ClockReturn
where
F: Fn(&Clock, ClockTime, &ClockId) -> bool + Send + 'static,
{
unsafe {
from_glib(ffi::gst_clock_id_wait_async(
self.to_glib_none().0,
Some(trampoline_wait_async),
into_raw_wait_async(func),
Some(destroy_closure_wait_async),
))
}
}
}
impl PartialOrd for ClockId {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ClockId {
fn cmp(&self, other: &Self) -> cmp::Ordering {
unsafe {
let res = ffi::gst_clock_id_compare_func(self.to_glib_none().0, other.to_glib_none().0);
if res < 0 {
cmp::Ordering::Less
} else if res > 0 {
cmp::Ordering::Greater
} else {
cmp::Ordering::Equal
}
}
}
}
impl PartialEq for ClockId {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == cmp::Ordering::Equal
}
}
impl Eq for ClockId {}
unsafe impl Send for ClockId {}
unsafe impl Sync for ClockId {}
pub trait ClockExtManual {
fn new_periodic_id(&self, start_time: ClockTime, interval: ClockTime) -> Option<ClockId>;
fn periodic_id_reinit(
&self,
id: &ClockId,
start_time: ClockTime,
interval: ClockTime,
) -> Result<(), glib::BoolError>;
fn new_single_shot_id(&self, time: ClockTime) -> Option<ClockId>;
fn single_shot_id_reinit(&self, id: &ClockId, time: ClockTime) -> Result<(), glib::BoolError>;
}
impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExtManual for O {
fn new_periodic_id(&self, start_time: ClockTime, interval: ClockTime) -> Option<ClockId> {
unsafe {
from_glib_full(ffi::gst_clock_new_periodic_id(
self.to_glib_none().0,
start_time,
interval,
))
}
}
fn periodic_id_reinit(
&self,
id: &ClockId,
start_time: ClockTime,
interval: ClockTime,
) -> Result<(), glib::BoolError> {
unsafe {
let res: bool = from_glib(ffi::gst_clock_periodic_id_reinit(
self.to_glib_none().0,
id.to_glib_none().0,
start_time,
interval,
));
if res {
Ok(())
} else {
Err(glib::BoolError("Failed to reinit periodic clock id"))
}
}
}
fn new_single_shot_id(&self, time: ClockTime) -> Option<ClockId> {
unsafe {
from_glib_full(ffi::gst_clock_new_single_shot_id(
self.to_glib_none().0,
time,
))
}
}
fn single_shot_id_reinit(&self, id: &ClockId, time: ClockTime) -> Result<(), glib::BoolError> {
unsafe {
let res: bool = from_glib(ffi::gst_clock_single_shot_id_reinit(
self.to_glib_none().0,
id.to_glib_none().0,
time,
));
if res {
Ok(())
} else {
Err(glib::BoolError("Failed to reinit single shot clock id"))
}
}
}
}
#[cfg(test)]
mod tests {