gstreamer/
stream_collection.rs
1use 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
13#[derive(Debug)]
14pub struct Iter<'a> {
15 collection: &'a StreamCollection,
16 idx: usize,
17 size: usize,
18}
19
20impl<'a> Iter<'a> {
21 fn new(collection: &'a StreamCollection) -> Iter<'a> {
22 skip_assert_initialized!();
23 Iter {
24 collection,
25 idx: 0,
26 size: collection.len(),
27 }
28 }
29}
30
31impl Iterator for Iter<'_> {
32 type Item = Stream;
33
34 fn next(&mut self) -> Option<Self::Item> {
35 if self.idx >= self.size {
36 return None;
37 }
38
39 let item = self.collection.stream(self.idx as u32).unwrap();
40 self.idx += 1;
41
42 Some(item)
43 }
44
45 fn size_hint(&self) -> (usize, Option<usize>) {
46 let remaining = self.size - self.idx;
47
48 (remaining, Some(remaining))
49 }
50
51 fn count(self) -> usize {
52 self.size - self.idx
53 }
54
55 fn nth(&mut self, n: usize) -> Option<Self::Item> {
56 let (end, overflow) = self.idx.overflowing_add(n);
57 if end >= self.size || overflow {
58 self.idx = self.size;
59 None
60 } else {
61 self.idx = end + 1;
62 Some(self.collection.stream(end as u32).unwrap())
63 }
64 }
65
66 fn last(self) -> Option<Self::Item> {
67 if self.idx == self.size {
68 None
69 } else {
70 Some(self.collection.stream(self.size as u32 - 1).unwrap())
71 }
72 }
73}
74
75impl DoubleEndedIterator for Iter<'_> {
76 fn next_back(&mut self) -> Option<Self::Item> {
77 if self.idx == self.size {
78 return None;
79 }
80
81 self.size -= 1;
82 Some(self.collection.stream(self.size as u32).unwrap())
83 }
84
85 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
86 let (end, overflow) = self.size.overflowing_sub(n);
87 if end <= self.idx || overflow {
88 self.idx = self.size;
89 None
90 } else {
91 self.size = end - 1;
92 Some(self.collection.stream(self.size as u32).unwrap())
93 }
94 }
95}
96
97impl ExactSizeIterator for Iter<'_> {}
98
99impl std::iter::FusedIterator for Iter<'_> {}
100
101#[derive(Debug, Clone)]
102#[must_use = "The builder must be built to be used"]
103pub struct StreamCollectionBuilder(StreamCollection);
104
105impl StreamCollectionBuilder {
106 #[doc(alias = "gst_stream_collection_add_stream")]
107 pub fn stream(self, stream: Stream) -> Self {
108 unsafe {
109 ffi::gst_stream_collection_add_stream(
110 (self.0).to_glib_none().0,
111 stream.into_glib_ptr(),
112 );
113 }
114
115 self
116 }
117
118 #[doc(alias = "gst_stream_collection_add_stream")]
119 pub fn stream_if(self, stream: Stream, predicate: bool) -> Self {
120 if predicate {
121 unsafe {
122 ffi::gst_stream_collection_add_stream(
123 (self.0).to_glib_none().0,
124 stream.into_glib_ptr(),
125 );
126 }
127
128 self
129 } else {
130 self
131 }
132 }
133
134 #[doc(alias = "gst_stream_collection_add_stream")]
135 pub fn stream_if_some(self, stream: Option<Stream>) -> Self {
136 if let Some(stream) = stream {
137 self.stream(stream)
138 } else {
139 self
140 }
141 }
142
143 pub fn streams(self, streams: impl IntoIterator<Item = Stream>) -> Self {
144 for stream in streams.into_iter() {
145 unsafe {
146 ffi::gst_stream_collection_add_stream(
147 (self.0).to_glib_none().0,
148 stream.into_glib_ptr(),
149 );
150 }
151 }
152
153 self
154 }
155
156 pub fn streams_if(self, streams: impl IntoIterator<Item = Stream>, predicate: bool) -> Self {
157 if predicate {
158 for stream in streams.into_iter() {
159 unsafe {
160 ffi::gst_stream_collection_add_stream(
161 (self.0).to_glib_none().0,
162 stream.into_glib_ptr(),
163 );
164 }
165 }
166
167 self
168 } else {
169 self
170 }
171 }
172
173 pub fn streams_if_some(self, streams: Option<impl IntoIterator<Item = Stream>>) -> Self {
174 if let Some(streams) = streams {
175 self.streams(streams)
176 } else {
177 self
178 }
179 }
180
181 pub fn streams_if_not_empty(self, streams: impl IntoIterator<Item = Stream>) -> Self {
182 let mut streams = streams.into_iter().peekable();
183 if streams.peek().is_some() {
184 self.streams(streams)
185 } else {
186 self
187 }
188 }
189
190 #[must_use = "Building the stream collection without using it has no effect"]
191 pub fn build(self) -> StreamCollection {
192 self.0
193 }
194}
195
196impl StreamCollection {
197 #[doc(alias = "gst_stream_collection_new")]
198 pub fn builder(upstream_id: Option<&str>) -> StreamCollectionBuilder {
199 assert_initialized_main_thread!();
200 let upstream_id = upstream_id.to_glib_none();
201 let collection = unsafe { from_glib_full(ffi::gst_stream_collection_new(upstream_id.0)) };
202
203 StreamCollectionBuilder(collection)
204 }
205
206 #[doc(alias = "stream-notify")]
213 pub fn connect_stream_notify<
214 F: Fn(&Self, &Stream, &glib::ParamSpec) + Send + Sync + 'static,
215 >(
216 &self,
217 detail: Option<&str>,
218 f: F,
219 ) -> SignalHandlerId {
220 unsafe extern "C" fn stream_notify_trampoline<
221 F: Fn(&StreamCollection, &Stream, &glib::ParamSpec) + Send + Sync + 'static,
222 >(
223 this: *mut ffi::GstStreamCollection,
224 object: *mut ffi::GstStream,
225 p0: *mut glib::gobject_ffi::GParamSpec,
226 f: glib::ffi::gpointer,
227 ) {
228 let f: &F = &*(f as *const F);
229 f(
230 &from_glib_borrow(this),
231 &from_glib_borrow(object),
232 &from_glib_borrow(p0),
233 )
234 }
235 unsafe {
236 let f: Box_<F> = Box_::new(f);
237 let detailed_signal_name = detail.map(|name| format!("stream-notify::{name}\0"));
238 let signal_name: &[u8] = detailed_signal_name
239 .as_ref()
240 .map_or(&b"stream-notify\0"[..], |n| n.as_bytes());
241 connect_raw(
242 self.as_ptr() as *mut _,
243 signal_name.as_ptr() as *const _,
244 Some(transmute::<*const (), unsafe extern "C" fn()>(
245 stream_notify_trampoline::<F> as *const (),
246 )),
247 Box_::into_raw(f),
248 )
249 }
250 }
251
252 pub fn iter(&self) -> Iter {
253 Iter::new(self)
254 }
255
256 pub fn len(&self) -> usize {
257 self.size() as usize
258 }
259
260 pub fn is_empty(&self) -> bool {
261 self.len() == 0
262 }
263
264 pub fn debug(&self) -> Debug {
265 Debug(self)
266 }
267}
268
269impl<'a> IntoIterator for &'a StreamCollection {
270 type IntoIter = Iter<'a>;
271 type Item = Stream;
272
273 fn into_iter(self) -> Self::IntoIter {
274 self.iter()
275 }
276}
277
278pub struct Debug<'a>(&'a StreamCollection);
279
280impl fmt::Debug for Debug<'_> {
281 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
282 struct Streams<'a>(&'a StreamCollection);
283
284 impl fmt::Debug for Streams<'_> {
285 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
286 let mut f = f.debug_list();
287
288 for stream in self.0.iter() {
289 f.entry(&stream.debug());
290 }
291
292 f.finish()
293 }
294 }
295
296 let streams = Streams(self.0);
297
298 f.debug_struct("StreamCollection")
299 .field("streams", &streams)
300 .finish()
301 }
302}