1 
2 //          Copyright 2018 - 2021 Michael D. Parker
3 // Distributed under the Boost Software License, Version 1.0.
4 //    (See accompanying file LICENSE_1_0.txt or copy at
5 //          http://www.boost.org/LICENSE_1_0.txt)
6 
7 module bindbc.sdl.mixer;
8 
9 import bindbc.sdl.config;
10 static if(bindSDLMixer):
11 
12 import bindbc.sdl.config;
13 import bindbc.sdl.bind.sdlaudio : AUDIO_S16LSB, SDL_MIX_MAXVOLUME;
14 import bindbc.sdl.bind.sdlerror : SDL_GetError, SDL_SetError, SDL_ClearError;
15 import bindbc.sdl.bind.sdlrwops : SDL_RWops, SDL_RWFromFile;
16 import bindbc.sdl.bind.sdlstdinc : SDL_bool;
17 import bindbc.sdl.bind.sdlversion : SDL_version, SDL_VERSIONNUM;
18 
19 alias Mix_SetError = SDL_SetError;
20 alias Mix_GetError = SDL_GetError;
21 alias Mix_ClearError = SDL_ClearError;
22 
23 enum SDLMixerSupport {
24     noLibrary,
25     badLibrary,
26     sdlMixer200 = 200,
27     sdlMixer201 = 201,
28     sdlMixer202 = 202,
29     sdlMixer204 = 204,
30 }
31 
32 enum ubyte SDL_MIXER_MAJOR_VERSION = 2;
33 enum ubyte SDL_MIXER_MINOR_VERSION = 0;
34 
35 version(SDL_Mixer_204) {
36     enum sdlMixerSupport = SDLMixerSupport.sdlMixer204;
37     enum ubyte SDL_MIXER_PATCHLEVEL = 4;
38 }
39 else version(SDL_Mixer_202) {
40     enum sdlMixerSupport = SDLMixerSupport.sdlMixer202;
41     enum ubyte SDL_MIXER_PATCHLEVEL = 2;
42 }
43 else version(SDL_Mixer_201) {
44     enum sdlMixerSupport = SDLMixerSupport.sdlMixer201;
45     enum ubyte SDL_MIXER_PATCHLEVEL = 1;
46 }
47 else {
48     enum sdlMixerSupport = SDLMixerSupport.sdlMixer200;
49     enum ubyte SDL_MIXER_PATCHLEVEL = 0;
50 }
51 
52 alias MIX_MAJOR_VERSION = SDL_MIXER_MAJOR_VERSION;
53 alias MIX_MINOR_VERSION = SDL_MIXER_MINOR_VERSION;
54 alias MIX_PATCH_LEVEL = SDL_MIXER_PATCHLEVEL;
55 
56 @nogc nothrow void SDL_MIXER_VERSION(SDL_version* X)
57 {
58     X.major     = SDL_MIXER_MAJOR_VERSION;
59     X.minor     = SDL_MIXER_MINOR_VERSION;
60     X.patch     = SDL_MIXER_PATCHLEVEL;
61 }
62 alias SDL_MIX_VERSION = SDL_MIX_MAXVOLUME;
63 
64 // These were implemented in SDL_mixer 2.0.2, but are fine for all versions.
65 enum SDL_MIXER_COMPILEDVERSION = SDL_VERSIONNUM!(SDL_MIXER_MAJOR_VERSION, SDL_MIXER_MINOR_VERSION, SDL_MIXER_PATCHLEVEL);
66 enum SDL_MIXER_VERSION_ATLEAST(ubyte X, ubyte Y, ubyte Z) = SDL_MIXER_COMPILEDVERSION >= SDL_VERSIONNUM!(X, Y, Z);
67 
68 static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer204) {
69     enum Mix_InitFlags {
70         MIX_INIT_FLAC = 0x00000001,
71         MIX_INIT_MOD = 0x00000002,
72         MIX_INIT_MP3 = 0x00000008,
73         MIX_INIT_OGG = 0x00000010,
74         MIX_INIT_MID = 0x00000020,
75         MIX_INIT_OPUS = 0x00000040,
76     }
77 }
78 else static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer202) {
79     enum Mix_InitFlags {
80         MIX_INIT_FLAC = 0x00000001,
81         MIX_INIT_MOD = 0x00000002,
82         MIX_INIT_MP3 = 0x00000008,
83         MIX_INIT_OGG = 0x00000010,
84         MIX_INIT_MID = 0x00000020,
85     }
86 }
87 else {
88     enum Mix_InitFlags {
89         MIX_INIT_FLAC = 0x00000001,
90         MIX_INIT_MOD = 0x00000002,
91         MIX_INIT_MODPLUG = 0x00000004,
92         MIX_INIT_MP3 = 0x00000008,
93         MIX_INIT_OGG = 0x00000010,
94         MIX_INIT_FLUIDSYNTH = 0x00000020,
95     }
96 }
97 mixin(expandEnum!Mix_InitFlags);
98 
99 enum {
100     MIX_CHANNELS              = 8,
101     MIX_DEFAULT_FREQUENCY     = 22050,
102     MIX_DEFAULT_CHANNELS      = 2,
103     MIX_MAX_VOLUME            = 128,
104     MIX_CHANNEL_POST          = -2,
105 }
106 
107 version(LittleEndian) {
108     enum MIX_DEFAULT_FORMAT = AUDIO_S16LSB;
109 } else {
110     enum MIX_DEFAULT_FORMAT = AUDIO_S16MSB;
111 }
112 
113 struct Mix_Chunk {
114    int allocated;
115    ubyte* abuf;
116    uint alen;
117    ubyte volume;
118 }
119 
120 enum Mix_Fading {
121    MIX_NO_FADING,
122    MIX_FADING_OUT,
123    MIX_FADING_IN
124 }
125 mixin(expandEnum!Mix_Fading);
126 
127 static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer204) {
128     enum Mix_MusicType {
129        MUS_NONE,
130        MUS_CMD,
131        MUS_WAV,
132        MUS_MOD,
133        MUS_MID,
134        MUS_OGG,
135        MUS_MP3,
136        MUS_MP3_MAD_UNUSED,
137        MUS_FLAC,
138        MUS_MODPLUG_UNUSED,
139        MUS_OPUS,
140     }
141 }
142 else static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer202) {
143     enum Mix_MusicType {
144        MUS_NONE,
145        MUS_CMD,
146        MUS_WAV,
147        MUS_MOD,
148        MUS_MID,
149        MUS_OGG,
150        MUS_MP3,
151        MUS_MP3_MAD_UNUSED,
152        MUS_FLAC,
153        MUS_MODPLUG_UNUSED,
154     }
155 }
156 else {
157     enum Mix_MusicType {
158        MUS_NONE,
159        MUS_CMD,
160        MUS_WAV,
161        MUS_MOD,
162        MUS_MID,
163        MUS_OGG,
164        MUS_MP3,
165        MUS_MP3_MAD,
166        MUS_FLAC,
167        MUS_MODPLUG,
168     }
169 }
170 mixin(expandEnum!Mix_MusicType);
171 
172 struct Mix_Music;
173 enum MIX_EFFECTSMAXSPEED = "MIX_EFFECTSMAXSPEED";
174 
175 extern(C) nothrow {
176     alias Mix_EffectFunc_t = void function(int,void*,int,void*);
177     alias Mix_EffectDone_t = void function(int,void*);
178 
179     // These aren't in SDL_mixer.h and are just here as a convenient and
180     // visible means to add the proper attributes these callbacks.
181     alias callbackVI = void function(int);
182     alias callbackVPVPUbI = void function(void*,ubyte*,int);
183     alias callbackV = void function();
184     alias callbackIPCPV = int function(const(char*),void*);
185 }
186 
187 @nogc nothrow {
188     Mix_Chunk* Mix_LoadWAV(const(char)* file) {
189         pragma(inline, true);
190         return Mix_LoadWAV_RW(SDL_RWFromFile(file,"rb"),1);
191     }
192 
193     int Mix_PlayChannel(int channel,Mix_Chunk* chunk,int loops) {
194         pragma(inline, true);
195         return Mix_PlayChannelTimed(channel,chunk,loops,-1);
196     }
197 
198     int Mix_FadeInChannel(int channel,Mix_Chunk* chunk,int loops,int ms) {
199         pragma(inline, true);
200         return Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1);
201     }
202 }
203 
204 static if(staticBinding) {
205     extern(C) @nogc nothrow {
206         const(SDL_version)* Mix_Linked_Version();
207         int Mix_Init(int flags);
208         void Mix_Quit();
209         int Mix_OpenAudio(int frequency, ushort format, int channels, int chunksize);
210         int Mix_AllocateChannels(int numchans);
211         int Mix_QuerySpec(int* frequency, ushort* format, int* channels);
212         Mix_Chunk* Mix_LoadWAV_RW(SDL_RWops* src, int freesrc);
213         Mix_Music* Mix_LoadMUS(const(char)* file);
214         Mix_Music* Mix_LoadMUS_RW(SDL_RWops* src, int freesrc);
215         Mix_Music* Mix_LoadMUSType_RW(SDL_RWops* src, Mix_MusicType type, int freesrc);
216         Mix_Chunk* Mix_QuickLoad_WAV(ubyte* mem);
217         Mix_Chunk* Mix_QuickLoad_RAW(ubyte* mem, uint len);
218         void Mix_FreeChunk(Mix_Chunk* chunk);
219         void Mix_FreeMusic(Mix_Music* music);
220         int Mix_GetNumChunkDecoders();
221         const(char)* Mix_GetChunkDecoder(int index);
222         int Mix_GetNumMusicDecoders();
223         const(char)* Mix_GetMusicDecoder(int index);
224         Mix_MusicType Mix_GetMusicType(const(Mix_Music)* music);
225         void Mix_SetPostMix(callbackVPVPUbI mix_func, void* arg);
226         void Mix_HookMusic(callbackVPVPUbI mix_func, void* arg);
227         void Mix_HookMusicFinished(callbackV music_finished);
228         void* Mix_GetMusicHookData();
229         void Mix_ChannelFinished(callbackVI channel_finished);
230         int Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, Mix_EffectDone_t d, void* arg);
231         int Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f);
232         int Mix_UnregisterAllEffects(int channel);
233         int Mix_SetPanning(int channel, ubyte left, ubyte right);
234         int Mix_SetPosition(int channel, short angle, ubyte distance);
235         int Mix_SetDistance(int channel, ubyte distance);
236         int Mix_SetReverseStereo(int channel, int flip);
237         int Mix_ReserveChannels(int num);
238         int Mix_GroupChannel(int which, int tag);
239         int Mix_GroupChannels(int from, int to, int tag);
240         int Mix_GroupAvailable(int tag);
241         int Mix_GroupCount(int tag);
242         int Mix_GroupOldest(int tag);
243         int Mix_GroupNewer(int tag);
244         int Mix_PlayChannelTimed(int channel, Mix_Chunk* chunk, int loops, int ticks);
245         int Mix_PlayMusic(Mix_Music* music, int loops);
246         int Mix_FadeInMusic(Mix_Music* music, int loops, int ms);
247         int Mix_FadeInMusicPos(Mix_Music* music, int loops, int ms, double position);
248         int Mix_FadeInChannelTimed(int channel, Mix_Chunk* chunk, int loops, int ms, int ticks);
249         int Mix_Volume(int channel, int volume);
250         int Mix_VolumeChunk(Mix_Chunk* chunk, int volume);
251         int Mix_VolumeMusic(int volume);
252         int Mix_HaltChannel(int channel);
253         int Mix_HaltGroup(int tag);
254         int Mix_HaltMusic();
255         int Mix_ExpireChannel(int channel, int ticks);
256         int Mix_FadeOutChannel(int which, int ms);
257         int Mix_FadeOutGroup(int tag, int ms);
258         int Mix_FadeOutMusic(int ms);
259         Mix_Fading Mix_FadingMusic();
260         Mix_Fading Mix_FadingChannel(int which);
261         void Mix_Pause(int channel);
262         void Mix_Resume(int channel);
263         int Mix_Paused(int channel);
264         void Mix_PauseMusic();
265         void Mix_ResumeMusic();
266         void Mix_RewindMusic();
267         int Mix_PausedMusic();
268         int Mix_SetMusicPosition(double position);
269         int Mix_Playing(int channel);
270         int Mix_PlayingMusic();
271         int Mix_SetMusicCMD(const(char)* command);
272         int Mix_SetSynchroValue(int value);
273         int Mix_GetSynchroValue();
274         int Mix_SetSoundFonts(const char *paths);
275         const(char)* Mix_GetSoundFonts();
276         int Mix_EachSoundFont(callbackIPCPV function_, void *data);
277         Mix_Chunk* Mix_GetChunk(int channel);
278         void Mix_CloseAudio();
279 
280         static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer202) {
281             int Mix_OpenAudioDevice(int frequency, ushort format, int channels, int chunksize, const(char)* device, int allowed_changes);
282             SDL_bool Mix_HasChunkDecoder(const(char)* name);
283 
284             // Declared in SDL_mixer.h, but not implemented
285             // SDL_bool Mix_HasMusicDecoder(const(char)*);
286         }
287     }
288 }
289 else {
290     import bindbc.loader;
291 
292     extern(C) @nogc nothrow {
293         alias pMix_Linked_Version = const(SDL_version)* function();
294         alias pMix_Init = int function(int flags);
295         alias pMix_Quit = void function();
296         alias pMix_OpenAudio = int function(int frequency, ushort format, int channels, int chunksize);
297         alias pMix_AllocateChannels = int function(int numchans);
298         alias pMix_QuerySpec = int function(int* frequency, ushort* format, int* channels);
299         alias pMix_LoadWAV_RW = Mix_Chunk* function(SDL_RWops* src, int freesrc);
300         alias pMix_LoadMUS = Mix_Music* function(const(char)* file);
301         alias pMix_LoadMUS_RW = Mix_Music* function(SDL_RWops* src, int freesrc);
302         alias pMix_LoadMUSType_RW = Mix_Music* function(SDL_RWops* src, Mix_MusicType type, int freesrc);
303         alias pMix_QuickLoad_WAV = Mix_Chunk* function(ubyte* mem);
304         alias pMix_QuickLoad_RAW = Mix_Chunk* function(ubyte* mem, uint len);
305         alias pMix_FreeChunk = void function(Mix_Chunk* chunk);
306         alias pMix_FreeMusic = void function(Mix_Music* music);
307         alias pMix_GetNumChunkDecoders = int function();
308         alias pMix_GetChunkDecoder = const(char)* function(int index);
309         alias pMix_GetNumMusicDecoders = int function();
310         alias pMix_GetMusicDecoder = const(char)* function(int index);
311         alias pMix_GetMusicType = Mix_MusicType function(const(Mix_Music)* music);
312         alias pMix_SetPostMix = void function(callbackVPVPUbI mix_func, void* arg);
313         alias pMix_HookMusic = void function(callbackVPVPUbI mix_func, void* arg);
314         alias pMix_HookMusicFinished = void function(callbackV music_finished);
315         alias pMix_GetMusicHookData = void* function();
316         alias pMix_ChannelFinished = void function(callbackVI channel_finished);
317         alias pMix_RegisterEffect = int function(int chan, Mix_EffectFunc_t f, Mix_EffectDone_t d, void* arg);
318         alias pMix_UnregisterEffect = int function(int channel, Mix_EffectFunc_t f);
319         alias pMix_UnregisterAllEffects = int function(int channel);
320         alias pMix_SetPanning = int function(int channel, ubyte left, ubyte right);
321         alias pMix_SetPosition = int function(int channel, short angle, ubyte distance);
322         alias pMix_SetDistance = int function(int channel, ubyte distance);
323         alias pMix_SetReverseStereo = int function(int channel, int flip);
324         alias pMix_ReserveChannels = int function(int num);
325         alias pMix_GroupChannel = int function(int which, int tag);
326         alias pMix_GroupChannels = int function(int from, int to, int tag);
327         alias pMix_GroupAvailable = int function(int tag);
328         alias pMix_GroupCount = int function(int tag);
329         alias pMix_GroupOldest = int function(int tag);
330         alias pMix_GroupNewer = int function(int tag);
331         alias pMix_PlayChannelTimed = int function(int channel, Mix_Chunk* chunk, int loops, int ticks);
332         alias pMix_PlayMusic = int function(Mix_Music* music, int loops);
333         alias pMix_FadeInMusic = int function(Mix_Music* music, int loops, int ms);
334         alias pMix_FadeInMusicPos = int function(Mix_Music* music, int loops, int ms, double position);
335         alias pMix_FadeInChannelTimed = int function(int channel, Mix_Chunk* chunk, int loops, int ms, int ticks);
336         alias pMix_Volume = int function(int channel, int volume);
337         alias pMix_VolumeChunk = int function(Mix_Chunk* chunk, int volume);
338         alias pMix_VolumeMusic = int function(int volume);
339         alias pMix_HaltChannel = int function(int channel);
340         alias pMix_HaltGroup = int function(int tag);
341         alias pMix_HaltMusic = int function();
342         alias pMix_ExpireChannel = int function(int channel, int ticks);
343         alias pMix_FadeOutChannel = int function(int which, int ms);
344         alias pMix_FadeOutGroup = int function(int tag, int ms);
345         alias pMix_FadeOutMusic = int function(int ms);
346         alias pMix_FadingMusic = Mix_Fading function();
347         alias pMix_FadingChannel = Mix_Fading function(int which);
348         alias pMix_Pause = void function(int channel);
349         alias pMix_Resume = void function(int channel);
350         alias pMix_Paused = int function(int channel);
351         alias pMix_PauseMusic = void function();
352         alias pMix_ResumeMusic = void function();
353         alias pMix_RewindMusic = void function();
354         alias pMix_PausedMusic = int function();
355         alias pMix_SetMusicPosition = int function(double position);
356         alias pMix_Playing = int function(int channel);
357         alias pMix_PlayingMusic = int function();
358         alias pMix_SetMusicCMD = int function(const(char)* command);
359         alias pMix_SetSynchroValue = int function(int value);
360         alias pMix_GetSynchroValue = int function();
361         alias pMix_SetSoundFonts = int function(const char *paths);
362         alias pMix_GetSoundFonts = const(char)* function();
363         alias pMix_EachSoundFont = int function(callbackIPCPV function_, void *data);
364         alias pMix_GetChunk = Mix_Chunk* function(int channel);
365         alias pMix_CloseAudio = void function();
366     }
367 
368     __gshared {
369         pMix_Linked_Version Mix_Linked_Version;
370         pMix_Init Mix_Init;
371         pMix_Quit Mix_Quit;
372         pMix_OpenAudio Mix_OpenAudio;
373         pMix_AllocateChannels Mix_AllocateChannels;
374         pMix_QuerySpec Mix_QuerySpec;
375         pMix_LoadWAV_RW Mix_LoadWAV_RW;
376         pMix_LoadMUS Mix_LoadMUS;
377         pMix_LoadMUS_RW Mix_LoadMUS_RW;
378         pMix_LoadMUSType_RW Mix_LoadMUSType_RW;
379         pMix_QuickLoad_WAV Mix_QuickLoad_WAV;
380         pMix_QuickLoad_RAW Mix_QuickLoad_RAW;
381         pMix_FreeChunk Mix_FreeChunk;
382         pMix_FreeMusic Mix_FreeMusic;
383         pMix_GetNumChunkDecoders Mix_GetNumChunkDecoders;
384         pMix_GetChunkDecoder Mix_GetChunkDecoder;
385         pMix_GetNumMusicDecoders Mix_GetNumMusicDecoders;
386         pMix_GetMusicDecoder Mix_GetMusicDecoder;
387         pMix_GetMusicType Mix_GetMusicType;
388         pMix_SetPostMix Mix_SetPostMix;
389         pMix_HookMusic Mix_HookMusic;
390         pMix_HookMusicFinished Mix_HookMusicFinished;
391         pMix_GetMusicHookData Mix_GetMusicHookData;
392         pMix_ChannelFinished Mix_ChannelFinished;
393         pMix_RegisterEffect Mix_RegisterEffect;
394         pMix_UnregisterEffect Mix_UnregisterEffect;
395         pMix_UnregisterAllEffects Mix_UnregisterAllEffects;
396         pMix_SetPanning Mix_SetPanning;
397         pMix_SetPosition Mix_SetPosition;
398         pMix_SetDistance Mix_SetDistance;
399         pMix_SetReverseStereo Mix_SetReverseStereo;
400         pMix_ReserveChannels Mix_ReserveChannels;
401         pMix_GroupChannel Mix_GroupChannel;
402         pMix_GroupChannels Mix_GroupChannels;
403         pMix_GroupAvailable Mix_GroupAvailable;
404         pMix_GroupCount Mix_GroupCount;
405         pMix_GroupOldest Mix_GroupOldest;
406         pMix_GroupNewer Mix_GroupNewer;
407         pMix_PlayChannelTimed Mix_PlayChannelTimed;
408         pMix_PlayMusic Mix_PlayMusic;
409         pMix_FadeInMusic Mix_FadeInMusic;
410         pMix_FadeInMusicPos Mix_FadeInMusicPos;
411         pMix_FadeInChannelTimed Mix_FadeInChannelTimed;
412         pMix_Volume Mix_Volume;
413         pMix_VolumeChunk Mix_VolumeChunk;
414         pMix_VolumeMusic Mix_VolumeMusic;
415         pMix_HaltChannel Mix_HaltChannel;
416         pMix_HaltGroup Mix_HaltGroup;
417         pMix_HaltMusic Mix_HaltMusic;
418         pMix_ExpireChannel Mix_ExpireChannel;
419         pMix_FadeOutChannel Mix_FadeOutChannel;
420         pMix_FadeOutGroup Mix_FadeOutGroup;
421         pMix_FadeOutMusic Mix_FadeOutMusic;
422         pMix_FadingMusic Mix_FadingMusic;
423         pMix_FadingChannel Mix_FadingChannel;
424         pMix_Pause Mix_Pause;
425         pMix_Resume Mix_Resume;
426         pMix_Paused Mix_Paused;
427         pMix_PauseMusic Mix_PauseMusic;
428         pMix_ResumeMusic Mix_ResumeMusic;
429         pMix_RewindMusic Mix_RewindMusic;
430         pMix_PausedMusic Mix_PausedMusic;
431         pMix_SetMusicPosition Mix_SetMusicPosition;
432         pMix_Playing Mix_Playing;
433         pMix_PlayingMusic Mix_PlayingMusic;
434         pMix_SetMusicCMD Mix_SetMusicCMD;
435         pMix_SetSynchroValue Mix_SetSynchroValue;
436         pMix_GetSynchroValue Mix_GetSynchroValue;
437         pMix_SetSoundFonts Mix_SetSoundFonts;
438         pMix_GetSoundFonts Mix_GetSoundFonts;
439         pMix_EachSoundFont Mix_EachSoundFont;
440         pMix_GetChunk Mix_GetChunk;
441         pMix_CloseAudio Mix_CloseAudio;
442     }
443 
444 
445     static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer202) {
446         extern(C) @nogc nothrow {
447             alias pMix_OpenAudioDevice = int function(int frequency, ushort format, int channels, int chunksize, const(char)* device, int allowed_changes);
448             alias pMix_HasChunkDecoder = SDL_bool function(const(char)* name);
449 
450             // Declared in SDL_mixer.h, but not implemented
451             //alias pMix_HasMusicDecoder = SDL_bool function(const(char)*);
452         }
453 
454         __gshared {
455             pMix_OpenAudioDevice Mix_OpenAudioDevice;
456             pMix_HasChunkDecoder Mix_HasChunkDecoder;
457             //pMix_HasMusicDecoder Mix_HasMusicDecoder;
458         }
459     }
460 
461     private {
462         SharedLib lib;
463         SDLMixerSupport loadedVersion;
464     }
465 
466 @nogc nothrow:
467     void unloadSDLMixer()
468     {
469         if(lib != invalidHandle) {
470             lib.unload();
471         }
472     }
473 
474     SDLMixerSupport loadedSDLMixerVersion() { return loadedVersion; }
475 
476     bool isSDLMixerLoaded()
477     {
478         return  lib != invalidHandle;
479     }
480 
481 
482     SDLMixerSupport loadSDLMixer()
483     {
484         version(Windows) {
485             const(char)[][1] libNames = ["SDL2_mixer.dll"];
486         }
487         else version(OSX) {
488             const(char)[][6] libNames = [
489                 "libSDL2_mixer.dylib",
490                 "/usr/local/lib/libSDL2_mixer.dylib",
491                 "../Frameworks/SDL2_mixer.framework/SDL2_mixer",
492                 "/Library/Frameworks/SDL2_mixer.framework/SDL2_mixer",
493                 "/System/Library/Frameworks/SDL2_mixer.framework/SDL2_mixer",
494                 "/opt/local/lib/libSDL2_mixer.dylib"
495             ];
496         }
497         else version(Posix) {
498             const(char)[][6] libNames = [
499                 "libSDL2_mixer.so",
500                 "/usr/local/lib/libSDL2_mixer.so",
501                 "libSDL2-2.0_mixer.so",
502                 "/usr/local/lib/libSDL2-2.0_mixer.so",
503                 "libSDL2-2.0_mixer.so.0",
504                 "/usr/local/lib/libSDL2-2.0_mixer.so.0"
505             ];
506         }
507         else static assert(0, "bindbc-sdl is not yet supported on this platform.");
508 
509         SDLMixerSupport ret;
510         foreach(name; libNames) {
511             ret = loadSDLMixer(name.ptr);
512             if(ret != SDLMixerSupport.noLibrary) break;
513         }
514         return ret;
515     }
516 
517     SDLMixerSupport loadSDLMixer(const(char)* libName)
518     {
519         lib = load(libName);
520         if(lib == invalidHandle) {
521             return SDLMixerSupport.noLibrary;
522         }
523 
524         auto errCount = errorCount();
525         loadedVersion = SDLMixerSupport.badLibrary;
526 
527         lib.bindSymbol(cast(void**)&Mix_Linked_Version,"Mix_Linked_Version");
528         lib.bindSymbol(cast(void**)&Mix_Init,"Mix_Init");
529         lib.bindSymbol(cast(void**)&Mix_Quit,"Mix_Quit");
530         lib.bindSymbol(cast(void**)&Mix_OpenAudio,"Mix_OpenAudio");
531         lib.bindSymbol(cast(void**)&Mix_AllocateChannels,"Mix_AllocateChannels");
532         lib.bindSymbol(cast(void**)&Mix_QuerySpec,"Mix_QuerySpec");
533         lib.bindSymbol(cast(void**)&Mix_LoadWAV_RW,"Mix_LoadWAV_RW");
534         lib.bindSymbol(cast(void**)&Mix_LoadMUS,"Mix_LoadMUS");
535         lib.bindSymbol(cast(void**)&Mix_LoadMUS_RW,"Mix_LoadMUS_RW");
536         lib.bindSymbol(cast(void**)&Mix_LoadMUSType_RW,"Mix_LoadMUSType_RW");
537         lib.bindSymbol(cast(void**)&Mix_QuickLoad_WAV,"Mix_QuickLoad_WAV");
538         lib.bindSymbol(cast(void**)&Mix_QuickLoad_RAW,"Mix_QuickLoad_RAW");
539         lib.bindSymbol(cast(void**)&Mix_FreeChunk,"Mix_FreeChunk");
540         lib.bindSymbol(cast(void**)&Mix_FreeMusic,"Mix_FreeMusic");
541         lib.bindSymbol(cast(void**)&Mix_GetNumChunkDecoders,"Mix_GetNumChunkDecoders");
542         lib.bindSymbol(cast(void**)&Mix_GetChunkDecoder,"Mix_GetChunkDecoder");
543         lib.bindSymbol(cast(void**)&Mix_GetNumMusicDecoders,"Mix_GetNumMusicDecoders");
544         lib.bindSymbol(cast(void**)&Mix_GetMusicDecoder,"Mix_GetMusicDecoder");
545         lib.bindSymbol(cast(void**)&Mix_GetMusicType,"Mix_GetMusicType");
546         lib.bindSymbol(cast(void**)&Mix_SetPostMix,"Mix_SetPostMix");
547         lib.bindSymbol(cast(void**)&Mix_HookMusic,"Mix_HookMusic");
548         lib.bindSymbol(cast(void**)&Mix_HookMusicFinished,"Mix_HookMusicFinished");
549         lib.bindSymbol(cast(void**)&Mix_GetMusicHookData,"Mix_GetMusicHookData");
550         lib.bindSymbol(cast(void**)&Mix_ChannelFinished,"Mix_ChannelFinished");
551         lib.bindSymbol(cast(void**)&Mix_RegisterEffect,"Mix_RegisterEffect");
552         lib.bindSymbol(cast(void**)&Mix_UnregisterEffect,"Mix_UnregisterEffect");
553         lib.bindSymbol(cast(void**)&Mix_UnregisterAllEffects,"Mix_UnregisterAllEffects");
554         lib.bindSymbol(cast(void**)&Mix_SetPanning,"Mix_SetPanning");
555         lib.bindSymbol(cast(void**)&Mix_SetPosition,"Mix_SetPosition");
556         lib.bindSymbol(cast(void**)&Mix_SetDistance,"Mix_SetDistance");
557         lib.bindSymbol(cast(void**)&Mix_SetReverseStereo,"Mix_SetReverseStereo");
558         lib.bindSymbol(cast(void**)&Mix_ReserveChannels,"Mix_ReserveChannels");
559         lib.bindSymbol(cast(void**)&Mix_GroupChannel,"Mix_GroupChannel");
560         lib.bindSymbol(cast(void**)&Mix_GroupChannels,"Mix_GroupChannels");
561         lib.bindSymbol(cast(void**)&Mix_GroupAvailable,"Mix_GroupAvailable");
562         lib.bindSymbol(cast(void**)&Mix_GroupCount,"Mix_GroupCount");
563         lib.bindSymbol(cast(void**)&Mix_GroupOldest,"Mix_GroupOldest");
564         lib.bindSymbol(cast(void**)&Mix_GroupNewer,"Mix_GroupNewer");
565         lib.bindSymbol(cast(void**)&Mix_PlayChannelTimed,"Mix_PlayChannelTimed");
566         lib.bindSymbol(cast(void**)&Mix_PlayMusic,"Mix_PlayMusic");
567         lib.bindSymbol(cast(void**)&Mix_FadeInMusic,"Mix_FadeInMusic");
568         lib.bindSymbol(cast(void**)&Mix_FadeInMusicPos,"Mix_FadeInMusicPos");
569         lib.bindSymbol(cast(void**)&Mix_FadeInChannelTimed,"Mix_FadeInChannelTimed");
570         lib.bindSymbol(cast(void**)&Mix_Volume,"Mix_Volume");
571         lib.bindSymbol(cast(void**)&Mix_VolumeChunk,"Mix_VolumeChunk");
572         lib.bindSymbol(cast(void**)&Mix_VolumeMusic,"Mix_VolumeMusic");
573         lib.bindSymbol(cast(void**)&Mix_HaltChannel,"Mix_HaltChannel");
574         lib.bindSymbol(cast(void**)&Mix_HaltGroup,"Mix_HaltGroup");
575         lib.bindSymbol(cast(void**)&Mix_HaltMusic,"Mix_HaltMusic");
576         lib.bindSymbol(cast(void**)&Mix_ExpireChannel,"Mix_ExpireChannel");
577         lib.bindSymbol(cast(void**)&Mix_FadeOutChannel,"Mix_FadeOutChannel");
578         lib.bindSymbol(cast(void**)&Mix_FadeOutGroup,"Mix_FadeOutGroup");
579         lib.bindSymbol(cast(void**)&Mix_FadeOutMusic,"Mix_FadeOutMusic");
580         lib.bindSymbol(cast(void**)&Mix_FadingMusic,"Mix_FadingMusic");
581         lib.bindSymbol(cast(void**)&Mix_FadingChannel,"Mix_FadingChannel");
582         lib.bindSymbol(cast(void**)&Mix_Pause,"Mix_Pause");
583         lib.bindSymbol(cast(void**)&Mix_Resume,"Mix_Resume");
584         lib.bindSymbol(cast(void**)&Mix_Paused,"Mix_Paused");
585         lib.bindSymbol(cast(void**)&Mix_PauseMusic,"Mix_PauseMusic");
586         lib.bindSymbol(cast(void**)&Mix_ResumeMusic,"Mix_ResumeMusic");
587         lib.bindSymbol(cast(void**)&Mix_RewindMusic,"Mix_RewindMusic");
588         lib.bindSymbol(cast(void**)&Mix_PausedMusic,"Mix_PausedMusic");
589         lib.bindSymbol(cast(void**)&Mix_SetMusicPosition,"Mix_SetMusicPosition");
590         lib.bindSymbol(cast(void**)&Mix_Playing,"Mix_Playing");
591         lib.bindSymbol(cast(void**)&Mix_PlayingMusic,"Mix_PlayingMusic");
592         lib.bindSymbol(cast(void**)&Mix_SetMusicCMD,"Mix_SetMusicCMD");
593         lib.bindSymbol(cast(void**)&Mix_SetSynchroValue,"Mix_SetSynchroValue");
594         lib.bindSymbol(cast(void**)&Mix_GetSynchroValue,"Mix_GetSynchroValue");
595         lib.bindSymbol(cast(void**)&Mix_SetSoundFonts,"Mix_SetSoundFonts");
596         lib.bindSymbol(cast(void**)&Mix_GetSoundFonts,"Mix_GetSoundFonts");
597         lib.bindSymbol(cast(void**)&Mix_EachSoundFont,"Mix_EachSoundFont");
598         lib.bindSymbol(cast(void**)&Mix_GetChunk,"Mix_GetChunk");
599         lib.bindSymbol(cast(void**)&Mix_CloseAudio,"Mix_CloseAudio");
600 
601         if(errorCount() != errCount) return SDLMixerSupport.badLibrary;
602         else loadedVersion = (sdlMixerSupport >= SDLMixerSupport.sdlMixer201) ? SDLMixerSupport.sdlMixer201 : SDLMixerSupport.sdlMixer200;
603 
604         static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer202) {
605             lib.bindSymbol(cast(void**)&Mix_OpenAudioDevice,"Mix_OpenAudioDevice");
606             lib.bindSymbol(cast(void**)&Mix_HasChunkDecoder,"Mix_HasChunkDecoder");
607 
608             if(errorCount() != errCount) return SDLMixerSupport.badLibrary;
609             else loadedVersion = (sdlMixerSupport >= SDLMixerSupport.sdlMixer204) ? SDLMixerSupport.sdlMixer204 : SDLMixerSupport.sdlMixer202;
610         }
611 
612         return loadedVersion;
613     }
614 }