2017-08-13 22:40:43 +00:00
|
|
|
// 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 glib;
|
2019-04-23 15:47:13 +00:00
|
|
|
#[cfg(any(feature = "v1_16", feature = "dox"))]
|
|
|
|
use glib::prelude::*;
|
2018-04-01 08:30:03 +00:00
|
|
|
use glib::translate::*;
|
2018-04-25 08:10:06 +00:00
|
|
|
use glib::IsA;
|
2019-03-19 07:58:20 +00:00
|
|
|
use glib_sys::{gboolean, gpointer};
|
|
|
|
use gst_sys;
|
2017-08-13 22:40:43 +00:00
|
|
|
use libc::c_void;
|
2018-04-01 08:30:03 +00:00
|
|
|
use std::cmp;
|
2020-10-10 09:10:52 +00:00
|
|
|
use std::convert;
|
2018-04-01 08:30:03 +00:00
|
|
|
use std::ptr;
|
2018-04-25 08:10:06 +00:00
|
|
|
use Clock;
|
2019-09-25 14:17:39 +00:00
|
|
|
use ClockEntryType;
|
2019-01-08 16:13:37 +00:00
|
|
|
use ClockError;
|
2019-09-25 13:46:46 +00:00
|
|
|
use ClockFlags;
|
2018-04-25 08:10:06 +00:00
|
|
|
use ClockReturn;
|
2019-01-08 16:13:37 +00:00
|
|
|
use ClockSuccess;
|
2018-04-25 08:10:06 +00:00
|
|
|
use ClockTime;
|
|
|
|
use ClockTimeDiff;
|
2017-08-13 22:40:43 +00:00
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
use futures_core::{Future, Stream};
|
2020-10-01 07:13:52 +00:00
|
|
|
use std::marker::Unpin;
|
|
|
|
use std::pin::Pin;
|
2019-09-25 14:17:39 +00:00
|
|
|
use std::sync::atomic;
|
|
|
|
use std::sync::atomic::AtomicI32;
|
|
|
|
|
2017-08-13 22:40:43 +00:00
|
|
|
glib_wrapper! {
|
2019-02-21 16:48:57 +00:00
|
|
|
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
2017-08-13 22:40:43 +00:00
|
|
|
pub struct ClockId(Shared<c_void>);
|
|
|
|
|
|
|
|
match fn {
|
2019-03-19 07:58:20 +00:00
|
|
|
ref => |ptr| gst_sys::gst_clock_id_ref(ptr),
|
|
|
|
unref => |ptr| gst_sys::gst_clock_id_unref(ptr),
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ClockId {
|
|
|
|
pub fn get_time(&self) -> ClockTime {
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe { from_glib(gst_sys::gst_clock_id_get_time(self.to_glib_none().0)) }
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unschedule(&self) {
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe { gst_sys::gst_clock_id_unschedule(self.to_glib_none().0) }
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
|
2019-01-08 16:13:37 +00:00
|
|
|
pub fn wait(&self) -> (Result<ClockSuccess, ClockError>, ClockTimeDiff) {
|
2017-08-13 22:40:43 +00:00
|
|
|
unsafe {
|
2019-07-11 12:34:28 +00:00
|
|
|
let mut jitter = 0;
|
2019-03-19 07:58:20 +00:00
|
|
|
let res: ClockReturn = from_glib(gst_sys::gst_clock_id_wait(
|
|
|
|
self.to_glib_none().0,
|
|
|
|
&mut jitter,
|
|
|
|
));
|
2019-01-08 16:13:37 +00:00
|
|
|
(res.into_result(), jitter)
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
pub fn compare_by_time(&self, other: &Self) -> cmp::Ordering {
|
|
|
|
unsafe {
|
|
|
|
let res =
|
|
|
|
gst_sys::gst_clock_id_compare_func(self.to_glib_none().0, other.to_glib_none().0);
|
|
|
|
res.cmp(&0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(feature = "v1_16", feature = "dox"))]
|
|
|
|
pub fn get_clock(&self) -> Option<Clock> {
|
|
|
|
unsafe { from_glib_full(gst_sys::gst_clock_id_get_clock(self.to_glib_none().0)) }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(feature = "v1_16", feature = "dox"))]
|
|
|
|
pub fn uses_clock<P: IsA<Clock>>(&self, clock: &P) -> bool {
|
|
|
|
unsafe {
|
|
|
|
from_glib(gst_sys::gst_clock_id_uses_clock(
|
|
|
|
self.to_glib_none().0,
|
|
|
|
clock.as_ref().as_ptr(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_type(&self) -> ClockEntryType {
|
|
|
|
unsafe {
|
|
|
|
let ptr: *mut gst_sys::GstClockEntry = self.to_glib_none().0 as *mut _;
|
|
|
|
from_glib((*ptr).type_)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_status(&self) -> &AtomicClockReturn {
|
|
|
|
unsafe {
|
|
|
|
let ptr: *mut gst_sys::GstClockEntry = self.to_glib_none().0 as *mut _;
|
|
|
|
&*((&(*ptr).status) as *const i32 as *const AtomicClockReturn)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
|
|
|
pub struct SingleShotClockId(ClockId);
|
|
|
|
|
|
|
|
impl std::ops::Deref for SingleShotClockId {
|
|
|
|
type Target = ClockId;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<SingleShotClockId> for ClockId {
|
|
|
|
fn from(id: SingleShotClockId) -> ClockId {
|
|
|
|
skip_assert_initialized!();
|
|
|
|
id.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl convert::TryFrom<ClockId> for SingleShotClockId {
|
|
|
|
type Error = glib::BoolError;
|
|
|
|
|
|
|
|
fn try_from(id: ClockId) -> Result<SingleShotClockId, glib::BoolError> {
|
|
|
|
skip_assert_initialized!();
|
|
|
|
match id.get_type() {
|
|
|
|
ClockEntryType::Single => Ok(SingleShotClockId(id)),
|
|
|
|
_ => Err(glib_bool_error!("Not a single-shot clock id")),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SingleShotClockId {
|
|
|
|
pub fn compare_by_time(&self, other: &Self) -> cmp::Ordering {
|
|
|
|
self.0.compare_by_time(&other.0)
|
|
|
|
}
|
|
|
|
|
2019-01-08 16:13:37 +00:00
|
|
|
pub fn wait_async<F>(&self, func: F) -> Result<ClockSuccess, ClockError>
|
2017-08-13 22:40:43 +00:00
|
|
|
where
|
2020-10-10 09:10:52 +00:00
|
|
|
F: FnOnce(&Clock, ClockTime, &ClockId) + Send + 'static,
|
2017-08-13 22:40:43 +00:00
|
|
|
{
|
2020-10-10 09:10:52 +00:00
|
|
|
unsafe extern "C" fn trampoline<F: FnOnce(&Clock, ClockTime, &ClockId) + Send + 'static>(
|
|
|
|
clock: *mut gst_sys::GstClock,
|
|
|
|
time: gst_sys::GstClockTime,
|
|
|
|
id: gpointer,
|
|
|
|
func: gpointer,
|
|
|
|
) -> gboolean {
|
|
|
|
let f: &mut Option<F> = &mut *(func as *mut Option<F>);
|
|
|
|
let f = f.take().unwrap();
|
|
|
|
|
|
|
|
f(
|
|
|
|
&from_glib_borrow(clock),
|
|
|
|
from_glib(time),
|
|
|
|
&from_glib_borrow(id),
|
|
|
|
);
|
|
|
|
|
|
|
|
glib_sys::GTRUE
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe extern "C" fn destroy_notify<
|
|
|
|
F: FnOnce(&Clock, ClockTime, &ClockId) + Send + 'static,
|
|
|
|
>(
|
|
|
|
ptr: gpointer,
|
|
|
|
) {
|
|
|
|
Box::<Option<F>>::from_raw(ptr as *mut _);
|
|
|
|
}
|
|
|
|
|
|
|
|
let func: Box<Option<F>> = Box::new(Some(func));
|
|
|
|
|
2019-01-08 16:13:37 +00:00
|
|
|
let ret: ClockReturn = unsafe {
|
2019-03-19 07:58:20 +00:00
|
|
|
from_glib(gst_sys::gst_clock_id_wait_async(
|
2017-08-13 22:40:43 +00:00
|
|
|
self.to_glib_none().0,
|
2020-10-10 09:10:52 +00:00
|
|
|
Some(trampoline::<F>),
|
|
|
|
Box::into_raw(func) as gpointer,
|
|
|
|
Some(destroy_notify::<F>),
|
2017-08-13 22:40:43 +00:00
|
|
|
))
|
2019-01-08 16:13:37 +00:00
|
|
|
};
|
|
|
|
ret.into_result()
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
|
2020-10-01 07:13:52 +00:00
|
|
|
#[allow(clippy::type_complexity)]
|
2020-10-10 09:10:52 +00:00
|
|
|
pub fn wait_async_future(
|
2020-10-01 07:13:52 +00:00
|
|
|
&self,
|
|
|
|
) -> Result<
|
2020-10-10 09:10:52 +00:00
|
|
|
Pin<
|
|
|
|
Box<
|
|
|
|
dyn Future<Output = Result<(ClockTime, ClockId), ClockError>>
|
|
|
|
+ Unpin
|
|
|
|
+ Send
|
|
|
|
+ 'static,
|
|
|
|
>,
|
|
|
|
>,
|
2020-10-01 07:13:52 +00:00
|
|
|
ClockError,
|
|
|
|
> {
|
2020-10-10 09:10:52 +00:00
|
|
|
use futures_channel::oneshot;
|
|
|
|
use futures_util::TryFutureExt;
|
2020-10-01 07:13:52 +00:00
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
let (sender, receiver) = oneshot::channel();
|
2020-10-01 07:13:52 +00:00
|
|
|
|
|
|
|
self.wait_async(move |_clock, jitter, id| {
|
2020-10-10 09:10:52 +00:00
|
|
|
if sender.send((jitter, id.clone())).is_err() {
|
2020-10-01 08:25:40 +00:00
|
|
|
// Unschedule any future calls if the receiver end is disconnected
|
|
|
|
id.unschedule();
|
|
|
|
}
|
2020-10-01 07:13:52 +00:00
|
|
|
})?;
|
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
Ok(Box::pin(receiver.map_err(|_| ClockError::Unscheduled)))
|
2020-10-01 07:13:52 +00:00
|
|
|
}
|
2020-10-10 09:10:52 +00:00
|
|
|
}
|
2020-10-01 07:13:52 +00:00
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
|
|
|
pub struct PeriodicClockId(ClockId);
|
|
|
|
|
|
|
|
impl std::ops::Deref for PeriodicClockId {
|
|
|
|
type Target = ClockId;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
2020-10-10 09:10:52 +00:00
|
|
|
}
|
2019-04-23 15:47:13 +00:00
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
impl From<PeriodicClockId> for ClockId {
|
|
|
|
fn from(id: PeriodicClockId) -> ClockId {
|
|
|
|
skip_assert_initialized!();
|
|
|
|
id.0
|
2019-04-23 15:47:13 +00:00
|
|
|
}
|
2020-10-10 09:10:52 +00:00
|
|
|
}
|
2019-04-23 15:47:13 +00:00
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
impl convert::TryFrom<ClockId> for PeriodicClockId {
|
|
|
|
type Error = glib::BoolError;
|
|
|
|
|
|
|
|
fn try_from(id: ClockId) -> Result<PeriodicClockId, glib::BoolError> {
|
|
|
|
skip_assert_initialized!();
|
|
|
|
match id.get_type() {
|
|
|
|
ClockEntryType::Periodic => Ok(PeriodicClockId(id)),
|
|
|
|
_ => Err(glib_bool_error!("Not a periodic clock id")),
|
2019-04-23 15:47:13 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-10 09:10:52 +00:00
|
|
|
}
|
2019-09-25 14:17:39 +00:00
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
impl PeriodicClockId {
|
|
|
|
pub fn get_interval(&self) -> ClockTime {
|
2019-09-25 14:17:39 +00:00
|
|
|
unsafe {
|
|
|
|
let ptr: *mut gst_sys::GstClockEntry = self.to_glib_none().0 as *mut _;
|
2020-10-10 09:10:52 +00:00
|
|
|
from_glib((*ptr).interval)
|
2019-09-25 14:17:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
pub fn compare_by_time(&self, other: &Self) -> cmp::Ordering {
|
|
|
|
self.0.compare_by_time(&other.0)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn wait_async<F>(&self, func: F) -> Result<ClockSuccess, ClockError>
|
|
|
|
where
|
|
|
|
F: Fn(&Clock, ClockTime, &ClockId) + Send + 'static,
|
|
|
|
{
|
|
|
|
unsafe extern "C" fn trampoline<F: Fn(&Clock, ClockTime, &ClockId) + Send + 'static>(
|
|
|
|
clock: *mut gst_sys::GstClock,
|
|
|
|
time: gst_sys::GstClockTime,
|
|
|
|
id: gpointer,
|
|
|
|
func: gpointer,
|
|
|
|
) -> gboolean {
|
|
|
|
let f: &F = &*(func as *const F);
|
|
|
|
f(
|
|
|
|
&from_glib_borrow(clock),
|
|
|
|
from_glib(time),
|
|
|
|
&from_glib_borrow(id),
|
|
|
|
);
|
|
|
|
glib_sys::GTRUE
|
2019-09-25 14:17:39 +00:00
|
|
|
}
|
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
unsafe extern "C" fn destroy_notify<F: Fn(&Clock, ClockTime, &ClockId) + Send + 'static>(
|
|
|
|
ptr: gpointer,
|
|
|
|
) {
|
|
|
|
Box::<F>::from_raw(ptr as *mut _);
|
2019-09-25 14:17:39 +00:00
|
|
|
}
|
2020-10-10 09:10:52 +00:00
|
|
|
|
|
|
|
let func: Box<F> = Box::new(func);
|
|
|
|
let ret: ClockReturn = unsafe {
|
|
|
|
from_glib(gst_sys::gst_clock_id_wait_async(
|
|
|
|
self.to_glib_none().0,
|
|
|
|
Some(trampoline::<F>),
|
|
|
|
Box::into_raw(func) as gpointer,
|
|
|
|
Some(destroy_notify::<F>),
|
|
|
|
))
|
|
|
|
};
|
|
|
|
ret.into_result()
|
2019-09-25 14:17:39 +00:00
|
|
|
}
|
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
#[allow(clippy::type_complexity)]
|
|
|
|
pub fn wait_async_stream(
|
|
|
|
&self,
|
|
|
|
) -> Result<
|
|
|
|
Pin<Box<dyn Stream<Item = (ClockTime, ClockId)> + Unpin + Send + 'static>>,
|
|
|
|
ClockError,
|
|
|
|
> {
|
|
|
|
use futures_channel::mpsc;
|
|
|
|
|
|
|
|
let (sender, receiver) = mpsc::unbounded();
|
|
|
|
|
|
|
|
self.wait_async(move |_clock, jitter, id| {
|
|
|
|
if sender.unbounded_send((jitter, id.clone())).is_err() {
|
|
|
|
// Unschedule any future calls if the receiver end is disconnected
|
|
|
|
id.unschedule();
|
|
|
|
}
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(Box::pin(receiver))
|
2019-09-25 14:17:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct AtomicClockReturn(AtomicI32);
|
|
|
|
|
|
|
|
impl AtomicClockReturn {
|
|
|
|
pub fn load(&self) -> ClockReturn {
|
|
|
|
from_glib(self.0.load(atomic::Ordering::SeqCst))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn store(&self, val: ClockReturn) {
|
|
|
|
self.0.store(val.to_glib(), atomic::Ordering::SeqCst)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn swap(&self, val: ClockReturn) -> ClockReturn {
|
|
|
|
from_glib(self.0.swap(val.to_glib(), atomic::Ordering::SeqCst))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn compare_and_swap(&self, current: ClockReturn, new: ClockReturn) -> ClockReturn {
|
|
|
|
from_glib(self.0.compare_and_swap(
|
|
|
|
current.to_glib(),
|
|
|
|
new.to_glib(),
|
|
|
|
atomic::Ordering::SeqCst,
|
|
|
|
))
|
|
|
|
}
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl Send for ClockId {}
|
|
|
|
unsafe impl Sync for ClockId {}
|
|
|
|
|
2017-12-18 07:39:37 +00:00
|
|
|
impl Clock {
|
|
|
|
pub fn adjust_with_calibration(
|
|
|
|
internal_target: ClockTime,
|
|
|
|
cinternal: ClockTime,
|
|
|
|
cexternal: ClockTime,
|
|
|
|
cnum: ClockTime,
|
|
|
|
cdenom: ClockTime,
|
|
|
|
) -> ClockTime {
|
2020-03-22 14:18:47 +00:00
|
|
|
skip_assert_initialized!();
|
2017-12-18 07:39:37 +00:00
|
|
|
unsafe {
|
2019-03-19 07:58:20 +00:00
|
|
|
from_glib(gst_sys::gst_clock_adjust_with_calibration(
|
2017-12-18 07:39:37 +00:00
|
|
|
ptr::null_mut(),
|
|
|
|
internal_target.to_glib(),
|
|
|
|
cinternal.to_glib(),
|
|
|
|
cexternal.to_glib(),
|
|
|
|
cnum.to_glib(),
|
|
|
|
cdenom.to_glib(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unadjust_with_calibration(
|
|
|
|
external_target: ClockTime,
|
|
|
|
cinternal: ClockTime,
|
|
|
|
cexternal: ClockTime,
|
|
|
|
cnum: ClockTime,
|
|
|
|
cdenom: ClockTime,
|
|
|
|
) -> ClockTime {
|
2020-03-22 14:18:47 +00:00
|
|
|
skip_assert_initialized!();
|
2017-12-18 07:39:37 +00:00
|
|
|
unsafe {
|
2019-03-19 07:58:20 +00:00
|
|
|
from_glib(gst_sys::gst_clock_unadjust_with_calibration(
|
2017-12-18 07:39:37 +00:00
|
|
|
ptr::null_mut(),
|
|
|
|
external_target.to_glib(),
|
|
|
|
cinternal.to_glib(),
|
|
|
|
cexternal.to_glib(),
|
|
|
|
cnum.to_glib(),
|
|
|
|
cdenom.to_glib(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 09:22:42 +00:00
|
|
|
pub trait ClockExtManual: 'static {
|
2019-12-17 19:00:42 +00:00
|
|
|
fn new_periodic_id(
|
|
|
|
&self,
|
|
|
|
start_time: ClockTime,
|
|
|
|
interval: ClockTime,
|
2020-10-10 09:10:52 +00:00
|
|
|
) -> Result<PeriodicClockId, glib::BoolError>;
|
2017-08-13 22:40:43 +00:00
|
|
|
|
|
|
|
fn periodic_id_reinit(
|
|
|
|
&self,
|
2020-10-10 09:10:52 +00:00
|
|
|
id: &PeriodicClockId,
|
2017-08-13 22:40:43 +00:00
|
|
|
start_time: ClockTime,
|
|
|
|
interval: ClockTime,
|
|
|
|
) -> Result<(), glib::BoolError>;
|
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
fn new_single_shot_id(&self, time: ClockTime) -> Result<SingleShotClockId, glib::BoolError>;
|
2017-08-13 22:40:43 +00:00
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
fn single_shot_id_reinit(
|
|
|
|
&self,
|
|
|
|
id: &SingleShotClockId,
|
|
|
|
time: ClockTime,
|
|
|
|
) -> Result<(), glib::BoolError>;
|
2019-09-25 13:46:46 +00:00
|
|
|
|
|
|
|
fn set_clock_flags(&self, flags: ClockFlags);
|
|
|
|
|
|
|
|
fn unset_clock_flags(&self, flags: ClockFlags);
|
|
|
|
|
|
|
|
fn get_clock_flags(&self) -> ClockFlags;
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 09:22:42 +00:00
|
|
|
impl<O: IsA<Clock>> ClockExtManual for O {
|
2019-12-17 19:00:42 +00:00
|
|
|
fn new_periodic_id(
|
|
|
|
&self,
|
|
|
|
start_time: ClockTime,
|
|
|
|
interval: ClockTime,
|
2020-10-10 09:10:52 +00:00
|
|
|
) -> Result<PeriodicClockId, glib::BoolError> {
|
2017-08-13 22:40:43 +00:00
|
|
|
unsafe {
|
2019-12-17 19:00:42 +00:00
|
|
|
Option::<_>::from_glib_full(gst_sys::gst_clock_new_periodic_id(
|
2019-01-16 11:32:58 +00:00
|
|
|
self.as_ref().to_glib_none().0,
|
2017-11-11 10:21:55 +00:00
|
|
|
start_time.to_glib(),
|
|
|
|
interval.to_glib(),
|
2017-08-13 22:40:43 +00:00
|
|
|
))
|
2020-10-10 09:10:52 +00:00
|
|
|
.map(PeriodicClockId)
|
2019-12-17 19:00:42 +00:00
|
|
|
.ok_or_else(|| glib_bool_error!("Failed to create new periodic clock id"))
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn periodic_id_reinit(
|
|
|
|
&self,
|
2020-10-10 09:10:52 +00:00
|
|
|
id: &PeriodicClockId,
|
2017-08-13 22:40:43 +00:00
|
|
|
start_time: ClockTime,
|
|
|
|
interval: ClockTime,
|
|
|
|
) -> Result<(), glib::BoolError> {
|
2017-08-30 11:39:09 +00:00
|
|
|
skip_assert_initialized!();
|
2017-08-13 22:40:43 +00:00
|
|
|
unsafe {
|
2019-03-19 07:58:20 +00:00
|
|
|
let res: bool = from_glib(gst_sys::gst_clock_periodic_id_reinit(
|
2019-01-16 11:32:58 +00:00
|
|
|
self.as_ref().to_glib_none().0,
|
2017-08-13 22:40:43 +00:00
|
|
|
id.to_glib_none().0,
|
2017-11-11 10:21:55 +00:00
|
|
|
start_time.to_glib(),
|
|
|
|
interval.to_glib(),
|
2017-08-13 22:40:43 +00:00
|
|
|
));
|
|
|
|
if res {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
2019-01-04 12:15:58 +00:00
|
|
|
Err(glib_bool_error!("Failed to reinit periodic clock id"))
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
fn new_single_shot_id(&self, time: ClockTime) -> Result<SingleShotClockId, glib::BoolError> {
|
2017-08-13 22:40:43 +00:00
|
|
|
unsafe {
|
2019-12-17 19:00:42 +00:00
|
|
|
Option::<_>::from_glib_full(gst_sys::gst_clock_new_single_shot_id(
|
2019-01-16 11:32:58 +00:00
|
|
|
self.as_ref().to_glib_none().0,
|
2017-11-11 10:21:55 +00:00
|
|
|
time.to_glib(),
|
2017-08-13 22:40:43 +00:00
|
|
|
))
|
2020-10-10 09:10:52 +00:00
|
|
|
.map(SingleShotClockId)
|
2019-12-17 19:00:42 +00:00
|
|
|
.ok_or_else(|| glib_bool_error!("Failed to create new single shot clock id"))
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-10 09:10:52 +00:00
|
|
|
fn single_shot_id_reinit(
|
|
|
|
&self,
|
|
|
|
id: &SingleShotClockId,
|
|
|
|
time: ClockTime,
|
|
|
|
) -> Result<(), glib::BoolError> {
|
2017-08-13 22:40:43 +00:00
|
|
|
unsafe {
|
2019-03-19 07:58:20 +00:00
|
|
|
let res: bool = from_glib(gst_sys::gst_clock_single_shot_id_reinit(
|
2019-01-16 11:32:58 +00:00
|
|
|
self.as_ref().to_glib_none().0,
|
2017-08-13 22:40:43 +00:00
|
|
|
id.to_glib_none().0,
|
2017-11-11 10:21:55 +00:00
|
|
|
time.to_glib(),
|
2017-08-13 22:40:43 +00:00
|
|
|
));
|
|
|
|
if res {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
2019-01-04 12:15:58 +00:00
|
|
|
Err(glib_bool_error!("Failed to reinit single shot clock id"))
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-25 13:46:46 +00:00
|
|
|
|
|
|
|
fn set_clock_flags(&self, flags: ClockFlags) {
|
|
|
|
unsafe {
|
|
|
|
let ptr: *mut gst_sys::GstObject = self.as_ptr() as *mut _;
|
|
|
|
let _guard = ::utils::MutexGuard::lock(&(*ptr).lock);
|
|
|
|
(*ptr).flags |= flags.to_glib();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn unset_clock_flags(&self, flags: ClockFlags) {
|
|
|
|
unsafe {
|
|
|
|
let ptr: *mut gst_sys::GstObject = self.as_ptr() as *mut _;
|
|
|
|
let _guard = ::utils::MutexGuard::lock(&(*ptr).lock);
|
|
|
|
(*ptr).flags &= !flags.to_glib();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_clock_flags(&self) -> ClockFlags {
|
|
|
|
unsafe {
|
|
|
|
let ptr: *mut gst_sys::GstObject = self.as_ptr() as *mut _;
|
|
|
|
let _guard = ::utils::MutexGuard::lock(&(*ptr).lock);
|
|
|
|
from_glib((*ptr).flags)
|
|
|
|
}
|
|
|
|
}
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::super::*;
|
2018-04-01 08:30:03 +00:00
|
|
|
use super::*;
|
2017-08-13 22:40:43 +00:00
|
|
|
use std::sync::mpsc::channel;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_wait() {
|
|
|
|
::init().unwrap();
|
|
|
|
|
|
|
|
let clock = SystemClock::obtain();
|
|
|
|
let now = clock.get_time();
|
2017-11-11 10:21:55 +00:00
|
|
|
let id = clock.new_single_shot_id(now + 20 * ::MSECOND).unwrap();
|
2017-08-13 22:40:43 +00:00
|
|
|
let (res, _) = id.wait();
|
|
|
|
|
2019-01-08 16:13:37 +00:00
|
|
|
assert!(res == Ok(ClockSuccess::Ok) || res == Err(ClockError::Early));
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_wait_async() {
|
|
|
|
::init().unwrap();
|
|
|
|
|
|
|
|
let (sender, receiver) = channel();
|
|
|
|
|
|
|
|
let clock = SystemClock::obtain();
|
|
|
|
let now = clock.get_time();
|
2017-11-11 10:21:55 +00:00
|
|
|
let id = clock.new_single_shot_id(now + 20 * ::MSECOND).unwrap();
|
2017-08-13 22:40:43 +00:00
|
|
|
let res = id.wait_async(move |_, _, _| {
|
|
|
|
sender.send(()).unwrap();
|
|
|
|
});
|
|
|
|
|
2019-01-08 16:13:37 +00:00
|
|
|
assert!(res == Ok(ClockSuccess::Ok));
|
2017-08-13 22:40:43 +00:00
|
|
|
|
|
|
|
assert_eq!(receiver.recv(), Ok(()));
|
|
|
|
}
|
2020-10-10 09:10:52 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_wait_periodic() {
|
|
|
|
::init().unwrap();
|
|
|
|
|
|
|
|
let clock = SystemClock::obtain();
|
|
|
|
let now = clock.get_time();
|
|
|
|
let id = clock
|
|
|
|
.new_periodic_id(now + 20 * ::MSECOND, 20 * ::MSECOND)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let (res, _) = id.wait();
|
|
|
|
assert!(res == Ok(ClockSuccess::Ok) || res == Err(ClockError::Early));
|
|
|
|
|
|
|
|
let (res, _) = id.wait();
|
|
|
|
assert!(res == Ok(ClockSuccess::Ok) || res == Err(ClockError::Early));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_wait_async_periodic() {
|
|
|
|
::init().unwrap();
|
|
|
|
|
|
|
|
let (sender, receiver) = channel();
|
|
|
|
|
|
|
|
let clock = SystemClock::obtain();
|
|
|
|
let now = clock.get_time();
|
|
|
|
let id = clock
|
|
|
|
.new_periodic_id(now + 20 * ::MSECOND, 20 * ::MSECOND)
|
|
|
|
.unwrap();
|
|
|
|
let res = id.wait_async(move |_, _, _| {
|
|
|
|
let _ = sender.send(());
|
|
|
|
});
|
|
|
|
|
|
|
|
assert!(res == Ok(ClockSuccess::Ok));
|
|
|
|
|
|
|
|
assert_eq!(receiver.recv(), Ok(()));
|
|
|
|
assert_eq!(receiver.recv(), Ok(()));
|
|
|
|
}
|
2017-08-13 22:40:43 +00:00
|
|
|
}
|