1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{boxed::Box as Box_, fmt, mem::transmute}; |
4 | |
5 | use glib::{ |
6 | object::ObjectType as ObjectType_, |
7 | signal::{connect_raw, SignalHandlerId}, |
8 | translate::*, |
9 | }; |
10 | |
11 | use crate::{ffi, Stream, StreamCollection}; |
12 | |
13 | #[derive (Debug)] |
14 | pub struct Iter<'a> { |
15 | collection: &'a StreamCollection, |
16 | idx: usize, |
17 | size: usize, |
18 | } |
19 | |
20 | impl<'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 | |
31 | impl 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 | |
75 | impl 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: usize, overflow: bool) = 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 | |
97 | impl ExactSizeIterator for Iter<'_> {} |
98 | |
99 | impl std::iter::FusedIterator for Iter<'_> {} |
100 | |
101 | #[derive (Debug, Clone)] |
102 | #[must_use = "The builder must be built to be used" ] |
103 | pub struct StreamCollectionBuilder(StreamCollection); |
104 | |
105 | impl 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 | |
196 | impl 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" )] |
207 | pub fn connect_stream_notify< |
208 | F: Fn(&Self, &Stream, &glib::ParamSpec) + Send + Sync + 'static, |
209 | >( |
210 | &self, |
211 | detail: Option<&str>, |
212 | f: F, |
213 | ) -> SignalHandlerId { |
214 | unsafe extern "C" fn stream_notify_trampoline< |
215 | F: Fn(&StreamCollection, &Stream, &glib::ParamSpec) + Send + Sync + 'static, |
216 | >( |
217 | this: *mut ffi::GstStreamCollection, |
218 | object: *mut ffi::GstStream, |
219 | p0: *mut glib::gobject_ffi::GParamSpec, |
220 | f: glib::ffi::gpointer, |
221 | ) { |
222 | let f: &F = &*(f as *const F); |
223 | f( |
224 | &from_glib_borrow(this), |
225 | &from_glib_borrow(object), |
226 | &from_glib_borrow(p0), |
227 | ) |
228 | } |
229 | unsafe { |
230 | let f: Box_<F> = Box_::new(f); |
231 | let detailed_signal_name = detail.map(|name| format!("stream-notify:: {name}\0" )); |
232 | let signal_name: &[u8] = detailed_signal_name |
233 | .as_ref() |
234 | .map_or(&b"stream-notify \0" [..], |n| n.as_bytes()); |
235 | connect_raw( |
236 | self.as_ptr() as *mut _, |
237 | signal_name.as_ptr() as *const _, |
238 | Some(transmute::<*const (), unsafe extern "C" fn()>( |
239 | stream_notify_trampoline::<F> as *const (), |
240 | )), |
241 | Box_::into_raw(f), |
242 | ) |
243 | } |
244 | } |
245 | |
246 | pub fn iter(&self) -> Iter { |
247 | Iter::new(self) |
248 | } |
249 | |
250 | pub fn len(&self) -> usize { |
251 | self.size() as usize |
252 | } |
253 | |
254 | pub fn is_empty(&self) -> bool { |
255 | self.len() == 0 |
256 | } |
257 | |
258 | pub fn debug(&self) -> Debug { |
259 | Debug(self) |
260 | } |
261 | } |
262 | |
263 | impl<'a> IntoIterator for &'a StreamCollection { |
264 | type IntoIter = Iter<'a>; |
265 | type Item = Stream; |
266 | |
267 | fn into_iter(self) -> Self::IntoIter { |
268 | self.iter() |
269 | } |
270 | } |
271 | |
272 | pub struct Debug<'a>(&'a StreamCollection); |
273 | |
274 | impl fmt::Debug for Debug<'_> { |
275 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
276 | struct Streams<'a>(&'a StreamCollection); |
277 | |
278 | impl fmt::Debug for Streams<'_> { |
279 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
280 | let mut f: DebugList<'_, '_> = f.debug_list(); |
281 | |
282 | for stream: Stream in self.0.iter() { |
283 | f.entry(&stream.debug()); |
284 | } |
285 | |
286 | f.finish() |
287 | } |
288 | } |
289 | |
290 | let streams: Streams<'_> = Streams(self.0); |
291 | |
292 | f&mut DebugStruct<'_, '_>.debug_struct("StreamCollection" ) |
293 | .field(name:"streams" , &streams) |
294 | .finish() |
295 | } |
296 | } |
297 | |