ndi_sdk_sys/
enums.rs

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/// This enum describes the preferred color format for receiving video frames.
11/// If you can handle all color formats you should use `Fastest`
12///
13/// C equivalent: `NDIlib_recv_color_format_e`
14#[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    /// Returns the FourCC type that will be used for frames without alpha channel.
40    ///
41    /// None indicates that the resulting FourCC type cannot statically be known
42    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    /// Returns the FourCC type that will be used for frames with alpha channel.
54    ///
55    /// None indicates that the resulting FourCC type cannot statically be known
56    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    /// Tries to create a preferred color format from the given FourCC types.
69    ///
70    /// Only a few combinations are allowed by the SDK, in case of an unsupported combination this will return Err(FromFourCCError::UnsupportedCombination).
71    ///
72    /// A None argument means Don't care
73    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/// Selects which types of frames are transmitted and which quality is used
140///
141/// This can be beneficial for preview screens or if you only want metadata
142///
143/// C equivalent: `NDIlib_recv_bandwidth_e`
144#[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/// Video frames can be fielded (even and odd lines are sent in separate frames), this enum
167/// describes if fielding is used and which half is in the current frame
168///
169/// C equivalent: `NDIlib_frame_format_type_e`
170#[repr(i32)]
171#[non_exhaustive]
172#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
173pub enum NDIFieldedFrameMode {
174    /// Progressive (non-fielded) video frame.
175    #[default]
176    Progressive = bindings::NDIlib_frame_format_type_e_NDIlib_frame_format_type_progressive,
177    /// This is a frame of video that is comprised of two fields.
178    /// The upper field comes first, and the lower comes second
179    Interleaved = bindings::NDIlib_frame_format_type_e_NDIlib_frame_format_type_interleaved,
180    /// This is an individual field 0 from a fielded video frame. This is the first temporal, upper field
181    Field0 = bindings::NDIlib_frame_format_type_e_NDIlib_frame_format_type_field_0,
182    /// This is an individual field 1 from a fielded video frame. This is the second temporal, lower field
183    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/// Describes which frame type was received
212#[must_use]
213#[non_exhaustive]
214#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
215pub enum NDIRecvType {
216    /// A video frame was received
217    Video,
218    /// An audio frame was received
219    Audio,
220    /// A metadata frame was received
221    Metadata,
222    /// No frame was received, most likely because the timeout was reached.
223    None,
224    /// No frame was received, but the status of the connection changed.
225    /// Things like the web control URL could have changed
226    StatusChange,
227    /// The source the receiver is connected to has changed
228    SourceChange,
229}
230
231#[non_exhaustive]
232#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
233pub enum NDIRecvError {
234    /// The SDK returned a frame type that is not recognized.
235    UnknownType,
236    /// The frame to be written to is not writable
237    NotWritable,
238}