1use num_enum::{IntoPrimitive, TryFromPrimitive};
2
3use crate::{
4 bindings::{
5 self, NDIlib_frame_format_type_e, NDIlib_recv_bandwidth_e, NDIlib_recv_color_format_e,
6 },
7 four_cc::FourCCVideo,
8};
9
10#[repr(i32)]
15#[non_exhaustive]
16#[allow(non_camel_case_types)]
17#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
18pub enum NDIPreferredColorFormat {
19 #[default]
20 Fastest = bindings::NDIlib_recv_color_format_e_NDIlib_recv_color_format_fastest,
21 Best = bindings::NDIlib_recv_color_format_e_NDIlib_recv_color_format_best,
22
23 BGRX_BGRA = bindings::NDIlib_recv_color_format_e_NDIlib_recv_color_format_BGRX_BGRA,
24 UYVY_BGRA = bindings::NDIlib_recv_color_format_e_NDIlib_recv_color_format_UYVY_BGRA,
25 RGBX_RGBA = bindings::NDIlib_recv_color_format_e_NDIlib_recv_color_format_RGBX_RGBA,
26 UYVY_RGBA = bindings::NDIlib_recv_color_format_e_NDIlib_recv_color_format_UYVY_RGBA,
27}
28
29impl NDIPreferredColorFormat {
30 pub(crate) fn to_ffi(self) -> NDIlib_recv_color_format_e {
31 self.into()
32 }
33
34 #[expect(unused)]
35 pub(crate) fn from_ffi(value: NDIlib_recv_color_format_e) -> Option<Self> {
36 Self::try_from_primitive(value).ok()
37 }
38
39 pub const fn without_alpha_four_cc(self) -> Option<FourCCVideo> {
43 match self {
44 NDIPreferredColorFormat::BGRX_BGRA => Some(FourCCVideo::BGRX),
45 NDIPreferredColorFormat::RGBX_RGBA => Some(FourCCVideo::RGBX),
46 NDIPreferredColorFormat::UYVY_BGRA | NDIPreferredColorFormat::UYVY_RGBA => {
47 Some(FourCCVideo::UYVY)
48 }
49 _ => None,
50 }
51 }
52
53 pub const fn with_alpha_four_cc(self) -> Option<FourCCVideo> {
57 match self {
58 NDIPreferredColorFormat::BGRX_BGRA | NDIPreferredColorFormat::UYVY_BGRA => {
59 Some(FourCCVideo::BGRA)
60 }
61 NDIPreferredColorFormat::RGBX_RGBA | NDIPreferredColorFormat::UYVY_RGBA => {
62 Some(FourCCVideo::RGBA)
63 }
64 _ => None,
65 }
66 }
67
68 pub fn from_four_cc(
74 with_alpha: Option<FourCCVideo>,
75 without_alpha: Option<FourCCVideo>,
76 ) -> Result<Self, FromFourCCError> {
77 use FourCCVideo::*;
78 use NDIPreferredColorFormat::*;
79 if let Some(format) = with_alpha {
80 match format {
81 BGRA | RGBA => {}
82 BGRX | RGBX | UYVY => {
83 return Err(FromFourCCError::WrongAlphaMode {
84 format,
85 has_alpha: false,
86 expected_alpha: true,
87 });
88 }
89 format => {
90 return Err(FromFourCCError::UnsupportedFormat { format });
91 }
92 }
93 }
94 if let Some(format) = without_alpha {
95 match format {
96 BGRX | RGBX | UYVY => {}
97 BGRA | RGBA => {
98 return Err(FromFourCCError::WrongAlphaMode {
99 format,
100 has_alpha: true,
101 expected_alpha: false,
102 });
103 }
104 format => {
105 return Err(FromFourCCError::UnsupportedFormat { format });
106 }
107 }
108 }
109 match (without_alpha, with_alpha) {
110 (Some(BGRX), Some(BGRA)) => Ok(BGRX_BGRA),
111 (Some(RGBX), Some(RGBA)) => Ok(RGBX_RGBA),
112 (Some(UYVY), Some(BGRA)) => Ok(UYVY_BGRA),
113 (Some(UYVY), Some(RGBA)) => Ok(UYVY_RGBA),
114 (Some(BGRX), None) => Ok(BGRX_BGRA),
115 (Some(RGBX), None) => Ok(RGBX_RGBA),
116 (Some(UYVY), None) => Ok(UYVY_BGRA),
117 (None, Some(BGRA)) => Ok(BGRX_BGRA),
118 (None, Some(RGBA)) => Ok(RGBX_RGBA),
119 (None, None) => Ok(Fastest),
120 _ => Err(FromFourCCError::UnsupportedCombination),
121 }
122 }
123}
124
125#[non_exhaustive]
126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127pub enum FromFourCCError {
128 UnsupportedFormat {
129 format: FourCCVideo,
130 },
131 WrongAlphaMode {
132 format: FourCCVideo,
133 has_alpha: bool,
134 expected_alpha: bool,
135 },
136 UnsupportedCombination,
137}
138
139#[repr(i32)]
145#[non_exhaustive]
146#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
147pub enum NDIBandwidthMode {
148 #[default]
149 Default = bindings::NDIlib_recv_bandwidth_e_NDIlib_recv_bandwidth_highest,
150 Preview = bindings::NDIlib_recv_bandwidth_e_NDIlib_recv_bandwidth_lowest,
151 AudioOnly = bindings::NDIlib_recv_bandwidth_e_NDIlib_recv_bandwidth_audio_only,
152 MetadataOnly = bindings::NDIlib_recv_bandwidth_e_NDIlib_recv_bandwidth_metadata_only,
153}
154
155impl NDIBandwidthMode {
156 pub(crate) fn to_ffi(self) -> NDIlib_recv_bandwidth_e {
157 self.into()
158 }
159
160 #[expect(unused)]
161 pub(crate) fn from_ffi(value: NDIlib_recv_bandwidth_e) -> Option<Self> {
162 Self::try_from_primitive(value).ok()
163 }
164}
165
166#[repr(i32)]
171#[non_exhaustive]
172#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
173pub enum NDIFieldedFrameMode {
174 #[default]
176 Progressive = bindings::NDIlib_frame_format_type_e_NDIlib_frame_format_type_progressive,
177 Interleaved = bindings::NDIlib_frame_format_type_e_NDIlib_frame_format_type_interleaved,
180 Field0 = bindings::NDIlib_frame_format_type_e_NDIlib_frame_format_type_field_0,
182 Field1 = bindings::NDIlib_frame_format_type_e_NDIlib_frame_format_type_field_1,
184}
185
186impl NDIFieldedFrameMode {
187 pub(crate) fn to_ffi(self) -> NDIlib_frame_format_type_e {
188 self.into()
189 }
190
191 pub(crate) fn from_ffi(value: NDIlib_frame_format_type_e) -> Option<Self> {
192 Self::try_from_primitive(value).ok()
193 }
194
195 pub const fn is_progressive(self) -> bool {
196 matches!(self, NDIFieldedFrameMode::Progressive)
197 }
198
199 pub const fn is_fielded(self) -> bool {
200 !self.is_progressive()
201 }
202
203 pub const fn is_single_field(self) -> bool {
204 matches!(
205 self,
206 NDIFieldedFrameMode::Field0 | NDIFieldedFrameMode::Field1
207 )
208 }
209}
210
211#[must_use]
213#[non_exhaustive]
214#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
215pub enum NDIRecvType {
216 Video,
218 Audio,
220 Metadata,
222 None,
224 StatusChange,
227 SourceChange,
229}
230
231#[non_exhaustive]
232#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
233pub enum NDIRecvError {
234 UnknownType,
236 NotWritable,
238}