use crate::internal::OnDrop;
use super::*;
use std::{ffi::CString, thread::yield_now, time::Instant};
#[derive(Debug, Clone)]
pub struct FindBuilder {
show_local_sources: Option<bool>,
groups: Option<String>,
extra_ips: Option<String>,
}
impl FindBuilder {
pub fn new() -> Self {
Self {
show_local_sources: None,
groups: None,
extra_ips: None,
}
}
pub fn show_local_sources(mut self, show_local_sources: bool) -> Self {
self.show_local_sources = Some(show_local_sources);
self
}
pub fn groups(mut self, groups: String) -> Self {
self.groups = Some(groups);
self
}
pub fn extra_ips(mut self, extra_ips: String) -> Self {
self.extra_ips = Some(extra_ips);
self
}
pub fn build(self) -> Result<Find, FindCreateError> {
let mut settings = NDIlib_find_create_t {
show_local_sources: true,
p_groups: null(),
p_extra_ips: null(),
};
if let Some(show_local_sources) = self.show_local_sources {
settings.show_local_sources = show_local_sources;
}
if let Some(groups) = self.groups {
let cstr = CString::new(groups).unwrap();
settings.p_groups = cstr.into_raw();
}
if let Some(extra_ips) = self.extra_ips {
let cstr = CString::new(extra_ips).unwrap();
settings.p_extra_ips = cstr.into_raw();
}
Find::with_settings(settings)
}
}
pub struct Find {
p_instance: Arc<OnDrop<NDIlib_find_instance_t>>,
}
unsafe impl core::marker::Send for Find {}
unsafe impl core::marker::Sync for Find {}
impl Find {
pub fn new() -> Result<Self, FindCreateError> {
let p_instance = unsafe { NDIlib_find_create_v2(null()) };
if p_instance.is_null() {
return Err(FindCreateError);
};
let p_instance = Arc::new(OnDrop::new(p_instance, |s| unsafe {
NDIlib_find_destroy(s)
}));
Ok(Self { p_instance })
}
fn with_settings(settings: NDIlib_find_create_t) -> Result<Self, FindCreateError> {
let p_instance = unsafe { NDIlib_find_create_v2(&settings) };
if p_instance.is_null() {
return Err(FindCreateError);
};
let p_instance = Arc::new(OnDrop::new(p_instance, |s| unsafe {
NDIlib_find_destroy(s)
}));
Ok(Self { p_instance })
}
pub fn current_sources(&self, timeout_ms: u128) -> Result<Vec<Source>, FindSourcesTimeout> {
let mut no_sources = 0;
let start = Instant::now();
let p_sources = loop {
if start.elapsed().as_millis() > timeout_ms {
return Err(FindSourcesTimeout);
}
let p_sources =
unsafe { NDIlib_find_get_current_sources(**self.p_instance, &mut no_sources) };
if no_sources != 0 {
break p_sources;
} else {
yield_now();
}
};
let mut sources: Vec<Source> = vec![];
for k in 0..no_sources {
let parent = SourceParent::Find(Arc::clone(&self.p_instance));
sources.push(Source::from_binding(parent, unsafe {
*p_sources.offset(k as _)
}));
}
Ok(sources)
}
}