use std::{ffi::CString, fmt::Debug};
use static_assertions::assert_impl_all;
use crate::{
bindings,
source::{NDISourceLike, NDISourceRef},
util::{SourceNameError, validate_source_name},
};
#[derive(Debug, Clone)]
pub struct NDIRouterBuilder {
name: CString,
}
assert_impl_all!(NDIRouterBuilder: Send, Sync);
impl NDIRouterBuilder {
pub fn new(name: &str) -> Result<Self, SourceNameError> {
Ok(Self {
name: validate_source_name(name)?,
})
}
pub fn build(self) -> Result<NDIRouter, NDIRouterBuilderError> {
let options = bindings::NDIlib_routing_create_t {
p_ndi_name: self.name.as_ptr(),
p_groups: std::ptr::null(),
};
let handle = unsafe { bindings::NDIlib_routing_create(&options) };
if handle.is_null() {
return Err(NDIRouterBuilderError::CreationFailed);
}
Ok(NDIRouter { handle })
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NDIRouterBuilderError {
CreationFailed,
}
impl std::fmt::Display for NDIRouterBuilderError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::CreationFailed => f.write_str("Creating NDI router failed"),
}
}
}
impl std::error::Error for NDIRouterBuilderError {}
#[derive(Debug)]
pub struct NDIRouter {
handle: bindings::NDIlib_routing_instance_t,
}
unsafe impl Send for NDIRouter {}
unsafe impl Sync for NDIRouter {}
impl NDIRouter {
pub fn switch(&mut self, source: &impl NDISourceLike) -> Option<()> {
let mut result = false;
source.with_descriptor(|source_ptr| {
result = unsafe { bindings::NDIlib_routing_change(self.handle, source_ptr) };
});
if result { Some(()) } else { None }
}
pub fn switch_clear(&mut self) -> Option<()> {
let result = unsafe { bindings::NDIlib_routing_clear(self.handle) };
if result { Some(()) } else { None }
}
pub fn get_source(&self) -> NDISourceRef<'_> {
let source = unsafe { bindings::NDIlib_routing_get_source_name(self.handle) };
unsafe {
NDISourceRef::from(
*source
.as_ref()
.expect("[Fatal FFI Error] NDI SDK returned nullptr for source descriptor"),
)
}
}
}
impl Drop for NDIRouter {
fn drop(&mut self) {
unsafe { bindings::NDIlib_routing_destroy(self.handle) };
}
}