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