SDL_mixer: Updated for the SDL3 RW -> IO changes

From e8fa3dc518edeb0cb27df079aa9925f9b3754db4 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 18 Mar 2024 13:02:37 -0700
Subject: [PATCH] Updated for the SDL3 RW -> IO changes

Fixes https://github.com/libsdl-org/SDL_mixer/issues/597
---
 examples/playmus.c                           |  16 +-
 examples/playwave.c                          |  10 +-
 external/SDL                                 |   2 +-
 include/SDL3_mixer/SDL_mixer.h               |  62 +++----
 src/SDL_mixer.sym                            |   6 +-
 src/codecs/load_aiff.c                       |  28 +--
 src/codecs/load_aiff.h                       |  10 +-
 src/codecs/load_sndfile.c                    |  34 ++--
 src/codecs/load_sndfile.h                    |  10 +-
 src/codecs/load_voc.c                        |  64 +++----
 src/codecs/load_voc.h                        |  10 +-
 src/codecs/mp3utils.c                        | 176 +++++++++----------
 src/codecs/mp3utils.h                        |  10 +-
 src/codecs/music_cmd.c                       |   2 +-
 src/codecs/music_drflac.c                    |  20 +--
 src/codecs/music_flac.c                      |  49 +++---
 src/codecs/music_fluidsynth.c                |  31 ++--
 src/codecs/music_gme.c                       |  14 +-
 src/codecs/music_minimp3.c                   |  20 +--
 src/codecs/music_modplug.c                   |  12 +-
 src/codecs/music_mpg123.c                    |  30 ++--
 src/codecs/music_nativemidi.c                |   6 +-
 src/codecs/music_ogg.c                       |  22 +--
 src/codecs/music_ogg_stb.c                   |  20 +--
 src/codecs/music_opus.c                      |  22 +--
 src/codecs/music_timidity.c                  |   8 +-
 src/codecs/music_wav.c                       |  74 ++++----
 src/codecs/music_wavpack.c                   |  76 ++++----
 src/codecs/music_xmp.c                       |  24 +--
 src/codecs/native_midi/native_midi.h         |   4 +-
 src/codecs/native_midi/native_midi_common.c  |  24 +--
 src/codecs/native_midi/native_midi_common.h  |   2 +-
 src/codecs/native_midi/native_midi_haiku.cpp |   8 +-
 src/codecs/native_midi/native_midi_macosx.c  |   8 +-
 src/codecs/native_midi/native_midi_win32.c   |   6 +-
 src/codecs/stb_vorbis/stb_vorbis.h           |  42 ++---
 src/codecs/timidity/CHANGES                  |   2 +-
 src/codecs/timidity/common.c                 |  12 +-
 src/codecs/timidity/common.h                 |   2 +-
 src/codecs/timidity/instrum.c                |  56 +++---
 src/codecs/timidity/readmidi.c               |  94 +++++-----
 src/codecs/timidity/timidity.c               |  22 +--
 src/codecs/timidity/timidity.h               |  12 +-
 src/mixer.c                                  |  52 +++---
 src/music.c                                  |  50 +++---
 src/music.h                                  |   8 +-
 46 files changed, 635 insertions(+), 637 deletions(-)

diff --git a/examples/playmus.c b/examples/playmus.c
index 03af89d4..d8747840 100644
--- a/examples/playmus.c
+++ b/examples/playmus.c
@@ -63,7 +63,7 @@ static void CleanUp(int exitcode)
 
 static void Usage(char *argv0)
 {
-    SDL_Log("Usage: %s [-i] [-l] [-8] [-f32] [-r rate] [-c channels] [-b buffers] [-v N] [-rwops] <musicfile>\n", argv0);
+    SDL_Log("Usage: %s [-i] [-l] [-8] [-f32] [-r rate] [-c channels] [-b buffers] [-v N] [-io] <musicfile>\n", argv0);
 }
 
 /*#define SEEK_TEST */
@@ -114,8 +114,8 @@ int main(int argc, char *argv[])
 {
     int audio_volume = MIX_MAX_VOLUME;
     int looping = 0;
-    int interactive = 0;
-    int rwops = 0;
+    SDL_bool interactive = SDL_FALSE;
+    SDL_bool use_io = SDL_FALSE;
     int i;
     const char *typ;
     const char *tag_title = NULL;
@@ -157,7 +157,7 @@ int main(int argc, char *argv[])
             looping = -1;
         } else
         if (SDL_strcmp(argv[i], "-i") == 0) {
-            interactive = 1;
+            interactive = SDL_TRUE;
         } else
         if (SDL_strcmp(argv[i], "-8") == 0) {
             spec.format = SDL_AUDIO_U8;
@@ -165,8 +165,8 @@ int main(int argc, char *argv[])
         if (SDL_strcmp(argv[i], "-f32") == 0) {
             spec.format = SDL_AUDIO_F32;
         } else
-        if (SDL_strcmp(argv[i], "-rwops") == 0) {
-            rwops = 1;
+        if (SDL_strcmp(argv[i], "-io") == 0) {
+            use_io = 1;
         } else {
             Usage(argv[0]);
             return 1;
@@ -211,8 +211,8 @@ int main(int argc, char *argv[])
         next_track = 0;
 
         /* Load the requested music file */
-        if (rwops) {
-            music = Mix_LoadMUS_RW(SDL_RWFromFile(argv[i], "rb"), SDL_TRUE);
+        if (use_io) {
+            music = Mix_LoadMUS_IO(SDL_IOFromFile(argv[i], "rb"), SDL_TRUE);
         } else {
             music = Mix_LoadMUS(argv[i]);
         }
diff --git a/examples/playwave.c b/examples/playwave.c
index b66223f0..a6c15fba 100644
--- a/examples/playwave.c
+++ b/examples/playwave.c
@@ -105,8 +105,8 @@ static void report_decoders(void)
 
 /* rcg06192001 Check new Mixer version API. */
 #if (defined TEST_MIX_VERSIONS)
-static void output_versions(const char *libname, const SDL_version *compiled,
-                            const SDL_version *linked)
+static void output_versions(const char *libname, const SDL_Version *compiled,
+                            const SDL_Version *linked)
 {
     SDL_Log("This program was compiled against %s %d.%d.%d,\n"
             " and is dynamically linked to %d.%d.%d.\n", libname,
@@ -116,15 +116,15 @@ static void output_versions(const char *libname, const SDL_version *compiled,
 
 static void test_versions(void)
 {
-    SDL_version compiled;
-    SDL_version linked;
+    SDL_Version compiled;
+    SDL_Version linked;
 
     SDL_VERSION(&compiled);
     SDL_GetVersion(&linked);
     output_versions("SDL", &compiled, &linked);
 
     SDL_MIXER_VERSION(&compiled);
-    SDL_memcpy(&linked, Mix_Linked_Version(), sizeof(SDL_version));
+    SDL_memcpy(&linked, Mix_Linked_Version(), sizeof(SDL_Version));
     output_versions("SDL_mixer", &compiled, &linked);
 }
 #endif
diff --git a/external/SDL b/external/SDL
index 814a94c3..f59dbf6a 160000
--- a/external/SDL
+++ b/external/SDL
@@ -1 +1 @@
-Subproject commit 814a94c34985c6d3a7fbd906885b1dfea0979925
+Subproject commit f59dbf6a1204552fdfeab7f3b156e5606ebb206a
diff --git a/include/SDL3_mixer/SDL_mixer.h b/include/SDL3_mixer/SDL_mixer.h
index 3decf818..9989d20d 100644
--- a/include/SDL3_mixer/SDL_mixer.h
+++ b/include/SDL3_mixer/SDL_mixer.h
@@ -400,20 +400,20 @@ extern DECLSPEC int SDLCALL Mix_AllocateChannels(int numchans);
  * fly. Also, crucially, there are as many channels for chunks as the app can
  * allocate, but SDL_mixer only offers a single "music" channel.
  *
- * If `freesrc` is SDL_TRUE, the RWops will be closed before returning,
+ * If `closeio` is SDL_TRUE, the IOStream will be closed before returning,
  * whether this function succeeds or not. SDL_mixer reads everything it needs
- * from the RWops during this call in any case.
+ * from the IOStream during this call in any case.
  *
  * There is a separate function (a macro, before SDL_mixer 3.0.0) to read
- * files from disk without having to deal with SDL_RWops:
+ * files from disk without having to deal with SDL_IOStream:
  * `Mix_LoadWAV("filename.wav")` will call this function and manage those
  * details for you.
  *
  * When done with a chunk, the app should dispose of it with a call to
  * Mix_FreeChunk().
  *
- * \param src an SDL_RWops that data will be read from.
- * \param freesrc SDL_TRUE to close/free the SDL_RWops before returning,
+ * \param src an SDL_IOStream that data will be read from.
+ * \param closeio SDL_TRUE to close the SDL_IOStream before returning,
  *                SDL_FALSE to leave it open.
  * \returns a new chunk, or NULL on error.
  *
@@ -422,7 +422,7 @@ extern DECLSPEC int SDLCALL Mix_AllocateChannels(int numchans);
  * \sa Mix_LoadWAV
  * \sa Mix_FreeChunk
  */
-extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, SDL_bool freesrc);
+extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_IO(SDL_IOStream *src, SDL_bool closeio);
 
 /**
  * Load a supported audio format into a chunk.
@@ -442,16 +442,16 @@ extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, SDL_bool free
  * fly. Also, crucially, there are as many channels for chunks as the app can
  * allocate, but SDL_mixer only offers a single "music" channel.
  *
- * If you would rather use the abstract SDL_RWops interface to load data from
- * somewhere other than the filesystem, you can use Mix_LoadWAV_RW() instead.
+ * If you would rather use the abstract SDL_IOStream interface to load data from
+ * somewhere other than the filesystem, you can use Mix_LoadWAV_IO() instead.
  *
  * When done with a chunk, the app should dispose of it with a call to
  * Mix_FreeChunk().
  *
  * Note that before SDL_mixer 3.0.0, this function was a macro that called
- * Mix_LoadWAV_RW(), creating a RWops and setting `freesrc` to SDL_TRUE. This
+ * Mix_LoadWAV_IO(), creating a IOStream and setting `closeio` to SDL_TRUE. This
  * macro has since been promoted to a proper API function. Older binaries
- * linked against a newer SDL_mixer will still call Mix_LoadWAV_RW directly,
+ * linked against a newer SDL_mixer will still call Mix_LoadWAV_IO directly,
  * as they are using the macro, which was available since the dawn of time.
  *
  * \param file the filesystem path to load data from.
@@ -459,7 +459,7 @@ extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, SDL_bool free
  *
  * \since This function is available since SDL_mixer 3.0.0
  *
- * \sa Mix_LoadWAV_RW
+ * \sa Mix_LoadWAV_IO
  * \sa Mix_FreeChunk
  */
 extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV(const char *file);
@@ -513,23 +513,23 @@ extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file);
  * fly. Also, crucially, there are as many channels for chunks as the app can
  * allocate, but SDL_mixer only offers a single "music" channel.
  *
- * If `freesrc` is SDL_TRUE, the RWops will be closed before returning,
+ * If `closeio` is SDL_TRUE, the IOStream will be closed before returning,
  * whether this function succeeds or not. SDL_mixer reads everything it needs
- * from the RWops during this call in any case.
+ * from the IOStream during this call in any case.
  *
  * As a convenience, there is a function to read files from disk without
- * having to deal with SDL_RWops: `Mix_LoadMUS("filename.mp3")` will manage
+ * having to deal with SDL_IOStream: `Mix_LoadMUS("filename.mp3")` will manage
  * those details for you.
  *
  * This function attempts to guess the file format from incoming data. If the
  * caller knows the format, or wants to force it, it should use
- * Mix_LoadMUSType_RW() instead.
+ * Mix_LoadMUSType_IO() instead.
  *
  * When done with this music, the app should dispose of it with a call to
  * Mix_FreeMusic().
  *
- * \param src an SDL_RWops that data will be read from.
- * \param freesrc SDL_TRUE to close/free the SDL_RWops before returning,
+ * \param src an SDL_IOStream that data will be read from.
+ * \param closeio SDL_TRUE to close the SDL_IOStream before returning,
  *                SDL_FALSE to leave it open.
  * \returns a new music object, or NULL on error.
  *
@@ -537,7 +537,7 @@ extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file);
  *
  * \sa Mix_FreeMusic
  */
-extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_RW(SDL_RWops *src, SDL_bool freesrc);
+extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_IO(SDL_IOStream *src, SDL_bool closeio);
 
 /**
  * Load an audio format into a music object, assuming a specific format.
@@ -573,20 +573,20 @@ extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_RW(SDL_RWops *src, SDL_bool free
  * - `MUS_OPUS` (Opus files)
  * - `MUS_WAVPACK` (WavPack files)
  *
- * If `freesrc` is SDL_TRUE, the RWops will be closed before returning,
+ * If `closeio` is SDL_TRUE, the IOStream will be closed before returning,
  * whether this function succeeds or not. SDL_mixer reads everything it needs
- * from the RWops during this call in any case.
+ * from the IOStream during this call in any case.
  *
  * As a convenience, there is a function to read files from disk without
- * having to deal with SDL_RWops: `Mix_LoadMUS("filename.mp3")` will manage
+ * having to deal with SDL_IOStream: `Mix_LoadMUS("filename.mp3")` will manage
  * those details for you (but not let you specify the music type explicitly)..
  *
  * When done with this music, the app should dispose of it with a call to
  * Mix_FreeMusic().
  *
- * \param src an SDL_RWops that data will be read from.
+ * \param src an SDL_IOStream that data will be read from.
  * \param type the type of audio data provided by `src`.
- * \param freesrc SDL_TRUE to close/free the SDL_RWops before returning,
+ * \param closeio SDL_TRUE to close the SDL_IOStream before returning,
  *                SDL_FALSE to leave it open.
  * \returns a new music object, or NULL on error.
  *
@@ -594,12 +594,12 @@ extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_RW(SDL_RWops *src, SDL_bool free
  *
  * \sa Mix_FreeMusic
  */
-extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW(SDL_RWops *src, Mix_MusicType type, SDL_bool freesrc);
+extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_IO(SDL_IOStream *src, Mix_MusicType type, SDL_bool closeio);
 
 /**
  * Load a WAV file from memory as quickly as possible.
  *
- * Unlike Mix_LoadWAV_RW, this function has several requirements, and unless
+ * Unlike Mix_LoadWAV_IO, this function has several requirements, and unless
  * you control all your audio data and know what you're doing, you should
  * consider this function unsafe and not use it.
  *
@@ -616,7 +616,7 @@ extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW(SDL_RWops *src, Mix_Music
  *
  * This function will do NO error checking! Be extremely careful here!
  *
- * (Seriously, use Mix_LoadWAV_RW instead.)
+ * (Seriously, use Mix_LoadWAV_IO instead.)
  *
  * If this function is successful, the provided memory buffer must remain
  * available until Mix_FreeChunk() is called on the returned chunk.
@@ -626,7 +626,7 @@ extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW(SDL_RWops *src, Mix_Music
  *
  * \since This function is available since SDL_mixer 3.0.0.
  *
- * \sa Mix_LoadWAV_RW
+ * \sa Mix_LoadWAV_IO
  * \sa Mix_FreeChunk
  */
 extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_WAV(Uint8 *mem);
@@ -666,7 +666,7 @@ extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len);
  * \since This function is available since SDL_mixer 3.0.0.
  *
  * \sa Mix_LoadWAV
- * \sa Mix_LoadWAV_RW
+ * \sa Mix_LoadWAV_IO
  * \sa Mix_QuickLoad_WAV
  * \sa Mix_QuickLoad_RAW
  */
@@ -686,8 +686,8 @@ extern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk);
  * \since This function is available since SDL_mixer 3.0.0.
  *
  * \sa Mix_LoadMUS
- * \sa Mix_LoadMUS_RW
- * \sa Mix_LoadMUSType_RW
+ * \sa Mix_LoadMUS_IO
+ * \sa Mix_LoadMUSType_IO
  */
 extern DECLSPEC void SDLCALL Mix_FreeMusic(Mix_Music *music);
 
@@ -852,7 +852,7 @@ extern DECLSPEC Mix_MusicType SDLCALL Mix_GetMusicType(const Mix_Music *music);
  * you'd rather have the actual metadata or nothing, use
  * Mix_GetMusicTitleTag() instead.
  *
- * Please note that if the music was loaded from an SDL_RWops instead of a
+ * Please note that if the music was loaded from an SDL_IOStream instead of a
  * filename, the filename returned will be an empty string ("").
  *
  * This function never returns NULL! If no data is available, it will return
diff --git a/src/SDL_mixer.sym b/src/SDL_mixer.sym
index cf183ee6..9710c436 100644
--- a/src/SDL_mixer.sym
+++ b/src/SDL_mixer.sym
@@ -53,10 +53,10 @@ SDL3_mixer_0.0.0 {
     Mix_Init;
     Mix_Linked_Version;
     Mix_LoadMUS;
-    Mix_LoadMUSType_RW;
-    Mix_LoadMUS_RW;
+    Mix_LoadMUSType_IO;
+    Mix_LoadMUS_IO;
     Mix_LoadWAV;
-    Mix_LoadWAV_RW;
+    Mix_LoadWAV_IO;
     Mix_MasterVolume;
     Mix_ModMusicJumpToOrder;
     Mix_MusicDuration;
diff --git a/src/codecs/load_aiff.c b/src/codecs/load_aiff.c
index 8bea7a44..02478fe4 100644
--- a/src/codecs/load_aiff.c
+++ b/src/codecs/load_aiff.c
@@ -20,8 +20,8 @@
 
   This is the source needed to decode an AIFF file into a waveform.
   It's pretty straightforward once you get going. The only
-  externally-callable function is Mix_LoadAIFF_RW(), which is meant to
-  act as identically to SDL_LoadWAV_RW() as possible.
+  externally-callable function is Mix_LoadAIFF_IO(), which is meant to
+  act as identically to SDL_LoadWAV_IO() as possible.
 
   This file by Torbjörn Andersson (torbjorn.andersson@eurotime.se)
   8SVX file support added by Marc Le Douarain (mavati@club-internet.fr)
@@ -60,10 +60,10 @@ static Uint32 SANE_to_Uint32 (Uint8 *sanebuf)
         | (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
 }
 
-/* This function is based on SDL_LoadWAV_RW(). */
+/* This function is based on SDL_LoadWAV_IO(). */
 
-SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, SDL_bool freesrc,
-    SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
+SDL_AudioSpec *Mix_LoadAIFF_IO (SDL_IOStream *src, SDL_bool closeio,
+                                SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
 {
     int found_SSND;
     int found_COMM;
@@ -145,7 +145,7 @@ SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, SDL_bool freesrc,
             !SDL_ReadU32BE(src, &chunk_length)) {
             goto done;
         }
-        next_chunk  = SDL_RWtell(src) + chunk_length;
+        next_chunk  = SDL_TellIO(src) + chunk_length;
 
         /* Paranoia to avoid infinite loops */
         if (chunk_length == 0) {
@@ -159,7 +159,7 @@ SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, SDL_bool freesrc,
                     !SDL_ReadU32BE(src, &blocksize)) {
                     goto done;
                 }
-                start = SDL_RWtell(src) + offset;
+                start = SDL_TellIO(src) + offset;
                 (void)blocksize; /* unused. */
                 break;
 
@@ -170,7 +170,7 @@ SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, SDL_bool freesrc,
                     !SDL_ReadU16BE(src, &samplesize)) {
                     goto done;
                 }
-                if (SDL_RWread(src, sane_freq, sizeof(sane_freq)) != sizeof(sane_freq)) {
+                if (SDL_ReadIO(src, sane_freq, sizeof(sane_freq)) != sizeof(sane_freq)) {
                     Mix_SetError("Bad AIFF sample frequency");
                     goto done;
                 }
@@ -197,7 +197,7 @@ SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, SDL_bool freesrc,
             case BODY:
                 found_BODY  = 1;
                 numsamples  = chunk_length;
-                start       = SDL_RWtell(src);
+                start       = SDL_TellIO(src);
                 break;
 
             default:
@@ -208,7 +208,7 @@ SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, SDL_bool freesrc,
             next_chunk++;
     } while ((((AIFFmagic == AIFF) && (!found_SSND || !found_COMM))
           || ((AIFFmagic == _8SVX) && (!found_VHDR || !found_BODY)))
-          && SDL_RWseek(src, next_chunk, SDL_RW_SEEK_SET) != 1);
+          && SDL_SeekIO(src, next_chunk, SDL_IO_SEEK_SET) != 1);
 
     if ((AIFFmagic == AIFF) && !found_SSND) {
         Mix_SetError("Bad AIFF (no SSND chunk)");
@@ -252,8 +252,8 @@ SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, SDL_bool freesrc,
         Mix_OutOfMemory();
         goto done;
     }
-    SDL_RWseek(src, start, SDL_RW_SEEK_SET);
-    if (SDL_RWread(src, *audio_buf, *audio_len) != *audio_len) {
+    SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
+    if (SDL_ReadIO(src, *audio_buf, *audio_len) != *audio_len) {
         Mix_SetError("Unable to read audio data");
         goto done;
     }
@@ -264,8 +264,8 @@ SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, SDL_bool freesrc,
     was_error = SDL_FALSE;
 
 done:
-    if (freesrc && src) {
-        SDL_RWclose(src);
+    if (closeio && src) {
+        SDL_CloseIO(src);
     }
     if (was_error) {
         if (audio_buf && *audio_buf) {
diff --git a/src/codecs/load_aiff.h b/src/codecs/load_aiff.h
index d36e2028..110ba893 100644
--- a/src/codecs/load_aiff.h
+++ b/src/codecs/load_aiff.h
@@ -20,14 +20,14 @@
 
     This is the source needed to decode an AIFF file into a waveform.
     It's pretty straightforward once you get going. The only
-    externally-callable function is Mix_LoadAIFF_RW(), which is meant to
-    act as identically to SDL_LoadWAV_RW() as possible.
+    externally-callable function is Mix_LoadAIFF_IO(), which is meant to
+    act as identically to SDL_LoadWAV_IO() as possible.
 
     This file by Torbjörn Andersson (torbjorn.andersson@eurotime.se)
 */
 
-/* Don't call this directly; use Mix_LoadWAV_RW() for now. */
-SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, SDL_bool freesrc,
-    SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
+/* Don't call this directly; use Mix_LoadWAV_IO() for now. */
+SDL_AudioSpec *Mix_LoadAIFF_IO (SDL_IOStream *src, SDL_bool closeio,
+				SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/codecs/load_sndfile.c b/src/codecs/load_sndfile.c
index 8ddd54f8..cac247f9 100644
--- a/src/codecs/load_sndfile.c
+++ b/src/codecs/load_sndfile.c
@@ -19,8 +19,8 @@
   3. This notice may not be removed or altered from any source distribution.
 
   This is the source needed to decode a file in any format supported by
-  libsndfile. The only externally-callable function is Mix_LoadSndFile_RW(),
-  which is meant to act as identically to SDL_LoadWAV_RW() as possible.
+  libsndfile. The only externally-callable function is Mix_LoadSndFile_IO(),
+  which is meant to act as identically to SDL_LoadWAV_IO() as possible.
 
   This file by Fabian Greffrath (fabian@greffrath.com).
 */
@@ -95,30 +95,30 @@ void SNDFILE_uninit (void)
 
 static sf_count_t sfvio_size(void *user_data)
 {
-    SDL_RWops *RWops = user_data;
-    return SDL_RWsize(RWops);
+    SDL_IOStream *io = user_data;
+    return SDL_GetIOSize(io);
 }
 
 static sf_count_t sfvio_seek(sf_count_t offset, int whence, void *user_data)
 {
-    SDL_RWops *RWops = user_data;
-    return SDL_RWseek(RWops, offset, whence);
+    SDL_IOStream *io = user_data;
+    return SDL_SeekIO(io, offset, whence);
 }
 
 static sf_count_t sfvio_read(void *ptr, sf_count_t count, void *user_data)
 {
-    SDL_RWops *RWops = user_data;
-    return SDL_RWread(RWops, ptr, count);
+    SDL_IOStream *io = user_data;
+    return SDL_ReadIO(io, ptr, count);
 }
 
 static sf_count_t sfvio_tell(void *user_data)
 {
-    SDL_RWops *RWops = user_data;
-    return SDL_RWtell(RWops);
+    SDL_IOStream *io = user_data;
+    return SDL_TellIO(io);
 }
 
-SDL_AudioSpec *Mix_LoadSndFile_RW (SDL_RWops *src, SDL_bool freesrc,
-        SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
+SDL_AudioSpec *Mix_LoadSndFile_IO (SDL_IOStream *src, SDL_bool closeio,
+                                   SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
 {
     SDL_bool was_error = SDL_TRUE;
     SNDFILE *sndfile = NULL;
@@ -207,8 +207,8 @@ SDL_AudioSpec *Mix_LoadSndFile_RW (SDL_RWops *src, SDL_bool freesrc,
     if (sndfile) {
         SF_sf_close(sndfile);
     }
-    if (freesrc && src) {
-        SDL_RWclose(src);
+    if (closeio && src) {
+        SDL_CloseIO(src);
     }
     if (was_error) {
         if (audio_buf && *audio_buf) {
@@ -225,11 +225,11 @@ SDL_AudioSpec *Mix_LoadSndFile_RW (SDL_RWops *src, SDL_bool freesrc,
 
 #else
 
-SDL_AudioSpec *Mix_LoadSndFile_RW (SDL_RWops *src, SDL_bool freesrc,
-        SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
+SDL_AudioSpec *Mix_LoadSndFile_IO (SDL_IOStream *src, SDL_bool closeio,
+                                   SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
 {
     (void) src;
-    (void) freesrc;
+    (void) closeio;
     (void) spec;
     (void) audio_buf;
     (void) audio_len;
diff --git a/src/codecs/load_sndfile.h b/src/codecs/load_sndfile.h
index cde16afb..2f03d3d1 100644
--- a/src/codecs/load_sndfile.h
+++ b/src/codecs/load_sndfile.h
@@ -19,8 +19,8 @@
   3. This notice may not be removed or altered from any source distribution.
 
   This is the source needed to decode a file in any format supported by
-  libsndfile. The only externally-callable function is Mix_LoadSndFile_RW(),
-  which is meant to act as identically to SDL_LoadWAV_RW() as possible.
+  libsndfile. The only externally-callable function is Mix_LoadSndFile_IO(),
+  which is meant to act as identically to SDL_LoadWAV_IO() as possible.
 
   This file by Fabian Greffrath (fabian@greffrath.com).
 */
@@ -30,9 +30,9 @@
 
 #include <SDL3_mixer/SDL_mixer.h>
 
-/* Don't call this directly; use Mix_LoadWAV_RW() for now. */
-SDL_AudioSpec *Mix_LoadSndFile_RW (SDL_RWops *src, SDL_bool freesrc,
-        SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
+/* Don't call this directly; use Mix_LoadWAV_IO() for now. */
+SDL_AudioSpec *Mix_LoadSndFile_IO (SDL_IOStream *src, SDL_bool closeio,
+				   SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
 
 void SNDFILE_uninit (void);
 
diff --git a/src/codecs/load_voc.c b/src/codecs/load_voc.c
index 40cde399..204f6433 100644
--- a/src/codecs/load_voc.c
+++ b/src/codecs/load_voc.c
@@ -20,8 +20,8 @@
 
   This is the source needed to decode a Creative Labs VOC file into a
   waveform. It's pretty straightforward once you get going. The only
-  externally-callable function is Mix_LoadVOC_RW(), which is meant to
-  act as identically to SDL_LoadWAV_RW() as possible.
+  externally-callable function is Mix_LoadVOC_IO(), which is meant to
+  act as identically to SDL_LoadWAV_IO() as possible.
 
   This file by Ryan C. Gordon (icculus@icculus.org).
 
@@ -80,15 +80,15 @@ typedef struct vocstuff {
 #define VOC_BAD_RATE  ~((Uint32)0)
 
 
-static int voc_check_header(SDL_RWops *src)
+static int voc_check_header(SDL_IOStream *src)
 {
     /* VOC magic header */
     Uint8  signature[20];  /* "Creative Voice File\032" */
     Uint16 datablockofs;
 
-    SDL_RWseek(src, 0, SDL_RW_SEEK_SET);
+    SDL_SeekIO(src, 0, SDL_IO_SEEK_SET);
 
-    if (SDL_RWread(src, signature, sizeof(signature)) != sizeof(signature)) {
+    if (SDL_ReadIO(src, signature, sizeof(signature)) != sizeof(signature)) {
         return 0;
     }
 
@@ -98,13 +98,13 @@ static int voc_check_header(SDL_RWops *src)
     }
 
     /* get the offset where the first datablock is located */
-    if (SDL_RWread(src, &datablockofs, sizeof(Uint16)) != sizeof(Uint16)) {
+    if (SDL_ReadIO(src, &datablockofs, sizeof(Uint16)) != sizeof(Uint16)) {
         return 0;
     }
 
     datablockofs = SDL_SwapLE16(datablockofs);
 
-    if (SDL_RWseek(src, datablockofs, SDL_RW_SEEK_SET) != datablockofs) {
+    if (SDL_SeekIO(src, datablockofs, SDL_IO_SEEK_SET) != datablockofs) {
         return 0;
     }
 
@@ -113,7 +113,7 @@ static int voc_check_header(SDL_RWops *src)
 
 
 /* Read next block header, save info, leave position at start of data */
-static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
+static int voc_get_block(SDL_IOStream *src, vs_t *v, SDL_AudioSpec *spec)
 {
     Uint8 bits24[3];
     Uint8 uc, block;
@@ -126,7 +126,7 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
 
     v->silent = 0;
     while (v->rest == 0) {
-        if (SDL_RWread(src, &block, sizeof(block)) != sizeof(block)) {
+        if (SDL_ReadIO(src, &block, sizeof(block)) != sizeof(block)) {
             return 1;  /* assume that's the end of the file. */
         }
 
@@ -134,7 +134,7 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
             return 1;
         }
 
-        if (SDL_RWread(src, bits24, sizeof(bits24)) != sizeof(bits24)) {
+        if (SDL_ReadIO(src, bits24, sizeof(bits24)) != sizeof(bits24)) {
             return 1;  /* assume that's the end of the file. */
         }
 
@@ -143,7 +143,7 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
 
         switch(block) {
             case VOC_DATA:
-                if (SDL_RWread(src, &uc, sizeof(uc)) != sizeof(uc)) {
+                if (SDL_ReadIO(src, &uc, sizeof(uc)) != sizeof(uc)) {
                     return 0;
                 }
 
@@ -165,7 +165,7 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
                     v->channels = 1;
                 }
 
-                if (SDL_RWread(src, &uc, sizeof(uc)) != sizeof(uc)) {
+                if (SDL_ReadIO(src, &uc, sizeof(uc)) != sizeof(uc)) {
                     return 0;
                 }
 
@@ -180,7 +180,7 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
                 return 1;
 
             case VOC_DATA_16:
-                if (SDL_RWread(src, &new_rate_long, sizeof(new_rate_long)) != sizeof(new_rate_long)) {
+                if (SDL_ReadIO(src, &new_rate_long, sizeof(new_rate_long)) != sizeof(new_rate_long)) {
                     return 0;
                 }
                 new_rate_long = SDL_SwapLE32(new_rate_long);
@@ -195,7 +195,7 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
                 v->rate = new_rate_long;
                 spec->freq = (int)new_rate_long;
 
-                if (SDL_RWread(src, &uc, sizeof(uc)) != sizeof(uc)) {
+                if (SDL_ReadIO(src, &uc, sizeof(uc)) != sizeof(uc)) {
                     return 0;
                 }
 
@@ -207,11 +207,11 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
                         return 0;
                 }
 
-                if (SDL_RWread(src, &v->channels, sizeof(Uint8)) != sizeof(Uint8)) {
+                if (SDL_ReadIO(src, &v->channels, sizeof(Uint8)) != sizeof(Uint8)) {
                     return 0;
                 }
 
-                if (SDL_RWread(src, trash, 6) != 6) {
+                if (SDL_ReadIO(src, trash, 6) != 6) {
                     return 0;
                 }
 
@@ -223,12 +223,12 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
                 return 1;
 
             case VOC_SILENCE:
-                if (SDL_RWread(src, &period, sizeof(period)) != sizeof(period)) {
+                if (SDL_ReadIO(src, &period, sizeof(period)) != sizeof(period)) {
                     return 0;
                 }
                 period = SDL_SwapLE16(period);
 
-                if (SDL_RWread(src, &uc, sizeof(uc)) != sizeof(uc)) {
+                if (SDL_ReadIO(src, &uc, sizeof(uc)) != sizeof(uc)) {
                     return 0;
                 }
                 if (uc == 0) {
@@ -252,7 +252,7 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
             case VOC_LOOP:
             case VOC_LOOPEND:
                 for (i = 0; i < sblen; i++) { /* skip repeat loops. */
-                    if (SDL_RWread(src, trash, sizeof(Uint8)) != sizeof(Uint8)) {
+                    if (SDL_ReadIO(src, trash, sizeof(Uint8)) != sizeof(Uint8)) {
                         return 0;
                     }
                 }
@@ -264,7 +264,7 @@ static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
                 /* value from the extended block and not the     */
                 /* data block.                     */
                 v->has_extended = 1;
-                if (SDL_RWread(src, &new_rate_short, sizeof(new_rate_short)) != sizeof(new_rate_short)) {
+                if (SDL_ReadIO(src, &new_rate_short, sizeof(new_rate_short)) != sizeof(new_rate_short)) {
                     return 0;
                 }
                 new_rate_short = SDL_SwapLE16(new_rate_

(Patch may be truncated, please check the link at the top of this post.)