Browse Source

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
pull/65/head
Steve Cook 2 years ago
parent
commit
9ecb86e33d
  1. 12
      ctru-rs/examples/camera-image.rs
  2. 227
      ctru-rs/src/services/cam.rs

12
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::hid::KeyPad;
use ctru::services::{Apt, Hid}; use ctru::services::{Apt, Hid};
use ctru::Gfx; use ctru::Gfx;
use std::time::Duration;
const WIDTH: usize = 400; const WIDTH: usize = 400;
const HEIGHT: usize = 240; const HEIGHT: usize = 240;
const BUF_SIZE: usize = WIDTH * HEIGHT * 2 * 2; const BUF_SIZE: usize = WIDTH * HEIGHT * 2 * 2;
const WAIT_TIMEOUT: i64 = 300000000; const WAIT_TIMEOUT: Duration = Duration::from_micros(300);
fn main() { fn main() {
ctru::init(); ctru::init();
@ -53,10 +54,6 @@ fn main() {
.set_trimming(false) .set_trimming(false)
.expect("Failed to disable trimming"); .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]; let mut buf = vec![0u8; BUF_SIZE];
println!("\nPress R to take a new picture"); println!("\nPress R to take a new picture");
@ -72,16 +69,15 @@ fn main() {
if keys_down.contains(KeyPad::KEY_R) { if keys_down.contains(KeyPad::KEY_R) {
println!("Capturing new image"); println!("Capturing new image");
cam.play_shutter_sound(CamShutterSoundType::NORMAL)
.expect("Failed to play shutter sound");
buf = camera buf = camera
.take_picture( .take_picture(
WIDTH.try_into().unwrap(), WIDTH.try_into().unwrap(),
HEIGHT.try_into().unwrap(), HEIGHT.try_into().unwrap(),
transfer_unit,
WAIT_TIMEOUT, WAIT_TIMEOUT,
) )
.expect("Failed to take picture"); .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); let img = convert_image_to_rgb8(&buf, 0, 0, WIDTH as usize, HEIGHT as usize);

227
ctru-rs/src/services/cam.rs

@ -2,6 +2,7 @@ use crate::services::gspgpu::FramebufferFormat;
use bitflags::bitflags; use bitflags::bitflags;
use ctru_sys::Handle; use ctru_sys::Handle;
use std::cell::RefCell; use std::cell::RefCell;
use std::time::Duration;
#[non_exhaustive] #[non_exhaustive]
pub struct Cam { pub struct Cam {
@ -273,28 +274,6 @@ pub trait Camera {
ctru_sys::PORT_CAM1 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<bool> { fn is_busy(&self) -> crate::Result<bool> {
unsafe { unsafe {
let mut is_busy = false; 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<u32> {
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<u32> {
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<u32> {
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<bool> {
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<u32> { fn get_transfer_bytes(&self) -> crate::Result<u32> {
unsafe { unsafe {
let mut transfer_bytes = 0; 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<()> { fn deactivate(&mut self) -> crate::Result<()> {
unsafe { unsafe {
let r = ctru_sys::CAMU_Activate(ctru_sys::SELECT_NONE); let r = ctru_sys::CAMU_Activate(ctru_sys::SELECT_NONE);
@ -898,36 +774,87 @@ pub trait Camera {
&mut self, &mut self,
width: u16, width: u16,
height: u16, height: u16,
transfer_unit: u32, timeout: Duration,
timeout: i64,
) -> crate::Result<Vec<u8>> { ) -> crate::Result<Vec<u8>> {
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 screen_size = u32::from(width) * u32::from(width) * 2;
let mut buf = vec![0u8; usize::try_from(screen_size).unwrap()]; let mut buf = vec![0u8; usize::try_from(screen_size).unwrap()];
self.set_transfer_bytes( unsafe {
let r = ctru_sys::CAMU_SetTransferBytes(
self.port_as_raw(),
transfer_unit, transfer_unit,
width.try_into().unwrap(), width as i16,
height.try_into().unwrap(), 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 = let receive_event = unsafe {
self.set_receiving(&mut buf, screen_size, transfer_unit.try_into().unwrap())?; 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 { 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 { if r < 0 {
return Err(r.into()); 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 { unsafe {
let r = ctru_sys::svcCloseHandle(receive_event); 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<u32> {
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<i16> {
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<()> { pub fn play_shutter_sound(&self, sound: CamShutterSoundType) -> crate::Result<()> {
unsafe { unsafe {
let r = ctru_sys::CAMU_PlayShutterSound(sound.bits()); let r = ctru_sys::CAMU_PlayShutterSound(sound.bits());

Loading…
Cancel
Save