1use std::{ffi::CString, fmt::Debug};
13
14use static_assertions::assert_impl_all;
15
16use crate::{
17 bindings,
18 source::{NDISourceLike, NDISourceRef},
19 util::{SourceNameError, validate_source_name},
20};
21
22#[derive(Debug, Clone)]
24pub struct NDIRouterBuilder {
25 name: CString,
26}
27assert_impl_all!(NDIRouterBuilder: Send, Sync);
28
29impl NDIRouterBuilder {
30 pub fn new(name: &str) -> Result<Self, SourceNameError> {
36 Ok(Self {
37 name: validate_source_name(name)?,
38 })
39 }
40
41 pub fn build(self) -> Result<NDIRouter, NDIRouterBuilderError> {
42 let options = bindings::NDIlib_routing_create_t {
43 p_ndi_name: self.name.as_ptr(),
45 p_groups: std::ptr::null(),
46 };
47 let handle = unsafe { bindings::NDIlib_routing_create(&options) };
48
49 if handle.is_null() {
50 return Err(NDIRouterBuilderError::CreationFailed);
51 }
52
53 Ok(NDIRouter { handle })
54 }
55}
56
57#[non_exhaustive]
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum NDIRouterBuilderError {
60 CreationFailed,
61}
62
63#[derive(Debug)]
67pub struct NDIRouter {
68 handle: bindings::NDIlib_routing_instance_t,
69}
70unsafe impl Send for NDIRouter {}
71unsafe impl Sync for NDIRouter {}
72
73impl NDIRouter {
74 pub fn switch(&mut self, source: &impl NDISourceLike) -> Option<()> {
75 let mut result = false;
76 source.with_descriptor(|source_ptr| {
77 result = unsafe { bindings::NDIlib_routing_change(self.handle, source_ptr) };
78 });
79 if result { Some(()) } else { None }
80 }
81
82 pub fn switch_clear(&mut self) -> Option<()> {
83 let result = unsafe { bindings::NDIlib_routing_clear(self.handle) };
84 if result { Some(()) } else { None }
85 }
86
87 pub fn get_source(&self) -> NDISourceRef<'_> {
89 let source = unsafe { bindings::NDIlib_routing_get_source_name(self.handle) };
91
92 unsafe {
93 NDISourceRef::from(
94 *source
95 .as_ref()
96 .expect("[Fatal FFI Error] NDI SDK returned nullptr for source descriptor"),
97 )
98 }
99 }
100}
101
102impl Drop for NDIRouter {
103 fn drop(&mut self) {
104 unsafe { bindings::NDIlib_routing_destroy(self.handle) };
105 }
106}