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