gstreamer/
stream_collection.rs1use std::{boxed::Box as Box_, fmt, mem::transmute};
4
5use glib::{
6 object::ObjectType as ObjectType_,
7 signal::{connect_raw, SignalHandlerId},
8 translate::*,
9};
10
11use crate::{ffi, Stream, StreamCollection};
12
13crate::utils::define_fixed_size_iter!(
14 Iter,
15 &'a StreamCollection,
16 Stream,
17 |collection: &StreamCollection| collection.len(),
18 |collection: &StreamCollection, idx: usize| unsafe {
19 from_glib_none(ffi::gst_stream_collection_get_stream(
20 collection.to_glib_none().0,
21 idx as u32,
22 ))
23 }
24);
25
26#[derive(Debug, Clone)]
27#[must_use = "The builder must be built to be used"]
28pub struct StreamCollectionBuilder(StreamCollection);
29
30impl StreamCollectionBuilder {
31 #[doc(alias = "gst_stream_collection_add_stream")]
32 pub fn stream(self, stream: Stream) -> Self {
33 unsafe {
34 ffi::gst_stream_collection_add_stream(
35 (self.0).to_glib_none().0,
36 stream.into_glib_ptr(),
37 );
38 }
39
40 self
41 }
42
43 #[doc(alias = "gst_stream_collection_add_stream")]
44 pub fn stream_if(self, stream: Stream, predicate: bool) -> Self {
45 if predicate {
46 unsafe {
47 ffi::gst_stream_collection_add_stream(
48 (self.0).to_glib_none().0,
49 stream.into_glib_ptr(),
50 );
51 }
52
53 self
54 } else {
55 self
56 }
57 }
58
59 #[doc(alias = "gst_stream_collection_add_stream")]
60 pub fn stream_if_some(self, stream: Option<Stream>) -> Self {
61 if let Some(stream) = stream {
62 self.stream(stream)
63 } else {
64 self
65 }
66 }
67
68 pub fn streams(self, streams: impl IntoIterator<Item = Stream>) -> Self {
69 for stream in streams.into_iter() {
70 unsafe {
71 ffi::gst_stream_collection_add_stream(
72 (self.0).to_glib_none().0,
73 stream.into_glib_ptr(),
74 );
75 }
76 }
77
78 self
79 }
80
81 pub fn streams_if(self, streams: impl IntoIterator<Item = Stream>, predicate: bool) -> Self {
82 if predicate {
83 for stream in streams.into_iter() {
84 unsafe {
85 ffi::gst_stream_collection_add_stream(
86 (self.0).to_glib_none().0,
87 stream.into_glib_ptr(),
88 );
89 }
90 }
91
92 self
93 } else {
94 self
95 }
96 }
97
98 pub fn streams_if_some(self, streams: Option<impl IntoIterator<Item = Stream>>) -> Self {
99 if let Some(streams) = streams {
100 self.streams(streams)
101 } else {
102 self
103 }
104 }
105
106 pub fn streams_if_not_empty(self, streams: impl IntoIterator<Item = Stream>) -> Self {
107 let mut streams = streams.into_iter().peekable();
108 if streams.peek().is_some() {
109 self.streams(streams)
110 } else {
111 self
112 }
113 }
114
115 #[must_use = "Building the stream collection without using it has no effect"]
116 pub fn build(self) -> StreamCollection {
117 self.0
118 }
119}
120
121impl StreamCollection {
122 #[doc(alias = "gst_stream_collection_new")]
123 pub fn builder(upstream_id: Option<&str>) -> StreamCollectionBuilder {
124 assert_initialized_main_thread!();
125 let upstream_id = upstream_id.to_glib_none();
126 let collection = unsafe { from_glib_full(ffi::gst_stream_collection_new(upstream_id.0)) };
127
128 StreamCollectionBuilder(collection)
129 }
130
131 #[doc(alias = "stream-notify")]
132 pub fn connect_stream_notify<
133 F: Fn(&Self, &Stream, &glib::ParamSpec) + Send + Sync + 'static,
134 >(
135 &self,
136 detail: Option<&str>,
137 f: F,
138 ) -> SignalHandlerId {
139 unsafe extern "C" fn stream_notify_trampoline<
140 F: Fn(&StreamCollection, &Stream, &glib::ParamSpec) + Send + Sync + 'static,
141 >(
142 this: *mut ffi::GstStreamCollection,
143 object: *mut ffi::GstStream,
144 p0: *mut glib::gobject_ffi::GParamSpec,
145 f: glib::ffi::gpointer,
146 ) {
147 let f: &F = &*(f as *const F);
148 f(
149 &from_glib_borrow(this),
150 &from_glib_borrow(object),
151 &from_glib_borrow(p0),
152 )
153 }
154 unsafe {
155 let f: Box_<F> = Box_::new(f);
156 let detailed_signal_name = detail.map(|name| format!("stream-notify::{name}\0"));
157 let signal_name: &[u8] = detailed_signal_name
158 .as_ref()
159 .map_or(&b"stream-notify\0"[..], |n| n.as_bytes());
160 connect_raw(
161 self.as_ptr() as *mut _,
162 signal_name.as_ptr() as *const _,
163 Some(transmute::<*const (), unsafe extern "C" fn()>(
164 stream_notify_trampoline::<F> as *const (),
165 )),
166 Box_::into_raw(f),
167 )
168 }
169 }
170
171 pub fn iter(&self) -> Iter<'_> {
172 Iter::new(self)
173 }
174
175 pub fn len(&self) -> usize {
176 self.size() as usize
177 }
178
179 pub fn is_empty(&self) -> bool {
180 self.len() == 0
181 }
182
183 pub fn debug(&self) -> Debug<'_> {
184 Debug(self)
185 }
186}
187
188impl<'a> IntoIterator for &'a StreamCollection {
189 type IntoIter = Iter<'a>;
190 type Item = Stream;
191
192 fn into_iter(self) -> Self::IntoIter {
193 self.iter()
194 }
195}
196
197pub struct Debug<'a>(&'a StreamCollection);
198
199impl fmt::Debug for Debug<'_> {
200 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
201 struct Streams<'a>(&'a StreamCollection);
202
203 impl fmt::Debug for Streams<'_> {
204 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
205 let mut f = f.debug_list();
206
207 for stream in self.0.iter() {
208 f.entry(&stream.debug());
209 }
210
211 f.finish()
212 }
213 }
214
215 let streams = Streams(self.0);
216
217 f.debug_struct("StreamCollection")
218 .field("streams", &streams)
219 .finish()
220 }
221}