use {
crate::{
IntoSfResult, SfResult,
audio::{SoundSource, SoundStatus, TimeSpan},
ffi::{self},
system::{InputStream, Time, Vector3f},
},
std::{
ffi::CString,
io::{Read, Seek},
marker::PhantomData,
},
};
#[derive(Debug)]
pub struct Music<'src> {
music: *mut ffi::audio::sfMusic,
_stream: PhantomData<&'src mut ()>,
}
unsafe impl Send for Music<'_> {}
unsafe impl Sync for Music<'_> {}
impl<'src> Music<'src> {
pub fn new() -> SfResult<Self> {
Ok(Self {
music: unsafe { ffi::audio::sfMusic_new() },
_stream: PhantomData,
})
}
pub fn from_file(filename: &str) -> SfResult<Self> {
let mut new = Self::new()?;
new.open_from_file(filename)?;
Ok(new)
}
pub fn from_stream<T: Read + Seek>(stream: &'src mut InputStream<T>) -> SfResult<Self> {
let mut new = Self::new()?;
new.open_from_stream(stream)?;
Ok(new)
}
pub fn from_memory(data: &'src [u8]) -> SfResult<Self> {
let mut new = Self::new()?;
new.open_from_memory(data)?;
Ok(new)
}
pub fn open_from_file(&mut self, filename: &str) -> SfResult<()> {
let c_str = CString::new(filename)?;
unsafe { ffi::audio::sfMusic_openFromFile(self.music, c_str.as_ptr()) }.into_sf_result()
}
pub fn open_from_stream<T: Read + Seek>(
&mut self,
stream: &'src mut InputStream<T>,
) -> SfResult<()> {
unsafe { ffi::audio::sfMusic_openFromStream(self.music, &mut *stream.stream) }
.into_sf_result()
}
pub fn open_from_memory(&mut self, data: &'src [u8]) -> SfResult<()> {
unsafe { ffi::audio::sfMusic_openFromMemory(self.music, data.as_ptr(), data.len()) }
.into_sf_result()
}
}
impl Music<'_> {
pub fn play(&mut self) {
unsafe { ffi::audio::sfMusic_play(self.music) }
}
pub fn pause(&mut self) {
unsafe { ffi::audio::sfMusic_pause(self.music) }
}
pub fn stop(&mut self) {
unsafe { ffi::audio::sfMusic_stop(self.music) }
}
}
impl Music<'_> {
#[must_use]
pub fn is_looping(&self) -> bool {
unsafe { ffi::audio::sfMusic_getLoop(self.music) }
}
#[must_use]
pub fn duration(&self) -> Time {
unsafe { Time::from_raw(ffi::audio::sfMusic_getDuration(self.music)) }
}
#[must_use]
pub fn channel_count(&self) -> u32 {
unsafe { ffi::audio::sfMusic_getChannelCount(self.music) }
}
#[must_use]
pub fn sample_rate(&self) -> u32 {
unsafe { ffi::audio::sfMusic_getSampleRate(self.music) }
}
#[must_use]
pub fn status(&self) -> SoundStatus {
unsafe { SoundStatus(ffi::audio::sfMusic_getStatus(self.music)) }
}
#[must_use]
pub fn playing_offset(&self) -> Time {
unsafe { Time::from_raw(ffi::audio::sfMusic_getPlayingOffset(self.music)) }
}
#[must_use]
pub fn loop_points(&self) -> TimeSpan {
TimeSpan::from_raw(unsafe { ffi::audio::sfMusic_getLoopPoints(self.music) })
}
}
impl Music<'_> {
pub fn set_looping(&mut self, looping: bool) {
unsafe { ffi::audio::sfMusic_setLoop(self.music, looping) }
}
pub fn set_playing_offset(&mut self, time_offset: Time) {
unsafe { ffi::audio::sfMusic_setPlayingOffset(self.music, time_offset.raw()) }
}
pub fn set_loop_points(&mut self, time_points: TimeSpan) {
unsafe { ffi::audio::sfMusic_setLoopPoints(self.music, time_points.into_raw()) }
}
}
impl SoundSource for Music<'_> {
fn set_pitch(&mut self, pitch: f32) {
unsafe { ffi::audio::sfMusic_setPitch(self.music, pitch) }
}
fn set_volume(&mut self, volume: f32) {
unsafe { ffi::audio::sfMusic_setVolume(self.music, volume) }
}
fn set_position<P: Into<Vector3f>>(&mut self, position: P) {
unsafe { ffi::audio::sfMusic_setPosition(self.music, position.into()) }
}
fn set_relative_to_listener(&mut self, relative: bool) {
unsafe { ffi::audio::sfMusic_setRelativeToListener(self.music, relative) }
}
fn set_min_distance(&mut self, distance: f32) {
unsafe { ffi::audio::sfMusic_setMinDistance(self.music, distance) }
}
fn set_attenuation(&mut self, attenuation: f32) {
unsafe { ffi::audio::sfMusic_setAttenuation(self.music, attenuation) }
}
fn pitch(&self) -> f32 {
unsafe { ffi::audio::sfMusic_getPitch(self.music) }
}
fn volume(&self) -> f32 {
unsafe { ffi::audio::sfMusic_getVolume(self.music) }
}
fn position(&self) -> Vector3f {
unsafe { ffi::audio::sfMusic_getPosition(self.music) }
}
fn is_relative_to_listener(&self) -> bool {
unsafe { ffi::audio::sfMusic_isRelativeToListener(self.music) }
}
fn min_distance(&self) -> f32 {
unsafe { ffi::audio::sfMusic_getMinDistance(self.music) }
}
fn attenuation(&self) -> f32 {
unsafe { ffi::audio::sfMusic_getAttenuation(self.music) }
}
}
impl Drop for Music<'_> {
fn drop(&mut self) {
unsafe {
ffi::audio::sfMusic_del(self.music);
}
}
}