From cddccf950254d2869c966fbf14eda09abda5ec22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 9 Feb 2020 19:07:18 +0200 Subject: [PATCH] gstreamer/promise: Add Future constructor for Promise This returns a tuple that basically works like a oneshot channel: the Promise acts as the "sender" and once the promise resolves the "receiver" contains the result. --- gstreamer/src/lib.rs | 4 ++-- gstreamer/src/promise.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index fd85a7f4f..00894837b 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -155,9 +155,9 @@ mod static_pad_template; pub use static_pad_template::*; #[cfg(any(feature = "v1_14", feature = "dox"))] -mod promise; +pub mod promise; #[cfg(any(feature = "v1_14", feature = "dox"))] -pub use promise::*; +pub use promise::{Promise, PromiseError}; pub mod bus; mod element; diff --git a/gstreamer/src/promise.rs b/gstreamer/src/promise.rs index 0c5fd9d2d..45ddd6cfe 100644 --- a/gstreamer/src/promise.rs +++ b/gstreamer/src/promise.rs @@ -13,6 +13,9 @@ use PromiseResult; use Structure; use StructureRef; +use std::pin::Pin; +use std::task::{Context, Poll}; + glib_wrapper! { #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Promise(Shared); @@ -86,6 +89,18 @@ impl Promise { } } + pub fn new_future() -> (Self, PromiseFuture) { + use futures_channel::oneshot; + + let (sender, receiver) = oneshot::channel(); + + let promise = Self::new_with_change_func(move |res| { + let _ = sender.send(res.map(|s| s.to_owned())); + }); + + (promise, PromiseFuture(receiver)) + } + pub fn expire(&self) { unsafe { gst_sys::gst_promise_expire(self.to_glib_none().0); @@ -129,6 +144,21 @@ impl Default for Promise { unsafe impl Send for Promise {} unsafe impl Sync for Promise {} +#[derive(Debug)] +pub struct PromiseFuture(futures_channel::oneshot::Receiver>); + +impl std::future::Future for PromiseFuture { + type Output = Result; + + fn poll(mut self: Pin<&mut Self>, context: &mut Context) -> Poll { + match Pin::new(&mut self.0).poll(context) { + Poll::Ready(Err(_)) => panic!("Sender dropped before callback was called"), + Poll::Ready(Ok(res)) => Poll::Ready(res), + Poll::Pending => Poll::Pending, + } + } +} + #[cfg(test)] mod tests { use super::*;