playa_ffmpeg/device/
extensions.rs

1use 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> {}