1 
2 //          Copyright Michael D. Parker 2018.
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 callbackI = void function(int);
182     alias callbackVUi8I = void function(void*,ubyte*,int);
183     alias callbackN = void function();
184 }
185 
186 @nogc nothrow {
187     Mix_Chunk* Mix_LoadWAV(const(char)* file) {
188         pragma(inline, true);
189         return Mix_LoadWAV_RW(SDL_RWFromFile(file,"rb"),1);
190     }
191 
192     int Mix_PlayChannel(int channel,Mix_Chunk* chunk,int loops) {
193         pragma(inline, true);
194         return Mix_PlayChannelTimed(channel,chunk,loops,-1);
195     }
196 
197     int Mix_FadeInChannel(int channel,Mix_Chunk* chunk,int loops,int ms) {
198         pragma(inline, true);
199         return Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1);
200     }
201 }
202 
203 static if(staticBinding) {
204     extern(C) @nogc nothrow {
205         const(SDL_version)* Mix_Linked_Version();
206         int Mix_Init(int);
207         void Mix_Quit();
208         int Mix_OpenAudio(int,ushort,int,int);
209         int Mix_AllocateChannels(int);
210         int Mix_QuerySpec(int*,ushort*,int*);
211         Mix_Chunk* Mix_LoadWAV_RW(SDL_RWops*,int);
212         Mix_Music* Mix_LoadMUS(const(char)*);
213         Mix_Music* Mix_LoadMUS_RW(SDL_RWops*,int);
214         Mix_Music* Mix_LoadMUSType_RW(SDL_RWops*,Mix_MusicType,int);
215         Mix_Chunk* Mix_QuickLoad_WAV(ubyte*);
216         Mix_Chunk* Mix_QuickLoad_RAW(ubyte*,uint);
217         void Mix_FreeChunk(Mix_Chunk*);
218         void Mix_FreeMusic(Mix_Music*);
219         int Mix_GetNumChunkDecoders();
220         const(char)* Mix_GetChunkDecoder(int);
221         int Mix_GetNumMusicDecoders();
222         const(char)* Mix_GetMusicDecoder(int);
223         Mix_MusicType Mix_GetMusicType(const(Mix_Music)*);
224         void Mix_SetPostMix(callbackVUi8I,void*);
225         void Mix_HookMusic(callbackVUi8I,void*);
226         void Mix_HookMusicFinished(callbackN);
227         void* Mix_GetMusicHookData();
228         void Mix_ChannelFinished(callbackI);
229         int Mix_RegisterEffect(int,Mix_EffectFunc_t,Mix_EffectDone_t,void*);
230         int Mix_UnregisterEffect(int,Mix_EffectFunc_t);
231         int Mix_UnregisterAllEffects(int);
232         int Mix_SetPanning(int,ubyte,ubyte);
233         int Mix_SetPosition(int,short,ubyte);
234         int Mix_SetDistance(int,ubyte);
235         int Mix_SetReverseStereo(int,int);
236         int Mix_ReserveChannels(int);
237         int Mix_GroupChannel(int,int);
238         int Mix_GroupChannels(int,int,int);
239         int Mix_GroupAvailable(int);
240         int Mix_GroupCount(int);
241         int Mix_GroupOldest(int);
242         int Mix_GroupNewer(int);
243         int Mix_PlayChannelTimed(int,Mix_Chunk*,int,int);
244         int Mix_PlayMusic(Mix_Music*,int);
245         int Mix_FadeInMusic(Mix_Music*,int,int);
246         int Mix_FadeInMusicPos(Mix_Music*,int,int,double);
247         int Mix_FadeInChannelTimed(int,Mix_Chunk*,int,int,int);
248         int Mix_Volume(int,int);
249         int Mix_VolumeChunk(Mix_Chunk*,int);
250         int Mix_VolumeMusic(int);
251         int Mix_HaltChannel(int);
252         int Mix_HaltGroup(int);
253         int Mix_HaltMusic();
254         int Mix_ExpireChannel(int,int);
255         int Mix_FadeOutChannel(int,int);
256         int Mix_FadeOutGroup(int,int);
257         int Mix_FadeOutMusic(int);
258         Mix_Fading Mix_FadingMusic();
259         Mix_Fading Mix_FadingChannel(int);
260         void Mix_Pause(int);
261         void Mix_Resume(int);
262         int Mix_Paused(int);
263         void Mix_PauseMusic();
264         void Mix_ResumeMusic();
265         void Mix_RewindMusic();
266         int Mix_PausedMusic();
267         int Mix_SetMusicPosition(double);
268         int Mix_Playing(int);
269         int Mix_PlayingMusic();
270         int Mix_SetMusicCMD(in char*);
271         int Mix_SetSynchroValue(int);
272         int Mix_GetSynchroValue();
273         Mix_Chunk* Mix_GetChunk(int);
274         void Mix_CloseAudio();
275 
276         static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer202) {
277             int Mix_OpenAudioDevice(int,ushort,int,int,const(char)*,int);
278             SDL_bool Mix_HasChunkDecoder(const(char)*);
279 
280             // Declared in SDL_mixer.h, but not implemented
281             // SDL_bool Mix_HasMusicDecoder(const(char)*);
282         }
283     }
284 }
285 else {
286     import bindbc.loader;
287 
288     extern(C) @nogc nothrow {
289         alias pMix_Linked_Version = const(SDL_version)* function();
290         alias pMix_Init = int function(int);
291         alias pMix_Quit = void function();
292         alias pMix_OpenAudio = int function(int,ushort,int,int);
293         alias pMix_AllocateChannels = int function(int);
294         alias pMix_QuerySpec = int function(int*,ushort*,int*);
295         alias pMix_LoadWAV_RW = Mix_Chunk* function(SDL_RWops*,int);
296         alias pMix_LoadMUS = Mix_Music* function(const(char)*);
297         alias pMix_LoadMUS_RW = Mix_Music* function(SDL_RWops*,int);
298         alias pMix_LoadMUSType_RW = Mix_Music* function(SDL_RWops*,Mix_MusicType,int);
299         alias pMix_QuickLoad_WAV = Mix_Chunk* function(ubyte*);
300         alias pMix_QuickLoad_RAW = Mix_Chunk* function(ubyte*,uint);
301         alias pMix_FreeChunk = void function(Mix_Chunk*);
302         alias pMix_FreeMusic = void function(Mix_Music*);
303         alias pMix_GetNumChunkDecoders = int function();
304         alias pMix_GetChunkDecoder = const(char)* function(int);
305         alias pMix_GetNumMusicDecoders = int function();
306         alias pMix_GetMusicDecoder = const(char)* function(int);
307         alias pMix_GetMusicType = Mix_MusicType function(const(Mix_Music)*);
308         alias pMix_SetPostMix = void function(callbackVUi8I,void*);
309         alias pMix_HookMusic = void function(callbackVUi8I,void*);
310         alias pMix_HookMusicFinished = void function(callbackN);
311         alias pMix_GetMusicHookData = void* function();
312         alias pMix_ChannelFinished = void function(callbackI);
313         alias pMix_RegisterEffect = int function(int,Mix_EffectFunc_t,Mix_EffectDone_t,void*);
314         alias pMix_UnregisterEffect = int function(int,Mix_EffectFunc_t);
315         alias pMix_UnregisterAllEffects = int function(int);
316         alias pMix_SetPanning = int function(int,ubyte,ubyte);
317         alias pMix_SetPosition = int function(int,short,ubyte);
318         alias pMix_SetDistance = int function(int,ubyte);
319         alias pMix_SetReverseStereo = int function(int,int);
320         alias pMix_ReserveChannels = int function(int);
321         alias pMix_GroupChannel = int function(int,int);
322         alias pMix_GroupChannels = int function(int,int,int);
323         alias pMix_GroupAvailable = int function(int);
324         alias pMix_GroupCount = int function(int);
325         alias pMix_GroupOldest = int function(int);
326         alias pMix_GroupNewer = int function(int);
327         alias pMix_PlayChannelTimed = int function(int,Mix_Chunk*,int,int);
328         alias pMix_PlayMusic = int function(Mix_Music*,int);
329         alias pMix_FadeInMusic = int function(Mix_Music*,int,int);
330         alias pMix_FadeInMusicPos = int function(Mix_Music*,int,int,double);
331         alias pMix_FadeInChannelTimed = int function(int,Mix_Chunk*,int,int,int);
332         alias pMix_Volume = int function(int,int);
333         alias pMix_VolumeChunk = int function(Mix_Chunk*,int);
334         alias pMix_VolumeMusic = int function(int);
335         alias pMix_HaltChannel = int function(int);
336         alias pMix_HaltGroup = int function(int);
337         alias pMix_HaltMusic = int function();
338         alias pMix_ExpireChannel = int function(int,int);
339         alias pMix_FadeOutChannel = int function(int,int);
340         alias pMix_FadeOutGroup = int function(int,int);
341         alias pMix_FadeOutMusic = int function(int);
342         alias pMix_FadingMusic = Mix_Fading function();
343         alias pMix_FadingChannel = Mix_Fading function(int);
344         alias pMix_Pause = void function(int);
345         alias pMix_Resume = void function(int);
346         alias pMix_Paused = int function(int);
347         alias pMix_PauseMusic = void function();
348         alias pMix_ResumeMusic = void function();
349         alias pMix_RewindMusic = void function();
350         alias pMix_PausedMusic = int function();
351         alias pMix_SetMusicPosition = int function(double);
352         alias pMix_Playing = int function(int);
353         alias pMix_PlayingMusic = int function();
354         alias pMix_SetMusicCMD = int function(in char*);
355         alias pMix_SetSynchroValue = int function(int);
356         alias pMix_GetSynchroValue = int function();
357         alias pMix_GetChunk = Mix_Chunk* function(int);
358         alias pMix_CloseAudio = void function();
359     }
360 
361     __gshared {
362         pMix_Linked_Version Mix_Linked_Version;
363         pMix_Init Mix_Init;
364         pMix_Quit Mix_Quit;
365         pMix_OpenAudio Mix_OpenAudio;
366         pMix_AllocateChannels Mix_AllocateChannels;
367         pMix_QuerySpec Mix_QuerySpec;
368         pMix_LoadWAV_RW Mix_LoadWAV_RW;
369         pMix_LoadMUS Mix_LoadMUS;
370         pMix_LoadMUS_RW Mix_LoadMUS_RW;
371         pMix_LoadMUSType_RW Mix_LoadMUSType_RW;
372         pMix_QuickLoad_WAV Mix_QuickLoad_WAV;
373         pMix_QuickLoad_RAW Mix_QuickLoad_RAW;
374         pMix_FreeChunk Mix_FreeChunk;
375         pMix_FreeMusic Mix_FreeMusic;
376         pMix_GetNumChunkDecoders Mix_GetNumChunkDecoders;
377         pMix_GetChunkDecoder Mix_GetChunkDecoder;
378         pMix_GetNumMusicDecoders Mix_GetNumMusicDecoders;
379         pMix_GetMusicDecoder Mix_GetMusicDecoder;
380         pMix_GetMusicType Mix_GetMusicType;
381         pMix_SetPostMix Mix_SetPostMix;
382         pMix_HookMusic Mix_HookMusic;
383         pMix_HookMusicFinished Mix_HookMusicFinished;
384         pMix_GetMusicHookData Mix_GetMusicHookData;
385         pMix_ChannelFinished Mix_ChannelFinished;
386         pMix_RegisterEffect Mix_RegisterEffect;
387         pMix_UnregisterEffect Mix_UnregisterEffect;
388         pMix_UnregisterAllEffects Mix_UnregisterAllEffects;
389         pMix_SetPanning Mix_SetPanning;
390         pMix_SetPosition Mix_SetPosition;
391         pMix_SetDistance Mix_SetDistance;
392         pMix_SetReverseStereo Mix_SetReverseStereo;
393         pMix_ReserveChannels Mix_ReserveChannels;
394         pMix_GroupChannel Mix_GroupChannel;
395         pMix_GroupChannels Mix_GroupChannels;
396         pMix_GroupAvailable Mix_GroupAvailable;
397         pMix_GroupCount Mix_GroupCount;
398         pMix_GroupOldest Mix_GroupOldest;
399         pMix_GroupNewer Mix_GroupNewer;
400         pMix_PlayChannelTimed Mix_PlayChannelTimed;
401         pMix_PlayMusic Mix_PlayMusic;
402         pMix_FadeInMusic Mix_FadeInMusic;
403         pMix_FadeInMusicPos Mix_FadeInMusicPos;
404         pMix_FadeInChannelTimed Mix_FadeInChannelTimed;
405         pMix_Volume Mix_Volume;
406         pMix_VolumeChunk Mix_VolumeChunk;
407         pMix_VolumeMusic Mix_VolumeMusic;
408         pMix_HaltChannel Mix_HaltChannel;
409         pMix_HaltGroup Mix_HaltGroup;
410         pMix_HaltMusic Mix_HaltMusic;
411         pMix_ExpireChannel Mix_ExpireChannel;
412         pMix_FadeOutChannel Mix_FadeOutChannel;
413         pMix_FadeOutGroup Mix_FadeOutGroup;
414         pMix_FadeOutMusic Mix_FadeOutMusic;
415         pMix_FadingMusic Mix_FadingMusic;
416         pMix_FadingChannel Mix_FadingChannel;
417         pMix_Pause Mix_Pause;
418         pMix_Resume Mix_Resume;
419         pMix_Paused Mix_Paused;
420         pMix_PauseMusic Mix_PauseMusic;
421         pMix_ResumeMusic Mix_ResumeMusic;
422         pMix_RewindMusic Mix_RewindMusic;
423         pMix_PausedMusic Mix_PausedMusic;
424         pMix_SetMusicPosition Mix_SetMusicPosition;
425         pMix_Playing Mix_Playing;
426         pMix_PlayingMusic Mix_PlayingMusic;
427         pMix_SetMusicCMD Mix_SetMusicCMD;
428         pMix_SetSynchroValue Mix_SetSynchroValue;
429         pMix_GetSynchroValue Mix_GetSynchroValue;
430         pMix_GetChunk Mix_GetChunk;
431         pMix_CloseAudio Mix_CloseAudio;
432     }
433 
434 
435     static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer202) {
436         extern(C) @nogc nothrow {
437             alias pMix_OpenAudioDevice = int function(int,ushort,int,int,const(char)*,int);
438             alias pMix_HasChunkDecoder = SDL_bool function(const(char)*);
439 
440             // Declared in SDL_mixer.h, but not implemented
441             //alias pMix_HasMusicDecoder = SDL_bool function(const(char)*);
442         }
443 
444         __gshared {
445             pMix_OpenAudioDevice Mix_OpenAudioDevice;
446             pMix_HasChunkDecoder Mix_HasChunkDecoder;
447             //pMix_HasMusicDecoder Mix_HasMusicDecoder;
448         }
449     }
450 
451     private {
452         SharedLib lib;
453         SDLMixerSupport loadedVersion;
454     }
455 
456     void unloadSDLMixer()
457     {
458         if(lib != invalidHandle) {
459             lib.unload();
460         }
461     }
462 
463     SDLMixerSupport loadedSDLMixerVersion() { return loadedVersion; }
464 
465     bool isSDLMixerLoaded()
466     {
467         return  lib != invalidHandle;
468     }
469 
470 
471     SDLMixerSupport loadSDLMixer()
472     {
473         version(Windows) {
474             const(char)[][1] libNames = ["SDL2_mixer.dll"];
475         }
476         else version(OSX) {
477             const(char)[][6] libNames = [
478                 "libSDL2_mixer.dylib",
479                 "/usr/local/lib/libSDL2_mixer.dylib",
480                 "../Frameworks/SDL2_mixer.framework/SDL2_mixer",
481                 "/Library/Frameworks/SDL2_mixer.framework/SDL2_mixer",
482                 "/System/Library/Frameworks/SDL2_mixer.framework/SDL2_mixer",
483                 "/opt/local/lib/libSDL2_mixer.dylib"
484             ];
485         }
486         else version(Posix) {
487             const(char)[][6] libNames = [
488                 "libSDL2_mixer.so",
489                 "/usr/local/lib/libSDL2_mixer.so",
490                 "libSDL2-2.0_mixer.so",
491                 "/usr/local/lib/libSDL2-2.0_mixer.so",
492                 "libSDL2-2.0_mixer.so.0",
493                 "/usr/local/lib/libSDL2-2.0_mixer.so.0"
494             ];
495         }
496         else static assert(0, "bindbc-sdl is not yet supported on this platform.");
497 
498         SDLMixerSupport ret;
499         foreach(name; libNames) {
500             ret = loadSDLMixer(name.ptr);
501             if(ret != SDLMixerSupport.noLibrary) break;
502         }
503         return ret;
504     }
505 
506     SDLMixerSupport loadSDLMixer(const(char)* libName)
507     {
508         lib = load(libName);
509         if(lib == invalidHandle) {
510             return SDLMixerSupport.noLibrary;
511         }
512 
513         auto errCount = errorCount();
514         loadedVersion = SDLMixerSupport.badLibrary;
515 
516         lib.bindSymbol(cast(void**)&Mix_Linked_Version,"Mix_Linked_Version");
517         lib.bindSymbol(cast(void**)&Mix_Init,"Mix_Init");
518         lib.bindSymbol(cast(void**)&Mix_Quit,"Mix_Quit");
519         lib.bindSymbol(cast(void**)&Mix_OpenAudio,"Mix_OpenAudio");
520         lib.bindSymbol(cast(void**)&Mix_AllocateChannels,"Mix_AllocateChannels");
521         lib.bindSymbol(cast(void**)&Mix_QuerySpec,"Mix_QuerySpec");
522         lib.bindSymbol(cast(void**)&Mix_LoadWAV_RW,"Mix_LoadWAV_RW");
523         lib.bindSymbol(cast(void**)&Mix_LoadMUS,"Mix_LoadMUS");
524         lib.bindSymbol(cast(void**)&Mix_LoadMUS_RW,"Mix_LoadMUS_RW");
525         lib.bindSymbol(cast(void**)&Mix_LoadMUSType_RW,"Mix_LoadMUSType_RW");
526         lib.bindSymbol(cast(void**)&Mix_QuickLoad_WAV,"Mix_QuickLoad_WAV");
527         lib.bindSymbol(cast(void**)&Mix_QuickLoad_RAW,"Mix_QuickLoad_RAW");
528         lib.bindSymbol(cast(void**)&Mix_FreeChunk,"Mix_FreeChunk");
529         lib.bindSymbol(cast(void**)&Mix_FreeMusic,"Mix_FreeMusic");
530         lib.bindSymbol(cast(void**)&Mix_GetNumChunkDecoders,"Mix_GetNumChunkDecoders");
531         lib.bindSymbol(cast(void**)&Mix_GetChunkDecoder,"Mix_GetChunkDecoder");
532         lib.bindSymbol(cast(void**)&Mix_GetNumMusicDecoders,"Mix_GetNumMusicDecoders");
533         lib.bindSymbol(cast(void**)&Mix_GetMusicDecoder,"Mix_GetMusicDecoder");
534         lib.bindSymbol(cast(void**)&Mix_GetMusicType,"Mix_GetMusicType");
535         lib.bindSymbol(cast(void**)&Mix_SetPostMix,"Mix_SetPostMix");
536         lib.bindSymbol(cast(void**)&Mix_HookMusic,"Mix_HookMusic");
537         lib.bindSymbol(cast(void**)&Mix_HookMusicFinished,"Mix_HookMusicFinished");
538         lib.bindSymbol(cast(void**)&Mix_GetMusicHookData,"Mix_GetMusicHookData");
539         lib.bindSymbol(cast(void**)&Mix_ChannelFinished,"Mix_ChannelFinished");
540         lib.bindSymbol(cast(void**)&Mix_RegisterEffect,"Mix_RegisterEffect");
541         lib.bindSymbol(cast(void**)&Mix_UnregisterEffect,"Mix_UnregisterEffect");
542         lib.bindSymbol(cast(void**)&Mix_UnregisterAllEffects,"Mix_UnregisterAllEffects");
543         lib.bindSymbol(cast(void**)&Mix_SetPanning,"Mix_SetPanning");
544         lib.bindSymbol(cast(void**)&Mix_SetPosition,"Mix_SetPosition");
545         lib.bindSymbol(cast(void**)&Mix_SetDistance,"Mix_SetDistance");
546         lib.bindSymbol(cast(void**)&Mix_SetReverseStereo,"Mix_SetReverseStereo");
547         lib.bindSymbol(cast(void**)&Mix_ReserveChannels,"Mix_ReserveChannels");
548         lib.bindSymbol(cast(void**)&Mix_GroupChannel,"Mix_GroupChannel");
549         lib.bindSymbol(cast(void**)&Mix_GroupChannels,"Mix_GroupChannels");
550         lib.bindSymbol(cast(void**)&Mix_GroupAvailable,"Mix_GroupAvailable");
551         lib.bindSymbol(cast(void**)&Mix_GroupCount,"Mix_GroupCount");
552         lib.bindSymbol(cast(void**)&Mix_GroupOldest,"Mix_GroupOldest");
553         lib.bindSymbol(cast(void**)&Mix_GroupNewer,"Mix_GroupNewer");
554         lib.bindSymbol(cast(void**)&Mix_PlayChannelTimed,"Mix_PlayChannelTimed");
555         lib.bindSymbol(cast(void**)&Mix_PlayMusic,"Mix_PlayMusic");
556         lib.bindSymbol(cast(void**)&Mix_FadeInMusic,"Mix_FadeInMusic");
557         lib.bindSymbol(cast(void**)&Mix_FadeInMusicPos,"Mix_FadeInMusicPos");
558         lib.bindSymbol(cast(void**)&Mix_FadeInChannelTimed,"Mix_FadeInChannelTimed");
559         lib.bindSymbol(cast(void**)&Mix_Volume,"Mix_Volume");
560         lib.bindSymbol(cast(void**)&Mix_VolumeChunk,"Mix_VolumeChunk");
561         lib.bindSymbol(cast(void**)&Mix_VolumeMusic,"Mix_VolumeMusic");
562         lib.bindSymbol(cast(void**)&Mix_HaltChannel,"Mix_HaltChannel");
563         lib.bindSymbol(cast(void**)&Mix_HaltGroup,"Mix_HaltGroup");
564         lib.bindSymbol(cast(void**)&Mix_HaltMusic,"Mix_HaltMusic");
565         lib.bindSymbol(cast(void**)&Mix_ExpireChannel,"Mix_ExpireChannel");
566         lib.bindSymbol(cast(void**)&Mix_FadeOutChannel,"Mix_FadeOutChannel");
567         lib.bindSymbol(cast(void**)&Mix_FadeOutGroup,"Mix_FadeOutGroup");
568         lib.bindSymbol(cast(void**)&Mix_FadeOutMusic,"Mix_FadeOutMusic");
569         lib.bindSymbol(cast(void**)&Mix_FadingMusic,"Mix_FadingMusic");
570         lib.bindSymbol(cast(void**)&Mix_FadingChannel,"Mix_FadingChannel");
571         lib.bindSymbol(cast(void**)&Mix_Pause,"Mix_Pause");
572         lib.bindSymbol(cast(void**)&Mix_Resume,"Mix_Resume");
573         lib.bindSymbol(cast(void**)&Mix_Paused,"Mix_Paused");
574         lib.bindSymbol(cast(void**)&Mix_PauseMusic,"Mix_PauseMusic");
575         lib.bindSymbol(cast(void**)&Mix_ResumeMusic,"Mix_ResumeMusic");
576         lib.bindSymbol(cast(void**)&Mix_RewindMusic,"Mix_RewindMusic");
577         lib.bindSymbol(cast(void**)&Mix_PausedMusic,"Mix_PausedMusic");
578         lib.bindSymbol(cast(void**)&Mix_SetMusicPosition,"Mix_SetMusicPosition");
579         lib.bindSymbol(cast(void**)&Mix_Playing,"Mix_Playing");
580         lib.bindSymbol(cast(void**)&Mix_PlayingMusic,"Mix_PlayingMusic");
581         lib.bindSymbol(cast(void**)&Mix_SetMusicCMD,"Mix_SetMusicCMD");
582         lib.bindSymbol(cast(void**)&Mix_SetSynchroValue,"Mix_SetSynchroValue");
583         lib.bindSymbol(cast(void**)&Mix_GetSynchroValue,"Mix_GetSynchroValue");
584         lib.bindSymbol(cast(void**)&Mix_GetChunk,"Mix_GetChunk");
585         lib.bindSymbol(cast(void**)&Mix_CloseAudio,"Mix_CloseAudio");
586 
587         if(errorCount() != errCount) return SDLMixerSupport.badLibrary;
588         else loadedVersion = (sdlMixerSupport >= SDLMixerSupport.sdlMixer201) ? SDLMixerSupport.sdlMixer201 : SDLMixerSupport.sdlMixer200;
589 
590         static if(sdlMixerSupport >= SDLMixerSupport.sdlMixer202) {
591             lib.bindSymbol(cast(void**)&Mix_OpenAudioDevice,"Mix_OpenAudioDevice");
592             lib.bindSymbol(cast(void**)&Mix_HasChunkDecoder,"Mix_HasChunkDecoder");
593 
594             if(errorCount() != errCount) return SDLMixerSupport.badLibrary;
595             else loadedVersion = (sdlMixerSupport >= SDLMixerSupport.sdlMixer204) ? SDLMixerSupport.sdlMixer204 : SDLMixerSupport.sdlMixer202;
596         }
597 
598         return loadedVersion;
599     }
600 }