use crate::core::RaylibThread;
use crate::ffi;
use std::ffi::CString;
make_thin_wrapper!(Wave, ffi::Wave, ffi::UnloadWave);
make_thin_wrapper!(Sound, ffi::Sound, ffi::UnloadSound);
make_thin_wrapper!(Music, ffi::Music, ffi::UnloadMusicStream);
make_thin_wrapper!(AudioStream, ffi::AudioStream, ffi::CloseAudioStream);
pub trait AudioSample {}
impl AudioSample for u8 {}
impl AudioSample for i16 {}
impl AudioSample for f32 {}
#[derive(Debug)]
pub struct RaylibAudio(());
impl RaylibAudio {
#[inline]
pub fn init_audio_device() -> RaylibAudio {
unsafe {
ffi::InitAudioDevice();
}
RaylibAudio(())
}
#[inline]
pub fn is_audio_device_ready(&self) -> bool {
unsafe { ffi::IsAudioDeviceReady() }
}
#[inline]
pub fn set_master_volume(&self, volume: f32) {
unsafe {
ffi::SetMasterVolume(volume);
}
}
#[inline]
pub fn play_sound(&mut self, sound: &Sound) {
unsafe {
ffi::PlaySound(sound.0);
}
}
#[inline]
pub fn pause_sound(&mut self, sound: &Sound) {
unsafe {
ffi::PauseSound(sound.0);
}
}
#[inline]
pub fn resume_sound(&mut self, sound: &Sound) {
unsafe {
ffi::ResumeSound(sound.0);
}
}
#[inline]
pub fn stop_sound(&mut self, sound: &Sound) {
unsafe {
ffi::StopSound(sound.0);
}
}
#[inline]
pub fn is_sound_playing(&self, sound: &Sound) -> bool {
unsafe { ffi::IsSoundPlaying(sound.0) }
}
#[inline]
pub fn set_sound_volume(&mut self, sound: &Sound, volume: f32) {
unsafe {
ffi::SetSoundVolume(sound.0, volume);
}
}
#[inline]
pub fn set_sound_pitch(&mut self, sound: &Sound, pitch: f32) {
unsafe {
ffi::SetSoundPitch(sound.0, pitch);
}
}
#[inline]
pub fn play_music_stream(&mut self, music: &mut Music) {
unsafe {
ffi::PlayMusicStream(music.0);
}
}
#[inline]
pub fn update_music_stream(&mut self, music: &mut Music) {
unsafe {
ffi::UpdateMusicStream(music.0);
}
}
#[inline]
pub fn stop_music_stream(&mut self, music: &mut Music) {
unsafe {
ffi::StopMusicStream(music.0);
}
}
#[inline]
pub fn pause_music_stream(&mut self, music: &mut Music) {
unsafe {
ffi::PauseMusicStream(music.0);
}
}
#[inline]
pub fn resume_music_stream(&mut self, music: &mut Music) {
unsafe {
ffi::ResumeMusicStream(music.0);
}
}
#[inline]
pub fn is_music_playing(&self, music: &Music) -> bool {
unsafe { ffi::IsMusicPlaying(music.0) }
}
#[inline]
pub fn set_music_volume(&mut self, music: &mut Music, volume: f32) {
unsafe {
ffi::SetMusicVolume(music.0, volume);
}
}
#[inline]
pub fn set_music_pitch(&mut self, music: &mut Music, pitch: f32) {
unsafe {
ffi::SetMusicPitch(music.0, pitch);
}
}
#[inline]
pub fn set_music_loop_count(&mut self, music: &mut Music, count: i32) {
unsafe {
ffi::SetMusicLoopCount(music.0, count);
}
}
#[inline]
pub fn get_music_time_length(&self, music: &Music) -> f32 {
unsafe { ffi::GetMusicTimeLength(music.0) }
}
#[inline]
pub fn get_music_time_played(&self, music: &Music) -> f32 {
unsafe { ffi::GetMusicTimePlayed(music.0) }
}
#[inline]
pub fn play_audio_stream(&mut self, stream: &mut AudioStream) {
unsafe {
ffi::PlayAudioStream(stream.0);
}
}
#[inline]
pub fn pause_audio_stream(&mut self, stream: &mut AudioStream) {
unsafe {
ffi::PauseAudioStream(stream.0);
}
}
#[inline]
pub fn resume_audio_stream(&mut self, stream: &mut AudioStream) {
unsafe {
ffi::ResumeAudioStream(stream.0);
}
}
#[inline]
pub fn is_audio_stream_playing(&self, stream: &AudioStream) -> bool {
unsafe { ffi::IsAudioStreamPlaying(stream.0) }
}
#[inline]
pub fn stop_audio_stream(&mut self, stream: &mut AudioStream) {
unsafe {
ffi::StopAudioStream(stream.0);
}
}
#[inline]
pub fn set_audio_stream_volume(&mut self, stream: &mut AudioStream, volume: f32) {
unsafe {
ffi::SetAudioStreamVolume(stream.0, volume);
}
}
#[inline]
pub fn set_audio_stream_pitch(&mut self, stream: &mut AudioStream, pitch: f32) {
unsafe {
ffi::SetAudioStreamPitch(stream.0, pitch);
}
}
}
impl Drop for RaylibAudio {
fn drop(&mut self) {
unsafe { ffi::CloseAudioDevice() }
}
}
impl Wave {
pub fn sample_count(&self) -> u32 {
self.0.sampleCount
}
pub fn smaple_rate(&self) -> u32 {
self.0.sampleRate
}
pub fn sample_size(&self) -> u32 {
self.0.sampleSize
}
pub fn channels(&self) -> u32 {
self.0.channels
}
pub unsafe fn inner(self) -> ffi::Wave {
let inner = self.0;
std::mem::forget(self);
inner
}
#[inline]
pub fn load_wave(filename: &str) -> Result<Wave, String> {
let c_filename = CString::new(filename).unwrap();
let w = unsafe { ffi::LoadWave(c_filename.as_ptr()) };
if w.data.is_null() {
return Err(format!("Cannot load wave {}", filename));
}
Ok(Wave(w))
}
#[inline]
pub fn load_wave_ex(
data: &[u8],
sample_count: i32,
sample_rate: i32,
sample_size: i32,
channels: i32,
) -> Result<Wave, String> {
let w = unsafe {
ffi::LoadWaveEx(
data.as_ptr() as *mut std::os::raw::c_void,
sample_count,
sample_rate,
sample_size,
channels,
)
};
if w.data.is_null() {
return Err(format!("Cannot load wave from data is it valid?"));
}
Ok(Wave(w))
}
#[inline]
pub fn export_wave(&self, filename: &str) {
let c_filename = CString::new(filename).unwrap();
unsafe { ffi::ExportWave(self.0, c_filename.as_ptr()) }
}
#[inline]
pub fn export_wave_as_code(&self, filename: &str) {
let c_filename = CString::new(filename).unwrap();
unsafe { ffi::ExportWaveAsCode(self.0, c_filename.as_ptr()) }
}
#[inline]
pub fn wave_format(&mut self, sample_rate: i32, sample_size: i32, channels: i32) {
unsafe {
ffi::WaveFormat(&mut self.0, sample_rate, sample_size, channels);
}
}
#[inline]
pub fn wave_copy(&self) -> Wave {
unsafe { Wave(ffi::WaveCopy(self.0)) }
}
#[inline]
pub fn wave_crop(&mut self, init_sample: i32, final_sample: i32) {
unsafe {
ffi::WaveCrop(&mut self.0, init_sample, final_sample);
}
}
#[inline]
pub fn get_wave_data(&self) -> Vec<f32> {
unsafe {
let data = ffi::GetWaveData(self.0);
let data_size = (self.sampleCount * self.channels) as usize;
let mut samples = Vec::with_capacity(data_size);
samples.set_len(data_size);
std::ptr::copy(data, samples.as_mut_ptr(), data_size);
libc::free(data as *mut libc::c_void);
samples
}
}
}
impl Sound {
pub fn source(&self) -> u32 {
self.0.source
}
pub fn buffer(&self) -> u32 {
self.0.buffer
}
pub fn format(&self) -> i32 {
self.0.format
}
pub unsafe fn inner(self) -> ffi::Sound {
let inner = self.0;
std::mem::forget(self);
inner
}
pub fn load_sound(filename: &str) -> Result<Sound, String> {
let c_filename = CString::new(filename).unwrap();
let s = unsafe { ffi::LoadSound(c_filename.as_ptr()) };
if s.audioBuffer.is_null() {
return Err(format!("failed to load sound {}", filename));
}
Ok(Sound(s))
}
pub fn load_sound_from_wave(wave: &Wave) -> Result<Sound, String> {
let s = unsafe { ffi::LoadSoundFromWave(wave.0) };
if s.audioBuffer.is_null() {
return Err(format!("failed to load sound from wave"));
}
Ok(Sound(s))
}
#[inline]
pub fn update_sound(&mut self, data: &[impl AudioSample]) {
unsafe {
ffi::UpdateSound(
self.0,
data.as_ptr() as *const std::os::raw::c_void,
data.len() as i32,
);
}
}
}
impl Music {
pub fn load_music_stream(_: &RaylibThread, filename: &str) -> Result<Music, String> {
let c_filename = CString::new(filename).unwrap();
let m = unsafe { ffi::LoadMusicStream(c_filename.as_ptr()) };
if m.is_null() {
return Err(format!("music could not be loaded from file {}", filename));
}
Ok(Music(m))
}
}
impl AudioStream {
pub fn sample_rate(&self) -> u32 {
self.0.sampleRate
}
pub fn sample_size(&self) -> u32 {
self.0.sampleSize
}
pub fn channels(&self) -> u32 {
self.0.channels
}
pub fn format(&self) -> i32 {
self.0.format
}
pub fn source(&self) -> u32 {
self.0.source
}
pub unsafe fn inner(self) -> ffi::AudioStream {
let inner = self.0;
std::mem::forget(self);
inner
}
#[inline]
pub fn init_audio_stream(
_: &RaylibThread,
sample_rate: u32,
sample_size: u32,
channels: u32,
) -> AudioStream {
unsafe { AudioStream(ffi::InitAudioStream(sample_rate, sample_size, channels)) }
}
#[inline]
pub fn update_audio_stream(&mut self, data: &[impl AudioSample]) {
unsafe {
ffi::UpdateAudioStream(
self.0,
data.as_ptr() as *const std::os::raw::c_void,
data.len() as i32,
);
}
}
#[inline]
pub fn is_audio_buffer_processed(&mut self) -> bool {
unsafe { ffi::IsAudioBufferProcessed(self.0) }
}
}