rscenes_raylib_connector/
raudio.rs

1use crate::{ext::wave::WaveType, utils::array_from_c};
2use raylib_ffi::*;
3use std::{
4    ffi::c_void,
5    fmt::{Debug, Display},
6    path::Path,
7};
8
9#[derive(Clone, Copy, Debug, Default)]
10pub(crate) struct RaudioImpl;
11
12/// Crate only methods
13impl RaudioImpl {
14    // Audio device management
15
16    pub fn __init_audio_device() {
17        unsafe { InitAudioDevice() }
18    }
19
20    pub fn __close_audio_device() {
21        unsafe { CloseAudioDevice() }
22    }
23
24    pub fn __is_audio_device_ready() -> bool {
25        unsafe { IsAudioDeviceReady() }
26    }
27
28    pub fn __set_master_volume(volume: f32) {
29        unsafe { SetMasterVolume(volume) }
30    }
31
32    pub fn __get_master_volume() -> f32 {
33        unsafe { GetMasterVolume() }
34    }
35
36    // Wave/Sound loading/unloading methods
37
38    pub fn __load_wave(filename: impl Display) -> Result<Wave, String> {
39        unsafe {
40            let wave = LoadWave(rl_str!(filename));
41            if wave.data.is_null() {
42                if Path::new(&filename.to_string()).exists() {
43                    Err(format!(
44                        "error loading wave from {}, have you initialised the audio device?",
45                        filename
46                    ))
47                } else {
48                    Err(format!(
49                        "error loading wave from {}, file not found",
50                        filename
51                    ))
52                }
53            } else {
54                Ok(wave)
55            }
56        }
57    }
58
59    pub fn __load_wave_from_memory(tpe: impl Display, data: &[u8]) -> Result<Wave, String> {
60        unsafe {
61            let size = data.len() as i32;
62            let wave = LoadWaveFromMemory(rl_str!(tpe), data.as_ptr(), size);
63            if wave.data.is_null() {
64                Err(
65                    "error loading wave from memory, have you initialised the audio device?"
66                        .to_owned(),
67                )
68            } else {
69                Ok(wave)
70            }
71        }
72    }
73
74    pub fn __is_wave_ready(wave: Wave) -> bool {
75        unsafe { IsWaveReady(wave) }
76    }
77
78    pub fn __load_sound(filename: impl Display) -> Result<Sound, String> {
79        unsafe {
80            let sound = LoadSound(rl_str!(filename));
81            if sound.stream.channels == 0 {
82                if Path::new(&filename.to_string()).exists() {
83                    Err(format!(
84                        "error loading sound from {}, have you initialised the audio device?",
85                        filename
86                    ))
87                } else {
88                    Err(format!(
89                        "error loading sound from {}, file not found",
90                        filename
91                    ))
92                }
93            } else {
94                Ok(sound)
95            }
96        }
97    }
98
99    pub fn __load_sound_from_wave(wave: Wave) -> Sound {
100        unsafe { LoadSoundFromWave(wave) }
101    }
102
103    pub fn __load_sound_alias(source: Sound) -> Sound {
104        unsafe { LoadSoundAlias(source) }
105    }
106
107    pub fn __is_sound_ready(sound: Sound) -> bool {
108        unsafe { IsSoundReady(sound) }
109    }
110
111    pub fn __unload_wave(wave: Wave) {
112        unsafe { UnloadWave(wave) }
113    }
114
115    pub fn __unload_sound(sound: Sound) {
116        unsafe { UnloadSound(sound) }
117    }
118
119    pub fn __unload_sound_alias(sound: Sound) {
120        unsafe { UnloadSoundAlias(sound) }
121    }
122
123    pub fn __export_wave(wave: Wave, filename: impl Display) -> bool {
124        unsafe { ExportWave(wave, rl_str!(filename)) }
125    }
126
127    pub fn __export_wave_as_code(wave: Wave, filename: impl Display) -> bool {
128        unsafe { ExportWaveAsCode(wave, rl_str!(filename)) }
129    }
130
131    // Wave/Sound management methods
132
133    pub fn __play_sound(sound: Sound) {
134        unsafe { PlaySound(sound) }
135    }
136
137    pub fn __stop_sound(sound: Sound) {
138        unsafe { StopSound(sound) }
139    }
140
141    pub fn __pause_sound(sound: Sound) {
142        unsafe { PauseSound(sound) }
143    }
144
145    pub fn __resume_sound(sound: Sound) {
146        unsafe { ResumeSound(sound) }
147    }
148
149    pub fn __is_sound_playing(sound: Sound) -> bool {
150        unsafe { IsSoundPlaying(sound) }
151    }
152
153    pub fn __set_sound_volume(sound: Sound, volume: f32) {
154        unsafe { SetSoundVolume(sound, volume) }
155    }
156
157    pub fn __set_sound_pitch(sound: Sound, pitch: f32) {
158        unsafe { SetSoundPitch(sound, pitch) }
159    }
160
161    pub fn __set_sound_pan(sound: Sound, pan: f32) {
162        unsafe { SetSoundPan(sound, pan) }
163    }
164
165    pub fn __wave_copy(wave: Wave) -> Wave {
166        unsafe { WaveCopy(wave) }
167    }
168
169    pub fn __wave_crop(wave: &mut Wave, init_sample: i32, final_sample: i32) {
170        unsafe { WaveCrop(wave, init_sample, final_sample) }
171    }
172
173    pub fn __wave_format(wave: &mut Wave, sample_rate: i32, sample_size: i32, channels: i32) {
174        unsafe { WaveFormat(wave, sample_rate, sample_size, channels) }
175    }
176
177    pub fn __load_wave_samples(wave: Wave) -> Result<Vec<f32>, String> {
178        unsafe {
179            let raw = LoadWaveSamples(wave);
180            // TODO: review this calculation
181            let count = wave.frameCount * wave.sampleSize / 32;
182            let res = array_from_c(raw, count as usize, || {
183                "couldn't load samples from wave".to_owned()
184            })?.to_vec();
185            UnloadWaveSamples(raw);
186            Ok(res)
187        }
188    }
189
190    // Music management methods
191
192    pub fn __load_music_stream(filename: impl Display) -> Result<Music, String> {
193        unsafe {
194            let music = LoadMusicStream(rl_str!(filename));
195            if music.stream.buffer.is_null() {
196                Err(format!("failed to load music stream from {}", filename))
197            } else {
198                Ok(music)
199            }
200        }
201    }
202
203    pub fn __load_music_stream_from_memory(
204        tpe: impl Display,
205        data: &[u8],
206    ) -> Result<Music, String> {
207        unsafe {
208            let size = data.len() as i32;
209            let data = data.as_ptr();
210            let music = LoadMusicStreamFromMemory(rl_str!(tpe), data, size);
211            if music.stream.buffer.is_null() {
212                Err("failed to load music stream from memory".to_owned())
213            } else {
214                Ok(music)
215            }
216        }
217    }
218
219    pub fn __is_music_ready(music: Music) -> bool {
220        unsafe { IsMusicReady(music) }
221    }
222
223    pub fn __unload_music_stream(music: Music) {
224        unsafe { UnloadMusicStream(music) }
225    }
226
227    pub fn __play_music_stream(music: Music) {
228        unsafe { PlayMusicStream(music) }
229    }
230
231    pub fn __is_music_stream_playing(music: Music) -> bool {
232        unsafe { IsMusicStreamPlaying(music) }
233    }
234
235    pub fn __update_music_stream(music: Music) {
236        unsafe { UpdateMusicStream(music) }
237    }
238
239    pub fn __stop_music_stream(music: Music) {
240        unsafe { StopMusicStream(music) }
241    }
242
243    pub fn __pause_music_stream(music: Music) {
244        unsafe { PauseMusicStream(music) }
245    }
246
247    pub fn __resume_music_stream(music: Music) {
248        unsafe { ResumeMusicStream(music) }
249    }
250
251    pub fn __seek_music_stream(music: Music, position: f32) {
252        unsafe { SeekMusicStream(music, position) }
253    }
254
255    pub fn __set_music_volume(music: Music, volume: f32) {
256        unsafe { SetMusicVolume(music, volume) }
257    }
258
259    pub fn __set_music_pitch(music: Music, pitch: f32) {
260        unsafe { SetMusicPitch(music, pitch) }
261    }
262
263    pub fn __set_music_pan(music: Music, pan: f32) {
264        unsafe { SetMusicPan(music, pan) }
265    }
266
267    pub fn __get_music_time_length(music: Music) -> f32 {
268        unsafe { GetMusicTimeLength(music) }
269    }
270
271    pub fn __get_music_time_played(music: Music) -> f32 {
272        unsafe { GetMusicTimePlayed(music) }
273    }
274
275    // AudioStream management methods
276
277    pub fn __load_audio_stream(
278        sample_rate: u32,
279        sample_size: u32,
280        channels: u32,
281    ) -> Result<AudioStream, String> {
282        unsafe {
283            // TODO: test whether audio stream was properly loaded
284            Ok(LoadAudioStream(sample_rate, sample_size, channels))
285        }
286    }
287
288    pub fn __is_audio_stream_ready(stream: AudioStream) -> bool {
289        unsafe { IsAudioStreamReady(stream) }
290    }
291
292    pub fn __unload_audio_stream(stream: AudioStream) {
293        unsafe { UnloadAudioStream(stream) }
294    }
295
296    pub fn __update_audio_stream(stream: AudioStream, data: &[u8]) {
297        unsafe {
298            let count = data.len() as i32;
299            let data = data.as_ptr() as *const c_void;
300            UpdateAudioStream(stream, data, count)
301        }
302    }
303
304    pub fn __is_audio_stream_processed(stream: AudioStream) -> bool {
305        unsafe { IsAudioStreamProcessed(stream) }
306    }
307
308    pub fn __play_audio_stream(stream: AudioStream) {
309        unsafe { PlayAudioStream(stream) }
310    }
311
312    pub fn __pause_audio_stream(stream: AudioStream) {
313        unsafe { PauseAudioStream(stream) }
314    }
315
316    pub fn __resume_audio_stream(stream: AudioStream) {
317        unsafe { ResumeAudioStream(stream) }
318    }
319
320    pub fn __is_audio_stream_playing(stream: AudioStream) -> bool {
321        unsafe { IsAudioStreamPlaying(stream) }
322    }
323
324    pub fn __stop_audio_stream(stream: AudioStream) {
325        unsafe { StopAudioStream(stream) }
326    }
327
328    pub fn __set_audio_stream_volume(stream: AudioStream, volume: f32) {
329        unsafe { SetAudioStreamVolume(stream, volume) }
330    }
331
332    pub fn __set_audio_stream_pitch(stream: AudioStream, pitch: f32) {
333        unsafe { SetAudioStreamPitch(stream, pitch) }
334    }
335
336    pub fn __set_audio_stream_pan(stream: AudioStream, pan: f32) {
337        unsafe { SetAudioStreamPan(stream, pan) }
338    }
339
340    pub fn __set_audio_stream_buffer_size_default(size: i32) {
341        unsafe { SetAudioStreamBufferSizeDefault(size) }
342    }
343
344    // TODO: SetAudioStreamCallback
345    // TODO: AttachAudioStreamProcessor
346    // TODO: DetachAudioStreamProcessor
347    // TODO: AttachAudioMixedProcessor
348    // TODO: DetachAudioMixedProcessor
349}
350
351/// Exported methods
352pub trait Raudio: Debug {
353    // Audio device management
354
355    /// Initialize audio device and context
356    fn init_audio_device(&self) {
357        RaudioImpl::__init_audio_device()
358    }
359
360    /// Close the audio device and context
361    fn close_audio_device(&self) {
362        RaudioImpl::__close_audio_device()
363    }
364
365    /// Check whether audio device has been initialized successfully
366    fn is_audio_device_ready(&self) -> bool {
367        RaudioImpl::__is_audio_device_ready()
368    }
369
370    /// Set master volume (listener)
371    fn set_master_volume(&self, volume: f32) {
372        RaudioImpl::__set_master_volume(volume)
373    }
374
375    /// Get master volume (listener)
376    fn get_master_volume(&self) -> f32 {
377        RaudioImpl::__get_master_volume()
378    }
379
380    // Wave/Sound loading/unloading methods
381
382    /// Load wave data from file
383    fn load_wave(&self, filename: impl Display) -> Result<Wave, String> {
384        RaudioImpl::__load_wave(filename)
385    }
386
387    /// Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
388    fn load_wave_from_memory(&self, tpe: WaveType, data: &[u8]) -> Result<Wave, String> {
389        RaudioImpl::__load_wave_from_memory(tpe, data)
390    }
391
392    /// Check whether wave data is ready
393    fn is_wave_ready(&self, wave: Wave) -> bool {
394        RaudioImpl::__is_wave_ready(wave)
395    }
396
397    /// Load sound from file
398    fn load_sound(&self, filename: impl Display) -> Result<Sound, String> {
399        RaudioImpl::__load_sound(filename)
400    }
401
402    /// Load sound from wave data
403    fn load_sound_from_wave(&self, wave: Wave) -> Sound {
404        RaudioImpl::__load_sound_from_wave(wave)
405    }
406
407    /// Create a new sound that shares the same sample data as the source sound, does not own the sound data
408    fn load_sound_alias(&self, source: Sound) -> Sound {
409        RaudioImpl::__load_sound_alias(source)
410    }
411
412    /// Check whether a sound is ready
413    fn is_sound_ready(&self, sound: Sound) -> bool {
414        RaudioImpl::__is_sound_ready(sound)
415    }
416
417    /// Unload wave data
418    fn unload_wave(&self, wave: Wave) {
419        RaudioImpl::__unload_wave(wave)
420    }
421
422    /// Unload sound
423    fn unload_sound(&self, sound: Sound) {
424        RaudioImpl::__unload_sound(sound)
425    }
426
427    /// Unload a sound alias (does not deallocate sample data)
428    fn unload_sound_alias(&self, sound: Sound) {
429        RaudioImpl::__unload_sound_alias(sound)
430    }
431
432    /// Export wave data to file, returns true on success
433    fn export_wave(&self, wave: Wave, filename: impl Display) -> bool {
434        RaudioImpl::__export_wave(wave, filename)
435    }
436
437    /// Export wave sample data to code (.h), returns true on success
438    fn export_wave_as_code(&self, wave: Wave, filename: impl Display) -> bool {
439        RaudioImpl::__export_wave_as_code(wave, filename)
440    }
441
442    // Wave/Sound management methods
443
444    /// Play a sound
445    fn play_sound(&self, sound: Sound) {
446        RaudioImpl::__play_sound(sound)
447    }
448
449    /// Stop playing a sound
450    fn stop_sound(&self, sound: Sound) {
451        RaudioImpl::__stop_sound(sound)
452    }
453
454    /// Pause a sound
455    fn pause_sound(&self, sound: Sound) {
456        RaudioImpl::__pause_sound(sound)
457    }
458
459    /// Resume a paused sound
460    fn resume_sound(&self, sound: Sound) {
461        RaudioImpl::__resume_sound(sound)
462    }
463
464    /// Check whether a sound is currently playing
465    fn is_sound_playing(&self, sound: Sound) -> bool {
466        RaudioImpl::__is_sound_playing(sound)
467    }
468
469    /// Set volume for a sound (1.0 is max level)
470    fn set_sound_volume(&self, sound: Sound, volume: f32) {
471        RaudioImpl::__set_sound_volume(sound, volume)
472    }
473
474    /// Set pitch for a sound (1.0 is base level)
475    fn set_sound_pitch(&self, sound: Sound, pitch: f32) {
476        RaudioImpl::__set_sound_pitch(sound, pitch)
477    }
478
479    /// Set pan for a sound (0.5 is center)
480    fn set_sound_pan(&self, sound: Sound, pan: f32) {
481        RaudioImpl::__set_sound_pan(sound, pan)
482    }
483
484    /// Copy a wave to a new wave
485    fn wave_copy(&self, wave: Wave) -> Wave {
486        RaudioImpl::__wave_copy(wave)
487    }
488
489    // Crop a wave to defined samples range
490    fn wave_crop(&self, wave: &mut Wave, init_sample: i32, final_sample: i32) {
491        RaudioImpl::__wave_crop(wave, init_sample, final_sample)
492    }
493
494    /// Convert wave data to desired format
495    fn wave_format(&self, wave: &mut Wave, sample_rate: i32, sample_size: i32, channels: i32) {
496        RaudioImpl::__wave_format(wave, sample_rate, sample_size, channels)
497    }
498
499    /// Load samples data from wave as a 32bit float data array
500    fn load_wave_samples(&self, wave: Wave) -> Result<Vec<f32>, String> {
501        RaudioImpl::__load_wave_samples(wave)
502    }
503
504    // Music management methods
505
506    /// Load music stream from file
507    fn load_music_stream(&self, filename: impl Display) -> Result<Music, String> {
508        RaudioImpl::__load_music_stream(filename)
509    }
510
511    /// Load music stream from data
512    fn load_music_stream_from_memory(
513        &self,
514        tpe: impl Display,
515        data: &[u8],
516    ) -> Result<Music, String> {
517        RaudioImpl::__load_music_stream_from_memory(tpe, data)
518    }
519
520    /// Check whether a music stream is ready
521    fn is_music_ready(&self, music: Music) -> bool {
522        RaudioImpl::__is_music_ready(music)
523    }
524
525    /// Unload music stream
526    fn unload_music_stream(&self, music: Music) {
527        RaudioImpl::__unload_music_stream(music)
528    }
529
530    /// Start music playing
531    fn play_music_stream(&self, music: Music) {
532        RaudioImpl::__play_music_stream(music)
533    }
534
535    /// Check whether music is playing
536    fn is_music_stream_playing(&self, music: Music) -> bool {
537        RaudioImpl::__is_music_stream_playing(music)
538    }
539
540    /// Updates buffers for music streaming
541    fn update_music_stream(&self, music: Music) {
542        RaudioImpl::__update_music_stream(music)
543    }
544
545    /// Stop music playing
546    fn stop_music_stream(&self, music: Music) {
547        RaudioImpl::__stop_music_stream(music)
548    }
549
550    /// Pause music playing
551    fn pause_music_stream(&self, music: Music) {
552        RaudioImpl::__pause_music_stream(music)
553    }
554
555    /// Resume playing paused music
556    fn resume_music_stream(&self, music: Music) {
557        RaudioImpl::__resume_music_stream(music)
558    }
559
560    /// Seek music to a position (in seconds)
561    fn seek_music_stream(&self, music: Music, position: f32) {
562        RaudioImpl::__seek_music_stream(music, position)
563    }
564
565    /// Set volume for music (1.0 is max level)
566    fn set_music_volume(&self, music: Music, volume: f32) {
567        RaudioImpl::__set_music_volume(music, volume)
568    }
569
570    /// Set pitch for a music (1.0 is base level)
571    fn set_music_pitch(&self, music: Music, pitch: f32) {
572        RaudioImpl::__set_music_pitch(music, pitch)
573    }
574
575    /// Set pan for a music (0.5 is center)
576    fn set_music_pan(&self, music: Music, pan: f32) {
577        RaudioImpl::__set_music_pan(music, pan)
578    }
579
580    /// Get music time length (in seconds)
581    fn get_music_time_length(&self, music: Music) -> f32 {
582        RaudioImpl::__get_music_time_length(music)
583    }
584
585    /// Get current music time played (in seconds)
586    fn get_music_time_played(&self, music: Music) -> f32 {
587        RaudioImpl::__get_music_time_played(music)
588    }
589
590    // AudioStream management methods
591
592    /// Load audio stream (to stream raw audio pcm data)
593    fn load_audio_stream(
594        &self,
595        sample_rate: u32,
596        sample_size: u32,
597        channels: u32,
598    ) -> Result<AudioStream, String> {
599        RaudioImpl::__load_audio_stream(sample_rate, sample_size, channels)
600    }
601
602    /// Check whether an audio stream is ready
603    fn is_audio_stream_ready(&self, stream: AudioStream) -> bool {
604        RaudioImpl::__is_audio_stream_ready(stream)
605    }
606
607    /// Unload audio stream and free memory
608    fn unload_audio_stream(&self, stream: AudioStream) {
609        RaudioImpl::__unload_audio_stream(stream)
610    }
611
612    /// Update audio stream buffers with data
613    fn update_audio_stream(&self, stream: AudioStream, data: &[u8]) {
614        RaudioImpl::__update_audio_stream(stream, data)
615    }
616
617    /// Check whether any audio stream buffers requires refill
618    fn is_audio_stream_processed(&self, stream: AudioStream) -> bool {
619        RaudioImpl::__is_audio_stream_processed(stream)
620    }
621
622    /// Play audio stream
623    fn play_audio_stream(&self, stream: AudioStream) {
624        RaudioImpl::__play_audio_stream(stream)
625    }
626
627    /// Pause audio stream
628    fn pause_audio_stream(&self, stream: AudioStream) {
629        RaudioImpl::__pause_audio_stream(stream)
630    }
631
632    /// Resume audio stream
633    fn resume_audio_stream(&self, stream: AudioStream) {
634        RaudioImpl::__resume_audio_stream(stream)
635    }
636
637    /// Check whether audio stream is playing
638    fn is_audio_stream_playing(&self, stream: AudioStream) -> bool {
639        RaudioImpl::__is_audio_stream_playing(stream)
640    }
641
642    /// Stop audio stream
643    fn stop_audio_stream(&self, stream: AudioStream) {
644        RaudioImpl::__stop_audio_stream(stream)
645    }
646
647    /// Set volume for audio stream (1.0 is max level)
648    fn set_audio_stream_volume(&self, stream: AudioStream, volume: f32) {
649        RaudioImpl::__set_audio_stream_volume(stream, volume)
650    }
651
652    /// Set pitch for audio stream (1.0 is base level)
653    fn set_audio_stream_pitch(&self, stream: AudioStream, pitch: f32) {
654        RaudioImpl::__set_audio_stream_pitch(stream, pitch)
655    }
656
657    /// Set pan for audio stream (0.5 is centered)
658    fn set_audio_stream_pan(&self, stream: AudioStream, pan: f32) {
659        RaudioImpl::__set_audio_stream_pan(stream, pan)
660    }
661
662    /// Default size for new audio streams
663    fn set_audio_stream_buffer_size_default(&self, size: i32) {
664        RaudioImpl::__set_audio_stream_buffer_size_default(size)
665    }
666}