Skip to main content

vmb_core/
system.rs

1//! RAII owner for the Vimba X runtime lifecycle.
2//!
3//! [`VmbSystem`] is the composition root for a running Vimba session. It
4//! is generic over any [`VmbRuntime`]: use the production FFI adapter in
5//! release code, an in-memory fake in tests.
6//!
7//! Construction calls [`VmbRuntime::startup`]; `Drop` calls
8//! [`VmbRuntime::shutdown`]. The "singleton" invariant (the FFI SDK is
9//! process-global) is enforced by the runtime — dropping a live system
10//! while another `VmbSystem` exists for the same runtime is prevented
11//! inside the FFI adapter, not here.
12
13use std::sync::Arc;
14
15use crate::camera::Camera;
16use crate::discovery::{register_camera_discovery, DiscoveryRegistration};
17use crate::port::VmbRuntime;
18use crate::types::{CameraInfo, DiscoveryEvent};
19use crate::Result;
20
21/// Owns the Vimba X runtime lifecycle.
22///
23/// On construction, calls [`VmbRuntime::startup`]; on drop, calls
24/// [`VmbRuntime::shutdown`].
25pub struct VmbSystem<R: VmbRuntime> {
26    runtime: Arc<R>,
27}
28
29impl<R: VmbRuntime> VmbSystem<R> {
30    /// Start the Vimba runtime with the given backend.
31    ///
32    /// Returns [`crate::VmbError::AlreadyStarted`] if another
33    /// `VmbSystem` built on the same process-global runtime is still
34    /// alive (applies to [`VmbFfiRuntime`] — fakes are per-instance).
35    ///
36    /// [`VmbFfiRuntime`]: #production-adapter
37    pub fn startup(runtime: R) -> Result<Self> {
38        let runtime = Arc::new(runtime);
39        runtime.startup()?;
40        Ok(Self { runtime })
41    }
42
43    /// Borrow the underlying runtime. Rarely needed by user code — most
44    /// operations are exposed directly on [`VmbSystem`], [`Camera`], or
45    /// [`DiscoveryRegistration`].
46    pub fn runtime(&self) -> &R {
47        &self.runtime
48    }
49
50    /// Enumerate currently-visible cameras.
51    pub fn list_cameras(&self) -> Result<Vec<CameraInfo>> {
52        self.runtime.list_cameras()
53    }
54
55    /// Open a camera by its transport-layer ID.
56    pub fn open_camera(&self, id: &str) -> Result<Camera<R>> {
57        Camera::open(self.runtime.clone(), id)
58    }
59
60    /// Register a camera-discovery subscription; the callback is invoked
61    /// for every plug / unplug / reachability event the runtime
62    /// surfaces.
63    pub fn register_discovery<F>(&self, callback: F) -> Result<DiscoveryRegistration<R>>
64    where
65        F: Fn(DiscoveryEvent) + Send + Sync + 'static,
66    {
67        register_camera_discovery(self.runtime.clone(), callback)
68    }
69}
70
71impl<R: VmbRuntime> Drop for VmbSystem<R> {
72    fn drop(&mut self) {
73        self.runtime.shutdown();
74    }
75}
76
77impl<R: VmbRuntime> std::fmt::Debug for VmbSystem<R> {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        f.debug_struct("VmbSystem").finish_non_exhaustive()
80    }
81}