1use std::marker::PhantomData;
2use std::ptr;
3
4use device;
5use ffi::*;
6use format::context::common::Context;
7use libc::c_int;
8use Error;
9
10impl Context {
11 pub fn devices(&self) -> Result<DeviceIter, Error> {
12 unsafe { DeviceIter::wrap(self.as_ptr()) }
13 }
14}
15
16pub struct DeviceIter<'a> {
17 ptr: *mut AVDeviceInfoList,
18 cur: c_int,
19
20 _marker: PhantomData<&'a ()>,
21}
22
23impl<'a> DeviceIter<'a> {
24 pub unsafe fn wrap(ctx: *const AVFormatContext) -> Result<Self, Error> {
25 let mut ptr: *mut AVDeviceInfoList = ptr::null_mut();
26
27 match avdevice_list_devices(ctx as *mut _, &mut ptr) {
28 n if n < 0 => Err(Error::from(n)),
29
30 _ => Ok(DeviceIter {
31 ptr,
32 cur: 0,
33 _marker: PhantomData,
34 }),
35 }
36 }
37}
38
39impl<'a> DeviceIter<'a> {
40 pub fn default(&self) -> usize {
41 unsafe { (*self.ptr).default_device as usize }
42 }
43}
44
45impl<'a> Drop for DeviceIter<'a> {
46 fn drop(&mut self) {
47 unsafe {
48 avdevice_free_list_devices(&mut self.ptr);
49 }
50 }
51}
52
53impl<'a> Iterator for DeviceIter<'a> {
54 type Item = device::Info<'a>;
55
56 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
57 unsafe {
58 if self.cur >= (*self.ptr).nb_devices {
59 None
60 } else {
61 self.cur += 1;
62 Some(device::Info::wrap(
63 *(*self.ptr).devices.offset((self.cur - 1) as isize),
64 ))
65 }
66 }
67 }
68
69 fn size_hint(&self) -> (usize, Option<usize>) {
70 unsafe {
71 let length: usize = (*self.ptr).nb_devices as usize;
72
73 (length - self.cur as usize, Some(length - self.cur as usize))
74 }
75 }
76}
77
78impl<'a> ExactSizeIterator for DeviceIter<'a> {}
79