From 9ecb86e33d9a25386c2b71cd91728f7a6eb01519 Mon Sep 17 00:00:00 2001 From: Steve Cook Date: Tue, 23 Aug 2022 00:10:08 -0400 Subject: [PATCH] Requested changes Made low level functions for camera manipulation internal Changed picture timeout to Duration from raw i64 Moved shutter sound before the actual picture taking --- ctru-rs/examples/camera-image.rs | 12 +- ctru-rs/src/services/cam.rs | 229 +++++++++---------------------- 2 files changed, 70 insertions(+), 171 deletions(-) diff --git a/ctru-rs/examples/camera-image.rs b/ctru-rs/examples/camera-image.rs index 91d8bcd..03ae2da 100644 --- a/ctru-rs/examples/camera-image.rs +++ b/ctru-rs/examples/camera-image.rs @@ -4,12 +4,13 @@ use ctru::services::cam::{Cam, CamOutputFormat, CamShutterSoundType, CamSize, Ca use ctru::services::hid::KeyPad; use ctru::services::{Apt, Hid}; use ctru::Gfx; +use std::time::Duration; const WIDTH: usize = 400; const HEIGHT: usize = 240; const BUF_SIZE: usize = WIDTH * HEIGHT * 2 * 2; -const WAIT_TIMEOUT: i64 = 300000000; +const WAIT_TIMEOUT: Duration = Duration::from_micros(300); fn main() { ctru::init(); @@ -53,10 +54,6 @@ fn main() { .set_trimming(false) .expect("Failed to disable trimming"); - let transfer_unit = cam - .get_max_bytes(WIDTH as i16, HEIGHT as i16) - .expect("Failed to get max bytes for dimensions"); - let mut buf = vec![0u8; BUF_SIZE]; println!("\nPress R to take a new picture"); @@ -72,16 +69,15 @@ fn main() { if keys_down.contains(KeyPad::KEY_R) { println!("Capturing new image"); + cam.play_shutter_sound(CamShutterSoundType::NORMAL) + .expect("Failed to play shutter sound"); buf = camera .take_picture( WIDTH.try_into().unwrap(), HEIGHT.try_into().unwrap(), - transfer_unit, WAIT_TIMEOUT, ) .expect("Failed to take picture"); - cam.play_shutter_sound(CamShutterSoundType::NORMAL) - .expect("Failed to play shutter sound"); } let img = convert_image_to_rgb8(&buf, 0, 0, WIDTH as usize, HEIGHT as usize); diff --git a/ctru-rs/src/services/cam.rs b/ctru-rs/src/services/cam.rs index 2ed40fb..deb86ef 100644 --- a/ctru-rs/src/services/cam.rs +++ b/ctru-rs/src/services/cam.rs @@ -2,6 +2,7 @@ use crate::services::gspgpu::FramebufferFormat; use bitflags::bitflags; use ctru_sys::Handle; use std::cell::RefCell; +use std::time::Duration; #[non_exhaustive] pub struct Cam { @@ -273,28 +274,6 @@ pub trait Camera { ctru_sys::PORT_CAM1 } - fn start_capture(&mut self) -> crate::Result<()> { - unsafe { - let r = ctru_sys::CAMU_StartCapture(self.port_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } - } - } - - fn stop_capture(&mut self) -> crate::Result<()> { - unsafe { - let r = ctru_sys::CAMU_StopCapture(self.port_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } - } - } - fn is_busy(&self) -> crate::Result { unsafe { let mut is_busy = false; @@ -307,98 +286,6 @@ pub trait Camera { } } - fn clear_buffer(&mut self) -> crate::Result<()> { - unsafe { - let r = ctru_sys::CAMU_ClearBuffer(self.port_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } - } - } - - fn get_vsync_interrupt_event(&self) -> crate::Result { - unsafe { - let mut event: Handle = 0; - let r = ctru_sys::CAMU_GetVsyncInterruptEvent(&mut event, self.port_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(event) - } - } - } - - fn get_buffer_error_interrupt_event(&self) -> crate::Result { - unsafe { - let mut event: Handle = 0; - let r = ctru_sys::CAMU_GetBufferErrorInterruptEvent(&mut event, self.port_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(event) - } - } - } - - fn set_receiving( - &mut self, - buf: &mut [u8], - size: u32, - transfer_unit: i16, - ) -> crate::Result { - unsafe { - let mut completion_handle: Handle = 0; - let r = ctru_sys::CAMU_SetReceiving( - &mut completion_handle, - buf.as_mut_ptr() as *mut ::libc::c_void, - self.port_as_raw(), - size, - transfer_unit, - ); - if r < 0 { - Err(r.into()) - } else { - Ok(completion_handle) - } - } - } - - fn is_finished_receiving(&self) -> crate::Result { - unsafe { - let mut finished_receiving = false; - let r = ctru_sys::CAMU_IsFinishedReceiving(&mut finished_receiving, self.port_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(finished_receiving) - } - } - } - - fn set_transfer_lines(&mut self, lines: i16, width: i16, height: i16) -> crate::Result<()> { - unsafe { - let r = ctru_sys::CAMU_SetTransferLines(self.port_as_raw(), lines, width, height); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } - } - } - - fn set_transfer_bytes(&mut self, buf_size: u32, width: i16, height: i16) -> crate::Result<()> { - unsafe { - let r = ctru_sys::CAMU_SetTransferBytes(self.port_as_raw(), buf_size, width, height); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } - } - } - fn get_transfer_bytes(&self) -> crate::Result { unsafe { let mut transfer_bytes = 0; @@ -500,17 +387,6 @@ pub trait Camera { } } - fn activate(&mut self) -> crate::Result<()> { - unsafe { - let r = ctru_sys::CAMU_Activate(self.camera_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } - } - } - fn deactivate(&mut self) -> crate::Result<()> { unsafe { let r = ctru_sys::CAMU_Activate(ctru_sys::SELECT_NONE); @@ -898,36 +774,87 @@ pub trait Camera { &mut self, width: u16, height: u16, - transfer_unit: u32, - timeout: i64, + timeout: Duration, ) -> crate::Result> { + let transfer_unit = unsafe { + let mut buf_size = 0; + let r = ctru_sys::CAMU_GetMaxBytes(&mut buf_size, width as i16, height as i16); + if r < 0 { + Err(crate::Error::from(r)) + } else { + Ok(buf_size) + } + }?; + let screen_size = u32::from(width) * u32::from(width) * 2; let mut buf = vec![0u8; usize::try_from(screen_size).unwrap()]; - self.set_transfer_bytes( - transfer_unit, - width.try_into().unwrap(), - height.try_into().unwrap(), - )?; + unsafe { + let r = ctru_sys::CAMU_SetTransferBytes( + self.port_as_raw(), + transfer_unit, + width as i16, + height as i16, + ); + if r < 0 { + return Err(r.into()); + } + }; - self.activate()?; + unsafe { + let r = ctru_sys::CAMU_Activate(self.camera_as_raw()); + if r < 0 { + return Err(r.into()); + } + }; - self.clear_buffer()?; + unsafe { + let r = ctru_sys::CAMU_ClearBuffer(self.port_as_raw()); + if r < 0 { + return Err(r.into()); + } + }; - self.start_capture()?; + unsafe { + let r = ctru_sys::CAMU_StartCapture(self.port_as_raw()); + if r < 0 { + return Err(r.into()); + } + }; - let receive_event = - self.set_receiving(&mut buf, screen_size, transfer_unit.try_into().unwrap())?; + let receive_event = unsafe { + let mut completion_handle: Handle = 0; + let r = ctru_sys::CAMU_SetReceiving( + &mut completion_handle, + buf.as_mut_ptr() as *mut ::libc::c_void, + self.port_as_raw(), + screen_size, + transfer_unit.try_into().unwrap(), + ); + if r < 0 { + Err(crate::Error::from(r)) + } else { + Ok(completion_handle) + } + }?; unsafe { - let r = ctru_sys::svcWaitSynchronization(receive_event, timeout); + let r = ctru_sys::svcWaitSynchronization( + receive_event, + timeout.as_nanos().try_into().unwrap(), + ); if r < 0 { return Err(r.into()); } }; - self.stop_capture()?; + unsafe { + let r = ctru_sys::CAMU_StopCapture(self.port_as_raw()); + if r < 0 { + return Err(r.into()); + } + }; unsafe { let r = ctru_sys::svcCloseHandle(receive_event); @@ -957,30 +884,6 @@ impl Cam { } } - pub fn get_max_bytes(&self, width: i16, height: i16) -> crate::Result { - unsafe { - let mut buf_size = 0; - let r = ctru_sys::CAMU_GetMaxBytes(&mut buf_size, width, height); - if r < 0 { - Err(r.into()) - } else { - Ok(buf_size) - } - } - } - - pub fn get_max_lines(&self, width: i16, height: i16) -> crate::Result { - unsafe { - let mut max_lines = 0; - let r = ctru_sys::CAMU_GetMaxLines(&mut max_lines, width, height); - if r < 0 { - Err(r.into()) - } else { - Ok(max_lines) - } - } - } - pub fn play_shutter_sound(&self, sound: CamShutterSoundType) -> crate::Result<()> { unsafe { let r = ctru_sys::CAMU_PlayShutterSound(sound.bits());