1use std::{boxed::Box as Box_, mem::transmute, path};
4
5use glib::{
6 prelude::*,
7 signal::{connect_raw, SignalHandlerId},
8 translate::*,
9 GString,
10};
11
12use crate::{ffi, prelude::*, Bin, BinFlags, Element, LoggableError};
13
14impl Bin {
15 #[doc(alias = "gst_bin_new")]
29 pub fn new() -> Bin {
30 assert_initialized_main_thread!();
31 unsafe { Element::from_glib_none(ffi::gst_bin_new(std::ptr::null())).unsafe_cast() }
32 }
33
34 #[doc(alias = "gst_bin_new")]
39 pub fn with_name(name: &str) -> Bin {
40 assert_initialized_main_thread!();
41 unsafe { Element::from_glib_none(ffi::gst_bin_new(name.to_glib_none().0)).unsafe_cast() }
42 }
43
44 pub fn builder() -> BinBuilder {
49 BinBuilder::new()
50 }
51}
52
53mod sealed {
54 pub trait Sealed {}
55 impl<T: super::IsA<super::Bin>> Sealed for T {}
56}
57
58pub trait GstBinExtManual: sealed::Sealed + IsA<Bin> + 'static {
59 #[doc(alias = "gst_bin_add_many")]
60 fn add_many(
61 &self,
62 elements: impl IntoIterator<Item = impl AsRef<Element>>,
63 ) -> Result<(), glib::BoolError> {
64 for e in elements {
65 unsafe {
66 glib::result_from_gboolean!(
67 ffi::gst_bin_add(self.as_ref().to_glib_none().0, e.as_ref().to_glib_none().0),
68 "Failed to add elements"
69 )?;
70 }
71 }
72
73 Ok(())
74 }
75
76 #[doc(alias = "gst_bin_remove_many")]
77 fn remove_many(
78 &self,
79 elements: impl IntoIterator<Item = impl AsRef<Element>>,
80 ) -> Result<(), glib::BoolError> {
81 for e in elements {
82 unsafe {
83 glib::result_from_gboolean!(
84 ffi::gst_bin_remove(
85 self.as_ref().to_glib_none().0,
86 e.as_ref().to_glib_none().0,
87 ),
88 "Failed to remove elements"
89 )?;
90 }
91 }
92
93 Ok(())
94 }
95
96 #[doc(alias = "do-latency")]
97 fn connect_do_latency<F: Fn(&Self) -> Result<(), LoggableError> + Send + Sync + 'static>(
98 &self,
99 f: F,
100 ) -> SignalHandlerId {
101 unsafe {
102 let f: Box_<F> = Box_::new(f);
103 connect_raw(
104 self.as_ptr() as *mut _,
105 b"do-latency\0".as_ptr() as *const _,
106 Some(transmute::<*const (), unsafe extern "C" fn()>(
107 do_latency_trampoline::<Self, F> as *const (),
108 )),
109 Box_::into_raw(f),
110 )
111 }
112 }
113
114 #[cfg(feature = "v1_18")]
115 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
116 #[doc(alias = "gst_bin_iterate_all_by_element_factory_name")]
117 fn iterate_all_by_element_factory_name(&self, factory_name: &str) -> crate::Iterator<Element> {
118 unsafe {
119 from_glib_full(ffi::gst_bin_iterate_all_by_element_factory_name(
120 self.as_ref().to_glib_none().0,
121 factory_name.to_glib_none().0,
122 ))
123 }
124 }
125 #[doc(alias = "gst_bin_iterate_all_by_interface")]
126 fn iterate_all_by_interface(&self, iface: glib::types::Type) -> crate::Iterator<Element> {
127 unsafe {
128 from_glib_full(ffi::gst_bin_iterate_all_by_interface(
129 self.as_ref().to_glib_none().0,
130 iface.into_glib(),
131 ))
132 }
133 }
134
135 #[doc(alias = "gst_bin_iterate_elements")]
136 fn iterate_elements(&self) -> crate::Iterator<Element> {
137 unsafe {
138 from_glib_full(ffi::gst_bin_iterate_elements(
139 self.as_ref().to_glib_none().0,
140 ))
141 }
142 }
143
144 #[doc(alias = "gst_bin_iterate_recurse")]
145 fn iterate_recurse(&self) -> crate::Iterator<Element> {
146 unsafe { from_glib_full(ffi::gst_bin_iterate_recurse(self.as_ref().to_glib_none().0)) }
147 }
148
149 #[doc(alias = "gst_bin_iterate_sinks")]
150 fn iterate_sinks(&self) -> crate::Iterator<Element> {
151 unsafe { from_glib_full(ffi::gst_bin_iterate_sinks(self.as_ref().to_glib_none().0)) }
152 }
153
154 #[doc(alias = "gst_bin_iterate_sorted")]
155 fn iterate_sorted(&self) -> crate::Iterator<Element> {
156 unsafe { from_glib_full(ffi::gst_bin_iterate_sorted(self.as_ref().to_glib_none().0)) }
157 }
158
159 #[doc(alias = "gst_bin_iterate_sources")]
160 fn iterate_sources(&self) -> crate::Iterator<Element> {
161 unsafe { from_glib_full(ffi::gst_bin_iterate_sources(self.as_ref().to_glib_none().0)) }
162 }
163
164 #[doc(alias = "get_children")]
165 fn children(&self) -> Vec<Element> {
166 unsafe {
167 let bin: &ffi::GstBin = &*(self.as_ptr() as *const _);
168 let _guard = self.as_ref().object_lock();
169 FromGlibPtrContainer::from_glib_none(bin.children)
170 }
171 }
172
173 #[doc(alias = "gst_debug_bin_to_dot_data")]
174 fn debug_to_dot_data(&self, details: crate::DebugGraphDetails) -> GString {
175 crate::auto::functions::debug_bin_to_dot_data(self, details)
176 }
177
178 #[doc(alias = "GST_DEBUG_BIN_TO_DOT_FILE")]
179 #[doc(alias = "gst_debug_bin_to_dot_file")]
180 fn debug_to_dot_file(
181 &self,
182 details: crate::DebugGraphDetails,
183 file_name: impl AsRef<path::Path>,
184 ) {
185 crate::auto::functions::debug_bin_to_dot_file(self, details, file_name)
186 }
187
188 #[doc(alias = "GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS")]
189 #[doc(alias = "gst_debug_bin_to_dot_file_with_ts")]
190 fn debug_to_dot_file_with_ts(
191 &self,
192 details: crate::DebugGraphDetails,
193 file_name: impl AsRef<path::Path>,
194 ) {
195 crate::auto::functions::debug_bin_to_dot_file_with_ts(self, details, file_name)
196 }
197
198 fn set_bin_flags(&self, flags: BinFlags) {
199 unsafe {
200 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
201 let _guard = self.as_ref().object_lock();
202 (*ptr).flags |= flags.into_glib();
203 }
204 }
205
206 fn unset_bin_flags(&self, flags: BinFlags) {
207 unsafe {
208 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
209 let _guard = self.as_ref().object_lock();
210 (*ptr).flags &= !flags.into_glib();
211 }
212 }
213
214 #[doc(alias = "get_bin_flags")]
215 fn bin_flags(&self) -> BinFlags {
216 unsafe {
217 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
218 let _guard = self.as_ref().object_lock();
219 from_glib((*ptr).flags)
220 }
221 }
222}
223
224impl<O: IsA<Bin>> GstBinExtManual for O {}
225
226impl Default for Bin {
227 fn default() -> Self {
228 glib::object::Object::new()
229 }
230}
231
232#[must_use = "The builder must be built to be used"]
237pub struct BinBuilder {
238 builder: glib::object::ObjectBuilder<'static, Bin>,
239}
240
241impl BinBuilder {
242 fn new() -> Self {
243 Self {
244 builder: glib::Object::builder(),
245 }
246 }
247
248 #[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
251 pub fn build(self) -> Bin {
252 self.builder.build()
253 }
254
255 pub fn async_handling(self, async_handling: bool) -> Self {
256 Self {
257 builder: self.builder.property("async-handling", async_handling),
258 }
259 }
260
261 pub fn async_handling_if_some(self, async_handling: Option<bool>) -> Self {
262 if let Some(async_handling) = async_handling {
263 self.async_handling(async_handling)
264 } else {
265 self
266 }
267 }
268
269 pub fn message_forward(self, message_forward: bool) -> Self {
270 Self {
271 builder: self.builder.property("message-forward", message_forward),
272 }
273 }
274
275 pub fn message_forward_if_some(self, message_forward: Option<bool>) -> Self {
276 if let Some(message_forward) = message_forward {
277 self.message_forward(message_forward)
278 } else {
279 self
280 }
281 }
282
283 pub fn name(self, name: impl Into<glib::GString>) -> Self {
284 Self {
285 builder: self.builder.property("name", name.into()),
286 }
287 }
288
289 pub fn name_if(self, name: impl Into<glib::GString>, predicate: bool) -> Self {
290 if predicate {
291 self.name(name)
292 } else {
293 self
294 }
295 }
296
297 pub fn name_if_some(self, name: Option<impl Into<glib::GString>>) -> Self {
298 if let Some(name) = name {
299 self.name(name)
300 } else {
301 self
302 }
303 }
304}
305
306unsafe extern "C" fn do_latency_trampoline<
307 P,
308 F: Fn(&P) -> Result<(), LoggableError> + Send + Sync + 'static,
309>(
310 this: *mut ffi::GstBin,
311 f: glib::ffi::gpointer,
312) -> glib::ffi::gboolean
313where
314 P: IsA<Bin>,
315{
316 let f: &F = &*(f as *const F);
317 match f(Bin::from_glib_borrow(this).unsafe_cast_ref()) {
318 Ok(()) => true,
319 Err(err) => {
320 err.log_with_object(&*Bin::from_glib_borrow(this));
321 false
322 }
323 }
324 .into_glib()
325}
326
327#[cfg(test)]
328mod tests {
329 use super::*;
330
331 #[test]
332 fn test_get_children() {
333 crate::init().unwrap();
334
335 let bin = crate::Bin::new();
336 bin.add(
337 &crate::ElementFactory::make("identity")
338 .name("identity0")
339 .build()
340 .unwrap(),
341 )
342 .unwrap();
343 bin.add(
344 &crate::ElementFactory::make("identity")
345 .name("identity1")
346 .build()
347 .unwrap(),
348 )
349 .unwrap();
350
351 let mut child_names = bin
352 .children()
353 .iter()
354 .map(|c| c.name())
355 .collect::<Vec<GString>>();
356 child_names.sort();
357 assert_eq!(
358 child_names,
359 vec![String::from("identity0"), String::from("identity1")]
360 );
361 }
362}