1 /*
2 libSDL2pp - C++11 bindings/wrapper for SDL2
3 Copyright (C) 2015-2016 Dmitry Marakasov <amdmi3@amdmi3.ru>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21
22 #include <SDL2pp/Mixer.hh>
23 #include <SDL2pp/Chunk.hh>
24 #include <SDL2pp/Music.hh>
25 #include <SDL2pp/Exception.hh>
26
27 namespace SDL2pp {
28
Mixer(int frequency,Uint16 format,int channels,int chunksize)29 Mixer::Mixer(int frequency, Uint16 format, int channels, int chunksize) : open_(true) {
30 if (Mix_OpenAudio(frequency, format, channels, chunksize) != 0)
31 throw Exception("Mix_OpenAudio");
32 }
33
~Mixer()34 Mixer::~Mixer() {
35 if (open_)
36 Mix_CloseAudio();
37 }
38
Mixer(Mixer && other)39 Mixer::Mixer(Mixer&& other) noexcept : open_(other.open_), current_music_hook_(std::move(other.current_music_hook_)) {
40 other.open_ = false;
41 }
42
operator =(Mixer && other)43 Mixer& Mixer::operator=(Mixer&& other) noexcept {
44 if (&other == this)
45 return *this;
46 if (open_)
47 Mix_CloseAudio();
48 open_ = other.open_;
49 current_music_hook_ = std::move(other.current_music_hook_);
50 other.open_ = false;
51 return *this;
52 }
53
AllocateChannels(int numchans)54 int Mixer::AllocateChannels(int numchans) {
55 return Mix_AllocateChannels(numchans);
56 }
57
GetNumChannels() const58 int Mixer::GetNumChannels() const {
59 return Mix_AllocateChannels(-1);
60 }
61
SetVolume(int channel,int volume)62 int Mixer::SetVolume(int channel, int volume) {
63 return Mix_Volume(channel, volume);
64 }
65
GetVolume(int channel) const66 int Mixer::GetVolume(int channel) const {
67 return Mix_Volume(channel, -1);
68 }
69
PlayChannel(int channel,const Chunk & chunk,int loops)70 int Mixer::PlayChannel(int channel, const Chunk& chunk, int loops) {
71 int chan;
72 if ((chan = Mix_PlayChannel(channel, chunk.Get(), loops)) == -1)
73 throw Exception("Mix_PlayChannel");
74 return chan;
75 }
76
PlayChannel(int channel,const Chunk & chunk,int loops,int ticks)77 int Mixer::PlayChannel(int channel, const Chunk& chunk, int loops, int ticks) {
78 int chan;
79 if ((chan = Mix_PlayChannelTimed(channel, chunk.Get(), loops, ticks)) == -1)
80 throw Exception("Mix_PlayChannelTimed");
81 return chan;
82 }
83
FadeInChannel(int channel,const Chunk & chunk,int loops,int ms)84 int Mixer::FadeInChannel(int channel, const Chunk& chunk, int loops, int ms) {
85 int chan;
86 if ((chan = Mix_FadeInChannel(channel, chunk.Get(), loops, ms)) == -1)
87 throw Exception("Mix_FadeInChannel");
88 return chan;
89 }
90
FadeInChannel(int channel,const Chunk & chunk,int loops,int ms,int ticks)91 int Mixer::FadeInChannel(int channel, const Chunk& chunk, int loops, int ms, int ticks) {
92 int chan;
93 if ((chan = Mix_FadeInChannelTimed(channel, chunk.Get(), loops, ms, ticks)) == -1)
94 throw Exception("Mix_FadeInChannelTimed");
95 return chan;
96 }
97
PauseChannel(int channel)98 void Mixer::PauseChannel(int channel) {
99 Mix_Pause(channel);
100 }
101
ResumeChannel(int channel)102 void Mixer::ResumeChannel(int channel) {
103 Mix_Resume(channel);
104 }
105
HaltChannel(int channel)106 void Mixer::HaltChannel(int channel) {
107 Mix_HaltChannel(channel);
108 }
109
ExpireChannel(int channel,int ticks)110 int Mixer::ExpireChannel(int channel, int ticks) {
111 return Mix_ExpireChannel(channel, ticks);
112 }
113
FadeOutChannel(int channel,int ms)114 int Mixer::FadeOutChannel(int channel, int ms) {
115 return Mix_FadeOutChannel(channel, ms);
116 }
117
SetChannelFinishedHandler(ChannelFinishedHandler channel_finished)118 void Mixer::SetChannelFinishedHandler(ChannelFinishedHandler channel_finished) {
119 Mix_ChannelFinished(channel_finished);
120 }
121
RemoveChannelFinishedHandler()122 void Mixer::RemoveChannelFinishedHandler() {
123 Mix_ChannelFinished(nullptr);
124 }
125
IsChannelPlaying(int channel) const126 int Mixer::IsChannelPlaying(int channel) const {
127 return Mix_Playing(channel);
128 }
129
IsChannelPaused(int channel) const130 int Mixer::IsChannelPaused(int channel) const {
131 return Mix_Paused(channel);
132 }
133
GetChannelFading(int which) const134 Mix_Fading Mixer::GetChannelFading(int which) const {
135 return Mix_FadingChannel(which);
136 }
137
ReserveChannels(int num)138 int Mixer::ReserveChannels(int num) {
139 return Mix_ReserveChannels(num);
140 }
141
GroupChannel(int which,int tag)142 void Mixer::GroupChannel(int which, int tag) {
143 if (Mix_GroupChannel(which, tag) != 1)
144 throw Exception("Mix_GroupChannel");
145 }
146
GroupChannels(int from,int to,int tag)147 void Mixer::GroupChannels(int from, int to, int tag) {
148 if (Mix_GroupChannels(from, to, tag) != to - from + 1)
149 throw Exception("Mix_GroupChannels");
150 }
151
GetGroupNumChannels(int tag) const152 int Mixer::GetGroupNumChannels(int tag) const {
153 return Mix_GroupCount(tag);
154 }
155
GetGroupAvailableChannel(int tag) const156 int Mixer::GetGroupAvailableChannel(int tag) const {
157 return Mix_GroupAvailable(tag);
158 }
159
GetGroupOldestChannel(int tag) const160 int Mixer::GetGroupOldestChannel(int tag) const {
161 return Mix_GroupOldest(tag);
162 }
163
GetGroupNewestChannel(int tag) const164 int Mixer::GetGroupNewestChannel(int tag) const {
165 return Mix_GroupNewer(tag);
166 }
167
FadeOutGroup(int tag,int ms)168 int Mixer::FadeOutGroup(int tag, int ms) {
169 return Mix_FadeOutGroup(tag, ms);
170 }
171
HaltGroup(int tag)172 void Mixer::HaltGroup(int tag) {
173 Mix_HaltGroup(tag);
174 }
175
PlayMusic(const Music & music,int loops)176 void Mixer::PlayMusic(const Music& music, int loops) {
177 if (Mix_PlayMusic(music.Get(), loops) == -1)
178 throw Exception("Mix_PlayMusic");
179 }
180
FadeInMusic(const Music & music,int loops,int ms)181 void Mixer::FadeInMusic(const Music& music, int loops, int ms) {
182 if (Mix_FadeInMusic(music.Get(), loops, ms) == -1)
183 throw Exception("Mix_FadeInMusic");
184 }
185
SetMusicVolume(int volume)186 int Mixer::SetMusicVolume(int volume) {
187 return Mix_VolumeMusic(volume);
188 }
189
GetMusicVolume() const190 int Mixer::GetMusicVolume() const {
191 return Mix_VolumeMusic(-1);
192 }
193
PauseMusic()194 void Mixer::PauseMusic() {
195 Mix_PauseMusic();
196 }
197
ResumeMusic()198 void Mixer::ResumeMusic() {
199 Mix_ResumeMusic();
200 }
201
RewindMusic()202 void Mixer::RewindMusic() {
203 Mix_RewindMusic();
204 }
205
SetMusicPosition(double position)206 void Mixer::SetMusicPosition(double position) {
207 if (Mix_SetMusicPosition(position) == -1)
208 throw Exception("Mix_SetMusicPosition");
209 }
210
HaltMusic()211 void Mixer::HaltMusic() {
212 Mix_HaltMusic();
213 }
214
FadeOutMusic(int ms)215 bool Mixer::FadeOutMusic(int ms) {
216 return Mix_FadeOutMusic(ms) > 0;
217 }
218
IsMusicPlaying() const219 bool Mixer::IsMusicPlaying() const {
220 return Mix_PlayingMusic() > 0;
221 }
222
IsMusicPaused() const223 bool Mixer::IsMusicPaused() const {
224 return Mix_PausedMusic() > 0;
225 }
226
GetMusicFading() const227 Mix_Fading Mixer::GetMusicFading() const {
228 return Mix_FadingMusic();
229 }
230
SetMusicFinishedHandler(MusicFinishedHandler music_finished)231 void Mixer::SetMusicFinishedHandler(MusicFinishedHandler music_finished) {
232 Mix_HookMusicFinished(music_finished);
233 }
234
RemoveMusicFinishedHandler()235 void Mixer::RemoveMusicFinishedHandler() {
236 Mix_HookMusicFinished(nullptr);
237 }
238
SetMusicHook(MusicHook && hook)239 void Mixer::SetMusicHook(MusicHook&& hook) {
240 if (!hook) {
241 Mix_HookMusic(nullptr, nullptr);
242 current_music_hook_.reset(nullptr);
243 return;
244 }
245
246 current_music_hook_.reset(new MusicHook(std::move(hook)));
247
248 Mix_HookMusic([](void *udata, Uint8 *stream, int len) {
249 static_cast<std::function<void(Uint8 *stream, int len)>*>(udata)->operator()(stream, len);
250 }, current_music_hook_.get());
251 }
252
SetPanning(int channel,Uint8 left,Uint8 right)253 void Mixer::SetPanning(int channel, Uint8 left, Uint8 right) {
254 if (Mix_SetPanning(channel, left, right) == 0)
255 throw Exception("Mix_SetPanning");
256 }
257
UnsetPanning(int channel)258 void Mixer::UnsetPanning(int channel) {
259 if (Mix_SetPanning(channel, 255, 255) == 0)
260 throw Exception("Mix_SetPanning");
261 }
262
SetDistance(int channel,Uint8 distance)263 void Mixer::SetDistance(int channel, Uint8 distance) {
264 if (Mix_SetDistance(channel, distance) == 0)
265 throw Exception("Mix_SetDistance");
266 }
267
UnsetDistance(int channel)268 void Mixer::UnsetDistance(int channel) {
269 if (Mix_SetDistance(channel, 0) == 0)
270 throw Exception("Mix_SetDistance");
271 }
272
SetPosition(int channel,Sint16 angle,Uint8 distance)273 void Mixer::SetPosition(int channel, Sint16 angle, Uint8 distance) {
274 if (Mix_SetPosition(channel, angle, distance) == 0)
275 throw Exception("Mix_SetPosition");
276 }
277
UnsetPosition(int channel)278 void Mixer::UnsetPosition(int channel) {
279 if (Mix_SetPosition(channel, 0, 0) == 0)
280 throw Exception("Mix_SetPosition");
281 }
282
SetReverseStereo(int channel)283 void Mixer::SetReverseStereo(int channel) {
284 if (Mix_SetReverseStereo(channel, 1) == 0)
285 throw Exception("Mix_SetReverseStereo");
286 }
287
UnsetReverseStereo(int channel)288 void Mixer::UnsetReverseStereo(int channel) {
289 if (Mix_SetReverseStereo(channel, 0) == 0)
290 throw Exception("Mix_SetReverseStereo");
291 }
292
293 }
294