use {
crate::{
audio::{SoundBuffer, SoundSource, SoundStatus},
ffi,
system::{Time, Vector3f},
},
std::{marker::PhantomData, ptr::NonNull},
};
#[derive(Debug)]
pub struct Sound<'buf> {
handle: NonNull<ffi::audio::sfSound>,
buffer: PhantomData<&'buf SoundBuffer>,
}
unsafe impl Send for Sound<'_> {}
unsafe impl Sync for Sound<'_> {}
impl<'buf> Sound<'buf> {
#[must_use]
pub fn new() -> Self {
let s = unsafe { ffi::audio::sfSound_new() };
Sound {
handle: NonNull::new(s).expect("Failed to create Sound"),
buffer: PhantomData,
}
}
#[must_use]
pub fn with_buffer(buffer: &'buf SoundBuffer) -> Self {
let mut s = Sound::new();
s.set_buffer(buffer);
s
}
}
impl Sound<'_> {
pub fn play(&mut self) {
unsafe { ffi::audio::sfSound_play(self.handle.as_ptr()) }
}
pub fn pause(&mut self) {
unsafe { ffi::audio::sfSound_pause(self.handle.as_ptr()) }
}
pub fn stop(&mut self) {
unsafe { ffi::audio::sfSound_stop(self.handle.as_ptr()) }
}
}
impl<'buf> Sound<'buf> {
#[must_use]
pub fn is_looping(&self) -> bool {
unsafe { ffi::audio::sfSound_getLoop(self.handle.as_ptr()) }
}
#[must_use]
pub fn status(&self) -> SoundStatus {
unsafe { SoundStatus(ffi::audio::sfSound_getStatus(self.handle.as_ptr())) }
}
#[must_use]
pub fn playing_offset(&self) -> Time {
unsafe { Time::from_raw(ffi::audio::sfSound_getPlayingOffset(self.handle.as_ptr())) }
}
#[must_use]
pub fn buffer(&self) -> Option<&'buf SoundBuffer> {
unsafe { ffi::audio::sfSound_getBuffer(self.handle.as_ptr()).as_ref() }
}
}
impl<'buf> Sound<'buf> {
pub fn set_looping(&mut self, looping: bool) {
unsafe { ffi::audio::sfSound_setLoop(self.handle.as_ptr(), looping) }
}
pub fn set_playing_offset(&mut self, time_offset: Time) {
unsafe { ffi::audio::sfSound_setPlayingOffset(self.handle.as_ptr(), time_offset.raw()) }
}
pub fn set_buffer(&mut self, buffer: &'buf SoundBuffer) {
unsafe { ffi::audio::sfSound_setBuffer(self.handle.as_ptr(), buffer) }
}
}
impl Default for Sound<'_> {
fn default() -> Self {
Self::new()
}
}
impl Clone for Sound<'_> {
fn clone(&self) -> Self {
let s = unsafe { ffi::audio::sfSound_cpy(self.handle.as_ptr()) };
Sound {
handle: NonNull::new(s).expect("Failed to copy Sound"),
buffer: self.buffer,
}
}
}
impl SoundSource for Sound<'_> {
fn set_pitch(&mut self, pitch: f32) {
unsafe { ffi::audio::sfSound_setPitch(self.handle.as_ptr(), pitch) }
}
fn set_volume(&mut self, volume: f32) {
unsafe { ffi::audio::sfSound_setVolume(self.handle.as_ptr(), volume) }
}
fn set_position<P: Into<Vector3f>>(&mut self, position: P) {
unsafe { ffi::audio::sfSound_setPosition(self.handle.as_ptr(), position.into()) }
}
fn set_relative_to_listener(&mut self, relative: bool) {
unsafe { ffi::audio::sfSound_setRelativeToListener(self.handle.as_ptr(), relative) }
}
fn set_min_distance(&mut self, distance: f32) {
unsafe { ffi::audio::sfSound_setMinDistance(self.handle.as_ptr(), distance) }
}
fn set_attenuation(&mut self, attenuation: f32) {
unsafe { ffi::audio::sfSound_setAttenuation(self.handle.as_ptr(), attenuation) }
}
fn pitch(&self) -> f32 {
unsafe { ffi::audio::sfSound_getPitch(self.handle.as_ptr()) }
}
fn volume(&self) -> f32 {
unsafe { ffi::audio::sfSound_getVolume(self.handle.as_ptr()) }
}
fn position(&self) -> Vector3f {
unsafe { ffi::audio::sfSound_getPosition(self.handle.as_ptr()) }
}
fn is_relative_to_listener(&self) -> bool {
unsafe { ffi::audio::sfSound_isRelativeToListener(self.handle.as_ptr()) }
}
fn min_distance(&self) -> f32 {
unsafe { ffi::audio::sfSound_getMinDistance(self.handle.as_ptr()) }
}
fn attenuation(&self) -> f32 {
unsafe { ffi::audio::sfSound_getAttenuation(self.handle.as_ptr()) }
}
}
impl Drop for Sound<'_> {
fn drop(&mut self) {
unsafe {
ffi::audio::sfSound_del(self.handle.as_ptr());
}
}
}