1use std::ffi;
2use std::sync::{Arc, Mutex};
3
4use crate::Source;
5use crate::{
6 sys::{NDIlib_routing_create_t, NDIlib_routing_instance_type},
7 NDIError, NDIResult, HANDLE,
8};
9
10struct RouteInstanceInner(*mut NDIlib_routing_instance_type);
11unsafe impl Send for RouteInstanceInner {}
12
13impl Drop for RouteInstanceInner {
14 fn drop(&mut self) {
15 if let Some(destroy_fn) = unsafe { (*HANDLE.lib).routing_destroy } {
16 unsafe { destroy_fn(self.0) };
17 }
18 }
19}
20
21pub struct RouteInstance {
22 inner: Arc<Mutex<RouteInstanceInner>>,
23}
24
25impl RouteInstance {
26 pub fn create(name: &str, groups: &[&str]) -> NDIResult<Self> {
27 let ndi_name = ffi::CString::new(name).unwrap();
28 let groups = ffi::CString::new(groups.join(",")).unwrap();
29 let settings = NDIlib_routing_create_t {
30 p_ndi_name: ndi_name.as_ptr(),
31 p_groups: groups.as_ptr(),
32 };
33
34 let Some(create_fn) = (unsafe { (*HANDLE.lib).routing_create }) else {
35 return Err(NDIError::MissingSymbolV5("routing_create"));
36 };
37 let create_t = unsafe { create_fn(&settings).as_mut() };
38 let inner = RouteInstanceInner(
39 create_t.ok_or_else(|| NDIError::UnexpectedNullPointer("routing_create"))?,
40 );
41 Ok(Self {
42 inner: Arc::new(Mutex::new(inner)),
43 })
44 }
45
46 pub fn change(&self, source: &Source) -> NDIResult<()> {
47 let Some(change_fn) = (unsafe { (*HANDLE.lib).routing_change }) else {
48 return Err(NDIError::MissingSymbolV5("routing_change"));
49 };
50
51 let guard = self.inner.lock().expect("Expected Mutex to work");
52 let _undefined = source.with_raw(|src| unsafe { change_fn((*guard).0, src) });
53 Ok(())
54 }
55
56 pub fn clear(&self) -> NDIResult<()> {
57 let Some(clear_fn) = (unsafe { (*HANDLE.lib).routing_clear }) else {
58 return Err(NDIError::MissingSymbolV5("routing_clear"));
59 };
60
61 let guard = self.inner.lock().expect("Expected Mutex to work");
62 let _undefined = unsafe { clear_fn((*guard).0) };
63 Ok(())
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn test_create() -> NDIResult<()> {
73 let _ri = RouteInstance::create("Router Test 1", &vec!["Public"])?;
74 Ok(())
75 }
76}