libcamera/
camera_manager.rs

1use std::{
2    ffi::{CStr, CString},
3    io,
4    marker::PhantomData,
5    ptr::NonNull,
6};
7
8use libcamera_sys::*;
9
10use crate::{camera::Camera, logging::LoggingLevel, utils::handle_result};
11
12/// Camera manager used to enumerate available cameras in the system.
13pub struct CameraManager {
14    ptr: NonNull<libcamera_camera_manager_t>,
15}
16
17impl CameraManager {
18    /// Initializes `libcamera` and creates [Self].
19    pub fn new() -> io::Result<Self> {
20        let ptr = NonNull::new(unsafe { libcamera_camera_manager_create() }).unwrap();
21        let ret = unsafe { libcamera_camera_manager_start(ptr.as_ptr()) };
22        handle_result(ret)?;
23        Ok(CameraManager { ptr })
24    }
25
26    /// Returns version string of the linked libcamera.
27    pub fn version(&self) -> &str {
28        unsafe { CStr::from_ptr(libcamera_camera_manager_version(self.ptr.as_ptr())) }
29            .to_str()
30            .unwrap()
31    }
32
33    /// Enumerates cameras within the system.
34    pub fn cameras(&self) -> CameraList<'_> {
35        unsafe { CameraList::from_ptr(NonNull::new(libcamera_camera_manager_cameras(self.ptr.as_ptr())).unwrap()) }
36    }
37
38    /// Set the log level.
39    ///
40    /// # Parameters
41    ///
42    /// * `category` - Free-form category string, a list of those can be seen by running `grep 'LOG_DEFINE_CATEGORY('
43    ///   -R` on the `libcamera` source code
44    /// * `level` - Maximum log importance level to show, anything more less important than that will be hidden.
45    pub fn log_set_level(&self, category: &str, level: LoggingLevel) {
46        let category = CString::new(category).expect("category contains null byte");
47        let level: &CStr = level.into();
48        unsafe {
49            libcamera_log_set_level(category.as_ptr(), level.as_ptr());
50        }
51    }
52}
53
54impl Drop for CameraManager {
55    fn drop(&mut self) {
56        unsafe {
57            libcamera_camera_manager_stop(self.ptr.as_ptr());
58            libcamera_camera_manager_destroy(self.ptr.as_ptr());
59        }
60    }
61}
62
63pub struct CameraList<'d> {
64    ptr: NonNull<libcamera_camera_list_t>,
65    _phantom: PhantomData<&'d ()>,
66}
67
68impl CameraList<'_> {
69    pub(crate) unsafe fn from_ptr(ptr: NonNull<libcamera_camera_list_t>) -> Self {
70        Self {
71            ptr,
72            _phantom: Default::default(),
73        }
74    }
75
76    /// Number of cameras
77    pub fn len(&self) -> usize {
78        unsafe { libcamera_camera_list_size(self.ptr.as_ptr()) }
79    }
80
81    /// Returns `true` if there are no cameras available
82    pub fn is_empty(&self) -> bool {
83        self.len() == 0
84    }
85
86    /// Returns camera at a given index.
87    ///
88    /// Returns [None] if index is out of range of available cameras.
89    pub fn get(&self, index: usize) -> Option<Camera<'_>> {
90        let cam_ptr = unsafe { libcamera_camera_list_get(self.ptr.as_ptr(), index as _) };
91        NonNull::new(cam_ptr).map(|p| unsafe { Camera::from_ptr(p) })
92    }
93}
94
95impl Drop for CameraList<'_> {
96    fn drop(&mut self) {
97        unsafe {
98            libcamera_camera_list_destroy(self.ptr.as_ptr());
99        }
100    }
101}