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::{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<'a> Iterator for Iter<'a> { |
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<'a> DoubleEndedIterator for Iter<'a> { |
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<'a> ExactSizeIterator for Iter<'a> {} |
98 | |
99 | impl<'a> std::iter::FusedIterator for Iter<'a> {} |
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 | pub fn streams(self, streams: impl IntoIterator<Item = Stream>) -> Self { |
119 | for stream in streams.into_iter() { |
120 | unsafe { |
121 | ffi::gst_stream_collection_add_stream( |
122 | (self.0).to_glib_none().0, |
123 | stream.into_glib_ptr(), |
124 | ); |
125 | } |
126 | } |
127 | |
128 | self |
129 | } |
130 | |
131 | #[must_use = "Building the stream collection without using it has no effect" ] |
132 | pub fn build(self) -> StreamCollection { |
133 | self.0 |
134 | } |
135 | } |
136 | |
137 | impl StreamCollection { |
138 | #[doc (alias = "gst_stream_collection_new" )] |
139 | pub fn builder(upstream_id: Option<&str>) -> StreamCollectionBuilder { |
140 | assert_initialized_main_thread!(); |
141 | let upstream_id = upstream_id.to_glib_none(); |
142 | let collection = unsafe { from_glib_full(ffi::gst_stream_collection_new(upstream_id.0)) }; |
143 | |
144 | StreamCollectionBuilder(collection) |
145 | } |
146 | |
147 | #[doc (alias = "stream-notify" )] |
148 | pub fn connect_stream_notify< |
149 | F: Fn(&Self, &Stream, &glib::ParamSpec) + Send + Sync + 'static, |
150 | >( |
151 | &self, |
152 | detail: Option<&str>, |
153 | f: F, |
154 | ) -> SignalHandlerId { |
155 | unsafe extern "C" fn stream_notify_trampoline< |
156 | F: Fn(&StreamCollection, &Stream, &glib::ParamSpec) + Send + Sync + 'static, |
157 | >( |
158 | this: *mut ffi::GstStreamCollection, |
159 | object: *mut ffi::GstStream, |
160 | p0: *mut glib::gobject_ffi::GParamSpec, |
161 | f: glib::ffi::gpointer, |
162 | ) { |
163 | let f: &F = &*(f as *const F); |
164 | f( |
165 | &from_glib_borrow(this), |
166 | &from_glib_borrow(object), |
167 | &from_glib_borrow(p0), |
168 | ) |
169 | } |
170 | unsafe { |
171 | let f: Box_<F> = Box_::new(f); |
172 | let detailed_signal_name = detail.map(|name| format!("stream-notify:: {name}\0" )); |
173 | let signal_name: &[u8] = detailed_signal_name |
174 | .as_ref() |
175 | .map_or(&b"stream-notify \0" [..], |n| n.as_bytes()); |
176 | connect_raw( |
177 | self.as_ptr() as *mut _, |
178 | signal_name.as_ptr() as *const _, |
179 | Some(transmute::<_, unsafe extern "C" fn()>( |
180 | stream_notify_trampoline::<F> as *const (), |
181 | )), |
182 | Box_::into_raw(f), |
183 | ) |
184 | } |
185 | } |
186 | |
187 | pub fn iter(&self) -> Iter { |
188 | Iter::new(self) |
189 | } |
190 | |
191 | pub fn len(&self) -> usize { |
192 | self.size() as usize |
193 | } |
194 | |
195 | pub fn is_empty(&self) -> bool { |
196 | self.len() == 0 |
197 | } |
198 | |
199 | pub fn debug(&self) -> Debug { |
200 | Debug(self) |
201 | } |
202 | } |
203 | |
204 | impl<'a> IntoIterator for &'a StreamCollection { |
205 | type IntoIter = Iter<'a>; |
206 | type Item = Stream; |
207 | |
208 | fn into_iter(self) -> Self::IntoIter { |
209 | self.iter() |
210 | } |
211 | } |
212 | |
213 | pub struct Debug<'a>(&'a StreamCollection); |
214 | |
215 | impl<'a> fmt::Debug for Debug<'a> { |
216 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
217 | struct Streams<'a>(&'a StreamCollection); |
218 | |
219 | impl<'a> fmt::Debug for Streams<'a> { |
220 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
221 | let mut f: DebugList<'_, '_> = f.debug_list(); |
222 | |
223 | for stream: Stream in self.0.iter() { |
224 | f.entry(&stream.debug()); |
225 | } |
226 | |
227 | f.finish() |
228 | } |
229 | } |
230 | |
231 | let streams: Streams<'_> = Streams(self.0); |
232 | |
233 | f&mut DebugStruct<'_, '_>.debug_struct("StreamCollection" ) |
234 | .field(name:"streams" , &streams) |
235 | .finish() |
236 | } |
237 | } |
238 | |