use crate::priv_prelude::*; use crate::wrap_gst; wrap_gst!(Element, gstreamer::Element); // pub trait IsElement { // fn upcast_ref(&self) -> ∈ // fn into_element(self) -> Element; // fn pad(&self, name: &str) -> Option { // use gstreamer::prelude::*; // self.upcast_ref().inner.static_pad(name).map(Pad::from) // } // } // impl IsElement for Element { // fn upcast_ref(&self) -> &Element { // self // } // // fn into_element(self) -> Element { // self // } // } impl Element { pub fn pad(&self, name: impl AsRef) -> Option { use gstreamer::prelude::*; self.inner.static_pad(name.as_ref()).map(Pad::from) } pub fn bus(&self) -> Result { use gstreamer::prelude::*; self.inner .bus() .map(Bus::from) .ok_or(Error) .attach_with(|| format!("Failed to get bus from Element: {}", self.inner.name())) } } pub trait Sink: ChildOf { fn sink(&self, name: impl AsRef) -> Pad { self.upcast_ref() .pad(name) .expect("Sink element has no sink pad") } } pub trait Source: ChildOf { fn source(&self, name: impl AsRef) -> Pad { self.upcast_ref() .pad(name) .expect("Source element has no src pad") } fn link(&self, sink: &S) -> Result where Self: Sized, { use gstreamer::prelude::*; if let Ok(bin) = self.upcast_ref().inner.clone().downcast::() { bin.add(&sink.upcast_ref().inner) .change_context(Error) .attach("Failed to add sink to bin")?; self.upcast_ref() .inner .link(&sink.upcast_ref().inner) .change_context(Error) .attach("Failed to link elements")?; Ok(Bin::from(bin)) } else { let bin = gstreamer::Bin::builder() .name(format!( "{}-link-{}", self.upcast_ref().inner.name(), sink.upcast_ref().inner.name() )) .build(); bin.add(&self.upcast_ref().inner) .change_context(Error) .attach("Failed to add source to bin")?; bin.add(&sink.upcast_ref().inner) .change_context(Error) .attach("Failed to add sink to bin")?; self.upcast_ref() .inner .link(&sink.upcast_ref().inner) .change_context(Error) .attach("Failed to link elements")?; if let Some(sink_pad) = self.upcast_ref().pad("sink") { let ghost_pad = Pad::ghost(&sink_pad)?; bin.add_pad(&ghost_pad.inner) .change_context(Error) .attach("Failed to add src pad to bin")?; ghost_pad.activate(true)?; } Ok(From::from(bin)) } } // fn link_pad(&self, sink: &S, src_pad_name: &str, sink_pad_name: &str) -> Result<()> { // use gstreamer::prelude::*; // let src_pad = self // .upcast_ref() // .pad(src_pad_name) // .ok_or(Error) // .attach("Source pad not found")?; // let sink_pad = sink // .upcast_ref() // .pad(sink_pad_name) // .ok_or(Error) // .attach("Sink pad not found")?; // src_pad // .inner // .link(&sink_pad.inner) // .change_context(Error) // .attach("Failed to link source pad to sink pad")?; // Ok(()) // } } pub trait ElementExt: ChildOf + Sync { #[track_caller] fn bus(&self) -> Result { self.upcast_ref().bus() } #[track_caller] fn pad(&self, name: impl AsRef) -> Option { self.upcast_ref().pad(name) } } impl + Sync> ElementExt for T {}