use std::path::Path;
use std::sync::Arc;
use crate::callback::FrameCallback;
use crate::types::{
CameraHandle, CameraInfo, DiscoveryCallbackId, DiscoveryEvent, DiscoveryRegistrationHandle,
FrameCallbackId, FrameSlotId,
};
use crate::Result;
pub struct DiscoveryCallback {
inner: Box<dyn Fn(DiscoveryEvent) + Send + Sync + 'static>,
}
impl DiscoveryCallback {
pub fn new<F>(f: F) -> Self
where
F: Fn(DiscoveryEvent) + Send + Sync + 'static,
{
Self { inner: Box::new(f) }
}
pub fn invoke(&self, event: DiscoveryEvent) {
(self.inner)(event);
}
}
pub trait VmbRuntime: Send + Sync + 'static {
fn startup(&self) -> Result<()>;
fn shutdown(&self);
fn list_cameras(&self) -> Result<Vec<CameraInfo>>;
fn open_camera(&self, id: &str) -> Result<CameraHandle>;
fn close_camera(&self, h: CameraHandle);
fn load_settings(&self, h: CameraHandle, path: &Path) -> Result<()>;
fn run_feature_command(&self, h: CameraHandle, name: &str) -> Result<()>;
fn payload_size(&self, h: CameraHandle) -> Result<u32>;
fn announce_frame(&self, h: CameraHandle, size: u32) -> Result<FrameSlotId>;
fn capture_start(&self, h: CameraHandle) -> Result<()>;
fn queue_frame(&self, h: CameraHandle, slot: FrameSlotId, cb: FrameCallbackId) -> Result<()>;
fn capture_end(&self, h: CameraHandle);
fn capture_queue_flush(&self, h: CameraHandle);
fn frame_revoke_all(&self, h: CameraHandle);
fn register_discovery(&self, cb: DiscoveryCallbackId) -> Result<DiscoveryRegistrationHandle>;
fn unregister_discovery(&self, r: DiscoveryRegistrationHandle);
fn install_frame_callback(&self, cb: Arc<FrameCallback>) -> FrameCallbackId;
fn uninstall_frame_callback(&self, id: FrameCallbackId);
fn install_discovery_callback(&self, cb: Arc<DiscoveryCallback>) -> DiscoveryCallbackId;
fn uninstall_discovery_callback(&self, id: DiscoveryCallbackId);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn discovery_callback_dispatches() {
use std::sync::atomic::{AtomicUsize, Ordering};
let counter = Arc::new(AtomicUsize::new(0));
let c = counter.clone();
let cb = DiscoveryCallback::new(move |event| {
if matches!(event, DiscoveryEvent::Detected(_)) {
c.fetch_add(1, Ordering::SeqCst);
}
});
cb.invoke(DiscoveryEvent::Detected("cam-a".into()));
cb.invoke(DiscoveryEvent::Missing("cam-b".into()));
cb.invoke(DiscoveryEvent::Detected("cam-c".into()));
assert_eq!(counter.load(Ordering::SeqCst), 2);
}
}