use crate::{log_to_console, pd_func_caller, pd_func_caller_log};
use crankstart_sys::ctypes;
use alloc::rc::Rc;
use anyhow::{anyhow, ensure, Error, Result};
#[derive(Debug)]
pub struct SamplePlayer {
raw_subsystem: *const crankstart_sys::playdate_sound_sampleplayer,
raw_player: *mut crankstart_sys::SamplePlayer,
sample: Option<AudioSample>,
}
impl Drop for SamplePlayer {
fn drop(&mut self) {
pd_func_caller_log!((*self.raw_subsystem).freePlayer, self.raw_player);
}
}
impl SamplePlayer {
pub(crate) fn new(
raw_subsystem: *const crankstart_sys::playdate_sound_sampleplayer,
raw_player: *mut crankstart_sys::SamplePlayer,
) -> Result<Self> {
ensure!(
!raw_subsystem.is_null(),
"Null pointer given as subsystem to SamplePlayer::new"
);
ensure!(
!raw_player.is_null(),
"Null pointer given as player to SamplePlayer::new"
);
Ok(Self {
raw_subsystem,
raw_player,
sample: None,
})
}
pub fn set_sample(&mut self, audio_sample: &AudioSample) -> Result<()> {
self.sample = Some(audio_sample.clone());
pd_func_caller!(
(*self.raw_subsystem).setSample,
self.raw_player,
audio_sample.inner.raw_audio_sample
)
}
pub fn play(&self, repeat_count: ctypes::c_int, playback_speed: f32) -> Result<()> {
let result = pd_func_caller!(
(*self.raw_subsystem).play,
self.raw_player,
repeat_count,
playback_speed
)?;
if result == 1 {
Ok(())
} else {
Err(anyhow!(
"sampleplayer.play should return 1; returned {}",
result
))
}
}
pub fn stop(&self) -> Result<()> {
pd_func_caller!((*self.raw_subsystem).stop, self.raw_player)
}
pub fn set_paused(&self, paused: bool) -> Result<()> {
pd_func_caller!(
(*self.raw_subsystem).setPaused,
self.raw_player,
paused as ctypes::c_int
)
}
pub fn is_playing(&self) -> Result<bool> {
let result = pd_func_caller!((*self.raw_subsystem).isPlaying, self.raw_player)?;
Ok(result == 1)
}
pub fn set_play_range(&self, start: ctypes::c_int, end: ctypes::c_int) -> Result<()> {
pd_func_caller!(
(*self.raw_subsystem).setPlayRange,
self.raw_player,
start,
end
)
}
pub fn get_offset(&self) -> Result<f32> {
pd_func_caller!((*self.raw_subsystem).getOffset, self.raw_player)
}
pub fn set_offset(&self, offset: f32) -> Result<()> {
pd_func_caller!((*self.raw_subsystem).setOffset, self.raw_player, offset)
}
pub fn get_volume(&self) -> Result<(f32, f32)> {
let mut left = 0.0;
let mut right = 0.0;
pd_func_caller!(
(*self.raw_subsystem).getVolume,
self.raw_player,
&mut left,
&mut right,
)?;
Ok((left, right))
}
pub fn set_volume(&self, left: f32, right: f32) -> Result<()> {
pd_func_caller!(
(*self.raw_subsystem).setVolume,
self.raw_player,
left,
right
)
}
pub fn get_rate(&self) -> Result<f32> {
pd_func_caller!((*self.raw_subsystem).getRate, self.raw_player)
}
pub fn set_rate(&self, playback_speed: f32) -> Result<()> {
pd_func_caller!(
(*self.raw_subsystem).setRate,
self.raw_player,
playback_speed
)
}
pub fn get_length(&self) -> Result<f32> {
pd_func_caller!((*self.raw_subsystem).getLength, self.raw_player)
}
}
#[derive(Clone, Debug)]
pub struct AudioSample {
inner: Rc<AudioSampleInner>,
}
#[derive(Debug)]
struct AudioSampleInner {
raw_subsystem: *const crankstart_sys::playdate_sound_sample,
raw_audio_sample: *mut crankstart_sys::AudioSample,
}
impl Drop for AudioSampleInner {
fn drop(&mut self) {
pd_func_caller_log!((*self.raw_subsystem).freeSample, self.raw_audio_sample);
}
}
impl AudioSample {
pub(crate) fn new(
raw_subsystem: *const crankstart_sys::playdate_sound_sample,
raw_audio_sample: *mut crankstart_sys::AudioSample,
) -> Result<Self, Error> {
ensure!(
!raw_subsystem.is_null(),
"Null pointer given as subsystem to AudioSample::new"
);
ensure!(
!raw_audio_sample.is_null(),
"Null pointer given as sample to AudioSample::new"
);
Ok(Self {
inner: Rc::new(AudioSampleInner {
raw_subsystem,
raw_audio_sample,
}),
})
}
pub fn get_length(&self) -> Result<f32> {
pd_func_caller!(
(*self.inner.raw_subsystem).getLength,
self.inner.raw_audio_sample
)
}
}