From ba19e96f8ccda191e67cf3e2f29532feec2abaab Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 31 Dec 2011 18:32:49 -0500 Subject: [PATCH] Fixed bugs 1003, 1021, 1168 - fixed memory leak loading music jjs@jjs.at 2011-03-11 11:37:57 PST When using SDL_Mixer to play WAVE music, the call to Mix_FreeMusic does not close the associated file handle. There is a check in WAVStream_FreeSong() of wavestream.c like this: if ( wave->freerw ) { SDL_FreeRW(wave->rw); } But the variable freerw is not referenced anywhere else. SDL_FreeRW would also not close the file from what I can tell. --- CHANGES | 2 + fluidsynth.c | 10 ++++- fluidsynth.h | 2 +- music.c | 19 ++++---- music_flac.c | 19 +++++--- music_flac.h | 3 +- music_mad.c | 21 ++++----- music_mad.h | 4 +- music_mod.c | 14 +++++- music_mod.h | 2 +- music_modplug.c | 39 +++++++++++----- music_modplug.h | 2 +- music_ogg.c | 27 +++++++---- music_ogg.h | 4 +- native_midi/native_midi.h | 2 +- native_midi/native_midi_haiku.cpp | 9 ++-- native_midi/native_midi_mac.c | 74 +++++-------------------------- native_midi/native_midi_macosx.c | 11 +++-- native_midi/native_midi_win32.c | 40 +++++++---------- playmus.c | 2 +- timidity/playmidi.c | 7 ++- timidity/timidity.h | 2 +- wavestream.c | 29 +++++++----- wavestream.h | 2 +- 24 files changed, 178 insertions(+), 168 deletions(-) diff --git a/CHANGES b/CHANGES index 1e03a5b0..aba30683 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,6 @@ 1.2.12: +Sam Lantinga - Sat Dec 31 18:32:05 EST 2011 + * Fixed memory leak in SDL_LoadMUS() Sam Lantinga - Sat Dec 31 10:22:05 EST 2011 * SDL_mixer is now under the zlib license James Le Cuirot - Mon Mar 21 16:54:11 PDT 2011 diff --git a/fluidsynth.c b/fluidsynth.c index 231f7252..3908f6c5 100644 --- a/fluidsynth.c +++ b/fluidsynth.c @@ -148,9 +148,15 @@ FluidSynthMidiSong *fluidsynth_loadsong(const char *midifile) return fluidsynth_loadsong_common(fluidsynth_loadsong_internal, (void*) midifile); } -FluidSynthMidiSong *fluidsynth_loadsong_RW(SDL_RWops *rw) +FluidSynthMidiSong *fluidsynth_loadsong_RW(SDL_RWops *rw, int freerw) { - return fluidsynth_loadsong_common(fluidsynth_loadsong_RW_internal, (void*) rw); + FluidSynthMidiSong *song; + + song = fluidsynth_loadsong_common(fluidsynth_loadsong_RW_internal, (void*) rw); + if (freerw) { + SDL_RWclose(rw); + } + return song; } void fluidsynth_freesong(FluidSynthMidiSong *song) diff --git a/fluidsynth.h b/fluidsynth.h index 34d006cf..a76b7ce0 100644 --- a/fluidsynth.h +++ b/fluidsynth.h @@ -37,7 +37,7 @@ typedef struct { int fluidsynth_init(SDL_AudioSpec *mixer); FluidSynthMidiSong *fluidsynth_loadsong(const char *midifile); -FluidSynthMidiSong *fluidsynth_loadsong_RW(SDL_RWops *rw); +FluidSynthMidiSong *fluidsynth_loadsong_RW(SDL_RWops *rw, int freerw); void fluidsynth_freesong(FluidSynthMidiSong *song); void fluidsynth_start(FluidSynthMidiSong *song); void fluidsynth_stop(FluidSynthMidiSong *song); diff --git a/music.c b/music.c index cf30a67d..452aacf7 100644 --- a/music.c +++ b/music.c @@ -1391,6 +1391,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) Uint8 moremagic[9]; Mix_Music *music; int start; + int freerw = 0; if (!rw) { Mix_SetError("RWops pointer is NULL"); @@ -1423,7 +1424,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) if ( ((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) || (strcmp((char *)magic, "FORM") == 0) ) { music->type = MUS_WAV; - music->data.wave = WAVStream_LoadSong_RW(rw, (char *)magic); + music->data.wave = WAVStream_LoadSong_RW(rw, (char *)magic, freerw); if ( music->data.wave == NULL ) { music->error = 1; } @@ -1434,7 +1435,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) /* Ogg Vorbis files have the magic four bytes "OggS" */ if ( strcmp((char *)magic, "OggS") == 0 ) { music->type = MUS_OGG; - music->data.ogg = OGG_new_RW(rw); + music->data.ogg = OGG_new_RW(rw, freerw); if ( music->data.ogg == NULL ) { music->error = 1; } @@ -1444,7 +1445,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) /* FLAC files have the magic four bytes "fLaC" */ if ( strcmp((char *)magic, "fLaC") == 0 ) { music->type = MUS_FLAC; - music->data.flac = FLAC_new_RW(rw); + music->data.flac = FLAC_new_RW(rw, freerw); if ( music->data.flac == NULL ) { music->error = 1; } @@ -1470,7 +1471,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) #ifdef MP3_MAD_MUSIC if ( ( magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) || ( strncmp((char *)magic, "ID3", 3) == 0 ) ) { music->type = MUS_MP3_MAD; - music->data.mp3_mad = mad_openFileRW(rw, &used_mixer); + music->data.mp3_mad = mad_openFileRW(rw, &used_mixer, freerw); if (music->data.mp3_mad == 0) { Mix_SetError("Could not initialize MPEG stream."); music->error = 1; @@ -1483,7 +1484,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) music->type = MUS_MID; #ifdef USE_NATIVE_MIDI if ( native_midi_ok ) { - music->data.nativemidi = native_midi_loadsong_RW(rw); + music->data.nativemidi = native_midi_loadsong_RW(rw, freerw); if ( music->data.nativemidi == NULL ) { Mix_SetError("%s", native_midi_error()); music->error = 1; @@ -1493,7 +1494,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) #endif #ifdef USE_FLUIDSYNTH_MIDI if ( fluidsynth_ok ) { - music->data.fluidsynthmidi = fluidsynth_loadsong_RW(rw); + music->data.fluidsynthmidi = fluidsynth_loadsong_RW(rw, freerw); if ( music->data.fluidsynthmidi == NULL ) { music->error = 1; } @@ -1502,7 +1503,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) #endif #ifdef USE_TIMIDITY_MIDI if ( timidity_ok ) { - music->data.midi = Timidity_LoadSong_RW(rw); + music->data.midi = Timidity_LoadSong_RW(rw, freerw); if ( music->data.midi == NULL ) { Mix_SetError("%s", Timidity_Error()); music->error = 1; @@ -1520,7 +1521,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) #ifdef MODPLUG_MUSIC if ( music->error ) { music->type = MUS_MODPLUG; - music->data.modplug = modplug_new_RW(rw); + music->data.modplug = modplug_new_RW(rw, freerw); if ( music->data.modplug ) { music->error = 0; } @@ -1529,7 +1530,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) #ifdef MOD_MUSIC if ( music->error ) { music->type = MUS_MOD; - music->data.module = MOD_new_RW(rw); + music->data.module = MOD_new_RW(rw, freerw); if ( music->data.module ) { music->error = 0; } diff --git a/music_flac.c b/music_flac.c index a211cda5..8c9a4545 100644 --- a/music_flac.c +++ b/music_flac.c @@ -60,7 +60,7 @@ FLAC_music *FLAC_new(const char *file) SDL_SetError ("Couldn't open %s", file); return NULL; } - return FLAC_new_RW (rw); + return FLAC_new_RW (rw, 1); } static FLAC__StreamDecoderReadStatus flac_read_music_cb( @@ -313,7 +313,7 @@ static void flac_error_music_cb( } /* Load an FLAC stream from an SDL_RWops object */ -FLAC_music *FLAC_new_RW(SDL_RWops *rw) +FLAC_music *FLAC_new_RW(SDL_RWops *rw, int freerw) { FLAC_music *music; int init_stage = 0; @@ -327,6 +327,7 @@ FLAC_music *FLAC_new_RW(SDL_RWops *rw) FLAC_setvolume (music, MIX_MAX_VOLUME); music->section = -1; music->rwops = rw; + music->freerw = freerw; music->flac_data.max_to_read = 0; music->flac_data.overflow = NULL; music->flac_data.overflow_len = 0; @@ -375,14 +376,19 @@ FLAC_music *FLAC_new_RW(SDL_RWops *rw) case 1: case 0: free(music); - SDL_RWclose(rw); + if (freerw) { + SDL_RWclose(rw); + } break; } return NULL; } - } - else { + } else { SDL_OutOfMemory(); + if (freerw) { + SDL_RWclose(rw); + } + return NULL; } return music; @@ -556,6 +562,9 @@ void FLAC_delete(FLAC_music *music) free (music->cvt.buf); } + if (music->freerw) { + SDL_RWclose(music->rwops); + } free (music); } } diff --git a/music_flac.h b/music_flac.h index b152d659..5696b5d0 100644 --- a/music_flac.h +++ b/music_flac.h @@ -52,6 +52,7 @@ typedef struct { FLAC__StreamDecoder *flac_decoder; FLAC_Data flac_data; SDL_RWops *rwops; + int freerw; SDL_AudioCVT cvt; int len_available; Uint8 *snd_available; @@ -69,7 +70,7 @@ extern void FLAC_setvolume(FLAC_music *music, int volume); extern FLAC_music *FLAC_new(const char *file); /* Load an FLAC stream from an SDL_RWops object */ -extern FLAC_music *FLAC_new_RW(SDL_RWops *rw); +extern FLAC_music *FLAC_new_RW(SDL_RWops *rw, int freerw); /* Start playback of a given FLAC stream */ extern void FLAC_play(FLAC_music *music); diff --git a/music_mad.c b/music_mad.c index 5cb23a96..f0cfc6bc 100644 --- a/music_mad.c +++ b/music_mad.c @@ -26,7 +26,8 @@ #include "music_mad.h" mad_data * -mad_openFile(const char *filename, SDL_AudioSpec *mixer) { +mad_openFile(const char *filename, SDL_AudioSpec *mixer) +{ SDL_RWops *rw; mad_data *mp3_mad; @@ -35,23 +36,18 @@ mad_openFile(const char *filename, SDL_AudioSpec *mixer) { return NULL; } - mp3_mad = mad_openFileRW(rw, mixer); - if (mp3_mad == NULL) { - SDL_FreeRW(rw); - return NULL; - } - mp3_mad->freerw = SDL_TRUE; - return mp3_mad; + return mad_openFileRW(rw, mixer, 1); } mad_data * -mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer) { +mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer, int freerw) +{ mad_data *mp3_mad; mp3_mad = (mad_data *)malloc(sizeof(mad_data)); if (mp3_mad) { mp3_mad->rw = rw; - mp3_mad->freerw = SDL_FALSE; + mp3_mad->freerw = freerw; mad_stream_init(&mp3_mad->stream); mad_frame_init(&mp3_mad->frame); mad_synth_init(&mp3_mad->synth); @@ -67,13 +63,14 @@ mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer) { } void -mad_closeFile(mad_data *mp3_mad) { +mad_closeFile(mad_data *mp3_mad) +{ mad_stream_finish(&mp3_mad->stream); mad_frame_finish(&mp3_mad->frame); mad_synth_finish(&mp3_mad->synth); if (mp3_mad->freerw) { - SDL_FreeRW(mp3_mad->rw); + SDL_RWclose(mp3_mad->rw); } free(mp3_mad); } diff --git a/music_mad.h b/music_mad.h index 5969ff41..fe2a4276 100644 --- a/music_mad.h +++ b/music_mad.h @@ -42,7 +42,7 @@ enum { typedef struct { SDL_RWops *rw; - SDL_bool freerw; + int freerw; struct mad_stream stream; struct mad_frame frame; struct mad_synth synth; @@ -59,7 +59,7 @@ typedef struct { } mad_data; mad_data *mad_openFile(const char *filename, SDL_AudioSpec *mixer); -mad_data *mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer); +mad_data *mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer, int freerw); void mad_closeFile(mad_data *mp3_mad); void mad_start(mad_data *mp3_mad); diff --git a/music_mod.c b/music_mod.c index b6236b39..63774f23 100644 --- a/music_mod.c +++ b/music_mod.c @@ -152,7 +152,7 @@ MODULE *MOD_new(const char *file) SDL_SetError("Couldn't open %s", file); return NULL; } - return MOD_new_RW(rw); + return MOD_new_RW(rw, 1); } @@ -215,18 +215,24 @@ MODULE *MikMod_LoadSongRW(SDL_RWops *rw, int maxchan) } /* Load a MOD stream from an SDL_RWops object */ -MODULE *MOD_new_RW(SDL_RWops *rw) +MODULE *MOD_new_RW(SDL_RWops *rw, int freerw) { MODULE *module; /* Make sure the mikmod library is loaded */ if ( !Mix_Init(MIX_INIT_MOD) ) { + if ( freerw ) { + SDL_RWclose(rw); + } return NULL; } module = MikMod_LoadSongRW(rw,64); if (!module) { Mix_SetError("%s", mikmod.MikMod_strerror(*mikmod.MikMod_errno)); + if ( freerw ) { + SDL_RWclose(rw); + } return NULL; } @@ -239,6 +245,10 @@ MODULE *MOD_new_RW(SDL_RWops *rw) to query the status of the song or set trigger actions. Hum. */ module->fadeout = 1; #endif + + if ( freerw ) { + SDL_RWclose(rw); + } return module; } diff --git a/music_mod.h b/music_mod.h index a951b6b5..a934240f 100644 --- a/music_mod.h +++ b/music_mod.h @@ -42,7 +42,7 @@ extern void MOD_setvolume(struct MODULE *music, int volume); extern struct MODULE *MOD_new(const char *file); /* Load a MOD stream from an SDL_RWops object */ -extern struct MODULE *MOD_new_RW(SDL_RWops *rw); +extern struct MODULE *MOD_new_RW(SDL_RWops *rw, int freerw); /* Start playback of a given MOD stream */ extern void MOD_play(struct MODULE *music); diff --git a/music_modplug.c b/music_modplug.c index a0d4262f..221d6205 100644 --- a/music_modplug.c +++ b/music_modplug.c @@ -85,12 +85,12 @@ modplug_data *modplug_new(const char *file) SDL_SetError("Couldn't open %s", file); return NULL; } - return modplug_new_RW(rw); + return modplug_new_RW(rw, 1); } /* Load a modplug stream from an SDL_RWops object */ -modplug_data *modplug_new_RW(SDL_RWops *rw) +modplug_data *modplug_new_RW(SDL_RWops *rw, int freerw) { modplug_data *music=NULL; long offset,sz; @@ -101,20 +101,35 @@ modplug_data *modplug_new_RW(SDL_RWops *rw) sz = SDL_RWtell(rw)-offset; SDL_RWseek(rw, offset, RW_SEEK_SET); buf=(char*)malloc(sz); - if(!buf) - return NULL; - if(SDL_RWread(rw, buf, sz, 1)==1) + if(buf) { - music=(modplug_data*)malloc(sizeof(modplug_data)); - music->playing=0; - music->file=ModPlug_Load(buf,sz); - if(!music->file) + if(SDL_RWread(rw, buf, sz, 1)==1) { - free(music); - music=NULL; + music=(modplug_data*)malloc(sizeof(modplug_data)); + if (music) + { + music->playing=0; + music->file=ModPlug_Load(buf,sz); + if(!music->file) + { + free(music); + music=NULL; + } + } + else + { + SDL_OutOfMemory(); + } } + free(buf); + } + else + { + SDL_OutOfMemory(); + } + if (freerw) { + SDL_RWclose(rw); } - free(buf); return music; } diff --git a/music_modplug.h b/music_modplug.h index 1c90b673..76cdfdc6 100644 --- a/music_modplug.h +++ b/music_modplug.h @@ -22,7 +22,7 @@ void modplug_setvolume(modplug_data *music, int volume); modplug_data *modplug_new(const char *file); /* Load a modplug stream from an SDL_RWops object */ -modplug_data *modplug_new_RW(SDL_RWops *rw); +modplug_data *modplug_new_RW(SDL_RWops *rw, int freerw); /* Start playback of a given modplug stream */ void modplug_play(modplug_data *music); diff --git a/music_ogg.c b/music_ogg.c index 6723d095..3f4d2c99 100644 --- a/music_ogg.c +++ b/music_ogg.c @@ -61,7 +61,7 @@ OGG_music *OGG_new(const char *file) SDL_SetError("Couldn't open %s", file); return NULL; } - return OGG_new_RW(rw); + return OGG_new_RW(rw, 1); } @@ -75,46 +75,52 @@ static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence) return SDL_RWseek((SDL_RWops*)datasource, (int)offset, whence); } -static int sdl_close_func(void *datasource) -{ - return SDL_RWclose((SDL_RWops*)datasource); -} - static long sdl_tell_func(void *datasource) { return SDL_RWtell((SDL_RWops*)datasource); } /* Load an OGG stream from an SDL_RWops object */ -OGG_music *OGG_new_RW(SDL_RWops *rw) +OGG_music *OGG_new_RW(SDL_RWops *rw, int freerw) { OGG_music *music; ov_callbacks callbacks; + SDL_memset(&callbacks, 0, sizeof(callbacks)); callbacks.read_func = sdl_read_func; callbacks.seek_func = sdl_seek_func; - callbacks.close_func = sdl_close_func; callbacks.tell_func = sdl_tell_func; music = (OGG_music *)malloc(sizeof *music); if ( music ) { /* Initialize the music structure */ memset(music, 0, (sizeof *music)); + music->rw = rw; + music->freerw = freerw; OGG_stop(music); OGG_setvolume(music, MIX_MAX_VOLUME); music->section = -1; if ( !Mix_Init(MIX_INIT_OGG) ) { + if ( freerw ) { + SDL_RWclose(rw); + } return(NULL); } if ( vorbis.ov_open_callbacks(rw, &music->vf, NULL, 0, callbacks) < 0 ) { free(music); - SDL_RWclose(rw); + if ( freerw ) { + SDL_RWclose(rw); + } SDL_SetError("Not an Ogg Vorbis audio stream"); return(NULL); } } else { + if ( freerw ) { + SDL_RWclose(rw); + } SDL_OutOfMemory(); + return(NULL); } return(music); } @@ -220,6 +226,9 @@ void OGG_delete(OGG_music *music) if ( music->cvt.buf ) { free(music->cvt.buf); } + if ( music->freerw ) { + SDL_RWclose(music->rw); + } vorbis.ov_clear(&music->vf); free(music); } diff --git a/music_ogg.h b/music_ogg.h index 87c2b15d..af70e01c 100644 --- a/music_ogg.h +++ b/music_ogg.h @@ -32,6 +32,8 @@ #endif typedef struct { + SDL_RWops *rw; + int freerw; int playing; int volume; OggVorbis_File vf; @@ -53,7 +55,7 @@ extern void OGG_setvolume(OGG_music *music, int volume); extern OGG_music *OGG_new(const char *file); /* Load an OGG stream from an SDL_RWops object */ -extern OGG_music *OGG_new_RW(SDL_RWops *rw); +extern OGG_music *OGG_new_RW(SDL_RWops *rw, int freerw); /* Start playback of a given OGG stream */ extern void OGG_play(OGG_music *music); diff --git a/native_midi/native_midi.h b/native_midi/native_midi.h index 2497d7ff..25846077 100644 --- a/native_midi/native_midi.h +++ b/native_midi/native_midi.h @@ -28,7 +28,7 @@ typedef struct _NativeMidiSong NativeMidiSong; int native_midi_detect(); NativeMidiSong *native_midi_loadsong(const char *midifile); -NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw); +NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw); void native_midi_freesong(NativeMidiSong *song); void native_midi_start(NativeMidiSong *song); void native_midi_stop(); diff --git a/native_midi/native_midi_haiku.cpp b/native_midi/native_midi_haiku.cpp index 0a2f5b9f..83645a29 100644 --- a/native_midi/native_midi_haiku.cpp +++ b/native_midi/native_midi_haiku.cpp @@ -213,12 +213,15 @@ void native_midi_setvolume(int volume) synth.SetVolume(volume / 128.0); } -NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) +NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw) { NativeMidiSong *song = new NativeMidiSong; song->store = new MidiEventsStore; status_t res = song->store->Import(rw); + if (freerw) { + SDL_RWclose(rw); + } if (res != B_OK) { snprintf(lasterr, sizeof lasterr, "Cannot Import() midi file: status_t=%d", res); @@ -233,9 +236,7 @@ NativeMidiSong *native_midi_loadsong(const char *midifile) { SDL_RWops *rw = SDL_RWFromFile(midifile, "rb"); if (!rw) return NULL; - NativeMidiSong *song = native_midi_loadsong_RW(rw); - SDL_RWclose(rw); - return song; + return native_midi_loadsong_RW(rw, 1); } void native_midi_freesong(NativeMidiSong *song) diff --git a/native_midi/native_midi_mac.c b/native_midi/native_midi_mac.c index eadf39c7..0a9e5c57 100644 --- a/native_midi/native_midi_mac.c +++ b/native_midi/native_midi_mac.c @@ -90,73 +90,17 @@ int native_midi_detect() NativeMidiSong *native_midi_loadsong(const char *midifile) { - NativeMidiSong *song = NULL; - MIDIEvent *evntlist = NULL; - int part_to_inst[32]; - int part_poly_max[32]; - int numParts = 0; - Uint16 ppqn; - SDL_RWops *rw; + SDL_RWops *rw; - /* Init the arrays */ - memset(part_poly_max,0,sizeof(part_poly_max)); - memset(part_to_inst,-1,sizeof(part_to_inst)); - /* Attempt to load the midi file */ rw = SDL_RWFromFile(midifile, "rb"); - if (rw) { - evntlist = CreateMIDIEventList(rw, &ppqn); - SDL_RWclose(rw); - if (!evntlist) - goto bail; - } - - /* Allocate memory for the song struct */ - song = malloc(sizeof(NativeMidiSong)); - if (!song) - goto bail; - - /* Build a tune sequence from the event list */ - song->tuneSequence = BuildTuneSequence(evntlist, ppqn, part_poly_max, part_to_inst, &numParts); - if(!song->tuneSequence) - goto bail; - - /* Now build a tune header from the data we collect above, create - all parts as needed and assign them the correct instrument. - */ - song->tuneHeader = BuildTuneHeader(part_poly_max, part_to_inst, numParts); - if(!song->tuneHeader) - goto bail; - - /* Increment the instance count */ - gInstaceCount++; - if (gTunePlayer == NULL) - gTunePlayer = OpenDefaultComponent(kTunePlayerComponentType, 0); - - /* Finally, free the event list */ - FreeMIDIEventList(evntlist); - - return song; - -bail: - if (evntlist) - FreeMIDIEventList(evntlist); - - if (song) - { - if(song->tuneSequence) - free(song->tuneSequence); - - if(song->tuneHeader) - DisposePtr((Ptr)song->tuneHeader); - - free(song); + if (!rw) { + return NULL; } - - return NULL; + return native_midi_loadsong_RW(rw, 1); } -NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) +NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw) { NativeMidiSong *song = NULL; MIDIEvent *evntlist = NULL; @@ -198,7 +142,10 @@ NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) /* Finally, free the event list */ FreeMIDIEventList(evntlist); - + + if (freerw) { + SDL_RWclose(rw); + } return song; bail: @@ -216,6 +163,9 @@ NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) free(song); } + if (freerw) { + SDL_RWclose(rw); + } return NULL; } diff --git a/native_midi/native_midi_macosx.c b/native_midi/native_midi_macosx.c index 73e5e03d..8a684df6 100644 --- a/native_midi/native_midi_macosx.c +++ b/native_midi/native_midi_macosx.c @@ -149,14 +149,13 @@ NativeMidiSong *native_midi_loadsong(const char *midifile) NativeMidiSong *retval = NULL; SDL_RWops *rw = SDL_RWFromFile(midifile, "rb"); if (rw != NULL) { - retval = native_midi_loadsong_RW(rw); - SDL_RWclose(rw); + retval = native_midi_loadsong_RW(rw, 1); } return retval; } -NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) +NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw) { NativeMidiSong *retval = NULL; void *buf = NULL; @@ -213,6 +212,9 @@ NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) if (MusicPlayerSetSequence(retval->player, retval->sequence) != noErr) goto fail; + if (freerw) + SDL_RWclose(rw); + return retval; fail: @@ -230,6 +232,9 @@ NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) if (buf) free(buf); + if (freerw) + SDL_RWclose(rw); + return NULL; } diff --git a/native_midi/native_midi_win32.c b/native_midi/native_midi_win32.c index 896ab4bc..69a726a4 100644 --- a/native_midi/native_midi_win32.c +++ b/native_midi/native_midi_win32.c @@ -189,42 +189,28 @@ int native_midi_detect() NativeMidiSong *native_midi_loadsong(const char *midifile) { - NativeMidiSong *newsong; - MIDIEvent *evntlist = NULL; - SDL_RWops *rw; - - newsong=malloc(sizeof(NativeMidiSong)); - if (!newsong) - return NULL; - memset(newsong,0,sizeof(NativeMidiSong)); + SDL_RWops *rw; /* Attempt to load the midi file */ rw = SDL_RWFromFile(midifile, "rb"); - if (rw) { - evntlist = CreateMIDIEventList(rw, &newsong->ppqn); - SDL_RWclose(rw); - if (!evntlist) - { - free(newsong); - return NULL; - } + if (!rw) { + return NULL; } - - MIDItoStream(newsong, evntlist); - - FreeMIDIEventList(evntlist); - - return newsong; + return native_midi_loadsong_RW(rw, 1); } -NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) +NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw) { NativeMidiSong *newsong; MIDIEvent *evntlist = NULL; newsong=malloc(sizeof(NativeMidiSong)); - if (!newsong) + if (!newsong) { + if (freerw) { + SDL_RWclose(rw); + } return NULL; + } memset(newsong,0,sizeof(NativeMidiSong)); /* Attempt to load the midi file */ @@ -232,6 +218,9 @@ NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) if (!evntlist) { free(newsong); + if (freerw) { + SDL_RWclose(rw); + } return NULL; } @@ -239,6 +228,9 @@ NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw) FreeMIDIEventList(evntlist); + if (freerw) { + SDL_RWclose(rw); + } return newsong; } diff --git a/playmus.c b/playmus.c index 02bcc034..2d473122 100644 --- a/playmus.c +++ b/playmus.c @@ -222,7 +222,7 @@ int main(int argc, char *argv[]) } Mix_FreeMusic(music); if ( rwops ) { - SDL_FreeRW(rwfp); + SDL_RWclose(rwfp); } music = NULL; diff --git a/timidity/playmidi.c b/timidity/playmidi.c index a778c556..0238547f 100644 --- a/timidity/playmidi.c +++ b/timidity/playmidi.c @@ -1703,7 +1703,7 @@ MidiSong *Timidity_LoadSong(const char *midifile) return(song); } -MidiSong *Timidity_LoadSong_RW(SDL_RWops *rw) +MidiSong *Timidity_LoadSong_RW(SDL_RWops *rw, int freerw) { MidiSong *song; int32 events; @@ -1714,7 +1714,10 @@ MidiSong *Timidity_LoadSong_RW(SDL_RWops *rw) strcpy(midi_name, "SDLrwops source"); - song->events=read_midi_file(rw, &events, &song->samples); + song->events = read_midi_file(rw, &events, &song->samples); + if (freerw) { + SDL_RWclose(rw); + } /* Make sure everything is okay */ if (!song->events) { diff --git a/timidity/timidity.h b/timidity/timidity.h index 9c703a87..72d61d02 100644 --- a/timidity/timidity.h +++ b/timidity/timidity.h @@ -13,7 +13,7 @@ extern const char *Timidity_Error(void); extern void Timidity_SetVolume(int volume); extern int Timidity_PlaySome(void *stream, int samples); extern MidiSong *Timidity_LoadSong(const char *midifile); -extern MidiSong *Timidity_LoadSong_RW(SDL_RWops *rw); +extern MidiSong *Timidity_LoadSong_RW(SDL_RWops *rw, int freerw); extern void Timidity_Start(MidiSong *song); extern int Timidity_Active(void); extern void Timidity_Stop(void); diff --git a/wavestream.c b/wavestream.c index 7ccf1d2b..265caca0 100644 --- a/wavestream.c +++ b/wavestream.c @@ -116,34 +116,32 @@ void WAVStream_SetVolume(int volume) WAVStream *WAVStream_LoadSong(const char *file, const char *magic) { SDL_RWops *rw; - WAVStream *wave; rw = SDL_RWFromFile(file, "rb"); if ( rw == NULL ) { SDL_SetError("Couldn't open %s", file); return NULL; } - wave = WAVStream_LoadSong_RW(rw, magic); - if ( wave == NULL ) { - SDL_FreeRW(rw); - return NULL; - } - return wave; + return WAVStream_LoadSong_RW(rw, magic, 1); } /* Load a WAV stream from the given file */ -WAVStream *WAVStream_LoadSong_RW(SDL_RWops *rw, const char *magic) +WAVStream *WAVStream_LoadSong_RW(SDL_RWops *rw, const char *magic, int freerw) { WAVStream *wave; SDL_AudioSpec wavespec; if ( ! mixer.format ) { Mix_SetError("WAV music output not started"); + if ( freerw ) { + SDL_RWclose(rw); + } return(NULL); } wave = (WAVStream *)malloc(sizeof *wave); if ( wave ) { memset(wave, 0, (sizeof *wave)); + wave->freerw = freerw; if ( strcmp(magic, "RIFF") == 0 ) { wave->rw = LoadWAVStream(rw, &wavespec, &wave->start, &wave->stop); @@ -156,11 +154,20 @@ WAVStream *WAVStream_LoadSong_RW(SDL_RWops *rw, const char *magic) } if ( wave->rw == NULL ) { free(wave); + if ( freerw ) { + SDL_RWclose(rw); + } return(NULL); } SDL_BuildAudioCVT(&wave->cvt, wavespec.format, wavespec.channels, wavespec.freq, mixer.format, mixer.channels, mixer.freq); + } else { + SDL_OutOfMemory(); + if ( freerw ) { + SDL_RWclose(rw); + } + return(NULL); } return(wave); } @@ -242,12 +249,12 @@ void WAVStream_FreeSong(WAVStream *wave) { if ( wave ) { /* Clean up associated data */ - if ( wave->freerw ) { - SDL_FreeRW(wave->rw); - } if ( wave->cvt.buf ) { free(wave->cvt.buf); } + if ( wave->freerw ) { + SDL_RWclose(wave->rw); + } free(wave); } } diff --git a/wavestream.h b/wavestream.h index 5a4ffb53..4d1e7db2 100644 --- a/wavestream.h +++ b/wavestream.h @@ -45,7 +45,7 @@ extern void WAVStream_SetVolume(int volume); extern WAVStream *WAVStream_LoadSong(const char *file, const char *magic); /* Load a WAV stream from an SDL_RWops object */ -extern WAVStream *WAVStream_LoadSong_RW(SDL_RWops *rw, const char *magic); +extern WAVStream *WAVStream_LoadSong_RW(SDL_RWops *rw, const char *magic, int freerw); /* Start playback of a given WAV stream */ extern void WAVStream_Start(WAVStream *wave);