linux_video_core/impls/
frmivals.rs

1use crate::{calls, types::*, Internal, Result};
2use core::mem::MaybeUninit;
3use std::os::unix::io::RawFd;
4
5impl FrmIvalEnum {
6    /// Get reference to value
7    pub fn try_ref<T: IsFrmIvalData>(&self) -> Option<&T> {
8        if T::TYPES.contains(&self.type_()) {
9            Some(unsafe { &*(&self.union_ as *const _ as *const T) })
10        } else {
11            None
12        }
13    }
14}
15
16impl Internal<FrmIvalEnum> {
17    pub fn query(
18        fd: RawFd,
19        index: u32,
20        pixel_format: FourCc,
21        width: u32,
22        height: u32,
23    ) -> Result<Option<Self>> {
24        let frm_ival = MaybeUninit::<FrmIvalEnum>::zeroed();
25
26        unsafe_call!({
27            let mut frm_ival = frm_ival.assume_init();
28            frm_ival.index = index;
29            frm_ival.pixel_format = pixel_format;
30            frm_ival.width = width;
31            frm_ival.height = height;
32            calls::enum_frame_intervals(fd, &mut frm_ival).map(|_| frm_ival)
33        })
34        .map(|frm_ival| Some(frm_ival.into()))
35        .or_else(|error| {
36            if error.kind() == std::io::ErrorKind::InvalidInput {
37                Ok(None)
38            } else {
39                Err(error)
40            }
41        })
42    }
43}
44
45pub trait IsFrmIvalData {
46    const TYPES: &'static [FrmIvalType];
47}
48
49macro_rules! frmsize_impl {
50    ($($type:ty: $($buf_type:ident)*,)*) => {
51        $(
52            impl IsFrmIvalData for $type {
53                const TYPES: &'static [FrmIvalType] = &[ $(FrmIvalType::$buf_type,)* ];
54            }
55        )*
56
57        impl core::fmt::Display for FrmIvalEnum {
58            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
59                '#'.fmt(f)?;
60                self.index.fmt(f)?;
61                ' '.fmt(f)?;
62                self.pixel_format.fmt(f)?;
63                ' '.fmt(f)?;
64                self.type_.fmt(f)?;
65                ' '.fmt(f)?;
66                match self.type_ {
67                    $(
68                        $(FrmIvalType::$buf_type)|* => self.try_ref::<$type>()
69                            .ok_or_else(Default::default)?.fmt(f),
70                    )*
71                    _ => Ok(()),
72                }
73            }
74        }
75    };
76}
77
78frmsize_impl! {
79    Fract: Discrete,
80    FrmIvalStepwise: Stepwise,
81}
82
83impl core::fmt::Display for FrmIvalStepwise {
84    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
85        self.min.fmt(f)?;
86        "..=".fmt(f)?;
87        self.max.fmt(f)?;
88        '+'.fmt(f)?;
89        self.step.fmt(f)
90    }
91}