/* Play a music chunk. Returns 0, or -1 if there was an error. */ static int music_internal_play(Mix_Music *music, double position) { int retval = 0; #if defined(__MACOSX__) && defined(USE_NATIVE_MIDI) /* This fixes a bug with native MIDI on Mac OS X, where you can't really stop and restart MIDI from the audio callback. */ if ( music == music_playing && music->type == MUS_MID && native_midi_ok ) { /* Just a seek suffices to restart playing */ music_internal_position(position); return 0; } #endif /* Note the music we're playing */ if ( music_playing ) { music_internal_halt(); } music_playing = music; /* Set the initial volume */ if ( music->type != MUS_MOD ) { music_internal_initialize_volume(); } /* Set up for playback */ switch (music->type) { #ifdef CMD_MUSIC case MUS_CMD: MusicCMD_Start(music->data.cmd); break; #endif #ifdef WAV_MUSIC case MUS_WAV: WAVStream_Start(music->data.wave); break; #endif #ifdef MODPLUG_MUSIC case MUS_MODPLUG: /* can't set volume until file is loaded, so finally set it now */ music_internal_initialize_volume(); modplug_play(music->data.modplug); break; #endif #ifdef MOD_MUSIC case MUS_MOD: MOD_play(music->data.module); /* Player_SetVolume() does nothing before Player_Start() */ music_internal_initialize_volume(); break; #endif #ifdef MID_MUSIC case MUS_MID: #ifdef USE_NATIVE_MIDI if ( native_midi_ok ) { native_midi_start(music->data.nativemidi, music_loops); goto skip; } #endif #ifdef USE_FLUIDSYNTH_MIDI if (fluidsynth_ok ) { fluidsynth_start(music->data.fluidsynthmidi); goto skip; } #endif #ifdef USE_TIMIDITY_MIDI if ( timidity_ok ) { Timidity_Start(music->data.midi); goto skip; } #endif break; #endif #ifdef OGG_MUSIC case MUS_OGG: OGG_play(music->data.ogg); break; #endif #ifdef FLAC_MUSIC case MUS_FLAC: FLAC_play(music->data.flac); break; #endif #ifdef MP3_MUSIC case MUS_MP3: smpeg.SMPEG_enableaudio(music->data.mp3,1); smpeg.SMPEG_enablevideo(music->data.mp3,0); smpeg.SMPEG_play(music_playing->data.mp3); break; #endif #ifdef MP3_MAD_MUSIC case MUS_MP3_MAD: mad_start(music->data.mp3_mad); break; #endif default: Mix_SetError("Can't play unknown music type"); retval = -1; break; } skip: /* Set the playback position, note any errors if an offset is used */ if ( retval == 0 ) { if ( position > 0.0 ) { if ( music_internal_position(position) < 0 ) { Mix_SetError("Position not implemented for music type"); retval = -1; } } else { music_internal_position(0.0); } } /* If the setup failed, we're not playing any music anymore */ if ( retval < 0 ) { music_playing = NULL; } return(retval); }
SDL_AudioSpec *Mix_LoadMP3_RW(SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) { /* note: spec is initialized to mixer spec */ #if defined(MP3_MUSIC) SMPEG* mp3 = 0; SMPEG_Info info; #elif defined(MP3_MAD_MUSIC) mad_data *mp3_mad; #endif long samplesize; int read_len; const Uint32 chunk_len = 4096; int err = 0; if ((!src) || (!spec) || (!audio_buf) || (!audio_len)) { return NULL; } if (!err) { *audio_len = 0; *audio_buf = (Uint8*) SDL_malloc(chunk_len); err = (*audio_buf == NULL); } if (!err) { err = ((Mix_Init(MIX_INIT_MP3) & MIX_INIT_MP3) == 0); } if (!err) { #if defined(MP3_MUSIC) mp3 = smpeg.SMPEG_new_rwops(src, &info, freesrc, 0); err = (mp3 == NULL); #elif defined(MP3_MAD_MUSIC) mp3_mad = mad_openFileRW(src, spec, freesrc); err = (mp3_mad == NULL); #endif } #if defined(MP3_MUSIC) if (!err) { err = !info.has_audio; } #endif if (!err) { #if defined(MP3_MUSIC) smpeg.SMPEG_actualSpec(mp3, spec); smpeg.SMPEG_enableaudio(mp3, 1); smpeg.SMPEG_enablevideo(mp3, 0); smpeg.SMPEG_play(mp3); /* read once for audio length */ while ((read_len = smpeg.SMPEG_playAudio(mp3, *audio_buf, chunk_len)) > 0) { *audio_len += read_len; } smpeg.SMPEG_stop(mp3); #elif defined(MP3_MAD_MUSIC) mad_start(mp3_mad); /* read once for audio length */ while ((read_len = mad_getSamples(mp3_mad, *audio_buf, chunk_len)) > 0) { *audio_len += read_len; } mad_stop(mp3_mad); #endif err = (read_len < 0); } if (!err) { /* reallocate, if needed */ if ((*audio_len > 0) && (*audio_len != chunk_len)) { *audio_buf = (Uint8*) SDL_realloc(*audio_buf, *audio_len); err = (*audio_buf == NULL); } } if (!err) { /* read again for audio buffer, if needed */ if (*audio_len > chunk_len) { #if defined(MP3_MUSIC) smpeg.SMPEG_rewind(mp3); smpeg.SMPEG_play(mp3); err = (*audio_len != smpeg.SMPEG_playAudio(mp3, *audio_buf, *audio_len)); smpeg.SMPEG_stop(mp3); #elif defined(MP3_MAD_MUSIC) mad_seek(mp3_mad, 0); mad_start(mp3_mad); err = (*audio_len != mad_getSamples(mp3_mad, *audio_buf, *audio_len)); mad_stop(mp3_mad); #endif } } if (!err) { /* Don't return a buffer that isn't a multiple of samplesize */ samplesize = ((spec->format & 0xFF)/8)*spec->channels; *audio_len &= ~(samplesize-1); } #if defined(MP3_MUSIC) if (mp3) { smpeg.SMPEG_delete(mp3); mp3 = NULL; /* Deleting the MP3 closed the source if desired */ freesrc = SDL_FALSE; } #elif defined(MP3_MAD_MUSIC) if (mp3_mad) { mad_closeFile(mp3_mad); mp3_mad = NULL; /* Deleting the MP3 closed the source if desired */ freesrc = SDL_FALSE; } #endif if (freesrc) { SDL_RWclose(src); src = NULL; } /* handle error */ if (err) { if (*audio_buf != NULL) { SDL_free(*audio_buf); *audio_buf = NULL; } *audio_len = 0; spec = NULL; } return spec; }