ndi_sdk_sys/
sdk.rs

1//! Contains methods for the whole SDK like startup/shutdown, CPU support tests and version lookup
2
3use std::ffi::CStr;
4
5use crate::bindings;
6
7/// Get the version of the NDI SDK.
8/// This may return None if the version cannot be determined.
9pub fn version() -> Option<&'static str> {
10    let version_ptr = unsafe { bindings::NDIlib_version() };
11    if version_ptr.is_null() {
12        return None;
13    }
14    let version = unsafe { CStr::from_ptr(version_ptr) };
15    version.to_str().ok()
16}
17
18#[cfg(test)]
19#[test]
20fn test_get_version() {
21    // This test is just to ensure that the version can be retrieved.
22    // It does not check the actual version string.
23    let version = version();
24    assert!(version.is_some(), "Failed to get NDI SDK version");
25}
26
27/// Detect whether the current CPU in the system is capable of running NDILib.
28/// Currently NDILib requires SSE4.2 instructions.
29///
30/// <https://docs.ndi.video/all/developing-with-ndi/sdk/cpu-requirements>
31pub fn cpu_supported() -> bool {
32    unsafe { bindings::NDIlib_is_supported_CPU() }
33}
34
35#[cfg(test)]
36#[test]
37fn test_cpu_supported() {
38    assert!(
39        cpu_supported(),
40        "CPU is not supported by NDI SDK, further tests will fail"
41    );
42}
43
44/// This is not actually required, but will start the libraries which might result in a slightly better
45/// performance in some cases. In general it is more "correct" to call it although it is not required.
46///
47/// C equivalent: `NDIlib_initialize`
48///
49/// <https://docs.ndi.video/all/developing-with-ndi/sdk/startup-and-shutdown>
50pub fn initialize() -> Result<(), NDIInitError> {
51    if unsafe { bindings::NDIlib_initialize() } {
52        Ok(())
53    } else if !cpu_supported() {
54        Err(NDIInitError::UnsupportedCPU)
55    } else {
56        Err(NDIInitError::GenericError)
57    }
58}
59
60/// This is not actually required, but will end the libraries which might result in a slightly better
61/// performance in some cases. In general it is more "correct" to call it although it is not required.
62/// There is no way a call it could have an adverse impact on anything (even calling destroy before
63/// you've deleted all your objects).
64///
65/// C equivalent: `NDIlib_destroy`
66///
67/// <https://docs.ndi.video/all/developing-with-ndi/sdk/startup-and-shutdown>
68pub fn destroy() {
69    unsafe { bindings::NDIlib_destroy() }
70}
71
72#[non_exhaustive]
73#[derive(Debug, Clone)]
74pub enum NDIInitError {
75    /// The CPU is not supported by the NDI SDK.
76    /// NDI requires SSE4.2 instructions
77    UnsupportedCPU,
78    GenericError,
79}