linux_video_core/impls/
frmivals.rs1use crate::{calls, types::*, Internal, Result};
2use core::mem::MaybeUninit;
3use std::os::unix::io::RawFd;
4
5impl FrmIvalEnum {
6 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}