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