1use {
2 crate::{
3 audio::{SoundBuffer, SoundSource, SoundStatus},
4 ffi,
5 system::{Time, Vector3f},
6 },
7 std::{marker::PhantomData, ptr::NonNull},
8};
9
10#[derive(Debug)]
33pub struct Sound<'buf> {
34 handle: NonNull<ffi::audio::sfSound>,
35 buffer: PhantomData<&'buf SoundBuffer>,
36}
37
38unsafe impl Send for Sound<'_> {}
40
41unsafe impl Sync for Sound<'_> {}
44
45impl<'buf> Sound<'buf> {
47 #[must_use]
53 pub fn new() -> Self {
54 let s = unsafe { ffi::audio::sfSound_new() };
55 Sound {
56 handle: NonNull::new(s).expect("Failed to create Sound"),
57 buffer: PhantomData,
58 }
59 }
60
61 #[must_use]
63 pub fn with_buffer(buffer: &'buf SoundBuffer) -> Self {
64 let mut s = Sound::new();
65 s.set_buffer(buffer);
66 s
67 }
68}
69
70impl Sound<'_> {
72 pub fn play(&mut self) {
80 unsafe { ffi::audio::sfSound_play(self.handle.as_ptr()) }
81 }
82
83 pub fn pause(&mut self) {
88 unsafe { ffi::audio::sfSound_pause(self.handle.as_ptr()) }
89 }
90
91 pub fn stop(&mut self) {
97 unsafe { ffi::audio::sfSound_stop(self.handle.as_ptr()) }
98 }
99}
100
101impl<'buf> Sound<'buf> {
103 #[must_use]
107 pub fn is_looping(&self) -> bool {
108 unsafe { ffi::audio::sfSound_getLoop(self.handle.as_ptr()) }
109 }
110
111 #[must_use]
115 pub fn status(&self) -> SoundStatus {
116 unsafe { SoundStatus(ffi::audio::sfSound_getStatus(self.handle.as_ptr())) }
117 }
118
119 #[must_use]
123 pub fn playing_offset(&self) -> Time {
124 unsafe { Time::from_raw(ffi::audio::sfSound_getPlayingOffset(self.handle.as_ptr())) }
125 }
126 #[must_use]
130 pub fn buffer(&self) -> Option<&'buf SoundBuffer> {
131 unsafe { ffi::audio::sfSound_getBuffer(self.handle.as_ptr()).as_ref() }
132 }
133}
134
135impl<'buf> Sound<'buf> {
137 pub fn set_looping(&mut self, looping: bool) {
139 unsafe { ffi::audio::sfSound_setLoop(self.handle.as_ptr(), looping) }
140 }
141
142 pub fn set_playing_offset(&mut self, time_offset: Time) {
150 unsafe { ffi::audio::sfSound_setPlayingOffset(self.handle.as_ptr(), time_offset.raw()) }
151 }
152
153 pub fn set_buffer(&mut self, buffer: &'buf SoundBuffer) {
158 unsafe { ffi::audio::sfSound_setBuffer(self.handle.as_ptr(), buffer) }
159 }
160}
161
162impl Default for Sound<'_> {
163 fn default() -> Self {
164 Self::new()
165 }
166}
167
168impl Clone for Sound<'_> {
169 fn clone(&self) -> Self {
170 let s = unsafe { ffi::audio::sfSound_cpy(self.handle.as_ptr()) };
171 Sound {
172 handle: NonNull::new(s).expect("Failed to copy Sound"),
173 buffer: self.buffer,
174 }
175 }
176}
177
178impl SoundSource for Sound<'_> {
179 fn set_pitch(&mut self, pitch: f32) {
180 unsafe { ffi::audio::sfSound_setPitch(self.handle.as_ptr(), pitch) }
181 }
182 fn set_volume(&mut self, volume: f32) {
183 unsafe { ffi::audio::sfSound_setVolume(self.handle.as_ptr(), volume) }
184 }
185 fn set_position<P: Into<Vector3f>>(&mut self, position: P) {
186 unsafe { ffi::audio::sfSound_setPosition(self.handle.as_ptr(), position.into()) }
187 }
188 fn set_relative_to_listener(&mut self, relative: bool) {
189 unsafe { ffi::audio::sfSound_setRelativeToListener(self.handle.as_ptr(), relative) }
190 }
191 fn set_min_distance(&mut self, distance: f32) {
192 unsafe { ffi::audio::sfSound_setMinDistance(self.handle.as_ptr(), distance) }
193 }
194 fn set_attenuation(&mut self, attenuation: f32) {
195 unsafe { ffi::audio::sfSound_setAttenuation(self.handle.as_ptr(), attenuation) }
196 }
197 fn pitch(&self) -> f32 {
198 unsafe { ffi::audio::sfSound_getPitch(self.handle.as_ptr()) }
199 }
200 fn volume(&self) -> f32 {
201 unsafe { ffi::audio::sfSound_getVolume(self.handle.as_ptr()) }
202 }
203 fn position(&self) -> Vector3f {
204 unsafe { ffi::audio::sfSound_getPosition(self.handle.as_ptr()) }
205 }
206 fn is_relative_to_listener(&self) -> bool {
207 unsafe { ffi::audio::sfSound_isRelativeToListener(self.handle.as_ptr()) }
208 }
209 fn min_distance(&self) -> f32 {
210 unsafe { ffi::audio::sfSound_getMinDistance(self.handle.as_ptr()) }
211 }
212 fn attenuation(&self) -> f32 {
213 unsafe { ffi::audio::sfSound_getAttenuation(self.handle.as_ptr()) }
214 }
215}
216
217impl Drop for Sound<'_> {
218 fn drop(&mut self) {
219 unsafe {
220 ffi::audio::sfSound_del(self.handle.as_ptr());
221 }
222 }
223}