diff --git a/Cargo.lock b/Cargo.lock index 1e93217..dda03c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -328,7 +328,7 @@ dependencies = [ [[package]] name = "libcamera-sys" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bindgen", "cc", diff --git a/libcamera-meta/src/bin/generate_from_git.rs b/libcamera-meta/src/bin/generate_from_git.rs index c8dda6f..c0ccfde 100644 --- a/libcamera-meta/src/bin/generate_from_git.rs +++ b/libcamera-meta/src/bin/generate_from_git.rs @@ -308,32 +308,25 @@ mod generate_rust { } out += "}\n"; - let ffi_binding = match ty { - ControlsType::Control => "libcamera_control_name_from_id", - ControlsType::Property => "libcamera_property_name_by_id", + let name_fn = match ty { + ControlsType::Control => "control_id_name", + ControlsType::Property => "property_id_name", }; - out += &format!("impl {} {{\n", name); + out += &format!("impl {name} {{\n"); out += r#" - fn id(&self) -> u32 { - *self as u32 + pub fn id(&self) -> u32 { + u32::from(*self) } "#; out += "\n"; - out += r#" - pub fn name(&self) -> String { - unsafe {"#; - out += &format!(" let c_str = {}(self.id());\n", ffi_binding); - out += r#" - if c_str.is_null() { - // Handle null pointer as empty strings - return "".into(); - } - // Convert the C string to a Rust &str - CStr::from_ptr(c_str).to_str().unwrap().into() - } - } - "#; + out += &format!( + " + pub fn name(&self) -> String {{ + {name_fn}(*self) + }} + " + ); out += "}\n"; @@ -458,10 +451,12 @@ mod generate_rust { pub fn generate_controls_file(controls: &[Control], ty: ControlsType) -> String { let header = r#" - use std::{ffi::CStr, ops::{{Deref, DerefMut}}}; + use std::ops::{{Deref, DerefMut}}; use num_enum::{{IntoPrimitive, TryFromPrimitive}}; #[allow(unused_imports)] - use crate::control::{{Control, Property, ControlEntry, DynControlEntry}}; + use crate::control::{{ + Control, Property, ControlEntry, DynControlEntry, control_id_name, property_id_name + }}; use crate::control_value::{{ControlValue, ControlValueError}}; #[allow(unused_imports)] use crate::geometry::{{Rectangle, Point, Size}}; diff --git a/libcamera-sys/Cargo.toml b/libcamera-sys/Cargo.toml index efef19c..1672f13 100644 --- a/libcamera-sys/Cargo.toml +++ b/libcamera-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libcamera-sys" -version = "0.4.0" +version = "0.5.0" edition = "2021" description = "Low-level unsafe bindings to libcamera" documentation = "https://docs.rs/libcamera-sys" diff --git a/libcamera-sys/c_api/controls.cpp b/libcamera-sys/c_api/controls.cpp index 1a6fb0c..f29ec01 100644 --- a/libcamera-sys/c_api/controls.cpp +++ b/libcamera-sys/c_api/controls.cpp @@ -41,7 +41,7 @@ enum libcamera_control_type libcamera_control_type_from_id(enum libcamera_contro return LIBCAMERA_CONTROL_TYPE_NONE; } -const char *libcamera_property_name_by_id(enum libcamera_property_id id) { +const char *libcamera_property_name_from_id(enum libcamera_property_id id) { auto it = libcamera::properties::properties.find(id); if (it != libcamera::properties::properties.end()) return it->second->name().c_str(); @@ -49,7 +49,7 @@ const char *libcamera_property_name_by_id(enum libcamera_property_id id) { return nullptr; } -enum libcamera_control_type libcamera_property_type_by_id(enum libcamera_property_id id) { +enum libcamera_control_type libcamera_property_type_from_id(enum libcamera_property_id id) { auto it = libcamera::properties::properties.find(id); if (it != libcamera::properties::properties.end()) return (enum libcamera_control_type)it->second->type(); diff --git a/libcamera-sys/c_api/controls.h b/libcamera-sys/c_api/controls.h index dd4b52c..0a20c9d 100644 --- a/libcamera-sys/c_api/controls.h +++ b/libcamera-sys/c_api/controls.h @@ -68,8 +68,8 @@ enum libcamera_control_id_enum libcamera_control_id(libcamera_control_id_t *cont const char *libcamera_control_name(libcamera_control_id_t *control); enum libcamera_control_type libcamera_control_type(libcamera_control_id_t *control); // --- libcamera_property_id --- -const char *libcamera_property_name_by_id(enum libcamera_property_id id); -enum libcamera_control_type libcamera_property_type_by_id(enum libcamera_property_id id); +const char *libcamera_property_name_from_id(enum libcamera_property_id id); +enum libcamera_control_type libcamera_property_type_from_id(enum libcamera_property_id id); // --- libcamera_control_list_t --- libcamera_control_list_t *libcamera_control_list_create(); diff --git a/libcamera-sys/examples/version.rs b/libcamera-sys/examples/version.rs index bd7a43d..fd06458 100644 --- a/libcamera-sys/examples/version.rs +++ b/libcamera-sys/examples/version.rs @@ -7,7 +7,7 @@ fn main() { let mgr = libcamera_camera_manager_create(); let version = CStr::from_ptr(libcamera_camera_manager_version(mgr)).to_str().unwrap(); - println!("libcamera: {}", version); + println!("libcamera: {version}"); libcamera_camera_manager_destroy(mgr); } diff --git a/libcamera/Cargo.toml b/libcamera/Cargo.toml index d7cfab6..163c4e4 100644 --- a/libcamera/Cargo.toml +++ b/libcamera/Cargo.toml @@ -25,7 +25,7 @@ vendor_rpi = [] bitflags = "2.0.0-rc.2" drm-fourcc = "2.2" libc = "0.2" -libcamera-sys = { path = "../libcamera-sys", version = "0.4.0", default-features = false } +libcamera-sys = { path = "../libcamera-sys", version = "0.5.0", default-features = false } num_enum = "0.6.1" smallvec = "1.10" thiserror = "1.0" diff --git a/libcamera/examples/cameras_iter.rs b/libcamera/examples/cameras_iter.rs deleted file mode 100644 index d4c8516..0000000 --- a/libcamera/examples/cameras_iter.rs +++ /dev/null @@ -1,20 +0,0 @@ -use libcamera::{camera_manager::CameraManager, logging::LoggingLevel, stream::StreamRole}; - -fn main() { - let mgr = CameraManager::new().unwrap(); - - mgr.log_set_level("Camera", LoggingLevel::Error); - - let cameras = mgr.cameras(); - - for cam in cameras.iter() { - println!("ID: {}", cam.id()); - - println!("Properties: {:#?}", cam.properties()); - println!("Controls: {:#?}", cam.controls()); - - let config = cam.generate_configuration(&[StreamRole::ViewFinder]).unwrap(); - let view_finder_cfg = config.get(0).unwrap(); - println!("Available formats: {:#?}", view_finder_cfg.formats()); - } -} diff --git a/libcamera/examples/jpeg_capture.rs b/libcamera/examples/jpeg_capture.rs index 10ab09d..5f2aa87 100644 --- a/libcamera/examples/jpeg_capture.rs +++ b/libcamera/examples/jpeg_capture.rs @@ -36,11 +36,11 @@ fn main() { // Use MJPEG format so we can write resulting frame directly into jpeg file cfgs.get_mut(0).unwrap().set_pixel_format(PIXEL_FORMAT_MJPEG); - println!("Generated config: {:#?}", cfgs); + println!("Generated config: {cfgs:#?}"); match cfgs.validate() { CameraConfigurationStatus::Valid => println!("Camera configuration valid!"), - CameraConfigurationStatus::Adjusted => println!("Camera configuration was adjusted: {:#?}", cfgs), + CameraConfigurationStatus::Adjusted => println!("Camera configuration was adjusted: {cfgs:#?}"), CameraConfigurationStatus::Invalid => panic!("Error validating camera configuration"), } @@ -91,7 +91,7 @@ fn main() { println!("Waiting for camera request execution"); let req = rx.recv_timeout(Duration::from_secs(2)).expect("Camera request failed"); - println!("Camera request {:?} completed!", req); + println!("Camera request {req:?} completed!"); println!("Metadata: {:#?}", req.metadata()); // Get framebuffer for our stream @@ -100,7 +100,7 @@ fn main() { // MJPEG format has only one data plane containing encoded jpeg data with all the headers let planes = framebuffer.data(); - let jpeg_data = planes.get(0).unwrap(); + let jpeg_data = planes.first().unwrap(); // Actual JPEG-encoded data will be smalled than framebuffer size, its length can be obtained from metadata. let jpeg_len = framebuffer.metadata().unwrap().planes().get(0).unwrap().bytes_used as usize; diff --git a/libcamera/examples/list_cameras.rs b/libcamera/examples/list_cameras.rs index 5fe1330..4dbf5a4 100644 --- a/libcamera/examples/list_cameras.rs +++ b/libcamera/examples/list_cameras.rs @@ -7,9 +7,8 @@ fn main() { let cameras = mgr.cameras(); - for i in 0..cameras.len() { - let cam = cameras.get(i).unwrap(); - println!("Camera {}", i); + for cam in cameras.iter() { + println!(""); println!("ID: {}", cam.id()); println!("Properties: {:#?}", cam.properties()); diff --git a/libcamera/examples/read_control.rs b/libcamera/examples/read_control.rs index f6f1022..8af153b 100644 --- a/libcamera/examples/read_control.rs +++ b/libcamera/examples/read_control.rs @@ -7,16 +7,16 @@ fn main() { let cameras = mgr.cameras(); - //Grab the first camera, if one exists - for cam in cameras.iter().take(1) { + // Grab the first camera, if one exists + if let Some(cam) = cameras.iter().next() { println!("ID: {}", cam.id()); - //Read the first ControlInfo - for (id, control_info) in cam.controls().into_iter().take(1) { - //Attempt to get ControlID + // Read the first ControlInfo + if let Some((id, control_info)) = cam.controls().into_iter().next() { + // Attempt to get ControlID match ControlId::try_from(id) { - Ok(id) => println!("Control Id {:?} - {:?}", id as u32, id), - Err(_) => println!("Control Id {:?} - UNKOWN", id), + Ok(control) => println!("Control Id {} - {:?}", id, control), + Err(_) => println!("Control Id {id} - UNKOWN"), } println!("Control Max: {:?}", control_info.max()); @@ -25,14 +25,16 @@ fn main() { let values = control_info.values(); - //Some controls only support specific values within their ranges. - //this will display those possible values if they exist - if values.len() > 0 { + // Some controls only support specific values within their ranges. + // this will display those possible values if they exist + if !values.is_empty() { println!("Supported Values:"); for value in values { - println!("{:?}", value); + println!("{value:?}"); } } } - } + } else { + eprintln!("No cameras found"); + }; } diff --git a/libcamera/examples/video_capture.rs b/libcamera/examples/video_capture.rs index cef1a67..881ec94 100644 --- a/libcamera/examples/video_capture.rs +++ b/libcamera/examples/video_capture.rs @@ -43,11 +43,11 @@ fn main() { cfgs.get_mut(0).unwrap().set_pixel_format(PIXEL_FORMAT_MJPEG); - println!("Generated config: {:#?}", cfgs); + println!("Generated config: {cfgs:#?}"); match cfgs.validate() { CameraConfigurationStatus::Valid => println!("Camera configuration valid!"), - CameraConfigurationStatus::Adjusted => println!("Camera configuration was adjusted: {:#?}", cfgs), + CameraConfigurationStatus::Adjusted => println!("Camera configuration was adjusted: {cfgs:#?}"), CameraConfigurationStatus::Invalid => panic!("Error validating camera configuration"), } @@ -110,7 +110,7 @@ fn main() { println!("Waiting for camera request execution"); let mut req = rx.recv_timeout(Duration::from_secs(2)).expect("Camera request failed"); - println!("Camera request {:?} completed!", req); + println!("Camera request {req:?} completed!"); println!("Metadata: {:#?}", req.metadata()); // Get framebuffer for our stream @@ -119,7 +119,7 @@ fn main() { // MJPEG format has only one data plane containing encoded jpeg data with all the headers let planes = framebuffer.data(); - let frame_data = planes.get(0).unwrap(); + let frame_data = planes.first().unwrap(); // Actual encoded data will be smalled than framebuffer size, its length can be obtained from metadata. let bytes_used = framebuffer.metadata().unwrap().planes().get(0).unwrap().bytes_used as usize; diff --git a/libcamera/src/camera_manager.rs b/libcamera/src/camera_manager.rs index de466c0..718e7f1 100644 --- a/libcamera/src/camera_manager.rs +++ b/libcamera/src/camera_manager.rs @@ -35,13 +35,6 @@ impl CameraManager { unsafe { CameraList::from_ptr(NonNull::new(libcamera_camera_manager_cameras(self.ptr.as_ptr())).unwrap()) } } - pub fn stop(&self) { - unsafe { - libcamera_camera_manager_stop(self.ptr.as_ptr()); - // libcamera_camera_manager_destroy(self.ptr.as_ptr()); - } - } - /// Set the log level. /// /// # Parameters diff --git a/libcamera/src/control.rs b/libcamera/src/control.rs index a91573d..64119c6 100644 --- a/libcamera/src/control.rs +++ b/libcamera/src/control.rs @@ -1,4 +1,4 @@ -use std::{marker::PhantomData, ptr::NonNull}; +use std::{ffi::CStr, marker::PhantomData, ptr::NonNull}; use libcamera_sys::*; use thiserror::Error; @@ -100,7 +100,7 @@ impl ControlInfo { let val_ptr = base_ptr.add(offset) as *const libcamera_control_value_t; if val_ptr.is_null() { - eprintln!("ControlValue at index {} is null", i); + eprintln!("ControlValue at index {i} is null"); continue; } @@ -108,7 +108,7 @@ impl ControlInfo { match ControlValue::read(NonNull::new(val_ptr.cast_mut()).unwrap()) { Ok(control_val) => control_values.push(control_val), Err(e) => { - eprintln!("Failed to read ControlValue at index {}: {:?}", i, e); + eprintln!("Failed to read ControlValue at index {i}: {e:?}"); } } } @@ -455,3 +455,17 @@ impl<'a> Drop for ControlInfoMapIter<'a> { } } } + +pub fn control_id_name(id: ControlId) -> String { + unsafe { CStr::from_ptr(libcamera_control_name_from_id(id.id())) } + .to_str() + .unwrap() + .into() +} + +pub fn property_id_name(id: PropertyId) -> String { + unsafe { CStr::from_ptr(libcamera_property_name_from_id(id.id())) } + .to_str() + .unwrap() + .into() +} diff --git a/libcamera/versioned_files/0.4.0/controls.rs b/libcamera/versioned_files/0.4.0/controls.rs index 2ea5fc8..910a040 100644 --- a/libcamera/versioned_files/0.4.0/controls.rs +++ b/libcamera/versioned_files/0.4.0/controls.rs @@ -1,7 +1,9 @@ -use std::{ffi::CStr, ops::{Deref, DerefMut}}; +use std::ops::{Deref, DerefMut}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[allow(unused_imports)] -use crate::control::{Control, Property, ControlEntry, DynControlEntry}; +use crate::control::{ + Control, Property, ControlEntry, DynControlEntry, control_id_name, property_id_name, +}; use crate::control_value::{ControlValue, ControlValueError}; #[allow(unused_imports)] use crate::geometry::{Rectangle, Point, Size}; @@ -634,17 +636,11 @@ pub enum ControlId { ScalerCrops = SCALER_CROPS, } impl ControlId { - fn id(&self) -> u32 { - *self as u32 + pub fn id(&self) -> u32 { + u32::from(*self) } pub fn name(&self) -> String { - unsafe { - let c_str = libcamera_control_name_from_id(self.id()); - if c_str.is_null() { - return "".into(); - } - CStr::from_ptr(c_str).to_str().unwrap().into() - } + control_id_name(*self) } } /// Enable or disable the AE. diff --git a/libcamera/versioned_files/0.4.0/properties.rs b/libcamera/versioned_files/0.4.0/properties.rs index d7f2836..0b64d57 100644 --- a/libcamera/versioned_files/0.4.0/properties.rs +++ b/libcamera/versioned_files/0.4.0/properties.rs @@ -1,7 +1,9 @@ -use std::{ffi::CStr, ops::{Deref, DerefMut}}; +use std::ops::{Deref, DerefMut}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[allow(unused_imports)] -use crate::control::{Control, Property, ControlEntry, DynControlEntry}; +use crate::control::{ + Control, Property, ControlEntry, DynControlEntry, control_id_name, property_id_name, +}; use crate::control_value::{ControlValue, ControlValueError}; #[allow(unused_imports)] use crate::geometry::{Rectangle, Point, Size}; @@ -721,17 +723,11 @@ pub enum PropertyId { ColorFilterArrangement = COLOR_FILTER_ARRANGEMENT, } impl PropertyId { - fn id(&self) -> u32 { - *self as u32 + pub fn id(&self) -> u32 { + u32::from(*self) } pub fn name(&self) -> String { - unsafe { - let c_str = libcamera_property_name_by_id(self.id()); - if c_str.is_null() { - return "".into(); - } - CStr::from_ptr(c_str).to_str().unwrap().into() - } + property_id_name(*self) } } /// Camera mounting location diff --git a/libcamera/versioned_files/0.5.0/controls.rs b/libcamera/versioned_files/0.5.0/controls.rs index 9b2dc07..c3e4265 100644 --- a/libcamera/versioned_files/0.5.0/controls.rs +++ b/libcamera/versioned_files/0.5.0/controls.rs @@ -1,7 +1,9 @@ -use std::{ffi::CStr, ops::{Deref, DerefMut}}; +use std::ops::{Deref, DerefMut}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[allow(unused_imports)] -use crate::control::{Control, Property, ControlEntry, DynControlEntry}; +use crate::control::{ + Control, Property, ControlEntry, DynControlEntry, control_id_name, property_id_name, +}; use crate::control_value::{ControlValue, ControlValueError}; #[allow(unused_imports)] use crate::geometry::{Rectangle, Point, Size}; @@ -767,17 +769,11 @@ pub enum ControlId { PispStatsOutput = PISP_STATS_OUTPUT, } impl ControlId { - fn id(&self) -> u32 { - *self as u32 + pub fn id(&self) -> u32 { + u32::from(*self) } pub fn name(&self) -> String { - unsafe { - let c_str = libcamera_control_name_from_id(self.id()); - if c_str.is_null() { - return "".into(); - } - CStr::from_ptr(c_str).to_str().unwrap().into() - } + control_id_name(*self) } } /// Enable or disable the AEGC algorithm. When this control is set to true, diff --git a/libcamera/versioned_files/0.5.0/properties.rs b/libcamera/versioned_files/0.5.0/properties.rs index d7f2836..0b64d57 100644 --- a/libcamera/versioned_files/0.5.0/properties.rs +++ b/libcamera/versioned_files/0.5.0/properties.rs @@ -1,7 +1,9 @@ -use std::{ffi::CStr, ops::{Deref, DerefMut}}; +use std::ops::{Deref, DerefMut}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[allow(unused_imports)] -use crate::control::{Control, Property, ControlEntry, DynControlEntry}; +use crate::control::{ + Control, Property, ControlEntry, DynControlEntry, control_id_name, property_id_name, +}; use crate::control_value::{ControlValue, ControlValueError}; #[allow(unused_imports)] use crate::geometry::{Rectangle, Point, Size}; @@ -721,17 +723,11 @@ pub enum PropertyId { ColorFilterArrangement = COLOR_FILTER_ARRANGEMENT, } impl PropertyId { - fn id(&self) -> u32 { - *self as u32 + pub fn id(&self) -> u32 { + u32::from(*self) } pub fn name(&self) -> String { - unsafe { - let c_str = libcamera_property_name_by_id(self.id()); - if c_str.is_null() { - return "".into(); - } - CStr::from_ptr(c_str).to_str().unwrap().into() - } + property_id_name(*self) } } /// Camera mounting location diff --git a/libcamera/versioned_files/0.5.1/controls.rs b/libcamera/versioned_files/0.5.1/controls.rs index 9b2dc07..c3e4265 100644 --- a/libcamera/versioned_files/0.5.1/controls.rs +++ b/libcamera/versioned_files/0.5.1/controls.rs @@ -1,7 +1,9 @@ -use std::{ffi::CStr, ops::{Deref, DerefMut}}; +use std::ops::{Deref, DerefMut}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[allow(unused_imports)] -use crate::control::{Control, Property, ControlEntry, DynControlEntry}; +use crate::control::{ + Control, Property, ControlEntry, DynControlEntry, control_id_name, property_id_name, +}; use crate::control_value::{ControlValue, ControlValueError}; #[allow(unused_imports)] use crate::geometry::{Rectangle, Point, Size}; @@ -767,17 +769,11 @@ pub enum ControlId { PispStatsOutput = PISP_STATS_OUTPUT, } impl ControlId { - fn id(&self) -> u32 { - *self as u32 + pub fn id(&self) -> u32 { + u32::from(*self) } pub fn name(&self) -> String { - unsafe { - let c_str = libcamera_control_name_from_id(self.id()); - if c_str.is_null() { - return "".into(); - } - CStr::from_ptr(c_str).to_str().unwrap().into() - } + control_id_name(*self) } } /// Enable or disable the AEGC algorithm. When this control is set to true, diff --git a/libcamera/versioned_files/0.5.1/properties.rs b/libcamera/versioned_files/0.5.1/properties.rs index d7f2836..0b64d57 100644 --- a/libcamera/versioned_files/0.5.1/properties.rs +++ b/libcamera/versioned_files/0.5.1/properties.rs @@ -1,7 +1,9 @@ -use std::{ffi::CStr, ops::{Deref, DerefMut}}; +use std::ops::{Deref, DerefMut}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[allow(unused_imports)] -use crate::control::{Control, Property, ControlEntry, DynControlEntry}; +use crate::control::{ + Control, Property, ControlEntry, DynControlEntry, control_id_name, property_id_name, +}; use crate::control_value::{ControlValue, ControlValueError}; #[allow(unused_imports)] use crate::geometry::{Rectangle, Point, Size}; @@ -721,17 +723,11 @@ pub enum PropertyId { ColorFilterArrangement = COLOR_FILTER_ARRANGEMENT, } impl PropertyId { - fn id(&self) -> u32 { - *self as u32 + pub fn id(&self) -> u32 { + u32::from(*self) } pub fn name(&self) -> String { - unsafe { - let c_str = libcamera_property_name_by_id(self.id()); - if c_str.is_null() { - return "".into(); - } - CStr::from_ptr(c_str).to_str().unwrap().into() - } + property_id_name(*self) } } /// Camera mounting location