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;
10 use glib::translate::{from_glib_full, from_glib_none};
11 use gst_sys;
12 use std::fmt;
13 
14 use miniobject::*;
15 use Buffer;
16 use BufferRef;
17 
18 gst_define_mini_object_wrapper!(
19     BufferList,
20     BufferListRef,
21     gst_sys::GstBufferList,
22     [Debug,],
23     || gst_sys::gst_buffer_list_get_type()
24 );
25 
26 impl BufferList {
new() -> Self27     pub fn new() -> Self {
28         assert_initialized_main_thread!();
29         unsafe { from_glib_full(gst_sys::gst_buffer_list_new()) }
30     }
31 
new_sized(size: usize) -> Self32     pub fn new_sized(size: usize) -> Self {
33         assert_initialized_main_thread!();
34         unsafe { from_glib_full(gst_sys::gst_buffer_list_new_sized(size as u32)) }
35     }
36 }
37 
38 impl BufferListRef {
insert(&mut self, idx: i32, buffer: Buffer)39     pub fn insert(&mut self, idx: i32, buffer: Buffer) {
40         unsafe {
41             gst_sys::gst_buffer_list_insert(self.as_mut_ptr(), idx, buffer.into_ptr());
42         }
43     }
44 
add(&mut self, buffer: Buffer)45     pub fn add(&mut self, buffer: Buffer) {
46         self.insert(-1, buffer);
47     }
48 
copy_deep(&self) -> BufferList49     pub fn copy_deep(&self) -> BufferList {
50         unsafe { from_glib_full(gst_sys::gst_buffer_list_copy_deep(self.as_ptr())) }
51     }
52 
remove(&mut self, idx: u32, len: u32)53     pub fn remove(&mut self, idx: u32, len: u32) {
54         unsafe { gst_sys::gst_buffer_list_remove(self.as_mut_ptr(), idx, len) }
55     }
56 
get(&self, idx: u32) -> Option<&BufferRef>57     pub fn get(&self, idx: u32) -> Option<&BufferRef> {
58         unsafe {
59             let ptr = gst_sys::gst_buffer_list_get(self.as_mut_ptr(), idx);
60             if ptr.is_null() {
61                 None
62             } else {
63                 Some(BufferRef::from_ptr(ptr))
64             }
65         }
66     }
67 
get_owned(&self, idx: u32) -> Option<Buffer>68     pub fn get_owned(&self, idx: u32) -> Option<Buffer> {
69         unsafe {
70             let ptr = gst_sys::gst_buffer_list_get(self.as_mut_ptr(), idx);
71             from_glib_none(ptr)
72         }
73     }
74 
75     #[cfg(any(feature = "v1_14", feature = "dox"))]
get_writable(&mut self, idx: u32) -> Option<&mut BufferRef>76     pub fn get_writable(&mut self, idx: u32) -> Option<&mut BufferRef> {
77         unsafe {
78             let ptr = gst_sys::gst_buffer_list_get_writable(self.as_mut_ptr(), idx);
79             if ptr.is_null() {
80                 None
81             } else {
82                 Some(BufferRef::from_mut_ptr(ptr))
83             }
84         }
85     }
86 
len(&self) -> usize87     pub fn len(&self) -> usize {
88         unsafe { gst_sys::gst_buffer_list_length(self.as_mut_ptr()) as usize }
89     }
90 
91     #[cfg(any(feature = "v1_14", feature = "dox"))]
calculate_size(&self) -> usize92     pub fn calculate_size(&self) -> usize {
93         unsafe { gst_sys::gst_buffer_list_calculate_size(self.as_mut_ptr()) as usize }
94     }
95 
is_empty(&self) -> bool96     pub fn is_empty(&self) -> bool {
97         self.len() == 0
98     }
99 
iter(&self) -> Iter100     pub fn iter(&self) -> Iter {
101         Iter::new(self)
102     }
103 
iter_owned(&self) -> IterOwned104     pub fn iter_owned(&self) -> IterOwned {
105         IterOwned::new(self)
106     }
107 }
108 
109 impl Default for BufferList {
default() -> Self110     fn default() -> Self {
111         Self::new()
112     }
113 }
114 
115 impl fmt::Debug for BufferListRef {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result116     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117         let size = self.iter().map(|b| b.get_size()).sum::<usize>();
118         let (pts, dts) = self
119             .get(0)
120             .map(|b| (b.get_pts(), b.get_dts()))
121             .unwrap_or((::ClockTime::none(), ::ClockTime::none()));
122 
123         f.debug_struct("BufferList")
124             .field("ptr", unsafe { &self.as_ptr() })
125             .field("buffers", &self.len())
126             .field("pts", &pts.to_string())
127             .field("dts", &dts.to_string())
128             .field("size", &size)
129             .finish()
130     }
131 }
132 
133 macro_rules! define_iter(
134     ($name:ident, $styp:ty, $get_item:expr) => {
135     #[derive(Debug)]
136     pub struct $name<'a> {
137         list: &'a BufferListRef,
138         idx: u32,
139         size: u32,
140     }
141 
142     impl<'a> $name<'a> {
143         fn new(list: &'a BufferListRef) -> $name<'a> {
144             skip_assert_initialized!();
145             $name {
146                 list,
147                 idx: 0,
148                 size: list.len() as u32,
149             }
150         }
151     }
152 
153     impl<'a> Iterator for $name<'a> {
154         type Item = $styp;
155 
156         fn next(&mut self) -> Option<Self::Item> {
157             if self.idx >= self.size {
158                 return None;
159             }
160 
161             let item = $get_item(self.list, self.idx)?;
162             self.idx += 1;
163 
164             Some(item)
165         }
166 
167         fn size_hint(&self) -> (usize, Option<usize>) {
168             if self.idx == self.size {
169                 return (0, Some(0));
170             }
171 
172             let remaining = (self.size - self.idx) as usize;
173 
174             (remaining, Some(remaining))
175         }
176     }
177 
178     impl<'a> DoubleEndedIterator for $name<'a> {
179         fn next_back(&mut self) -> Option<Self::Item> {
180             if self.idx == self.size {
181                 return None;
182             }
183 
184             self.size -= 1;
185             $get_item(self.list, self.size)
186         }
187     }
188 
189     impl<'a> ExactSizeIterator for $name<'a> {}
190     }
191 );
192 
193 define_iter!(Iter, &'a BufferRef, |list: &'a BufferListRef, idx| {
194     list.get(idx)
195 });
196 
197 define_iter!(IterOwned, Buffer, |list: &BufferListRef, idx| {
198     list.get_owned(idx)
199 });
200