1 // Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8 
9 use glib::object::IsA;
10 use glib::translate::*;
11 use gst_sys;
12 use std::fmt;
13 use Stream;
14 use StreamCollection;
15 
16 #[derive(Debug)]
17 pub struct Iter<'a> {
18     collection: &'a StreamCollection,
19     idx: u32,
20     size: u32,
21 }
22 
23 impl<'a> Iter<'a> {
new(collection: &'a StreamCollection) -> Iter<'a>24     fn new(collection: &'a StreamCollection) -> Iter<'a> {
25         skip_assert_initialized!();
26         Iter {
27             collection,
28             idx: 0,
29             size: collection.len() as u32,
30         }
31     }
32 }
33 
34 impl<'a> Iterator for Iter<'a> {
35     type Item = Stream;
36 
next(&mut self) -> Option<Self::Item>37     fn next(&mut self) -> Option<Self::Item> {
38         if self.idx >= self.size {
39             return None;
40         }
41 
42         let item = self.collection.get_stream(self.idx);
43         self.idx += 1;
44 
45         item
46     }
47 
size_hint(&self) -> (usize, Option<usize>)48     fn size_hint(&self) -> (usize, Option<usize>) {
49         if self.idx == self.size {
50             return (0, Some(0));
51         }
52 
53         let remaining = (self.size - self.idx) as usize;
54 
55         (remaining, Some(remaining))
56     }
57 }
58 
59 impl<'a> DoubleEndedIterator for Iter<'a> {
next_back(&mut self) -> Option<Self::Item>60     fn next_back(&mut self) -> Option<Self::Item> {
61         if self.idx == self.size {
62             return None;
63         }
64 
65         self.size -= 1;
66         self.collection.get_stream(self.size)
67     }
68 }
69 
70 impl<'a> ExactSizeIterator for Iter<'a> {}
71 
72 impl StreamCollection {
new(upstream_id: Option<&str>) -> StreamCollection73     pub fn new(upstream_id: Option<&str>) -> StreamCollection {
74         assert_initialized_main_thread!();
75         let upstream_id = upstream_id.to_glib_none();
76         let (major, minor, _, _) = ::version();
77         if (major, minor) > (1, 12) {
78             unsafe { from_glib_full(gst_sys::gst_stream_collection_new(upstream_id.0)) }
79         } else {
80             // Work-around for 1.14 switching from transfer-floating to transfer-full
81             unsafe { from_glib_none(gst_sys::gst_stream_collection_new(upstream_id.0)) }
82         }
83     }
84 
85     #[cfg(any(feature = "v1_10", feature = "dox"))]
add_stream<P: IsA<Stream>>(&self, stream: &P)86     pub fn add_stream<P: IsA<Stream>>(&self, stream: &P) {
87         unsafe {
88             gst_sys::gst_stream_collection_add_stream(
89                 self.to_glib_none().0,
90                 stream.as_ref().to_glib_full(),
91             );
92         }
93     }
94 
iter(&self) -> Iter95     pub fn iter(&self) -> Iter {
96         Iter::new(self)
97     }
98 
len(&self) -> usize99     pub fn len(&self) -> usize {
100         self.get_size() as usize
101     }
102 
is_empty(&self) -> bool103     pub fn is_empty(&self) -> bool {
104         self.len() == 0
105     }
106 
debug(&self) -> Debug107     pub fn debug(&self) -> Debug {
108         Debug(self)
109     }
110 }
111 
112 pub struct Debug<'a>(&'a StreamCollection);
113 
114 impl<'a> fmt::Debug for Debug<'a> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result115     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116         struct Streams<'a>(&'a StreamCollection);
117 
118         impl<'a> fmt::Debug for Streams<'a> {
119             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120                 let mut f = f.debug_list();
121 
122                 for stream in self.0.iter() {
123                     f.entry(&stream.debug());
124                 }
125 
126                 f.finish()
127             }
128         }
129 
130         let streams = Streams(self.0);
131 
132         f.debug_struct("StreamCollection")
133             .field("streams", &streams)
134             .finish()
135     }
136 }
137