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