feat: Added PipelineExt trait for all Children of Pipelines
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
#[derive(Debug, Clone)]
|
use crate::priv_prelude::*;
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct Bus {
|
wrap_gst!(Bus);
|
||||||
pub(crate) bus: gstreamer::Bus,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bus {
|
impl Bus {
|
||||||
pub fn iter_timed(
|
pub fn iter_timed(
|
||||||
@@ -13,14 +11,10 @@ impl Bus {
|
|||||||
Some(dur) => gstreamer::ClockTime::try_from(dur).ok(),
|
Some(dur) => gstreamer::ClockTime::try_from(dur).ok(),
|
||||||
None => gstreamer::ClockTime::NONE,
|
None => gstreamer::ClockTime::NONE,
|
||||||
};
|
};
|
||||||
self.bus.iter_timed(clocktime)
|
self.inner.iter_timed(clocktime)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stream(&self) -> gstreamer::bus::BusStream {
|
pub fn stream(&self) -> gstreamer::bus::BusStream {
|
||||||
self.bus.stream()
|
self.inner.stream()
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_inner(self) -> gstreamer::Bus {
|
|
||||||
self.bus
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,6 @@
|
|||||||
use crate::priv_prelude::*;
|
use crate::priv_prelude::*;
|
||||||
|
/// Pads are link points between elements
|
||||||
#[derive(Debug)]
|
wrap_gst!(Pad, gstreamer::Pad);
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct Pad {
|
|
||||||
pub(crate) inner: gstreamer::Pad,
|
|
||||||
}
|
|
||||||
impl From<gstreamer::Pad> for Pad {
|
|
||||||
fn from(inner: gstreamer::Pad) -> Self {
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl From<Pad> for gstreamer::Pad {
|
|
||||||
fn from(wrapper: Pad) -> Self {
|
|
||||||
wrapper.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Pad {
|
|
||||||
pub fn into_inner(self) -> gstreamer::Pad {
|
|
||||||
self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl GstWrapper for Pad {
|
|
||||||
type GstType = gstreamer::Pad;
|
|
||||||
fn from_gst(gst: Self::GstType) -> Self {
|
|
||||||
Self { inner: gst }
|
|
||||||
}
|
|
||||||
fn into_gst(self) -> Self::GstType {
|
|
||||||
self.inner
|
|
||||||
}
|
|
||||||
fn as_gst_ref(&self) -> &Self::GstType {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pad {
|
impl Pad {
|
||||||
pub fn ghost(target: &Pad) -> Result<Pad> {
|
pub fn ghost(target: &Pad) -> Result<Pad> {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ impl Pipeline {
|
|||||||
.bus()
|
.bus()
|
||||||
.ok_or(Error)
|
.ok_or(Error)
|
||||||
.attach("Failed to get bus from pipeline")?;
|
.attach("Failed to get bus from pipeline")?;
|
||||||
Ok(Bus { bus })
|
Ok(Bus::from_gst(bus))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the state
|
/// Get the state
|
||||||
@@ -31,57 +31,6 @@ impl Pipeline {
|
|||||||
Ok(current)
|
Ok(current)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn wait_non_null_sync(&self) -> Result<()> {
|
|
||||||
// if dbg!(
|
|
||||||
// self.state(core::time::Duration::ZERO)
|
|
||||||
// .change_context(Error)
|
|
||||||
// .attach("Failed to get video context")
|
|
||||||
// )? != gstreamer::State::Null
|
|
||||||
// {
|
|
||||||
// Ok(())
|
|
||||||
// } else {
|
|
||||||
// let bus = self.bus()?;
|
|
||||||
// for message in bus.iter_timed(None) {
|
|
||||||
// let view = message.view();
|
|
||||||
// dbg!(&view);
|
|
||||||
// panic!();
|
|
||||||
// if let gstreamer::MessageView::StateChanged(change) = view
|
|
||||||
// && change.current() != State::Null
|
|
||||||
// {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Waits for the pipeline to be ready
|
|
||||||
// pub async fn wait_non_null(&self) -> Result<()> {
|
|
||||||
// if self
|
|
||||||
// .state(None)
|
|
||||||
// .change_context(Error)
|
|
||||||
// .attach("Failed to get video context")?
|
|
||||||
// != gstreamer::State::Null
|
|
||||||
// {
|
|
||||||
// Ok(())
|
|
||||||
// } else {
|
|
||||||
// use futures::StreamExt;
|
|
||||||
// self.bus()?
|
|
||||||
// .stream()
|
|
||||||
// .filter(|message: &gstreamer::Message| {
|
|
||||||
// let view = message.view();
|
|
||||||
// if let gstreamer::MessageView::StateChanged(change) = view {
|
|
||||||
// core::future::ready(change.current() != gstreamer::State::Null)
|
|
||||||
// } else {
|
|
||||||
// core::future::ready(false)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .next()
|
|
||||||
// .await;
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn play(&self) -> Result<()> {
|
pub fn play(&self) -> Result<()> {
|
||||||
self.inner
|
self.inner
|
||||||
.set_state(gstreamer::State::Playing)
|
.set_state(gstreamer::State::Playing)
|
||||||
@@ -115,3 +64,36 @@ impl Pipeline {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait PipelineExt {
|
||||||
|
fn bus(&self) -> Result<Bus>;
|
||||||
|
fn play(&self) -> Result<()>;
|
||||||
|
fn pause(&self) -> Result<()>;
|
||||||
|
fn ready(&self) -> Result<()>;
|
||||||
|
fn set_state(&self, state: gstreamer::State) -> Result<gstreamer::StateChangeSuccess>;
|
||||||
|
fn state(&self, timeout: impl Into<Option<core::time::Duration>>) -> Result<gstreamer::State>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> PipelineExt for T
|
||||||
|
where
|
||||||
|
T: ChildOf<Pipeline>,
|
||||||
|
{
|
||||||
|
fn bus(&self) -> Result<Bus> {
|
||||||
|
self.upcast_ref().bus()
|
||||||
|
}
|
||||||
|
fn play(&self) -> Result<()> {
|
||||||
|
self.upcast_ref().play()
|
||||||
|
}
|
||||||
|
fn pause(&self) -> Result<()> {
|
||||||
|
self.upcast_ref().pause()
|
||||||
|
}
|
||||||
|
fn ready(&self) -> Result<()> {
|
||||||
|
self.upcast_ref().ready()
|
||||||
|
}
|
||||||
|
fn set_state(&self, state: gstreamer::State) -> Result<gstreamer::StateChangeSuccess> {
|
||||||
|
self.upcast_ref().set_state(state)
|
||||||
|
}
|
||||||
|
fn state(&self, timeout: impl Into<Option<core::time::Duration>>) -> Result<gstreamer::State> {
|
||||||
|
self.upcast_ref().state(timeout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ impl AppSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_caps(mut self, caps: Caps) -> Self {
|
pub fn with_caps(mut self, caps: Caps) -> Self {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
self.inner.set_property("caps", caps.inner);
|
self.inner.set_property("caps", caps.inner);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -34,7 +33,6 @@ impl AppSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pull_sample(&self) -> Result<Sample> {
|
pub fn pull_sample(&self) -> Result<Sample> {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
self.appsink()
|
self.appsink()
|
||||||
.pull_sample()
|
.pull_sample()
|
||||||
.change_context(Error)
|
.change_context(Error)
|
||||||
@@ -45,7 +43,6 @@ impl AppSink {
|
|||||||
&self,
|
&self,
|
||||||
timeout: impl Into<Option<core::time::Duration>>,
|
timeout: impl Into<Option<core::time::Duration>>,
|
||||||
) -> Result<Option<Sample>> {
|
) -> Result<Option<Sample>> {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.appsink()
|
.appsink()
|
||||||
.try_pull_sample(duration_to_clocktime(timeout)?)
|
.try_pull_sample(duration_to_clocktime(timeout)?)
|
||||||
@@ -53,7 +50,6 @@ impl AppSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pull_preroll(&self) -> Result<Sample> {
|
pub fn pull_preroll(&self) -> Result<Sample> {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
self.appsink()
|
self.appsink()
|
||||||
.pull_preroll()
|
.pull_preroll()
|
||||||
.change_context(Error)
|
.change_context(Error)
|
||||||
@@ -65,7 +61,6 @@ impl AppSink {
|
|||||||
&self,
|
&self,
|
||||||
timeout: impl Into<Option<core::time::Duration>>,
|
timeout: impl Into<Option<core::time::Duration>>,
|
||||||
) -> Result<Option<Sample>> {
|
) -> Result<Option<Sample>> {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.appsink()
|
.appsink()
|
||||||
.try_pull_preroll(duration_to_clocktime(timeout)?)
|
.try_pull_preroll(duration_to_clocktime(timeout)?)
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ impl Drop for Playbin3 {
|
|||||||
|
|
||||||
impl Playbin3 {
|
impl Playbin3 {
|
||||||
pub fn new(name: impl AsRef<str>) -> Result<Self> {
|
pub fn new(name: impl AsRef<str>) -> Result<Self> {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
gstreamer::ElementFactory::make("playbin3")
|
gstreamer::ElementFactory::make("playbin3")
|
||||||
.name(name.as_ref())
|
.name(name.as_ref())
|
||||||
.build()
|
.build()
|
||||||
@@ -22,51 +21,33 @@ impl Playbin3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_uri(self, uri: impl AsRef<str>) -> Self {
|
pub fn with_uri(self, uri: impl AsRef<str>) -> Self {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
self.inner.set_property("uri", uri.as_ref());
|
self.inner.set_property("uri", uri.as_ref());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_video_sink(self, video_sink: &impl ChildOf<Element>) -> Self {
|
pub fn with_video_sink(self, video_sink: &impl ChildOf<Element>) -> Self {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
self.inner
|
self.inner
|
||||||
.set_property("video-sink", &video_sink.upcast_ref().inner);
|
.set_property("video-sink", &video_sink.upcast_ref().inner);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_text_sink(self, text_sink: &impl ChildOf<Element>) -> Self {
|
pub fn with_text_sink(self, text_sink: &impl ChildOf<Element>) -> Self {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
self.inner
|
self.inner
|
||||||
.set_property("text-sink", &text_sink.upcast_ref().inner);
|
.set_property("text-sink", &text_sink.upcast_ref().inner);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_audio_sink(self, audio_sink: &impl ChildOf<Element>) -> Self {
|
pub fn with_audio_sink(self, audio_sink: &impl ChildOf<Element>) -> Self {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
self.inner
|
self.inner
|
||||||
.set_property("audio-sink", &audio_sink.upcast_ref().inner);
|
.set_property("audio-sink", &audio_sink.upcast_ref().inner);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_volume(&self, volume: f64) {
|
pub fn set_volume(&self, volume: f64) {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
self.inner.set_property("volume", volume.clamp(1.0, 100.0))
|
self.inner.set_property("volume", volume.clamp(1.0, 100.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_volume(&self) -> f64 {
|
pub fn get_volume(&self) -> f64 {
|
||||||
use gstreamer::prelude::*;
|
|
||||||
self.inner.property::<f64>("volume")
|
self.inner.property::<f64>("volume")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::ops::Deref for Playbin3 {
|
|
||||||
type Target = Pipeline;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
let gp = self
|
|
||||||
.inner
|
|
||||||
.downcast_ref::<gstreamer::Pipeline>()
|
|
||||||
.expect("BUG: Playbin3 must be a pipeline");
|
|
||||||
unsafe { &*(gp as *const _ as *const Pipeline) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,32 +1,35 @@
|
|||||||
pub trait GstWrapper {
|
pub trait GstWrapper {
|
||||||
type GstType: glib::prelude::ObjectType;
|
type GstType: glib::prelude::ObjectType;
|
||||||
fn from_gst(gst: Self::GstType) -> Self;
|
fn from_gst(gst: Self::GstType) -> Self;
|
||||||
fn into_gst(self) -> Self::GstType;
|
// fn into_gst(self) -> Self::GstType;
|
||||||
fn as_gst_ref(&self) -> &Self::GstType;
|
fn as_gst_ref(&self) -> &Self::GstType;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! wrap_gst {
|
macro_rules! wrap_gst {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
wrap_gst!($name, gstreamer::$name);
|
$crate::wrap_gst!($name, gstreamer::$name);
|
||||||
};
|
};
|
||||||
($name:ident, $inner:ty) => {
|
($name:ident, $inner:ty) => {
|
||||||
|
$crate::wrap_gst!(core $name, $inner);
|
||||||
|
$crate::wrap_gst!($name, $inner, into_inner);
|
||||||
|
};
|
||||||
|
($name:ident, $inner:ty, skip_inner) => {
|
||||||
|
$crate::wrap_gst!(core $name, $inner);
|
||||||
|
};
|
||||||
|
|
||||||
|
(core $name:ident, $inner:ty) => {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct $name {
|
pub struct $name {
|
||||||
pub(crate) inner: $inner,
|
pub(crate) inner: $inner,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<$inner> for $name {
|
// impl From<$name> for $inner {
|
||||||
fn from(inner: $inner) -> Self {
|
// fn from(wrapper: $name) -> Self {
|
||||||
Self { inner }
|
// wrapper.into_inner()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
impl From<$name> for $inner {
|
|
||||||
fn from(wrapper: $name) -> Self {
|
|
||||||
wrapper.into_inner()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $name {
|
impl $name {
|
||||||
pub fn into_inner(self) -> $inner {
|
pub fn into_inner(self) -> $inner {
|
||||||
@@ -41,9 +44,9 @@ macro_rules! wrap_gst {
|
|||||||
Self { inner: gst }
|
Self { inner: gst }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_gst(self) -> Self::GstType {
|
// fn into_gst(self) -> Self::GstType {
|
||||||
self.inner.clone()
|
// self.inner.clone()
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn as_gst_ref(&self) -> &Self::GstType {
|
fn as_gst_ref(&self) -> &Self::GstType {
|
||||||
&self.inner
|
&self.inner
|
||||||
@@ -56,6 +59,13 @@ macro_rules! wrap_gst {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
($name:ident, $inner:ty, into_inner) => {
|
||||||
|
impl From<$inner> for $name {
|
||||||
|
fn from(inner: $inner) -> Self {
|
||||||
|
Self { inner }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait for types that can be upcasted to type T.
|
/// A trait for types that can be upcasted to type T.
|
||||||
@@ -93,5 +103,31 @@ macro_rules! parent_child {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}; // ($parent:ty, $child:ty, deref) => {
|
||||||
|
// $crate::parent_child!($parent, $child);
|
||||||
|
// $crate::parent_child!($parent, $child, __deref);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// ($parent:ty, $child:ty, downcast, deref) => {
|
||||||
|
// $crate::parent_child!($parent, $child, downcast);
|
||||||
|
// $crate::parent_child!($parent, $child, __deref);
|
||||||
|
// };
|
||||||
|
// ($parent:ty, $child:ty, deref, downcast) => {
|
||||||
|
// $crate::parent_child!($parent, $child, downcast);
|
||||||
|
// $crate::parent_child!($parent, $child, __deref);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// ($parent:ty, $child:ty, __deref) => {
|
||||||
|
// impl core::ops::Deref for $child
|
||||||
|
// where
|
||||||
|
// $child: GstWrapper,
|
||||||
|
// $parent: GstWrapper,
|
||||||
|
// {
|
||||||
|
// type Target = $parent;
|
||||||
|
//
|
||||||
|
// fn deref(&self) -> &Self::Target {
|
||||||
|
// self.upcast_ref()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user