Subversion Repositories Kolibri OS

Rev

Rev 9097 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.   SDL_mixer:  An audio mixer library based on the SDL library
  3.   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
  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. /* $Id$ */
  23.  
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include <assert.h>
  28. #include "SDL_endian.h"
  29. #include "SDL_audio.h"
  30. #include "SDL_timer.h"
  31.  
  32. #include "SDL_mixer.h"
  33.  
  34. #ifdef CMD_MUSIC
  35. #include "music_cmd.h"
  36. #endif
  37. #ifdef WAV_MUSIC
  38. #include "wavestream.h"
  39. #endif
  40. #ifdef MODPLUG_MUSIC
  41. #include "music_modplug.h"
  42. #endif
  43. #ifdef MOD_MUSIC
  44. #include "music_mod.h"
  45. #endif
  46. #ifdef MID_MUSIC
  47. #  ifdef USE_TIMIDITY_MIDI
  48. #    include "timidity.h"
  49. #  endif
  50. #  ifdef USE_FLUIDSYNTH_MIDI
  51. #    include "fluidsynth.h"
  52. #  endif
  53. #  ifdef USE_NATIVE_MIDI
  54. #    include "native_midi.h"
  55. #  endif
  56. #endif
  57. #ifdef OGG_MUSIC
  58. #include "music_ogg.h"
  59. #endif
  60. #ifdef MP3_MUSIC
  61. #include "dynamic_mp3.h"
  62. #endif
  63. #ifdef MP3_MAD_MUSIC
  64. #include "music_mad.h"
  65. #endif
  66. #ifdef FLAC_MUSIC
  67. #include "music_flac.h"
  68. #endif
  69.  
  70. #if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
  71. static SDL_AudioSpec used_mixer;
  72. #endif
  73.  
  74.  
  75. int volatile music_active = 1;
  76. static int volatile music_stopped = 0;
  77. static int music_loops = 0;
  78. static char *music_cmd = NULL;
  79. static Mix_Music * volatile music_playing = NULL;
  80. static int music_volume = MIX_MAX_VOLUME;
  81.  
  82. struct _Mix_Music {
  83.         Mix_MusicType type;
  84.         union {
  85. #ifdef CMD_MUSIC
  86.                 MusicCMD *cmd;
  87. #endif
  88. #ifdef WAV_MUSIC
  89.                 WAVStream *wave;
  90. #endif
  91. #ifdef MODPLUG_MUSIC
  92.                 modplug_data *modplug;
  93. #endif
  94. #ifdef MOD_MUSIC
  95.                 struct MODULE *module;
  96. #endif
  97. #ifdef MID_MUSIC
  98. #ifdef USE_TIMIDITY_MIDI
  99.                 MidiSong *midi;
  100. #endif
  101. #ifdef USE_FLUIDSYNTH_MIDI
  102.                 FluidSynthMidiSong *fluidsynthmidi;
  103. #endif
  104. #ifdef USE_NATIVE_MIDI
  105.                 NativeMidiSong *nativemidi;
  106. #endif
  107. #endif
  108. #ifdef OGG_MUSIC
  109.                 OGG_music *ogg;
  110. #endif
  111. #ifdef MP3_MUSIC
  112.                 SMPEG *mp3;
  113. #endif
  114. #ifdef MP3_MAD_MUSIC
  115.                 mad_data *mp3_mad;
  116. #endif
  117. #ifdef FLAC_MUSIC
  118.                 FLAC_music *flac;
  119. #endif
  120.         } data;
  121.         Mix_Fading fading;
  122.         int fade_step;
  123.         int fade_steps;
  124.         int error;
  125. };
  126. #ifdef MID_MUSIC
  127. #ifdef USE_TIMIDITY_MIDI
  128. static int timidity_ok;
  129. static int samplesize;
  130. #endif
  131. #ifdef USE_FLUIDSYNTH_MIDI
  132. static int fluidsynth_ok;
  133. #endif
  134. #ifdef USE_NATIVE_MIDI
  135. static int native_midi_ok;
  136. #endif
  137. #endif
  138.  
  139. /* Used to calculate fading steps */
  140. static int ms_per_step;
  141.  
  142. /* rcg06042009 report available decoders at runtime. */
  143. static const char **music_decoders = NULL;
  144. static int num_decoders = 0;
  145.  
  146. /* Semicolon-separated SoundFont paths */
  147. #ifdef MID_MUSIC
  148. char* soundfont_paths = NULL;
  149. #endif
  150.  
  151. int Mix_GetNumMusicDecoders(void)
  152. {
  153.         return(num_decoders);
  154. }
  155.  
  156. const char *Mix_GetMusicDecoder(int index)
  157. {
  158.         if ((index < 0) || (index >= num_decoders)) {
  159.                 return NULL;
  160.         }
  161.         return(music_decoders[index]);
  162. }
  163.  
  164. static void add_music_decoder(const char *decoder)
  165. {
  166.         void *ptr = SDL_realloc(music_decoders, (num_decoders + 1) * sizeof (const char **));
  167.         if (ptr == NULL) {
  168.                 return;  /* oh well, go on without it. */
  169.         }
  170.         music_decoders = (const char **) ptr;
  171.         music_decoders[num_decoders++] = decoder;
  172. }
  173.  
  174. /* Local low-level functions prototypes */
  175. static void music_internal_initialize_volume(void);
  176. static void music_internal_volume(int volume);
  177. static int  music_internal_play(Mix_Music *music, double position);
  178. static int  music_internal_position(double position);
  179. static int  music_internal_playing();
  180. static void music_internal_halt(void);
  181.  
  182.  
  183. /* Support for hooking when the music has finished */
  184. static void (*music_finished_hook)(void) = NULL;
  185.  
  186. void Mix_HookMusicFinished(void (*music_finished)(void))
  187. {
  188.         SDL_LockAudio();
  189.         music_finished_hook = music_finished;
  190.         SDL_UnlockAudio();
  191. }
  192.  
  193.  
  194. /* If music isn't playing, halt it if no looping is required, restart it */
  195. /* otherwhise. NOP if the music is playing */
  196. static int music_halt_or_loop (void)
  197. {
  198.         /* Restart music if it has to loop */
  199.        
  200.         if (!music_internal_playing())
  201.         {
  202. #ifdef USE_NATIVE_MIDI
  203.                 /* Native MIDI handles looping internally */
  204.                 if (music_playing->type == MUS_MID && native_midi_ok) {
  205.                         music_loops = 0;
  206.                 }
  207. #endif
  208.  
  209.                 /* Restart music if it has to loop at a high level */
  210.                 if (music_loops)
  211.                 {
  212.                         Mix_Fading current_fade;
  213.                         --music_loops;
  214.                         current_fade = music_playing->fading;
  215.                         music_internal_play(music_playing, 0.0);
  216.                         music_playing->fading = current_fade;
  217.                 }
  218.                 else
  219.                 {
  220.                         music_internal_halt();
  221.                         if (music_finished_hook)
  222.                                 music_finished_hook();
  223.                        
  224.                         return 0;
  225.                 }
  226.         }
  227.        
  228.         return 1;
  229. }
  230.  
  231.  
  232.  
  233. /* Mixing function */
  234. void music_mixer(void *udata, Uint8 *stream, int len)
  235. {
  236.         int left = 0;
  237.  
  238.         if ( music_playing && music_active ) {
  239.                 /* Handle fading */
  240.                 if ( music_playing->fading != MIX_NO_FADING ) {
  241.                         if ( music_playing->fade_step++ < music_playing->fade_steps ) {
  242.                                 int volume;
  243.                                 int fade_step = music_playing->fade_step;
  244.                                 int fade_steps = music_playing->fade_steps;
  245.  
  246.                                 if ( music_playing->fading == MIX_FADING_OUT ) {
  247.                                         volume = (music_volume * (fade_steps-fade_step)) / fade_steps;
  248.                                 } else { /* Fading in */
  249.                                         volume = (music_volume * fade_step) / fade_steps;
  250.                                 }
  251.                                 music_internal_volume(volume);
  252.                         } else {
  253.                                 if ( music_playing->fading == MIX_FADING_OUT ) {
  254.                                         music_internal_halt();
  255.                                         if ( music_finished_hook ) {
  256.                                                 music_finished_hook();
  257.                                         }
  258.                                         return;
  259.                                 }
  260.                                 music_playing->fading = MIX_NO_FADING;
  261.                         }
  262.                 }
  263.                
  264.                 music_halt_or_loop();
  265.                 if (!music_internal_playing())
  266.                         return;
  267.  
  268.                 switch (music_playing->type) {
  269. #ifdef CMD_MUSIC
  270.                         case MUS_CMD:
  271.                                 /* The playing is done externally */
  272.                                 break;
  273. #endif
  274. #ifdef WAV_MUSIC
  275.                         case MUS_WAV:
  276.                                 left = WAVStream_PlaySome(stream, len);
  277.                                 break;
  278. #endif
  279. #ifdef MODPLUG_MUSIC
  280.                         case MUS_MODPLUG:
  281.                                 left = modplug_playAudio(music_playing->data.modplug, stream, len);
  282.                                 break;
  283. #endif
  284. #ifdef MOD_MUSIC
  285.                         case MUS_MOD:
  286.                                 left = MOD_playAudio(music_playing->data.module, stream, len);
  287.                                 break;
  288. #endif
  289. #ifdef MID_MUSIC
  290.                         case MUS_MID:
  291. #ifdef USE_NATIVE_MIDI
  292.                                 if ( native_midi_ok ) {
  293.                                         /* Native midi is handled asynchronously */
  294.                                         goto skip;
  295.                                 }
  296. #endif
  297. #ifdef USE_FLUIDSYNTH_MIDI
  298.                                 if ( fluidsynth_ok ) {
  299.                                         fluidsynth_playsome(music_playing->data.fluidsynthmidi, stream, len);
  300.                                         goto skip;
  301.                                 }
  302. #endif
  303. #ifdef USE_TIMIDITY_MIDI
  304.                                 if ( timidity_ok ) {
  305.                                         int samples = len / samplesize;
  306.                                         Timidity_PlaySome(stream, samples);
  307.                                         goto skip;
  308.                                 }
  309. #endif
  310.                                 break;
  311. #endif
  312. #ifdef OGG_MUSIC
  313.                         case MUS_OGG:
  314.                                
  315.                                 left = OGG_playAudio(music_playing->data.ogg, stream, len);
  316.                                 break;
  317. #endif
  318. #ifdef FLAC_MUSIC
  319.                         case MUS_FLAC:
  320.                                 left = FLAC_playAudio(music_playing->data.flac, stream, len);
  321.                                 break;
  322. #endif
  323. #ifdef MP3_MUSIC
  324.                         case MUS_MP3:
  325.                                 left = (len - smpeg.SMPEG_playAudio(music_playing->data.mp3, stream, len));
  326.                                 break;
  327. #endif
  328. #ifdef MP3_MAD_MUSIC
  329.                         case MUS_MP3_MAD:
  330.                                 left = mad_getSamples(music_playing->data.mp3_mad, stream, len);
  331.                                 break;
  332. #endif
  333.                         default:
  334.                                 /* Unknown music type?? */
  335.                                 break;
  336.                 }
  337.         }
  338.  
  339. skip:
  340.         /* Handle seamless music looping */
  341.         if (left > 0 && left < len) {
  342.                 music_halt_or_loop();
  343.                 if (music_internal_playing())
  344.                         music_mixer(udata, stream+(len-left), left);
  345.         }
  346. }
  347.  
  348. /* Initialize the music players with a certain desired audio format */
  349. int open_music(SDL_AudioSpec *mixer)
  350. {
  351. #ifdef WAV_MUSIC
  352.         if ( WAVStream_Init(mixer) == 0 ) {
  353.                 add_music_decoder("WAVE");
  354.         }
  355. #endif
  356. #ifdef MODPLUG_MUSIC
  357.         if ( modplug_init(mixer) == 0 ) {
  358.                 add_music_decoder("MODPLUG");
  359.         }
  360. #endif
  361. #ifdef MOD_MUSIC
  362.         if ( MOD_init(mixer) == 0 ) {
  363.                 add_music_decoder("MIKMOD");
  364.         }
  365. #endif
  366. #ifdef MID_MUSIC
  367. #ifdef USE_TIMIDITY_MIDI
  368.         samplesize = mixer->size / mixer->samples;
  369.         if ( Timidity_Init(mixer->freq, mixer->format,
  370.                             mixer->channels, mixer->samples) == 0 ) {
  371.                 timidity_ok = 1;
  372.                 add_music_decoder("TIMIDITY");
  373.         } else {
  374.                 timidity_ok = 0;
  375.         }
  376. #endif
  377. #ifdef USE_FLUIDSYNTH_MIDI
  378.         if ( fluidsynth_init(mixer) == 0 ) {
  379.                 fluidsynth_ok = 1;
  380.                 add_music_decoder("FLUIDSYNTH");
  381.         } else {
  382.                 fluidsynth_ok = 0;
  383.         }
  384. #endif
  385. #ifdef USE_NATIVE_MIDI
  386. #ifdef USE_FLUIDSYNTH_MIDI
  387.         native_midi_ok = !fluidsynth_ok;
  388.         if ( native_midi_ok )
  389. #endif
  390. #ifdef USE_TIMIDITY_MIDI
  391.                 native_midi_ok = !timidity_ok;
  392.         if ( !native_midi_ok ) {
  393.                 native_midi_ok = (getenv("SDL_NATIVE_MUSIC") != NULL);
  394.         }
  395.         if ( native_midi_ok )
  396. #endif
  397.                 native_midi_ok = native_midi_detect();
  398.         if ( native_midi_ok )
  399.                 add_music_decoder("NATIVEMIDI");
  400. #endif
  401. #endif
  402. #ifdef OGG_MUSIC
  403.         if ( OGG_init(mixer) == 0 ) {
  404.                 add_music_decoder("OGG");
  405.         }
  406. #endif
  407. #ifdef FLAC_MUSIC
  408.         if ( FLAC_init(mixer) == 0 ) {
  409.                 add_music_decoder("FLAC");
  410.         }
  411. #endif
  412. #if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
  413.         /* Keep a copy of the mixer */
  414.         used_mixer = *mixer;
  415.         add_music_decoder("MP3");
  416. #endif
  417.  
  418.         music_playing = NULL;
  419.         music_stopped = 0;
  420.         Mix_VolumeMusic(SDL_MIX_MAXVOLUME);
  421.  
  422.         /* Calculate the number of ms for each callback */
  423.         ms_per_step = (int) (((float)mixer->samples * 1000.0) / mixer->freq);
  424.  
  425.         return(0);
  426. }
  427.  
  428. /* Portable case-insensitive string compare function */
  429. int MIX_string_equals(const char *str1, const char *str2)
  430. {
  431.         while ( *str1 && *str2 ) {
  432.                 if ( toupper((unsigned char)*str1) !=
  433.                      toupper((unsigned char)*str2) )
  434.                         break;
  435.                 ++str1;
  436.                 ++str2;
  437.         }
  438.         return (!*str1 && !*str2);
  439. }
  440.  
  441. static int detect_mp3(Uint8 *magic)
  442. {
  443.         if ( strncmp((char *)magic, "ID3", 3) == 0 ) {
  444.                 return 1;
  445.         }
  446.  
  447.         /* Detection code lifted from SMPEG */
  448.         if(((magic[0] & 0xff) != 0xff) || // No sync bits
  449.            ((magic[1] & 0xf0) != 0xf0) || //
  450.            ((magic[2] & 0xf0) == 0x00) || // Bitrate is 0
  451.            ((magic[2] & 0xf0) == 0xf0) || // Bitrate is 15
  452.            ((magic[2] & 0x0c) == 0x0c) || // Frequency is 3
  453.            ((magic[1] & 0x06) == 0x00)) { // Layer is 4
  454.                 return(0);
  455.         }
  456.         return 1;
  457. }
  458.  
  459. /* MUS_MOD can't be auto-detected. If no other format was detected, MOD is
  460.  * assumed and MUS_MOD will be returned, meaning that the format might not
  461.  * actually be MOD-based.
  462.  *
  463.  * Returns MUS_NONE in case of errors. */
  464. static Mix_MusicType detect_music_type(SDL_RWops *rw)
  465. {
  466.         Uint8 magic[5];
  467.         Uint8 moremagic[9];
  468.  
  469.         int start = SDL_RWtell(rw);
  470.         if (SDL_RWread(rw, magic, 1, 4) != 4 || SDL_RWread(rw, moremagic, 1, 8) != 8 ) {
  471.                 Mix_SetError("Couldn't read from RWops");
  472.                 return MUS_NONE;
  473.         }
  474.         SDL_RWseek(rw, start, RW_SEEK_SET);
  475.         magic[4]='\0';
  476.         moremagic[8] = '\0';
  477.  
  478.         /* WAVE files have the magic four bytes "RIFF"
  479.            AIFF files have the magic 12 bytes "FORM" XXXX "AIFF" */
  480.         if (((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) ||
  481.                 (strcmp((char *)magic, "FORM") == 0)) {
  482.                 return MUS_WAV;
  483.         }
  484.  
  485.         /* Ogg Vorbis files have the magic four bytes "OggS" */
  486.         if (strcmp((char *)magic, "OggS") == 0) {
  487.                 return MUS_OGG;
  488.         }
  489.  
  490.         /* FLAC files have the magic four bytes "fLaC" */
  491.         if (strcmp((char *)magic, "fLaC") == 0) {
  492.                 return MUS_FLAC;
  493.         }
  494.  
  495.         /* MIDI files have the magic four bytes "MThd" */
  496.         if (strcmp((char *)magic, "MThd") == 0) {
  497.                 return MUS_MID;
  498.         }
  499.  
  500.         if (detect_mp3(magic)) {
  501.                 return MUS_MP3;
  502.         }
  503.  
  504.         /* Assume MOD format.
  505.          *
  506.          * Apparently there is no way to check if the file is really a MOD,
  507.          * or there are too many formats supported by MikMod/ModPlug, or
  508.          * MikMod/ModPlug does this check by itself. */
  509.         return MUS_MOD;
  510. }
  511.  
  512. /* Load a music file */
  513. Mix_Music *Mix_LoadMUS(const char *file)
  514. {
  515.         SDL_RWops *rw;
  516.         Mix_Music *music;
  517.         Mix_MusicType type;
  518.         char *ext = strrchr(file, '.');
  519.  
  520. #ifdef CMD_MUSIC
  521.         if ( music_cmd ) {
  522.                 /* Allocate memory for the music structure */
  523.                 music = (Mix_Music *)SDL_malloc(sizeof(Mix_Music));
  524.                 if ( music == NULL ) {
  525.                         Mix_SetError("Out of memory");
  526.                         return(NULL);
  527.                 }
  528.                 music->error = 0;
  529.                 music->type = MUS_CMD;
  530.                 music->data.cmd = MusicCMD_LoadSong(music_cmd, file);
  531.                 if ( music->data.cmd == NULL ) {
  532.                         SDL_free(music);
  533.                         music == NULL;
  534.                 }
  535.                 return music;
  536.         }
  537. #endif
  538.  
  539.         rw = SDL_RWFromFile(file, "rb");
  540.         if ( rw == NULL ) {
  541.                 Mix_SetError("Couldn't open '%s'", file);
  542.                 return NULL;
  543.         }
  544.  
  545.         /* Use the extension as a first guess on the file type */
  546.         type = MUS_NONE;
  547.         ext = strrchr(file, '.');
  548.         /* No need to guard these with #ifdef *_MUSIC stuff,
  549.          * since we simply call Mix_LoadMUSType_RW() later */
  550.         if ( ext ) {
  551.                 ++ext; /* skip the dot in the extension */
  552.                 if ( MIX_string_equals(ext, "WAV") ) {
  553.                         type = MUS_WAV;
  554.                 } else if ( MIX_string_equals(ext, "MID") ||
  555.                             MIX_string_equals(ext, "MIDI") ||
  556.                             MIX_string_equals(ext, "KAR") ) {
  557.                         type = MUS_MID;
  558.                 } else if ( MIX_string_equals(ext, "OGG") ) {
  559.                         type = MUS_OGG;
  560.                 } else if ( MIX_string_equals(ext, "FLAC") ) {
  561.                         type = MUS_FLAC;
  562.                 } else  if ( MIX_string_equals(ext, "MPG") ||
  563.                              MIX_string_equals(ext, "MPEG") ||
  564.                              MIX_string_equals(ext, "MP3") ||
  565.                              MIX_string_equals(ext, "MAD") ) {
  566.                         type = MUS_MP3;
  567.                 }
  568.         }
  569.         if ( type == MUS_NONE ) {
  570.                 type = detect_music_type(rw);
  571.         }
  572.  
  573.         /* We need to know if a specific error occurs; if not, we'll set a
  574.          * generic one, so we clear the current one. */
  575.         Mix_SetError("");
  576.         music = Mix_LoadMUSType_RW(rw, type, SDL_TRUE);
  577.         if ( music == NULL && Mix_GetError()[0] == '\0' ) {
  578.                 SDL_FreeRW(rw);
  579.                 Mix_SetError("Couldn't open '%s'", file);
  580.         }
  581.         return music;
  582. }
  583.  
  584. Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw)
  585. {
  586.         return Mix_LoadMUSType_RW(rw, MUS_NONE, SDL_FALSE);
  587. }
  588.  
  589. Mix_Music *Mix_LoadMUSType_RW(SDL_RWops *rw, Mix_MusicType type, int freesrc)
  590. {
  591.         Mix_Music *music;
  592.  
  593.         if (!rw) {
  594.                 Mix_SetError("RWops pointer is NULL");
  595.                 return NULL;
  596.         }
  597.  
  598.         /* If the caller wants auto-detection, figure out what kind of file
  599.          * this is. */
  600.         if (type == MUS_NONE) {
  601.                 if ((type = detect_music_type(rw)) == MUS_NONE) {
  602.                         /* Don't call Mix_SetError() here since detect_music_type()
  603.                          * does that. */
  604.                         return NULL;
  605.                 }
  606.         }
  607.  
  608.         /* Allocate memory for the music structure */
  609.         music = (Mix_Music *)SDL_malloc(sizeof(Mix_Music));
  610.         if (music == NULL ) {
  611.                 Mix_SetError("Out of memory");
  612.                 return NULL;
  613.         }
  614.         music->error = 0;
  615.  
  616.         switch (type) {
  617. #ifdef WAV_MUSIC
  618.         case MUS_WAV:
  619.                 /* The WAVE loader needs the first 4 bytes of the header */
  620.                 {
  621.                         Uint8 magic[5];
  622.                         int start = SDL_RWtell(rw);
  623.                         if (SDL_RWread(rw, magic, 1, 4) != 4) {
  624.                                 Mix_SetError("Couldn't read from RWops");
  625.                                 return MUS_NONE;
  626.                         }
  627.                         SDL_RWseek(rw, start, RW_SEEK_SET);
  628.                         magic[4] = '\0';
  629.                         music->type = MUS_WAV;
  630.                         music->data.wave = WAVStream_LoadSong_RW(rw, (char *)magic, freesrc);
  631.                 }
  632.                 if (music->data.wave == NULL) {
  633.                         music->error = 1;
  634.                 }
  635.                 break;
  636. #endif
  637. #ifdef OGG_MUSIC
  638.         case MUS_OGG:
  639.                 music->type = MUS_OGG;
  640.                 music->data.ogg = OGG_new_RW(rw, freesrc);
  641.                 if ( music->data.ogg == NULL ) {
  642.                         music->error = 1;
  643.                 }
  644.                 break;
  645. #endif
  646. #ifdef FLAC_MUSIC
  647.         case MUS_FLAC:
  648.                 music->type = MUS_FLAC;
  649.                 music->data.flac = FLAC_new_RW(rw, freesrc);
  650.                 if ( music->data.flac == NULL ) {
  651.                         music->error = 1;
  652.                 }
  653.                 break;
  654. #endif
  655. #ifdef MP3_MUSIC
  656.         case MUS_MP3:
  657.                 if ( Mix_Init(MIX_INIT_MP3) ) {
  658.                         SMPEG_Info info;
  659.                         music->type = MUS_MP3;
  660.                         music->data.mp3 = smpeg.SMPEG_new_rwops(rw, &info, 0);
  661.                         if ( !info.has_audio ) {
  662.                                 Mix_SetError("MPEG file does not have any audio stream.");
  663.                                 music->error = 1;
  664.                         } else {
  665.                                 smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer);
  666.                         }
  667.                 } else {
  668.                         music->error = 1;
  669.                 }
  670.                 break;
  671. #elif defined(MP3_MAD_MUSIC)
  672.         case MUS_MP3:
  673.                 music->type = MUS_MP3_MAD;
  674.                 music->data.mp3_mad = mad_openFileRW(rw, &used_mixer, freesrc);
  675.                 if (music->data.mp3_mad == 0) {
  676.                         Mix_SetError("Could not initialize MPEG stream.");
  677.                         music->error = 1;
  678.                 }
  679.                 break;
  680. #endif
  681. #ifdef MID_MUSIC
  682.         case MUS_MID:
  683.                 music->type = MUS_MID;
  684. #ifdef USE_NATIVE_MIDI
  685.                 if ( native_midi_ok ) {
  686.                         music->data.nativemidi = native_midi_loadsong_RW(rw, freesrc);
  687.                         if ( music->data.nativemidi == NULL ) {
  688.                                 Mix_SetError("%s", native_midi_error());
  689.                                 music->error = 1;
  690.                         }
  691.                         break;
  692.                 }
  693. #endif
  694. #ifdef USE_FLUIDSYNTH_MIDI
  695.                 if ( fluidsynth_ok ) {
  696.                         music->data.fluidsynthmidi = fluidsynth_loadsong_RW(rw, freesrc);
  697.                         if ( music->data.fluidsynthmidi == NULL ) {
  698.                                 music->error = 1;
  699.                         }
  700.                         break;
  701.                 }
  702. #endif
  703. #ifdef USE_TIMIDITY_MIDI
  704.                 if ( timidity_ok ) {
  705.                         music->data.midi = Timidity_LoadSong_RW(rw, freesrc);
  706.                         if ( music->data.midi == NULL ) {
  707.                                 Mix_SetError("%s", Timidity_Error());
  708.                                 music->error = 1;
  709.                         }
  710.                 } else {
  711.                         Mix_SetError("%s", Timidity_Error());
  712.                         music->error = 1;
  713.                 }
  714. #endif
  715.                 break;
  716. #endif
  717. #if defined(MODPLUG_MUSIC) || defined(MOD_MUSIC)
  718.         case MUS_MOD:
  719.                 music->error = 1;
  720. #ifdef MODPLUG_MUSIC
  721.                 if ( music->error ) {
  722.                         music->type = MUS_MODPLUG;
  723.                         music->data.modplug = modplug_new_RW(rw, freesrc);
  724.                         if ( music->data.modplug ) {
  725.                                 music->error = 0;
  726.                         }
  727.                 }
  728. #endif
  729. #ifdef MOD_MUSIC
  730.                 if ( music->error ) {
  731.                         music->type = MUS_MOD;
  732.                         music->data.module = MOD_new_RW(rw, freesrc);
  733.                         if ( music->data.module ) {
  734.                                 music->error = 0;
  735.                         }
  736.                 }
  737. #endif
  738.                 break;
  739. #endif
  740.  
  741.         default:
  742.                 Mix_SetError("Unrecognized music format");
  743.                 music->error=1;
  744.         } /* switch (want) */
  745.  
  746.  
  747.         if (music->error) {
  748.                 SDL_free(music);
  749.                 music=NULL;
  750.         }
  751.         return(music);
  752. }
  753.  
  754. /* Free a music chunk previously loaded */
  755. void Mix_FreeMusic(Mix_Music *music)
  756. {
  757.         if ( music ) {
  758.                 /* Stop the music if it's currently playing */
  759.                 SDL_LockAudio();
  760.                 if ( music == music_playing ) {
  761.                         /* Wait for any fade out to finish */
  762.                         while ( music->fading == MIX_FADING_OUT ) {
  763.                                 SDL_UnlockAudio();
  764.                                 SDL_Delay(100);
  765.                                 SDL_LockAudio();
  766.                         }
  767.                         if ( music == music_playing ) {
  768.                                 music_internal_halt();
  769.                         }
  770.                 }
  771.                 SDL_UnlockAudio();
  772.                 switch (music->type) {
  773. #ifdef CMD_MUSIC
  774.                         case MUS_CMD:
  775.                                 MusicCMD_FreeSong(music->data.cmd);
  776.                                 break;
  777. #endif
  778. #ifdef WAV_MUSIC
  779.                         case MUS_WAV:
  780.                                 WAVStream_FreeSong(music->data.wave);
  781.                                 break;
  782. #endif
  783. #ifdef MODPLUG_MUSIC
  784.                         case MUS_MODPLUG:
  785.                                 modplug_delete(music->data.modplug);
  786.                                 break;
  787. #endif
  788. #ifdef MOD_MUSIC
  789.                         case MUS_MOD:
  790.                                 MOD_delete(music->data.module);
  791.                                 break;
  792. #endif
  793. #ifdef MID_MUSIC
  794.                         case MUS_MID:
  795. #ifdef USE_NATIVE_MIDI
  796.                                 if ( native_midi_ok ) {
  797.                                         native_midi_freesong(music->data.nativemidi);
  798.                                         goto skip;
  799.                                 }
  800. #endif
  801. #ifdef USE_FLUIDSYNTH_MIDI
  802.                                 if ( fluidsynth_ok ) {
  803.                                         fluidsynth_freesong(music->data.fluidsynthmidi);
  804.                                         goto skip;
  805.                                 }
  806. #endif
  807. #ifdef USE_TIMIDITY_MIDI
  808.                                 if ( timidity_ok ) {
  809.                                         Timidity_FreeSong(music->data.midi);
  810.                                         goto skip;
  811.                                 }
  812. #endif
  813.                                 break;
  814. #endif
  815. #ifdef OGG_MUSIC
  816.                         case MUS_OGG:
  817.                                 OGG_delete(music->data.ogg);
  818.                                 break;
  819. #endif
  820. #ifdef FLAC_MUSIC
  821.                         case MUS_FLAC:
  822.                                 FLAC_delete(music->data.flac);
  823.                                 break;
  824. #endif
  825. #ifdef MP3_MUSIC
  826.                         case MUS_MP3:
  827.                                 smpeg.SMPEG_delete(music->data.mp3);
  828.                                 break;
  829. #endif
  830. #ifdef MP3_MAD_MUSIC
  831.                         case MUS_MP3_MAD:
  832.                                 mad_closeFile(music->data.mp3_mad);
  833.                                 break;
  834. #endif
  835.                         default:
  836.                                 /* Unknown music type?? */
  837.                                 break;
  838.                 }
  839.  
  840.     skip:
  841.                 SDL_free(music);
  842.         }
  843. }
  844.  
  845. /* Find out the music format of a mixer music, or the currently playing
  846.    music, if 'music' is NULL.
  847. */
  848. Mix_MusicType Mix_GetMusicType(const Mix_Music *music)
  849. {
  850.         Mix_MusicType type = MUS_NONE;
  851.  
  852.         if ( music ) {
  853.                 type = music->type;
  854.         } else {
  855.                 SDL_LockAudio();
  856.                 if ( music_playing ) {
  857.                         type = music_playing->type;
  858.                 }
  859.                 SDL_UnlockAudio();
  860.         }
  861.         return(type);
  862. }
  863.  
  864. /* Play a music chunk.  Returns 0, or -1 if there was an error.
  865.  */
  866. static int music_internal_play(Mix_Music *music, double position)
  867. {
  868.         int retval = 0;
  869.  
  870. #if defined(__MACOSX__) && defined(USE_NATIVE_MIDI)
  871.         /* This fixes a bug with native MIDI on Mac OS X, where you
  872.            can't really stop and restart MIDI from the audio callback.
  873.         */
  874.         if ( music == music_playing && music->type == MUS_MID && native_midi_ok ) {
  875.                 /* Just a seek suffices to restart playing */
  876.                 music_internal_position(position);
  877.                 return 0;
  878.         }
  879. #endif
  880.  
  881.         /* Note the music we're playing */
  882.         if ( music_playing ) {
  883.                 music_internal_halt();
  884.         }
  885.         music_playing = music;
  886.  
  887.         /* Set the initial volume */
  888.         if ( music->type != MUS_MOD ) {
  889.                 music_internal_initialize_volume();
  890.         }
  891.  
  892.         /* Set up for playback */
  893.         switch (music->type) {
  894. #ifdef CMD_MUSIC
  895.             case MUS_CMD:
  896.                 MusicCMD_Start(music->data.cmd);
  897.                 break;
  898. #endif
  899. #ifdef WAV_MUSIC
  900.             case MUS_WAV:
  901.                 WAVStream_Start(music->data.wave);
  902.                 break;
  903. #endif
  904. #ifdef MODPLUG_MUSIC
  905.             case MUS_MODPLUG:
  906.                 /* can't set volume until file is loaded, so finally set it now */
  907.                 music_internal_initialize_volume();
  908.                 modplug_play(music->data.modplug);
  909.                 break;
  910. #endif
  911. #ifdef MOD_MUSIC
  912.             case MUS_MOD:
  913.                 MOD_play(music->data.module);
  914.                 /* Player_SetVolume() does nothing before Player_Start() */
  915.                 music_internal_initialize_volume();
  916.                 break;
  917. #endif
  918. #ifdef MID_MUSIC
  919.             case MUS_MID:
  920. #ifdef USE_NATIVE_MIDI
  921.                 if ( native_midi_ok ) {
  922.                         native_midi_start(music->data.nativemidi, music_loops);
  923.                         goto skip;
  924.                 }
  925. #endif
  926. #ifdef USE_FLUIDSYNTH_MIDI
  927.                 if (fluidsynth_ok ) {
  928.                         fluidsynth_start(music->data.fluidsynthmidi);
  929.                         goto skip;
  930.                 }
  931. #endif
  932. #ifdef USE_TIMIDITY_MIDI
  933.                 if ( timidity_ok ) {
  934.                         Timidity_Start(music->data.midi);
  935.                         goto skip;
  936.                 }
  937. #endif
  938.                 break;
  939. #endif
  940. #ifdef OGG_MUSIC
  941.             case MUS_OGG:
  942.                 OGG_play(music->data.ogg);
  943.                 break;
  944. #endif
  945. #ifdef FLAC_MUSIC
  946.             case MUS_FLAC:
  947.                 FLAC_play(music->data.flac);
  948.                 break;
  949. #endif
  950. #ifdef MP3_MUSIC
  951.             case MUS_MP3:
  952.                 smpeg.SMPEG_enableaudio(music->data.mp3,1);
  953.                 smpeg.SMPEG_enablevideo(music->data.mp3,0);
  954.                 smpeg.SMPEG_play(music_playing->data.mp3);
  955.                 break;
  956. #endif
  957. #ifdef MP3_MAD_MUSIC
  958.             case MUS_MP3_MAD:
  959.                 mad_start(music->data.mp3_mad);
  960.                 break;
  961. #endif
  962.             default:
  963.                 Mix_SetError("Can't play unknown music type");
  964.                 retval = -1;
  965.                 break;
  966.         }
  967.  
  968. skip:
  969.         /* Set the playback position, note any errors if an offset is used */
  970.         if ( retval == 0 ) {
  971.                 if ( position > 0.0 ) {
  972.                         if ( music_internal_position(position) < 0 ) {
  973.                                 Mix_SetError("Position not implemented for music type");
  974.                                 retval = -1;
  975.                         }
  976.                 } else {
  977.                         music_internal_position(0.0);
  978.                 }
  979.         }
  980.  
  981.         /* If the setup failed, we're not playing any music anymore */
  982.         if ( retval < 0 ) {
  983.                 music_playing = NULL;
  984.         }
  985.         return(retval);
  986. }
  987. int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position)
  988. {
  989.         int retval;
  990.  
  991.         if ( ms_per_step == 0 ) {
  992.                 SDL_SetError("Audio device hasn't been opened");
  993.                 return(-1);
  994.         }
  995.  
  996.         /* Don't play null pointers :-) */
  997.         if ( music == NULL ) {
  998.                 Mix_SetError("music parameter was NULL");
  999.                 return(-1);
  1000.         }
  1001.  
  1002.         /* Setup the data */
  1003.         if ( ms ) {
  1004.                 music->fading = MIX_FADING_IN;
  1005.         } else {
  1006.                 music->fading = MIX_NO_FADING;
  1007.         }
  1008.         music->fade_step = 0;
  1009.         music->fade_steps = ms/ms_per_step;
  1010.  
  1011.         /* Play the puppy */
  1012.         SDL_LockAudio();
  1013.         /* If the current music is fading out, wait for the fade to complete */
  1014.         while ( music_playing && (music_playing->fading == MIX_FADING_OUT) ) {
  1015.                 SDL_UnlockAudio();
  1016.                 SDL_Delay(100);
  1017.                 SDL_LockAudio();
  1018.         }
  1019.         music_active = 1;
  1020.         if (loops == 1) {
  1021.                 /* Loop is the number of times to play the audio */
  1022.                 loops = 0;
  1023.         }
  1024.         music_loops = loops;
  1025.         retval = music_internal_play(music, position);
  1026.         SDL_UnlockAudio();
  1027.  
  1028.         return(retval);
  1029. }
  1030. int Mix_FadeInMusic(Mix_Music *music, int loops, int ms)
  1031. {
  1032.         return Mix_FadeInMusicPos(music, loops, ms, 0.0);
  1033. }
  1034. int Mix_PlayMusic(Mix_Music *music, int loops)
  1035. {
  1036.         return Mix_FadeInMusicPos(music, loops, 0, 0.0);
  1037. }
  1038.  
  1039. /* Set the playing music position */
  1040. int music_internal_position(double position)
  1041. {
  1042.         int retval = 0;
  1043.  
  1044.         switch (music_playing->type) {
  1045. #ifdef MODPLUG_MUSIC
  1046.             case MUS_MODPLUG:
  1047.                 modplug_jump_to_time(music_playing->data.modplug, position);
  1048.                 break;
  1049. #endif
  1050. #ifdef MOD_MUSIC
  1051.             case MUS_MOD:
  1052.                 MOD_jump_to_time(music_playing->data.module, position);
  1053.                 break;
  1054. #endif
  1055. #ifdef OGG_MUSIC
  1056.             case MUS_OGG:
  1057.                 OGG_jump_to_time(music_playing->data.ogg, position);
  1058.                 break;
  1059. #endif
  1060. #ifdef FLAC_MUSIC
  1061.             case MUS_FLAC:
  1062.                 FLAC_jump_to_time(music_playing->data.flac, position);
  1063.                 break;
  1064. #endif
  1065. #ifdef MP3_MUSIC
  1066.             case MUS_MP3:
  1067.                 smpeg.SMPEG_rewind(music_playing->data.mp3);
  1068.                 smpeg.SMPEG_play(music_playing->data.mp3);
  1069.                 if ( position > 0.0 ) {
  1070.                         smpeg.SMPEG_skip(music_playing->data.mp3, (float)position);
  1071.                 }
  1072.                 break;
  1073. #endif
  1074. #ifdef MP3_MAD_MUSIC
  1075.             case MUS_MP3_MAD:
  1076.                 mad_seek(music_playing->data.mp3_mad, position);
  1077.                 break;
  1078. #endif
  1079.             default:
  1080.                 /* TODO: Implement this for other music backends */
  1081.                 retval = -1;
  1082.                 break;
  1083.         }
  1084.         return(retval);
  1085. }
  1086. int Mix_SetMusicPosition(double position)
  1087. {
  1088.         int retval;
  1089.  
  1090.         SDL_LockAudio();
  1091.         if ( music_playing ) {
  1092.                 retval = music_internal_position(position);
  1093.                 if ( retval < 0 ) {
  1094.                         Mix_SetError("Position not implemented for music type");
  1095.                 }
  1096.         } else {
  1097.                 Mix_SetError("Music isn't playing");
  1098.                 retval = -1;
  1099.         }
  1100.         SDL_UnlockAudio();
  1101.  
  1102.         return(retval);
  1103. }
  1104.  
  1105. /* Set the music's initial volume */
  1106. static void music_internal_initialize_volume(void)
  1107. {
  1108.         if ( music_playing->fading == MIX_FADING_IN ) {
  1109.                 music_internal_volume(0);
  1110.         } else {
  1111.                 music_internal_volume(music_volume);
  1112.         }
  1113. }
  1114.  
  1115. /* Set the music volume */
  1116. static void music_internal_volume(int volume)
  1117. {
  1118.         switch (music_playing->type) {
  1119. #ifdef CMD_MUSIC
  1120.             case MUS_CMD:
  1121.                 MusicCMD_SetVolume(volume);
  1122.                 break;
  1123. #endif
  1124. #ifdef WAV_MUSIC
  1125.             case MUS_WAV:
  1126.                 WAVStream_SetVolume(volume);
  1127.                 break;
  1128. #endif
  1129. #ifdef MODPLUG_MUSIC
  1130.             case MUS_MODPLUG:
  1131.                 modplug_setvolume(music_playing->data.modplug, volume);
  1132.                 break;
  1133. #endif
  1134. #ifdef MOD_MUSIC
  1135.             case MUS_MOD:
  1136.                 MOD_setvolume(music_playing->data.module, volume);
  1137.                 break;
  1138. #endif
  1139. #ifdef MID_MUSIC
  1140.             case MUS_MID:
  1141. #ifdef USE_NATIVE_MIDI
  1142.                 if ( native_midi_ok ) {
  1143.                         native_midi_setvolume(volume);
  1144.                         return;
  1145.                 }
  1146. #endif
  1147. #ifdef USE_FLUIDSYNTH_MIDI
  1148.                 if ( fluidsynth_ok ) {
  1149.                         fluidsynth_setvolume(music_playing->data.fluidsynthmidi, volume);
  1150.                         return;
  1151.                 }
  1152. #endif
  1153. #ifdef USE_TIMIDITY_MIDI
  1154.                 if ( timidity_ok ) {
  1155.                         Timidity_SetVolume(volume);
  1156.                         return;
  1157.                 }
  1158. #endif
  1159.                 break;
  1160. #endif
  1161. #ifdef OGG_MUSIC
  1162.             case MUS_OGG:
  1163.                 OGG_setvolume(music_playing->data.ogg, volume);
  1164.                 break;
  1165. #endif
  1166. #ifdef FLAC_MUSIC
  1167.             case MUS_FLAC:
  1168.                 FLAC_setvolume(music_playing->data.flac, volume);
  1169.                 break;
  1170. #endif
  1171. #ifdef MP3_MUSIC
  1172.             case MUS_MP3:
  1173.                 smpeg.SMPEG_setvolume(music_playing->data.mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0));
  1174.                 break;
  1175. #endif
  1176. #ifdef MP3_MAD_MUSIC
  1177.             case MUS_MP3_MAD:
  1178.                 mad_setVolume(music_playing->data.mp3_mad, volume);
  1179.                 break;
  1180. #endif
  1181.             default:
  1182.                 /* Unknown music type?? */
  1183.                 break;
  1184.         }
  1185. }
  1186. int Mix_VolumeMusic(int volume)
  1187. {
  1188.         int prev_volume;
  1189.  
  1190.         prev_volume = music_volume;
  1191.         if ( volume < 0 ) {
  1192.                 return prev_volume;
  1193.         }
  1194.         if ( volume > SDL_MIX_MAXVOLUME ) {
  1195.                 volume = SDL_MIX_MAXVOLUME;
  1196.         }
  1197.         music_volume = volume;
  1198.         SDL_LockAudio();
  1199.         if ( music_playing ) {
  1200.                 music_internal_volume(music_volume);
  1201.         }
  1202.         SDL_UnlockAudio();
  1203.         return(prev_volume);
  1204. }
  1205.  
  1206. /* Halt playing of music */
  1207. static void music_internal_halt(void)
  1208. {
  1209.         switch (music_playing->type) {
  1210. #ifdef CMD_MUSIC
  1211.             case MUS_CMD:
  1212.                 MusicCMD_Stop(music_playing->data.cmd);
  1213.                 break;
  1214. #endif
  1215. #ifdef WAV_MUSIC
  1216.             case MUS_WAV:
  1217.                 WAVStream_Stop();
  1218.                 break;
  1219. #endif
  1220. #ifdef MODPLUG_MUSIC
  1221.             case MUS_MODPLUG:
  1222.                 modplug_stop(music_playing->data.modplug);
  1223.                 break;
  1224. #endif
  1225. #ifdef MOD_MUSIC
  1226.             case MUS_MOD:
  1227.                 MOD_stop(music_playing->data.module);
  1228.                 break;
  1229. #endif
  1230. #ifdef MID_MUSIC
  1231.             case MUS_MID:
  1232. #ifdef USE_NATIVE_MIDI
  1233.                 if ( native_midi_ok ) {
  1234.                         native_midi_stop();
  1235.                         goto skip;
  1236.                 }
  1237. #endif
  1238. #ifdef USE_FLUIDSYNTH_MIDI
  1239.                 if ( fluidsynth_ok ) {
  1240.                         fluidsynth_stop(music_playing->data.fluidsynthmidi);
  1241.                         goto skip;
  1242.                 }
  1243. #endif
  1244. #ifdef USE_TIMIDITY_MIDI
  1245.                 if ( timidity_ok ) {
  1246.                         Timidity_Stop();
  1247.                         goto skip;
  1248.                 }
  1249. #endif
  1250.                 break;
  1251. #endif
  1252. #ifdef OGG_MUSIC
  1253.             case MUS_OGG:
  1254.                 OGG_stop(music_playing->data.ogg);
  1255.                 break;
  1256. #endif
  1257. #ifdef FLAC_MUSIC
  1258.             case MUS_FLAC:
  1259.                 FLAC_stop(music_playing->data.flac);
  1260.                 break;
  1261. #endif
  1262. #ifdef MP3_MUSIC
  1263.             case MUS_MP3:
  1264.                 smpeg.SMPEG_stop(music_playing->data.mp3);
  1265.                 break;
  1266. #endif
  1267. #ifdef MP3_MAD_MUSIC
  1268.             case MUS_MP3_MAD:
  1269.                 mad_stop(music_playing->data.mp3_mad);
  1270.                 break;
  1271. #endif
  1272.             default:
  1273.                 /* Unknown music type?? */
  1274.                 return;
  1275.         }
  1276.  
  1277. skip:
  1278.         music_playing->fading = MIX_NO_FADING;
  1279.         music_playing = NULL;
  1280. }
  1281. int Mix_HaltMusic(void)
  1282. {
  1283.         SDL_LockAudio();
  1284.         if ( music_playing ) {
  1285.                 music_internal_halt();
  1286.         }
  1287.         SDL_UnlockAudio();
  1288.  
  1289.         return(0);
  1290. }
  1291.  
  1292. /* Progressively stop the music */
  1293. int Mix_FadeOutMusic(int ms)
  1294. {
  1295.         int retval = 0;
  1296.  
  1297.         if ( ms_per_step == 0 ) {
  1298.                 SDL_SetError("Audio device hasn't been opened");
  1299.                 return 0;
  1300.         }
  1301.  
  1302.         if (ms <= 0) {  /* just halt immediately. */
  1303.                 Mix_HaltMusic();
  1304.                 return 1;
  1305.         }
  1306.  
  1307.         SDL_LockAudio();
  1308.         if ( music_playing) {
  1309.                 int fade_steps = (ms + ms_per_step - 1)/ms_per_step;
  1310.                 if ( music_playing->fading == MIX_NO_FADING ) {
  1311.                         music_playing->fade_step = 0;
  1312.                 } else {
  1313.                         int step;
  1314.                         int old_fade_steps = music_playing->fade_steps;
  1315.                         if ( music_playing->fading == MIX_FADING_OUT ) {
  1316.                                 step = music_playing->fade_step;
  1317.                         } else {
  1318.                                 step = old_fade_steps
  1319.                                         - music_playing->fade_step + 1;
  1320.                         }
  1321.                         music_playing->fade_step = (step * fade_steps)
  1322.                                 / old_fade_steps;
  1323.                 }
  1324.                 music_playing->fading = MIX_FADING_OUT;
  1325.                 music_playing->fade_steps = fade_steps;
  1326.                 retval = 1;
  1327.         }
  1328.         SDL_UnlockAudio();
  1329.  
  1330.         return(retval);
  1331. }
  1332.  
  1333. Mix_Fading Mix_FadingMusic(void)
  1334. {
  1335.         Mix_Fading fading = MIX_NO_FADING;
  1336.  
  1337.         SDL_LockAudio();
  1338.         if ( music_playing ) {
  1339.                 fading = music_playing->fading;
  1340.         }
  1341.         SDL_UnlockAudio();
  1342.  
  1343.         return(fading);
  1344. }
  1345.  
  1346. /* Pause/Resume the music stream */
  1347. void Mix_PauseMusic(void)
  1348. {
  1349.         music_active = 0;
  1350. }
  1351.  
  1352. void Mix_ResumeMusic(void)
  1353. {
  1354.         music_active = 1;
  1355. }
  1356.  
  1357. void Mix_RewindMusic(void)
  1358. {
  1359.         Mix_SetMusicPosition(0.0);
  1360. }
  1361.  
  1362. int Mix_PausedMusic(void)
  1363. {
  1364.         return (music_active == 0);
  1365. }
  1366.  
  1367. /* Check the status of the music */
  1368. static int music_internal_playing()
  1369. {
  1370.         int playing = 1;
  1371.  
  1372.         if (music_playing == NULL) {
  1373.                 return 0;
  1374.         }
  1375.  
  1376.         switch (music_playing->type) {
  1377. #ifdef CMD_MUSIC
  1378.             case MUS_CMD:
  1379.                 if (!MusicCMD_Active(music_playing->data.cmd)) {
  1380.                         playing = 0;
  1381.                 }
  1382.                 break;
  1383. #endif
  1384. #ifdef WAV_MUSIC
  1385.             case MUS_WAV:
  1386.                 if ( ! WAVStream_Active() ) {
  1387.                         playing = 0;
  1388.                 }
  1389.                 break;
  1390. #endif
  1391. #ifdef MODPLUG_MUSIC
  1392.             case MUS_MODPLUG:
  1393.                 if ( ! modplug_playing(music_playing->data.modplug) ) {
  1394.                         playing = 0;
  1395.                 }
  1396.                 break;
  1397. #endif
  1398. #ifdef MOD_MUSIC
  1399.             case MUS_MOD:
  1400.                 if ( ! MOD_playing(music_playing->data.module) ) {
  1401.                         playing = 0;
  1402.                 }
  1403.                 break;
  1404. #endif
  1405. #ifdef MID_MUSIC
  1406.             case MUS_MID:
  1407. #ifdef USE_NATIVE_MIDI
  1408.                 if ( native_midi_ok ) {
  1409.                         if ( ! native_midi_active() )
  1410.                                 playing = 0;
  1411.                         goto skip;
  1412.                 }
  1413. #endif
  1414. #ifdef USE_FLUIDSYNTH_MIDI
  1415.                 if ( fluidsynth_ok ) {
  1416.                         if ( ! fluidsynth_active(music_playing->data.fluidsynthmidi) )
  1417.                                 playing = 0;
  1418.                         goto skip;
  1419.                 }
  1420. #endif
  1421. #ifdef USE_TIMIDITY_MIDI
  1422.                 if ( timidity_ok ) {
  1423.                         if ( ! Timidity_Active() )
  1424.                                 playing = 0;
  1425.                         goto skip;
  1426.                 }
  1427. #endif
  1428.                 break;
  1429. #endif
  1430. #ifdef OGG_MUSIC
  1431.             case MUS_OGG:
  1432.                 if ( ! OGG_playing(music_playing->data.ogg) ) {
  1433.                         playing = 0;
  1434.                 }
  1435.                 break;
  1436. #endif
  1437. #ifdef FLAC_MUSIC
  1438.             case MUS_FLAC:
  1439.                 if ( ! FLAC_playing(music_playing->data.flac) ) {
  1440.                         playing = 0;
  1441.                 }
  1442.                 break;
  1443. #endif
  1444. #ifdef MP3_MUSIC
  1445.             case MUS_MP3:
  1446.                 if ( smpeg.SMPEG_status(music_playing->data.mp3) != SMPEG_PLAYING )
  1447.                         playing = 0;
  1448.                 break;
  1449. #endif
  1450. #ifdef MP3_MAD_MUSIC
  1451.             case MUS_MP3_MAD:
  1452.                 if (!mad_isPlaying(music_playing->data.mp3_mad)) {
  1453.                         playing = 0;
  1454.                 }
  1455.                 break;
  1456. #endif
  1457.             default:
  1458.                 playing = 0;
  1459.                 break;
  1460.         }
  1461.  
  1462. skip:
  1463.         return(playing);
  1464. }
  1465. int Mix_PlayingMusic(void)
  1466. {
  1467.         int playing = 0;
  1468.  
  1469.         SDL_LockAudio();
  1470.         if ( music_playing ) {
  1471.                 playing = music_loops || music_internal_playing();
  1472.         }
  1473.         SDL_UnlockAudio();
  1474.  
  1475.         return(playing);
  1476. }
  1477.  
  1478. /* Set the external music playback command */
  1479. int Mix_SetMusicCMD(const char *command)
  1480. {
  1481.         Mix_HaltMusic();
  1482.         if ( music_cmd ) {
  1483.                 SDL_free(music_cmd);
  1484.                 music_cmd = NULL;
  1485.         }
  1486.         if ( command ) {
  1487.                 music_cmd = (char *)SDL_malloc(strlen(command)+1);
  1488.                 if ( music_cmd == NULL ) {
  1489.                         return(-1);
  1490.                 }
  1491.                 strcpy(music_cmd, command);
  1492.         }
  1493.         return(0);
  1494. }
  1495.  
  1496. int Mix_SetSynchroValue(int i)
  1497. {
  1498.         /* Not supported by any players at this time */
  1499.         return(-1);
  1500. }
  1501.  
  1502. int Mix_GetSynchroValue(void)
  1503. {
  1504.         /* Not supported by any players at this time */
  1505.         return(-1);
  1506. }
  1507.  
  1508.  
  1509. /* Uninitialize the music players */
  1510. void close_music(void)
  1511. {
  1512.         Mix_HaltMusic();
  1513. #ifdef CMD_MUSIC
  1514.         Mix_SetMusicCMD(NULL);
  1515. #endif
  1516. #ifdef MODPLUG_MUSIC
  1517.         modplug_exit();
  1518. #endif
  1519. #ifdef MOD_MUSIC
  1520.         MOD_exit();
  1521. #endif
  1522. #ifdef MID_MUSIC
  1523. # ifdef USE_TIMIDITY_MIDI
  1524.         Timidity_Close();
  1525. # endif
  1526. #endif
  1527.  
  1528.         /* rcg06042009 report available decoders at runtime. */
  1529.         SDL_free(music_decoders);
  1530.         music_decoders = NULL;
  1531.         num_decoders = 0;
  1532.  
  1533.         ms_per_step = 0;
  1534. }
  1535.  
  1536. int Mix_SetSoundFonts(const char *paths)
  1537. {
  1538. #ifdef MID_MUSIC
  1539.         if (soundfont_paths) {
  1540.                 SDL_free(soundfont_paths);
  1541.                 soundfont_paths = NULL;
  1542.         }
  1543.  
  1544.         if (paths) {
  1545.                 if (!(soundfont_paths = SDL_strdup(paths))) {
  1546.                         Mix_SetError("Insufficient memory to set SoundFonts");
  1547.                         return 0;
  1548.                 }
  1549.         }
  1550. #endif
  1551.         return 1;
  1552. }
  1553.  
  1554. #ifdef MID_MUSIC
  1555. const char* Mix_GetSoundFonts(void)
  1556. {
  1557.         const char* force = getenv("SDL_FORCE_SOUNDFONTS");
  1558.  
  1559.         if (!soundfont_paths || (force && force[0] == '1')) {
  1560.                 return getenv("SDL_SOUNDFONTS");
  1561.         } else {
  1562.                 return soundfont_paths;
  1563.         }
  1564. }
  1565.  
  1566. int Mix_EachSoundFont(int (*function)(const char*, void*), void *data)
  1567. {
  1568.         char *context, *path, *paths;
  1569.         const char* cpaths = Mix_GetSoundFonts();
  1570.  
  1571.         if (!cpaths) {
  1572.                 Mix_SetError("No SoundFonts have been requested");
  1573.                 return 0;
  1574.         }
  1575.  
  1576.         if (!(paths = SDL_strdup(cpaths))) {
  1577.                 Mix_SetError("Insufficient memory to iterate over SoundFonts");
  1578.                 return 0;
  1579.         }
  1580.  
  1581. #if defined(__MINGW32__) || defined(__MINGW64__)
  1582.         for (path = strtok(paths, ";"); path; path = strtok(NULL, ";")) {
  1583. #elif defined(_WIN32)
  1584.         for (path = strtok_s(paths, ";", &context); path; path = strtok_s(NULL, ";", &context)) {
  1585. #else
  1586.         for (path = strtok_r(paths, ":;", &context); path; path = strtok_r(NULL, ":;", &context)) {
  1587. #endif
  1588.                 if (!function(path, data)) {
  1589.                         SDL_free(paths);
  1590.                         return 0;
  1591.                 }
  1592.         }
  1593.  
  1594.         SDL_free(paths);
  1595.         return 1;
  1596. }
  1597. #endif
  1598.