sdl12-compat: update to latest dr_mp3.h from mainstream

From 3547d7a189f852641768b217d988484b56a37fc5 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Wed, 23 Jul 2025 11:56:50 +0300
Subject: [PATCH] update to latest dr_mp3.h from mainstream

---
 src/SDL12_compat.c |  9 ++---
 src/dr_mp3.h       | 96 +++++++++++++++++++++++-----------------------
 2 files changed, 51 insertions(+), 54 deletions(-)

diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index 1c30e521d..02b787e22 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -8882,15 +8882,15 @@ mp3_sdlrwops_read(void *data, void *buf, size_t bytesToRead)
 static drmp3_bool32
 mp3_sdlrwops_seek(void *data, int offset, drmp3_seek_origin origin)
 {
-    int whence = (origin == drmp3_seek_origin_start) ? RW_SEEK_SET : RW_SEEK_CUR;
+    int whence;
     switch (origin) {
-    case drmp3_seek_origin_start:
+    case DRMP3_SEEK_SET:
         whence = RW_SEEK_SET;
         break;
-    case drmp3_seek_origin_current:
+    case DRMP3_SEEK_CUR:
         whence = RW_SEEK_CUR;
         break;
-    case drmp3_seek_origin_end:
+    case DRMP3_SEEK_END:
         whence = RW_SEEK_END;
         break;
     default:
@@ -8906,7 +8906,6 @@ mp3_sdlrwops_tell(void *data, drmp3_int64 *pos)
     return (*pos != -1) ? DRMP3_TRUE : DRMP3_FALSE;
 }
 
-
 static SDL_bool OpenSDL2AudioDevice(SDL_AudioSpec *want);
 static int CloseSDL2AudioDevice(void);
 static SDL_bool ResetAudioStream(SDL_AudioStream **_stream, SDL_AudioSpec *spec, const SDL_AudioSpec *to, const SDL_AudioFormat fromfmt, const Uint8 fromchannels, const int fromfreq);
diff --git a/src/dr_mp3.h b/src/dr_mp3.h
index e5c9aee67..b2bc1fc92 100644
--- a/src/dr_mp3.h
+++ b/src/dr_mp3.h
@@ -1,6 +1,6 @@
 /*
 MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
-dr_mp3 - v0.7.0 - TBD
+dr_mp3 - v0.7.0 - 2025-07-23
 
 David Reid - mackron@gmail.com
 
@@ -293,9 +293,9 @@ Main API (Pull API)
 */
 typedef enum
 {
-    drmp3_seek_origin_start,
-    drmp3_seek_origin_current,
-    drmp3_seek_origin_end
+    DRMP3_SEEK_SET,
+    DRMP3_SEEK_CUR,
+    DRMP3_SEEK_END
 } drmp3_seek_origin;
 
 typedef struct
@@ -2676,13 +2676,13 @@ static size_t drmp3__on_read_clamped(drmp3* pMP3, void* pBufferOut, size_t bytes
 static drmp3_bool32 drmp3__on_seek(drmp3* pMP3, int offset, drmp3_seek_origin origin)
 {
     DRMP3_ASSERT(offset >= 0);
-    DRMP3_ASSERT(origin == drmp3_seek_origin_start || origin == drmp3_seek_origin_current);
+    DRMP3_ASSERT(origin == DRMP3_SEEK_SET || origin == DRMP3_SEEK_CUR);
 
     if (!pMP3->onSeek(pMP3->pUserData, offset, origin)) {
         return DRMP3_FALSE;
     }
 
-    if (origin == drmp3_seek_origin_start) {
+    if (origin == DRMP3_SEEK_SET) {
         pMP3->streamCursor = (drmp3_uint64)offset;
     } else{
         pMP3->streamCursor += offset;
@@ -2698,19 +2698,19 @@ static drmp3_bool32 drmp3__on_seek_64(drmp3* pMP3, drmp3_uint64 offset, drmp3_se
     }
 
     /* Getting here "offset" is too large for a 32-bit integer. We just keep seeking forward until we hit the offset. */
-    if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_start)) {
+    if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, DRMP3_SEEK_SET)) {
         return DRMP3_FALSE;
     }
 
     offset -= 0x7FFFFFFF;
     while (offset > 0) {
         if (offset <= 0x7FFFFFFF) {
-            if (!drmp3__on_seek(pMP3, (int)offset, drmp3_seek_origin_current)) {
+            if (!drmp3__on_seek(pMP3, (int)offset, DRMP3_SEEK_CUR)) {
                 return DRMP3_FALSE;
             }
             offset = 0;
         } else {
-            if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_current)) {
+            if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, DRMP3_SEEK_CUR)) {
                 return DRMP3_FALSE;
             }
             offset -= 0x7FFFFFFF;
@@ -2977,7 +2977,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
     /* We'll first check for any ID3v1 or APE tags. */
     #if 1
     if (onSeek != NULL && onTell != NULL) {
-        if (onSeek(pUserData, 0, drmp3_seek_origin_end)) {
+        if (onSeek(pUserData, 0, DRMP3_SEEK_END)) {
             drmp3_int64 streamLen;
             int streamEndOffset = 0;
         
@@ -2986,7 +2986,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                 /* ID3v1 */
                 if (streamLen > 128) {
                     char id3[3];
-                    if (onSeek(pUserData, streamEndOffset - 128, drmp3_seek_origin_end)) {
+                    if (onSeek(pUserData, streamEndOffset - 128, DRMP3_SEEK_END)) {
                         if (onRead(pUserData, id3, 3) == 3 && id3[0] == 'T' && id3[1] == 'A' && id3[2] == 'G') {
                             /* We have an ID3v1 tag. */
                             streamEndOffset -= 128;
@@ -3014,7 +3014,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                 /* APE */
                 if (streamLen > 32) {
                     char ape[32];   /* The footer. */
-                    if (onSeek(pUserData, streamEndOffset - 32, drmp3_seek_origin_end)) {
+                    if (onSeek(pUserData, streamEndOffset - 32, DRMP3_SEEK_END)) {
                         if (onRead(pUserData, ape, 32) == 32 && ape[0] == 'A' && ape[1] == 'P' && ape[2] == 'E' && ape[3] == 'T' && ape[4] == 'A' && ape[5] == 'G' && ape[6] == 'E' && ape[7] == 'X') {
                             /* We have an APE tag. */
                             drmp3_uint32 tagSize =
@@ -3029,7 +3029,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                             /* Fire a metadata callback for the APE data. Must include both the main content and footer. */
                             if (onMeta != NULL) {
                                 /* We first need to seek to the start of the APE tag. */
-                                if (onSeek(pUserData, streamEndOffset, drmp3_seek_origin_end)) {
+                                if (onSeek(pUserData, streamEndOffset, DRMP3_SEEK_END)) {
                                     size_t apeTagSize = (size_t)tagSize + 32;
                                     drmp3_uint8* pTagData = (drmp3_uint8*)drmp3_malloc(apeTagSize, pAllocationCallbacks);
                                     if (pTagData != NULL) {
@@ -3048,7 +3048,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                 }
 
                 /* Seek back to the start. */
-                if (!onSeek(pUserData, 0, drmp3_seek_origin_start)) {
+                if (!onSeek(pUserData, 0, DRMP3_SEEK_SET)) {
                     return DRMP3_FALSE; /* Failed to seek back to the start. */
                 }
 
@@ -3059,7 +3059,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                 }
             } else {
                 /* Failed to get the length of the stream. ID3v1 and APE tags cannot be skipped. */
-                if (!onSeek(pUserData, 0, drmp3_seek_origin_start)) {
+                if (!onSeek(pUserData, 0, DRMP3_SEEK_SET)) {
                     return DRMP3_FALSE; /* Failed to seek back to the start. */
                 }
             }
@@ -3105,7 +3105,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                 } else {
                     /* Don't have a metadata callback, so just skip the tag. */
                     if (onSeek != NULL) {
-                        if (!onSeek(pUserData, tagSize, drmp3_seek_origin_current)) {
+                        if (!onSeek(pUserData, tagSize, DRMP3_SEEK_CUR)) {
                             return DRMP3_FALSE; /* Failed to seek past the ID3v2 tag. */
                         }
                     } else {
@@ -3132,7 +3132,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
             } else {
                 /* Not an ID3v2 tag. Seek back to the start. */
                 if (onSeek != NULL) {
-                    if (!onSeek(pUserData, 0, drmp3_seek_origin_start)) {
+                    if (!onSeek(pUserData, 0, DRMP3_SEEK_SET)) {
                         return DRMP3_FALSE; /* Failed to seek back to the start. */
                     }
                 } else {
@@ -3321,40 +3321,34 @@ static size_t drmp3__on_read_memory(void* pUserData, void* pBufferOut, size_t by
 static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3_seek_origin origin)
 {
     drmp3* pMP3 = (drmp3*)pUserData;
+    drmp3_int64 newCursor;
 
     DRMP3_ASSERT(pMP3 != NULL);
 
-    if (origin == drmp3_seek_origin_current) {
-        if (byteOffset > 0) {
-            if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) {
-                return DRMP3_FALSE;  /* Trying to seek too far forward. */
-            }
-        } else {
-            if (pMP3->memory.currentReadPos < (size_t)-byteOffset) {
-                return DRMP3_FALSE;  /* Trying to seek too far backwards. */
-            }
-        }
+    newCursor = pMP3->memory.currentReadPos;
 
-        /* This will never underflow thanks to the clamps above. */
-        pMP3->memory.currentReadPos += byteOffset;
-    } else if (origin == drmp3_seek_origin_start) {
-        if ((drmp3_uint32)byteOffset <= pMP3->memory.dataSize) {
-            pMP3->memory.currentReadPos = byteOffset;
-        } else {
-            return DRMP3_FALSE;  /* Trying to seek too far forward. */
-        }
-    } else if (origin == drmp3_seek_origin_end) {
-        if (byteOffset > 0) {
-            return DRMP3_FALSE;  /* Trying to seek beyond the end of the buffer. */
-        }
+    if (origin == DRMP3_SEEK_SET) {
+        newCursor = 0;
+    } else if (origin == DRMP3_SEEK_CUR) {
+        newCursor = (drmp3_int64)pMP3->memory.currentReadPos;
+    } else if (origin == DRMP3_SEEK_END) {
+        newCursor = (drmp3_int64)pMP3->memory.dataSize;
+    } else {
+        DRMP3_ASSERT(!"Invalid seek origin");
+        return DRMP3_FALSE;
+    }
 
-        if ((size_t)(-byteOffset) > pMP3->memory.dataSize) {
-            return DRMP3_FALSE;  /* Trying to seek too far back. */
-        }
+    newCursor += byteOffset;
 
-        pMP3->memory.currentReadPos = pMP3->memory.dataSize - (size_t)(-byteOffset);
+    if (newCursor < 0) {
+        return DRMP3_FALSE;  /* Trying to seek prior to the start of the buffer. */
+    }
+    if ((size_t)newCursor > pMP3->memory.dataSize) {
+        return DRMP3_FALSE;  /* Trying to seek beyond the end of the buffer. */
     }
 
+    pMP3->memory.currentReadPos = (size_t)newCursor;
+
     return DRMP3_TRUE;
 }
 
@@ -3987,9 +3981,9 @@ static size_t drmp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t byt
 static drmp3_bool32 drmp3__on_seek_stdio(void* pUserData, int offset, drmp3_seek_origin origin)
 {
     int whence = SEEK_SET;
-    if (origin == drmp3_seek_origin_current) {
+    if (origin == DRMP3_SEEK_CUR) {
         whence = SEEK_CUR;
-    } else if (origin == drmp3_seek_origin_end) {
+    } else if (origin == DRMP3_SEEK_END) {
         whence = SEEK_END;
     }
 
@@ -4330,7 +4324,7 @@ static drmp3_bool32 drmp3_seek_to_start_of_stream(drmp3* pMP3)
     DRMP3_ASSERT(pMP3->onSeek != NULL);
 
     /* Seek to the start of the stream to begin with. */
-    if (!drmp3__on_seek_64(pMP3, pMP3->streamStartOffset, drmp3_seek_origin_start)) {
+    if (!drmp3__on_seek_64(pMP3, pMP3->streamStartOffset, DRMP3_SEEK_SET)) {
         return DRMP3_FALSE;
     }
 
@@ -4430,7 +4424,7 @@ static drmp3_bool32 drmp3_seek_to_pcm_frame__seek_table(drmp3* pMP3, drmp3_uint6
     }
 
     /* First thing to do is seek to the first byte of the relevant MP3 frame. */
-    if (!drmp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, drmp3_seek_origin_start)) {
+    if (!drmp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, DRMP3_SEEK_SET)) {
         return DRMP3_FALSE; /* Failed to seek. */
     }
 
@@ -5014,9 +5008,13 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3
 /*
 REVISION HISTORY
 ================
-v0.7.0 - TBD
+v0.7.0 - 2025-07-23
   - The old `DRMP3_IMPLEMENTATION` has been removed. Use `DR_MP3_IMPLEMENTATION` instead. The reason for this change is that in the future everything will eventually be using the underscored naming convention in the future, so `drmp3` will become `dr_mp3`.
-  - API CHANGE: Add drmp3_seek_origin_end as a seek origin for the seek callback. This is required for detection of ID3v1 and APE tags.
+  - API CHANGE: Seek origins have been renamed to match the naming convention used by dr_wav and my other libraries.
+    - drmp3_seek_origin_start   -> DRMP3_SEEK_SET
+    - drmp3_seek_origin_current -> DRMP3_SEEK_CUR
+    - DRMP3_SEEK_END (new)
+  - API CHANGE: Add DRMP3_SEEK_END as a seek origin for the seek callback. This is required for detection of ID3v1 and APE tags.
   - API CHANGE: Add onTell callback to `drmp3_init()`. This is needed in order to track the location of ID3v1 and APE tags.
   - API CHANGE: Add onMeta callback to `drmp3_init()`. This is used for reporting tag data back to the caller. Currently this only reports the raw tag data which means applications need to parse the data themselves.
   - API CHANGE: Rename `drmp3dec_frame_info.hz` to `drmp3dec_frame_info.sample_rate`.