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 #ifndef SDL2PP_MIXER_HH
23 #define SDL2PP_MIXER_HH
24 
25 #include <functional>
26 #include <memory>
27 
28 #include <SDL_stdinc.h>
29 #include <SDL_mixer.h>
30 
31 #include <SDL2pp/Export.hh>
32 
33 namespace SDL2pp {
34 
35 class Chunk;
36 class Music;
37 
38 ////////////////////////////////////////////////////////////
39 /// \brief Audio mixer
40 ///
41 /// \ingroup mixer
42 ///
43 /// \headerfile SDL2pp/Mixer.hh
44 ///
45 /// This class represents open SDL_mixer audio device. Object
46 /// of this class must be constructed before calling any other
47 /// mixer functions.
48 ///
49 ////////////////////////////////////////////////////////////
50 class SDL2PP_EXPORT Mixer {
51 public:
52 	typedef void (*ChannelFinishedHandler)(int); ///< Function type for channel finished callback
53 	typedef void (*MusicFinishedHandler)();      ///< Function type for music finished callback
54 
55 	typedef std::function<void(Uint8 *stream, int len)> MusicHook; ///< Custom music hook
56 
57 private:
58 	bool open_;
59 	std::unique_ptr<MusicHook> current_music_hook_;
60 
61 public:
62 
63 	///@{
64 	/// \name Construction and destruction
65 
66 	////////////////////////////////////////////////////////////
67 	/// \brief Construct a mixer and open an audio device
68 	///
69 	/// \param[in] frequency Output sampling frequency in samples
70 	///                      per second (Hz). You might use
71 	///                      MIX_DEFAULT_FREQUENCY(22050) since that
72 	///                      is a good value for most games
73 	/// \param[in] format Output sample format
74 	/// \param[in] channels Number of sound channels in output. Set
75 	///                     to 2 for stereo, 1 for mono. This has
76 	///                     nothing to do with mixing channels
77 	/// \param[in] chunksize Bytes used per output sample
78 	///
79 	/// \throws SDL2pp::Exception
80 	///
81 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC11
82 	///
83 	////////////////////////////////////////////////////////////
84 	Mixer(int frequency, Uint16 format, int channels, int chunksize);
85 
86 	////////////////////////////////////////////////////////////
87 	/// \brief Destructor
88 	///
89 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC12
90 	///
91 	////////////////////////////////////////////////////////////
92 	~Mixer();
93 
94 	///@}
95 
96 	///@{
97 	/// \name Copy and move
98 
99 	////////////////////////////////////////////////////////////
100 	/// \brief Move constructor
101 	///
102 	/// \param[in] other SDL2pp::Mixer object to move data from
103 	///
104 	////////////////////////////////////////////////////////////
105 	Mixer(Mixer&& other) noexcept;
106 
107 	////////////////////////////////////////////////////////////
108 	/// \brief Move assignment operator
109 	///
110 	/// \param[in] other SDL2pp::Mixer object to move data from
111 	///
112 	/// \returns Reference to self
113 	///
114 	////////////////////////////////////////////////////////////
115 	Mixer& operator=(Mixer&& other) noexcept;
116 
117 	////////////////////////////////////////////////////////////
118 	/// \brief Deleted copy constructor
119 	///
120 	/// This class is not copyable
121 	///
122 	////////////////////////////////////////////////////////////
123 	Mixer(const Mixer& other) = delete;
124 
125 	////////////////////////////////////////////////////////////
126 	/// \brief Deleted assignment operator
127 	///
128 	/// This class is not copyable
129 	///
130 	////////////////////////////////////////////////////////////
131 	Mixer& operator=(const Mixer& other) = delete;
132 
133 	///@}
134 
135 	///@{
136 	/// \name Channels: setup
137 
138 	////////////////////////////////////////////////////////////
139 	/// \brief Set the number of channels to mix
140 	///
141 	/// \param[in] numchans Number of channels to allocate for mixing
142 	///
143 	/// \returns The number of channels allocated
144 	///
145 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC26
146 	///
147 	////////////////////////////////////////////////////////////
148 	int AllocateChannels(int numchans);
149 
150 	////////////////////////////////////////////////////////////
151 	/// \brief Get the number of channels being mixed
152 	///
153 	/// \returns The number of channels allocated
154 	///
155 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC26
156 	///
157 	////////////////////////////////////////////////////////////
158 	int GetNumChannels() const;
159 
160 	////////////////////////////////////////////////////////////
161 	/// \brief Set the mix volume of a channel
162 	///
163 	/// \param[in] channel Channel to set mix volume for.
164 	///                    -1 will set the volume for all allocated
165 	///                    channels.
166 	/// \param[in] volume The volume to use from 0 to MIX_MAX_VOLUME(128)
167 	///
168 	/// \returns Current volume of the channel. If channel is -1,
169 	///          the average volume is returned
170 	///
171 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC27
172 	///
173 	////////////////////////////////////////////////////////////
174 	int SetVolume(int channel, int volume);
175 
176 	////////////////////////////////////////////////////////////
177 	/// \brief Get the mix volume of a channel
178 	///
179 	/// \param[in] channel Channel to set mix volume for.
180 	///                    -1 will return the average volume.
181 	///
182 	/// \returns Current volume of the channel. If channel is -1,
183 	///          the average volume is returned
184 	///
185 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC27
186 	///
187 	////////////////////////////////////////////////////////////
188 	int GetVolume(int channel) const;
189 
190 	///@}
191 
192 	///@{
193 	/// \name Channels: playing
194 
195 	////////////////////////////////////////////////////////////
196 	/// \brief Play loop
197 	///
198 	/// \param[in] channel Channel to play on, or -1 for the first
199 	///                    free unreserved channel
200 	/// \param[in] chunk Sample to play
201 	/// \param[in] loops Number of loops, -1 is infinite loops.
202 	///                  Passing one here plays the sample twice (1 loop).
203 	///
204 	/// \returns The channel the sample is played on
205 	///
206 	/// \throws SDL2pp::Exception
207 	///
208 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC28
209 	///
210 	////////////////////////////////////////////////////////////
211 	int PlayChannel(int channel, const Chunk& chunk, int loops = 0);
212 
213 	////////////////////////////////////////////////////////////
214 	/// \brief Play loop and limit by time
215 	///
216 	/// \param[in] channel Channel to play on, or -1 for the first
217 	///                    free unreserved channel
218 	/// \param[in] chunk Sample to play
219 	/// \param[in] loops Number of loops, -1 is infinite loops.
220 	///                  Passing one here plays the sample twice (1 loop).
221 	/// \param[in] ticks Millisecond limit to play sample, at most.
222 	///                  If not enough loops or the sample chunk is not
223 	///                  long enough, then the sample may stop before
224 	///                  this timeout occurs. -1 means play forever
225 	///
226 	/// \returns The channel the sample is played on
227 	///
228 	/// \throws SDL2pp::Exception
229 	///
230 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC29
231 	///
232 	////////////////////////////////////////////////////////////
233 	int PlayChannel(int channel, const Chunk& chunk, int loops, int ticks);
234 
235 	////////////////////////////////////////////////////////////
236 	/// \brief Play loop with fade in
237 	///
238 	/// \param[in] channel Channel to play on, or -1 for the first
239 	///                    free unreserved channel
240 	/// \param[in] chunk Sample to play
241 	/// \param[in] loops Number of loops, -1 is infinite loops.
242 	///                  Passing one here plays the sample twice (1 loop).
243 	/// \param[in] ms Milliseconds of time that the fade-in effect
244 	///               should take to go from silence to full volume
245 	///
246 	/// \returns The channel the sample is played on
247 	///
248 	/// \throws SDL2pp::Exception
249 	///
250 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC30
251 	///
252 	////////////////////////////////////////////////////////////
253 	int FadeInChannel(int channel, const Chunk& chunk, int loops, int ms);
254 
255 	////////////////////////////////////////////////////////////
256 	/// \brief  loop with fade in and limit by time
257 	///
258 	/// \param[in] channel Channel to play on, or -1 for the first
259 	///                    free unreserved channel
260 	/// \param[in] chunk Sample to play
261 	/// \param[in] loops Number of loops, -1 is infinite loops.
262 	///                  Passing one here plays the sample twice (1 loop).
263 	/// \param[in] ms Milliseconds of time that the fade-in effect
264 	///               should take to go from silence to full volume
265 	/// \param[in] ticks Millisecond limit to play sample, at most.
266 	///                  If not enough loops or the sample chunk is not
267 	///                  long enough, then the sample may stop before
268 	///                  this timeout occurs. -1 means play forever
269 	///
270 	/// \returns The channel the sample is played on
271 	///
272 	/// \throws SDL2pp::Exception
273 	///
274 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC31
275 	///
276 	////////////////////////////////////////////////////////////
277 	int FadeInChannel(int channel, const Chunk& chunk, int loops, int ms, int ticks);
278 
279 	///@}
280 
281 	///@{
282 	/// \name Channels: pausing
283 
284 	////////////////////////////////////////////////////////////
285 	/// \brief Pause a channel
286 	///
287 	/// \param[in] channel Channel to pause on, or -1 for all channels
288 	///
289 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC32
290 	///
291 	////////////////////////////////////////////////////////////
292 	void PauseChannel(int channel = -1);
293 
294 	////////////////////////////////////////////////////////////
295 	/// \brief Resume a paused channel
296 	///
297 	/// \param[in] channel Channel to resume playing, or -1 for all channels
298 	///
299 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC33
300 	///
301 	////////////////////////////////////////////////////////////
302 	void ResumeChannel(int channel = -1);
303 
304 	///@}
305 
306 	///@{
307 	/// \name Channels: stopping
308 
309 	////////////////////////////////////////////////////////////
310 	/// \brief Stop playing on a channel
311 	///
312 	/// \param[in] channel Channel to stop playing, or -1 for all channels
313 	///
314 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC34
315 	///
316 	////////////////////////////////////////////////////////////
317 	void HaltChannel(int channel = -1);
318 
319 	////////////////////////////////////////////////////////////
320 	/// \brief Change the timed stoppage of a channel
321 	///
322 	/// \param[in] channel Channel to stop playing, or -1 for all channels
323 	/// \param[in] ticks Millisecons until channel(s) halt playback
324 	///
325 	/// \returns Number of channels set to expire. Whether or not they are active
326 	///
327 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC35
328 	///
329 	////////////////////////////////////////////////////////////
330 	int ExpireChannel(int channel, int ticks);
331 
332 	////////////////////////////////////////////////////////////
333 	/// \brief Stop playing channel after timed fade out
334 	///
335 	/// \param[in] channel Channel to fade out, or -1 to fade all channels out
336 	/// \param[in] ms Milliseconds of time that the fade-out effect should
337 	///               take to go to silence, starting now
338 	///
339 	/// \returns The number of channels set to fade out
340 	///
341 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC36
342 	///
343 	////////////////////////////////////////////////////////////
344 	int FadeOutChannel(int channel, int ms);
345 
346 	////////////////////////////////////////////////////////////
347 	/// \brief Set callback for when channel finishes playing
348 	///
349 	/// \param[in] channel_finished Function to call when any channel
350 	///                             finishes playback
351 	///
352 	/// \note Since Mix_ChannelFinished doesn't take any custom data
353 	///       pointer, unfortunately there's no safe way of using
354 	///       std::function here.
355 	///
356 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC37
357 	///
358 	////////////////////////////////////////////////////////////
359 	void SetChannelFinishedHandler(ChannelFinishedHandler channel_finished);
360 
361 	////////////////////////////////////////////////////////////
362 	/// \brief Remove callback for when channel finishes playing
363 	///
364 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC37
365 	///
366 	////////////////////////////////////////////////////////////
367 	void RemoveChannelFinishedHandler();
368 
369 	///@}
370 
371 	///@{
372 	/// \name Channels: info
373 
374 	////////////////////////////////////////////////////////////
375 	/// \brief Get the active playing status of a channel
376 	///
377 	/// \param[in] channel Channel to test whether it is playing or not.
378 	///                    -1 will tell you how many channels are playing
379 	///
380 	/// \returns Zero if the channel is not playing. Otherwise if you passed
381 	///          in -1, the number of channels playing is returned. If you
382 	///          passed in a specific channel, then 1 is returned if it is
383 	///          playing.
384 	///
385 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC38
386 	///
387 	////////////////////////////////////////////////////////////
388 	int IsChannelPlaying(int channel) const;
389 
390 	////////////////////////////////////////////////////////////
391 	/// \brief Get the pause status of a channel
392 	///
393 	/// \param[in] channel Channel to test whether it is paused or not.
394 	///                    -1 will tell you how many channels are playing
395 	///
396 	/// \returns Zero if the channel is not paused. Otherwise if you passed
397 	///          in -1, the number of paused channels is returned. If you
398 	///          passed in a specific channel, then 1 is returned if it is
399 	///          paused.
400 	///
401 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC39
402 	///
403 	////////////////////////////////////////////////////////////
404 	int IsChannelPaused(int channel) const;
405 
406 	////////////////////////////////////////////////////////////
407 	/// \brief Get the fade status of a channel
408 	///
409 	/// \param[in] which Channel to get the fade activity status from
410 	///
411 	/// \returns The fading status
412 	///
413 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC40
414 	///
415 	////////////////////////////////////////////////////////////
416 	Mix_Fading GetChannelFading(int which) const;
417 
418 	///@}
419 
420 	///@{
421 	/// \name Groups: setup
422 
423 	////////////////////////////////////////////////////////////
424 	/// \brief Prevent channels from being used in default group
425 	///
426 	/// \param[in] num Number of channels to reserve from default mixing.
427 	///                Zero removes all reservations
428 	///
429 	/// \returns The number of channels reserved. Never fails,
430 	///          but may return less channels than you ask for,
431 	///          depending on the number of channels previously
432 	///          allocated
433 	///
434 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC43
435 	///
436 	////////////////////////////////////////////////////////////
437 	int ReserveChannels(int num);
438 
439 	////////////////////////////////////////////////////////////
440 	/// \brief Add/remove channel to/from group
441 	///
442 	/// \param[in] which Channel number to assign tag to.
443 	/// \param[in] tag A group number. Any positive numbers
444 	///                (including zero). -1 is the default group.
445 	///                Use -1 to remove a group tag essentially.
446 	///
447 	/// \throws SDL2pp::Exception
448 	///
449 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC44
450 	///
451 	////////////////////////////////////////////////////////////
452 	void GroupChannel(int which, int tag);
453 
454 	////////////////////////////////////////////////////////////
455 	/// \brief Add/remove segment of channels to/from group
456 	///
457 	/// \param[in] from First Channel number of channels to assign tag to.
458 	/// \param[in] to Last Channel number of channels to assign tag to
459 	/// \param[in] tag A group number. Any positive numbers (including zero).
460 	///                -1 is the default group. Use -1 to remove a group tag
461 	///                essentially.
462 	///
463 	/// \throws SDL2pp::Exception
464 	///
465 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC45
466 	///
467 	////////////////////////////////////////////////////////////
468 	void GroupChannels(int from, int to, int tag);
469 
470 	///@}
471 
472 	///@{
473 	/// \name Groups: info
474 
475 	////////////////////////////////////////////////////////////
476 	/// \brief Get number of channels in group
477 	///
478 	/// \param[in] tag A group number
479 	///
480 	/// \returns The number of channels found in the group
481 	///
482 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC46
483 	///
484 	////////////////////////////////////////////////////////////
485 	int GetGroupNumChannels(int tag) const;
486 
487 	////////////////////////////////////////////////////////////
488 	/// \brief Get first inactive channel in group
489 	///
490 	/// \param[in] tag A group number
491 	///
492 	/// \returns The channel found on success. -1 is returned when
493 	///          no channels in the group are available
494 	///
495 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC47
496 	///
497 	////////////////////////////////////////////////////////////
498 	int GetGroupAvailableChannel(int tag) const;
499 
500 	////////////////////////////////////////////////////////////
501 	/// \brief Get oldest busy channel in group
502 	///
503 	/// \param[in] tag A group number
504 	///
505 	/// \returns The channel found on success. -1 is returned when
506 	///          no channels in the group are available
507 	///
508 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC48
509 	///
510 	////////////////////////////////////////////////////////////
511 	int GetGroupOldestChannel(int tag) const;
512 
513 	////////////////////////////////////////////////////////////
514 	/// \brief Get youngest busy channel in group
515 	///
516 	/// \param[in] tag A group number
517 	///
518 	/// \returns The channel found on success. -1 is returned when
519 	///          no channels in the group are available
520 	///
521 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC49
522 	///
523 	////////////////////////////////////////////////////////////
524 	int GetGroupNewestChannel(int tag) const;
525 
526 	///@}
527 
528 	///@{
529 	/// \name Groups: stopping
530 
531 	////////////////////////////////////////////////////////////
532 	/// \brief Fade out a group over time
533 	///
534 	/// \param[in] tag Group to fade out
535 	/// \param[in] ms Milliseconds of time that the fade-out effect
536 	///               should take to go to silence, starting now
537 	///
538 	/// \returns The number of channels set to fade out
539 	///
540 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC50
541 	///
542 	////////////////////////////////////////////////////////////
543 	int FadeOutGroup(int tag, int ms);
544 
545 	////////////////////////////////////////////////////////////
546 	/// \brief Stop a group
547 	///
548 	/// \param[in] tag Group to fade out
549 	///
550 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC51
551 	///
552 	////////////////////////////////////////////////////////////
553 	void HaltGroup(int tag);
554 
555 	///@}
556 
557 	///@{
558 	/// \name Music: playing
559 
560 	////////////////////////////////////////////////////////////
561 	/// \brief Play music
562 	///
563 	/// \param[in] music Music to play
564 	/// \param[in] loops number of times to play through the music.
565 	///                  0 plays the music zero times...
566 	///                  -1 plays the music forever
567 	///
568 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC57
569 	///
570 	////////////////////////////////////////////////////////////
571 	void PlayMusic(const Music& music, int loops = -1);
572 
573 	////////////////////////////////////////////////////////////
574 	/// \brief Play music, with looping, and fade in
575 	///
576 	/// \param[in] music Music to play
577 	/// \param[in] loops number of times to play through the music.
578 	///                  0 plays the music zero times...
579 	///                  -1 plays the music forever
580 	/// \param[in] ms Milliseconds for the fade-in effect to complete
581 	///
582 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC57
583 	///
584 	////////////////////////////////////////////////////////////
585 	void FadeInMusic(const Music& music, int loops = -1, int ms = 0);
586 
587 	////////////////////////////////////////////////////////////
588 	/// \brief Hook for a custom music player
589 	///
590 	/// \param[in] hook Music player mixer function
591 	///
592 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC60
593 	///
594 	////////////////////////////////////////////////////////////
595 	void SetMusicHook(MusicHook&& hook);
596 
597 	///@}
598 
599 	///@{
600 	/// \name Music: settings
601 
602 	////////////////////////////////////////////////////////////
603 	/// \brief Set music volume
604 	///
605 	/// \param[in] volume The volume to use from 0 to MIX_MAX_VOLUME(128)
606 	///
607 	/// \returns The previous volume setting
608 	///
609 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC61
610 	///
611 	////////////////////////////////////////////////////////////
612 	int SetMusicVolume(int volume);
613 
614 	////////////////////////////////////////////////////////////
615 	/// \brief Get music volume
616 	///
617 	/// \returns Current volume setting
618 	///
619 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC61
620 	///
621 	////////////////////////////////////////////////////////////
622 	int GetMusicVolume() const;
623 
624 	////////////////////////////////////////////////////////////
625 	/// \brief Pause music
626 	///
627 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC62
628 	///
629 	////////////////////////////////////////////////////////////
630 	void PauseMusic();
631 
632 	////////////////////////////////////////////////////////////
633 	/// \brief Resume paused music
634 	///
635 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC63
636 	///
637 	////////////////////////////////////////////////////////////
638 	void ResumeMusic();
639 
640 	////////////////////////////////////////////////////////////
641 	/// \brief Rewind music to beginning
642 	///
643 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC64
644 	///
645 	////////////////////////////////////////////////////////////
646 	void RewindMusic();
647 
648 	////////////////////////////////////////////////////////////
649 	/// \brief Set position of playback in stream
650 	///
651 	/// \param[in] position Posistion to play from
652 	///
653 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC65
654 	///
655 	////////////////////////////////////////////////////////////
656 	void SetMusicPosition(double position);
657 
658 	///@}
659 
660 	///@{
661 	/// \name Music: stopping
662 
663 	////////////////////////////////////////////////////////////
664 	/// \brief Stop music playback
665 	///
666 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC67
667 	///
668 	////////////////////////////////////////////////////////////
669 	void HaltMusic();
670 
671 	////////////////////////////////////////////////////////////
672 	/// \brief Stop music, with fade out
673 	///
674 	/// \param[in] ms Milliseconds of time that the fade-out effect
675 	///               should take to go to silence, starting now.
676 	///
677 	/// \returns True in success, false on failure
678 	///
679 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC68
680 	///
681 	////////////////////////////////////////////////////////////
682 	bool FadeOutMusic(int ms);
683 
684 	////////////////////////////////////////////////////////////
685 	/// \brief Set a callback for when music stops
686 	///
687 	/// \param[in] music_finished Function to call when music stops
688 	///
689 	/// \note Since Mix_HookMusicFinished  doesn't take any custom data
690 	///       pointer, unfortunately there's no safe way of using
691 	///       std::function here.
692 	///
693 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC69
694 	///
695 	////////////////////////////////////////////////////////////
696 	void SetMusicFinishedHandler(MusicFinishedHandler music_finished);
697 
698 	////////////////////////////////////////////////////////////
699 	/// \brief Remove a callback for when music stops
700 	///
701 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC69
702 	///
703 	////////////////////////////////////////////////////////////
704 	void RemoveMusicFinishedHandler();
705 
706 	///@}
707 
708 	///@{
709 	/// \name Music: info
710 
711 	////////////////////////////////////////////////////////////
712 	/// \brief Test whether music is playing
713 	///
714 	/// \returns True if music is actively playing
715 	///
716 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC71
717 	///
718 	////////////////////////////////////////////////////////////
719 	bool IsMusicPlaying() const;
720 
721 	////////////////////////////////////////////////////////////
722 	/// \brief Test whether music is paused
723 	///
724 	/// \returns True if music is paused
725 	///
726 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC72
727 	///
728 	////////////////////////////////////////////////////////////
729 	bool IsMusicPaused() const;
730 
731 	////////////////////////////////////////////////////////////
732 	/// \brief Get status of current music fade activity
733 	///
734 	/// \returns The fading status
735 	///
736 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC73
737 	///
738 	////////////////////////////////////////////////////////////
739 	Mix_Fading GetMusicFading() const;
740 
741 	///@}
742 
743 	///@{
744 	/// \name Effects
745 
746 	// TODO: custom effects
747 
748 	////////////////////////////////////////////////////////////
749 	/// \brief Stereo panning
750 	///
751 	/// \param[in] channel Channel number to register this effect on or
752 	///                    MIX_CHANNEL_POST to process the postmix stream
753 	/// \param[in] left Volume for the left channel, range is 0 (silence)
754 	///                 to 255 (loud)
755 	/// \param[in] right Volume for the right channel, range is 0 (silence)
756 	///                  to 255 (loud)
757 	///
758 	/// \throws SDL2pp::Exception
759 	///
760 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC80
761 	///
762 	////////////////////////////////////////////////////////////
763 	void SetPanning(int channel, Uint8 left, Uint8 right);
764 
765 	////////////////////////////////////////////////////////////
766 	/// \brief Disable stereo panning
767 	///
768 	/// \param[in] channel Channel number to unregister this effect from or
769 	///                    MIX_CHANNEL_POST to unregister from the postmix stream
770 	///
771 	/// \throws SDL2pp::Exception
772 	///
773 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC80
774 	///
775 	////////////////////////////////////////////////////////////
776 	void UnsetPanning(int channel);
777 
778 	////////////////////////////////////////////////////////////
779 	/// \brief Distance attenuation (volume)
780 	///
781 	/// \param[in] channel Channel number to register this effect on or
782 	///                    MIX_CHANNEL_POST to process the postmix stream
783 	/// \param[in] distance Specify the distance from the listener,
784 	///                     from 0 (close/loud) to 255 (far/quiet)
785 	///
786 	/// \throws SDL2pp::Exception
787 	///
788 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC81
789 	///
790 	////////////////////////////////////////////////////////////
791 	void SetDistance(int channel, Uint8 distance);
792 
793 	////////////////////////////////////////////////////////////
794 	/// \brief Disable distance attenuation
795 	///
796 	/// \param[in] channel Channel number to unregister this effect from or
797 	///                    MIX_CHANNEL_POST to unregister from the postmix stream
798 	///
799 	/// \throws SDL2pp::Exception
800 	///
801 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC81
802 	///
803 	////////////////////////////////////////////////////////////
804 	void UnsetDistance(int channel);
805 
806 	////////////////////////////////////////////////////////////
807 	/// \brief Panning (angular) and distance
808 	///
809 	/// \param[in] channel Channel number to register this effect on or
810 	///                    MIX_CHANNEL_POST to process the postmix stream
811 	/// \param[in] angle Direction in relation to forward from 0 to 360 degrees.
812 	///                  Larger angles will be reduced to this range using angles
813 	///                  % 360. 0 = directly in front, 90 = directly to the right
814 	///                  etc.
815 	/// \param[in] distance Specify the distance from the listener,
816 	///                     from 0 (close/loud) to 255 (far/quiet)
817 	///
818 	/// \throws SDL2pp::Exception
819 	///
820 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC82
821 	///
822 	////////////////////////////////////////////////////////////
823 	void SetPosition(int channel, Sint16 angle, Uint8 distance);
824 
825 	////////////////////////////////////////////////////////////
826 	/// \brief Disable panning and distance
827 	///
828 	/// \param[in] channel Channel number to unregister this effect from or
829 	///                    MIX_CHANNEL_POST to unregister from the postmix stream
830 	///
831 	/// \throws SDL2pp::Exception
832 	///
833 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC82
834 	///
835 	////////////////////////////////////////////////////////////
836 	void UnsetPosition(int channel);
837 
838 	////////////////////////////////////////////////////////////
839 	/// \brief Swap stereo left and right
840 	///
841 	/// \param[in] channel Channel number to register this effect on or
842 	///                    MIX_CHANNEL_POST to process the postmix stream
843 	///
844 	/// \throws SDL2pp::Exception
845 	///
846 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC83
847 	///
848 	////////////////////////////////////////////////////////////
849 	void SetReverseStereo(int channel);
850 
851 	////////////////////////////////////////////////////////////
852 	/// \brief Disable stereo swapping
853 	///
854 	/// \param[in] channel Channel number to unregister this effect from or
855 	///                    MIX_CHANNEL_POST to unregister from the postmix stream
856 	///
857 	/// \throws SDL2pp::Exception
858 	///
859 	/// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC83
860 	///
861 	////////////////////////////////////////////////////////////
862 	void UnsetReverseStereo(int channel);
863 
864 	///@}
865 };
866 
867 }
868 
869 #endif
870