backport commits db2d266 to 092f7e1 from default / 2.0: SDL-1.2
authorOzkan Sezer
Sat, 14 Dec 2019 18:10:10 +0300
branchSDL-1.2
changeset 10797a242c02ac24
parent 1068 36ec29b83b62
child 1080 dcccb70e568f
backport commits db2d266 to 092f7e1 from default / 2.0:

- move tag skip and SDL_RW with bookkeeping code into separate mp3utils.c
- remove unnecessary file rewind calls in tag detection code.
- music_mpg: use tag handling from mp3utils to avoid frame error reports
- initial support for skipping the old MusicMatch tags
Makefile.in
VisualC/SDL_mixer.vcproj
Xcode-iOS/SDL_mixer.xcodeproj/project.pbxproj
Xcode/SDL_mixer.xcodeproj/project.pbxproj
configure
configure.in
dynamic_mp3.c
mp3utils.c
mp3utils.h
music_mad.c
music_mad.h
music_mpg.c
music_mpg.h
     1.1 --- a/Makefile.in	Sun Dec 08 15:50:02 2019 +0300
     1.2 +++ b/Makefile.in	Sat Dec 14 18:10:10 2019 +0300
     1.3 @@ -39,7 +39,7 @@
     1.4  PLAYWAVE_OBJECTS = @PLAYWAVE_OBJECTS@
     1.5  PLAYMUS_OBJECTS = @PLAYMUS_OBJECTS@
     1.6  
     1.7 -DIST = Android.mk CHANGES COPYING CWProjects.sea.bin MPWmake.sea.bin Makefile.in SDL_mixer.pc.in README SDL_mixer.h SDL_mixer.qpg.in SDL_mixer.spec SDL_mixer.spec.in VisualC Watcom-OS2.zip Xcode Xcode-iOS acinclude autogen.sh build-scripts configure configure.in dynamic_flac.c dynamic_flac.h dynamic_fluidsynth.c dynamic_fluidsynth.h dynamic_mod.c dynamic_mod.h dynamic_mp3.c dynamic_mp3.h dynamic_ogg.c dynamic_ogg.h effect_position.c effect_stereoreverse.c effects_internal.c effects_internal.h fluidsynth.c fluidsynth.h gcc-fat.sh libmikmod-3.1.12.zip load_aiff.c load_aiff.h load_flac.c load_flac.h load_ogg.c load_ogg.h load_voc.c load_voc.h mixer.c music.c music_cmd.c music_cmd.h music_flac.c music_flac.h music_mad.c music_mad.h music_mod.c music_mod.h music_modplug.c music_modplug.h music_ogg.c music_ogg.h native_midi playmus.c playwave.c timidity wavestream.c wavestream.h version.rc
     1.8 +DIST = Android.mk CHANGES COPYING CWProjects.sea.bin MPWmake.sea.bin Makefile.in SDL_mixer.pc.in README SDL_mixer.h SDL_mixer.qpg.in SDL_mixer.spec SDL_mixer.spec.in VisualC Watcom-OS2.zip Xcode Xcode-iOS acinclude autogen.sh build-scripts configure configure.in dynamic_flac.c dynamic_flac.h dynamic_fluidsynth.c dynamic_fluidsynth.h dynamic_mod.c dynamic_mod.h dynamic_mp3.c dynamic_mp3.h dynamic_ogg.c dynamic_ogg.h effect_position.c effect_stereoreverse.c effects_internal.c effects_internal.h fluidsynth.c fluidsynth.h gcc-fat.sh libmikmod-3.1.12.zip load_aiff.c load_aiff.h load_flac.c load_flac.h load_ogg.c load_ogg.h load_voc.c load_voc.h mixer.c mp3utils.c mp3utils.h music.c music_cmd.c music_cmd.h music_flac.c music_flac.h music_mad.c music_mad.h music_mod.c music_mod.h music_modplug.c music_modplug.h music_ogg.c music_ogg.h native_midi playmus.c playwave.c timidity wavestream.c wavestream.h version.rc
     1.9  
    1.10  LT_AGE      = @LT_AGE@
    1.11  LT_CURRENT  = @LT_CURRENT@
     2.1 --- a/VisualC/SDL_mixer.vcproj	Sun Dec 08 15:50:02 2019 +0300
     2.2 +++ b/VisualC/SDL_mixer.vcproj	Sat Dec 14 18:10:10 2019 +0300
     2.3 @@ -884,6 +884,14 @@
     2.4  			>
     2.5  		</File>
     2.6  		<File
     2.7 +			RelativePath="..\mp3utils.c"
     2.8 +			>
     2.9 +		</File>
    2.10 +		<File
    2.11 +			RelativePath="..\mp3utils.h"
    2.12 +			>
    2.13 +		</File>
    2.14 +		<File
    2.15  			RelativePath="..\music_mad.c"
    2.16  			>
    2.17  		</File>
    2.18 @@ -892,6 +900,14 @@
    2.19  			>
    2.20  		</File>
    2.21  		<File
    2.22 +			RelativePath="..\music_mpg.c"
    2.23 +			>
    2.24 +		</File>
    2.25 +		<File
    2.26 +			RelativePath="..\music_mpg.h"
    2.27 +			>
    2.28 +		</File>
    2.29 +		<File
    2.30  			RelativePath="..\music_mod.c"
    2.31  			>
    2.32  		</File>
    2.33 @@ -900,14 +916,6 @@
    2.34  			>
    2.35  		</File>
    2.36  		<File
    2.37 -			RelativePath="..\music_mpg.c"
    2.38 -			>
    2.39 -		</File>
    2.40 -		<File
    2.41 -			RelativePath="..\music_mpg.h"
    2.42 -			>
    2.43 -		</File>
    2.44 -		<File
    2.45  			RelativePath="..\music_ogg.c"
    2.46  			>
    2.47  			<FileConfiguration
     3.1 --- a/Xcode-iOS/SDL_mixer.xcodeproj/project.pbxproj	Sun Dec 08 15:50:02 2019 +0300
     3.2 +++ b/Xcode-iOS/SDL_mixer.xcodeproj/project.pbxproj	Sat Dec 14 18:10:10 2019 +0300
     3.3 @@ -14,6 +14,10 @@
     3.4  		00938E57108A397A0009CF19 /* dynamic_ogg.h in Headers */ = {isa = PBXBuildFile; fileRef = 00938E4D108A397A0009CF19 /* dynamic_ogg.h */; };
     3.5  		04A8FCA60A19CAEC0046373F /* dynamic_mp3.c in Sources */ = {isa = PBXBuildFile; fileRef = 04A8FCA40A19CAEC0046373F /* dynamic_mp3.c */; };
     3.6  		04A8FCAB0A19CB070046373F /* dynamic_ogg.c in Sources */ = {isa = PBXBuildFile; fileRef = 04A8FCA90A19CB070046373F /* dynamic_ogg.c */; };
     3.7 +		639090F823A5305400D5554E /* music_mpg.c in Sources */ = {isa = PBXBuildFile; fileRef = 639090F623A5305400D5554E /* music_mpg.c */; };
     3.8 +		639090F923A5305400D5554E /* music_mpg.h in Headers */ = {isa = PBXBuildFile; fileRef = 639090F723A5305400D5554E /* music_mpg.h */; };
     3.9 +		639090FC23A5306500D5554E /* mp3utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 639090FA23A5306500D5554E /* mp3utils.c */; };
    3.10 +		639090FD23A5306500D5554E /* mp3utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 639090FB23A5306500D5554E /* mp3utils.h */; };
    3.11  		AA5F0F0914B6A6490036992F /* dynamic_fluidsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = AA5F0F0214B6A6490036992F /* dynamic_fluidsynth.c */; };
    3.12  		AA5F0F0A14B6A6490036992F /* dynamic_fluidsynth.h in Headers */ = {isa = PBXBuildFile; fileRef = AA5F0F0314B6A6490036992F /* dynamic_fluidsynth.h */; };
    3.13  		AA5F0F0B14B6A6490036992F /* dynamic_mod.h in Headers */ = {isa = PBXBuildFile; fileRef = AA5F0F0414B6A6490036992F /* dynamic_mod.h */; };
    3.14 @@ -116,6 +120,10 @@
    3.15  		5CC1B898012FB8CD7F000001 /* timidity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = timidity.h; sourceTree = "<group>"; };
    3.16  		5CC1B89B012FB8CD7F000001 /* wavestream.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = wavestream.c; path = ../wavestream.c; sourceTree = "<group>"; };
    3.17  		5CC1B89C012FB8CD7F000001 /* wavestream.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = wavestream.h; path = ../wavestream.h; sourceTree = "<group>"; };
    3.18 +		639090F623A5305400D5554E /* music_mpg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = music_mpg.c; path = ../music_mpg.c; sourceTree = SOURCE_ROOT; };
    3.19 +		639090F723A5305400D5554E /* music_mpg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = music_mpg.h; path = ../music_mpg.h; sourceTree = SOURCE_ROOT; };
    3.20 +		639090FA23A5306500D5554E /* mp3utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mp3utils.c; path = ../mp3utils.c; sourceTree = SOURCE_ROOT; };
    3.21 +		639090FB23A5306500D5554E /* mp3utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mp3utils.h; path = ../mp3utils.h; sourceTree = SOURCE_ROOT; };
    3.22  		AA5F0F0214B6A6490036992F /* dynamic_fluidsynth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dynamic_fluidsynth.c; path = ../dynamic_fluidsynth.c; sourceTree = "<group>"; };
    3.23  		AA5F0F0314B6A6490036992F /* dynamic_fluidsynth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dynamic_fluidsynth.h; path = ../dynamic_fluidsynth.h; sourceTree = "<group>"; };
    3.24  		AA5F0F0414B6A6490036992F /* dynamic_mod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dynamic_mod.h; path = ../dynamic_mod.h; sourceTree = "<group>"; };
    3.25 @@ -184,6 +192,10 @@
    3.26  		08FB77ACFE841707C02AAC07 /* Library Source */ = {
    3.27  			isa = PBXGroup;
    3.28  			children = (
    3.29 +				639090FA23A5306500D5554E /* mp3utils.c */,
    3.30 +				639090FB23A5306500D5554E /* mp3utils.h */,
    3.31 +				639090F623A5305400D5554E /* music_mpg.c */,
    3.32 +				639090F723A5305400D5554E /* music_mpg.h */,
    3.33  				00938E49108A397A0009CF19 /* dynamic_flac.c */,
    3.34  				00938E4A108A397A0009CF19 /* dynamic_flac.h */,
    3.35  				AA5F0F0214B6A6490036992F /* dynamic_fluidsynth.c */,
    3.36 @@ -295,6 +307,8 @@
    3.37  				AA5F0F0B14B6A6490036992F /* dynamic_mod.h in Headers */,
    3.38  				AA5F0F0D14B6A6490036992F /* fluidsynth.h in Headers */,
    3.39  				AA5F0F0F14B6A6490036992F /* music_modplug.h in Headers */,
    3.40 +				639090F923A5305400D5554E /* music_mpg.h in Headers */,
    3.41 +				639090FD23A5306500D5554E /* mp3utils.h in Headers */,
    3.42  			);
    3.43  			runOnlyForDeploymentPostprocessing = 0;
    3.44  		};
    3.45 @@ -394,6 +408,8 @@
    3.46  				AA5F0F0914B6A6490036992F /* dynamic_fluidsynth.c in Sources */,
    3.47  				AA5F0F0C14B6A6490036992F /* fluidsynth.c in Sources */,
    3.48  				AA5F0F0E14B6A6490036992F /* music_modplug.c in Sources */,
    3.49 +				639090F823A5305400D5554E /* music_mpg.c in Sources */,
    3.50 +				639090FC23A5306500D5554E /* mp3utils.c in Sources */,
    3.51  			);
    3.52  			runOnlyForDeploymentPostprocessing = 0;
    3.53  		};
     4.1 --- a/Xcode/SDL_mixer.xcodeproj/project.pbxproj	Sun Dec 08 15:50:02 2019 +0300
     4.2 +++ b/Xcode/SDL_mixer.xcodeproj/project.pbxproj	Sat Dec 14 18:10:10 2019 +0300
     4.3 @@ -37,6 +37,10 @@
     4.4  		639076AC216EC43000ED9E54 /* music_mpg.c in Sources */ = {isa = PBXBuildFile; fileRef = 639076AA216EC43000ED9E54 /* music_mpg.c */; };
     4.5  		639076AE216EC49000ED9E54 /* music_mpg.h in Headers */ = {isa = PBXBuildFile; fileRef = 639076AD216EC49000ED9E54 /* music_mpg.h */; };
     4.6  		639076AF216EC49000ED9E54 /* music_mpg.h in Headers */ = {isa = PBXBuildFile; fileRef = 639076AD216EC49000ED9E54 /* music_mpg.h */; };
     4.7 +		639090DF23A52FF400D5554E /* mp3utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 639090DD23A52FF400D5554E /* mp3utils.c */; };
     4.8 +		639090E023A52FF400D5554E /* mp3utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 639090DE23A52FF400D5554E /* mp3utils.h */; };
     4.9 +		639090E123A52FF400D5554E /* mp3utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 639090DD23A52FF400D5554E /* mp3utils.c */; };
    4.10 +		639090E223A52FF400D5554E /* mp3utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 639090DE23A52FF400D5554E /* mp3utils.h */; };
    4.11  		63CB2527216EC68100928244 /* mpg123.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 639076A3216EC3E200ED9E54 /* mpg123.framework */; };
    4.12  		AA9F7DB514B15ADC00278D1E /* Ogg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA9F7DB314B15ADC00278D1E /* Ogg.framework */; };
    4.13  		AA9F7DB614B15ADC00278D1E /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA9F7DB414B15ADC00278D1E /* Vorbis.framework */; };
    4.14 @@ -218,6 +222,8 @@
    4.15  		639076A3216EC3E200ED9E54 /* mpg123.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mpg123.framework; path = Frameworks/mpg123.framework; sourceTree = "<group>"; };
    4.16  		639076AA216EC43000ED9E54 /* music_mpg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = music_mpg.c; path = ../music_mpg.c; sourceTree = SOURCE_ROOT; };
    4.17  		639076AD216EC49000ED9E54 /* music_mpg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = music_mpg.h; path = ../music_mpg.h; sourceTree = SOURCE_ROOT; };
    4.18 +		639090DD23A52FF400D5554E /* mp3utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mp3utils.c; path = ../mp3utils.c; sourceTree = SOURCE_ROOT; };
    4.19 +		639090DE23A52FF400D5554E /* mp3utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mp3utils.h; path = ../mp3utils.h; sourceTree = SOURCE_ROOT; };
    4.20  		AA9F7DB314B15ADC00278D1E /* Ogg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Ogg.framework; path = Frameworks/Ogg.framework; sourceTree = "<group>"; };
    4.21  		AA9F7DB414B15ADC00278D1E /* Vorbis.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Vorbis.framework; path = Frameworks/Vorbis.framework; sourceTree = "<group>"; };
    4.22  		AA9F7DB714B15AE700278D1E /* FLAC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FLAC.framework; path = Frameworks/FLAC.framework; sourceTree = "<group>"; };
    4.23 @@ -308,6 +314,8 @@
    4.24  		08FB77ACFE841707C02AAC07 /* Library Source */ = {
    4.25  			isa = PBXGroup;
    4.26  			children = (
    4.27 +				639090DD23A52FF400D5554E /* mp3utils.c */,
    4.28 +				639090DE23A52FF400D5554E /* mp3utils.h */,
    4.29  				639076AD216EC49000ED9E54 /* music_mpg.h */,
    4.30  				639076AA216EC43000ED9E54 /* music_mpg.c */,
    4.31  				00938E49108A397A0009CF19 /* dynamic_flac.c */,
    4.32 @@ -466,6 +474,7 @@
    4.33  				00938E51108A397A0009CF19 /* dynamic_mp3.h in Headers */,
    4.34  				00938E52108A397A0009CF19 /* dynamic_ogg.h in Headers */,
    4.35  				639076AE216EC49000ED9E54 /* music_mpg.h in Headers */,
    4.36 +				639090E023A52FF400D5554E /* mp3utils.h in Headers */,
    4.37  			);
    4.38  			runOnlyForDeploymentPostprocessing = 0;
    4.39  		};
    4.40 @@ -496,6 +505,7 @@
    4.41  				00938E56108A397A0009CF19 /* dynamic_mp3.h in Headers */,
    4.42  				00938E57108A397A0009CF19 /* dynamic_ogg.h in Headers */,
    4.43  				639076AF216EC49000ED9E54 /* music_mpg.h in Headers */,
    4.44 +				639090E223A52FF400D5554E /* mp3utils.h in Headers */,
    4.45  			);
    4.46  			runOnlyForDeploymentPostprocessing = 0;
    4.47  		};
    4.48 @@ -695,6 +705,7 @@
    4.49  				00938E50108A397A0009CF19 /* dynamic_mod.c in Sources */,
    4.50  				0448E8AE108B937A00C9D3EA /* native_midi_macosx.c in Sources */,
    4.51  				639076AB216EC43000ED9E54 /* music_mpg.c in Sources */,
    4.52 +				639090DF23A52FF400D5554E /* mp3utils.c in Sources */,
    4.53  			);
    4.54  			runOnlyForDeploymentPostprocessing = 0;
    4.55  		};
    4.56 @@ -732,6 +743,7 @@
    4.57  				00938E55108A397A0009CF19 /* dynamic_mod.c in Sources */,
    4.58  				0448E8AF108B937A00C9D3EA /* native_midi_macosx.c in Sources */,
    4.59  				639076AC216EC43000ED9E54 /* music_mpg.c in Sources */,
    4.60 +				639090E123A52FF400D5554E /* mp3utils.c in Sources */,
    4.61  			);
    4.62  			runOnlyForDeploymentPostprocessing = 0;
    4.63  		};
     5.1 --- a/configure	Sun Dec 08 15:50:02 2019 +0300
     5.2 +++ b/configure	Sat Dec 14 18:10:10 2019 +0300
     5.3 @@ -14883,6 +14883,7 @@
     5.4    enable_music_mp3_shared=yes
     5.5  fi
     5.6  
     5.7 +have_mpg123=no
     5.8  if test x$enable_music_mp3 = xyes; then
     5.9      if test "${ac_cv_header_mpg123_h+set}" = set; then
    5.10    { $as_echo "$as_me:$LINENO: checking for mpg123.h" >&5
    5.11 @@ -15119,10 +15120,10 @@
    5.12    enable_music_mp3_mad_gpl=no
    5.13  fi
    5.14  
    5.15 +have_libmad=no
    5.16  if test x$enable_music_mp3_mad_gpl = xyes; then
    5.17      { $as_echo "$as_me:$LINENO: checking for libmad headers" >&5
    5.18  $as_echo_n "checking for libmad headers... " >&6; }
    5.19 -    have_libmad=no
    5.20      cat >conftest.$ac_ext <<_ACEOF
    5.21  /* confdefs.h.  */
    5.22  _ACEOF
    5.23 @@ -15185,6 +15186,8 @@
    5.24  if test x$have_mpg123 != xyes -a x$have_libmad != xyes; then
    5.25      { $as_echo "$as_me:$LINENO: WARNING: MP3 support disabled" >&5
    5.26  $as_echo "$as_me: WARNING: MP3 support disabled" >&2;}
    5.27 +else
    5.28 +    SOURCES="$SOURCES $srcdir/mp3utils.c"
    5.29  fi
    5.30  
    5.31  EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LIBM"
     6.1 --- a/configure.in	Sun Dec 08 15:50:02 2019 +0300
     6.2 +++ b/configure.in	Sat Dec 14 18:10:10 2019 +0300
     6.3 @@ -558,6 +558,7 @@
     6.4  AC_ARG_ENABLE([music-mp3-shared],
     6.5  AC_HELP_STRING([--enable-music-mp3-shared], [dynamically load MP3 support [[default=yes]]]),
     6.6                [], [enable_music_mp3_shared=yes])
     6.7 +have_mpg123=no
     6.8  if test x$enable_music_mp3 = xyes; then
     6.9      AC_CHECK_HEADER([mpg123.h], [have_mpg123_hdr=yes])
    6.10      AC_CHECK_LIB([mpg123], [mpg123_replace_reader_handle], [have_mpg123_lib=yes])
    6.11 @@ -590,9 +591,9 @@
    6.12  AC_ARG_ENABLE(music-mp3-mad-gpl,
    6.13  AC_HELP_STRING([--enable-music-mp3-mad-gpl], [enable MP3 music via libmad GPL code [[default=no]]]),
    6.14                    [], [enable_music_mp3_mad_gpl=no])
    6.15 +have_libmad=no
    6.16  if test x$enable_music_mp3_mad_gpl = xyes; then
    6.17      AC_MSG_CHECKING(for libmad headers)
    6.18 -    have_libmad=no
    6.19      AC_TRY_COMPILE([
    6.20       #include "mad.h"
    6.21      ],[
    6.22 @@ -611,6 +612,8 @@
    6.23  
    6.24  if test x$have_mpg123 != xyes -a x$have_libmad != xyes; then
    6.25      AC_MSG_WARN([MP3 support disabled])
    6.26 +else
    6.27 +    SOURCES="$SOURCES $srcdir/mp3utils.c"
    6.28  fi
    6.29  
    6.30  EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LIBM"
     7.1 --- a/dynamic_mp3.c	Sun Dec 08 15:50:02 2019 +0300
     7.2 +++ b/dynamic_mp3.c	Sat Dec 14 18:10:10 2019 +0300
     7.3 @@ -57,7 +57,7 @@
     7.4  		FUNCTION_LOADER(mpg123_new, mpg123_handle *(*)(const char* decoder, int *error))
     7.5  		FUNCTION_LOADER(mpg123_open_handle, int (*)(mpg123_handle *mh, void *iohandle))
     7.6  		FUNCTION_LOADER(mpg123_plain_strerror, const char* (*)(int errcode))
     7.7 -		FUNCTION_LOADER(mpg123_rates, void (*)(const long **list, size_t *number));
     7.8 +		FUNCTION_LOADER(mpg123_rates, void (*)(const long **list, size_t *number))
     7.9  		FUNCTION_LOADER(mpg123_read, int (*)(mpg123_handle *mh, unsigned char *outmemory, size_t outmemsize, size_t *done ))
    7.10  		FUNCTION_LOADER(mpg123_replace_reader_handle, int (*)( mpg123_handle *mh, ssize_t (*r_read) (void *, void *, size_t), off_t (*r_lseek)(void *, off_t, int), void (*cleanup)(void*) ))
    7.11  		FUNCTION_LOADER(mpg123_seek, off_t (*)( mpg123_handle *mh, off_t sampleoff, int whence ))
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/mp3utils.c	Sat Dec 14 18:10:10 2019 +0300
     8.3 @@ -0,0 +1,374 @@
     8.4 +/*
     8.5 +  SDL_mixer:  An audio mixer library based on the SDL library
     8.6 +  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     8.7 +
     8.8 +  This software is provided 'as-is', without any express or implied
     8.9 +  warranty.  In no event will the authors be held liable for any damages
    8.10 +  arising from the use of this software.
    8.11 +
    8.12 +  Permission is granted to anyone to use this software for any purpose,
    8.13 +  including commercial applications, and to alter it and redistribute it
    8.14 +  freely, subject to the following restrictions:
    8.15 +
    8.16 +  1. The origin of this software must not be misrepresented; you must not
    8.17 +     claim that you wrote the original software. If you use this software
    8.18 +     in a product, an acknowledgment in the product documentation would be
    8.19 +     appreciated but is not required.
    8.20 +  2. Altered source versions must be plainly marked as such, and must not be
    8.21 +     misrepresented as being the original software.
    8.22 +  3. This notice may not be removed or altered from any source distribution.
    8.23 +*/
    8.24 +
    8.25 +#include "SDL_stdinc.h"
    8.26 +#include "SDL_rwops.h"
    8.27 +
    8.28 +#include "mp3utils.h"
    8.29 +
    8.30 +#if defined(MP3_MAD_MUSIC) || defined(MP3_MUSIC)
    8.31 +
    8.32 +/*********************** SDL_RW WITH BOOKKEEPING ************************/
    8.33 +
    8.34 +int MP3_RWread(struct mp3file_t *fil, void *ptr, int size, int maxnum) {
    8.35 +    int remaining = fil->length - fil->pos;
    8.36 +    int ret;
    8.37 +    maxnum *= size;
    8.38 +    if (maxnum > remaining) maxnum = remaining;
    8.39 +    ret = SDL_RWread(fil->rw, ptr, 1, maxnum);
    8.40 +    if (ret > 0) fil->pos += ret;
    8.41 +    return ret;
    8.42 +}
    8.43 +
    8.44 +int MP3_RWseek(struct mp3file_t *fil, int offset, int whence) {
    8.45 +    int ret;
    8.46 +    switch (whence) { /* assumes a legal whence value */
    8.47 +    case RW_SEEK_CUR:
    8.48 +        offset += fil->pos;
    8.49 +        break;
    8.50 +    case RW_SEEK_END:
    8.51 +        offset = fil->length + offset;
    8.52 +        break;
    8.53 +    }
    8.54 +    if (offset < 0) return -1;
    8.55 +    if (offset > fil->length)
    8.56 +        offset = fil->length;
    8.57 +    ret = SDL_RWseek(fil->rw, fil->start + offset, RW_SEEK_SET);
    8.58 +    if (ret < 0) return ret;
    8.59 +    fil->pos = offset;
    8.60 +    return (fil->pos - fil->start);
    8.61 +}
    8.62 +
    8.63 +
    8.64 +/*************************** TAG HANDLING: ******************************/
    8.65 +
    8.66 +static __inline__ SDL_bool is_id3v1(const unsigned char *data, int length)
    8.67 +{
    8.68 +    /* http://id3.org/ID3v1 :  3 bytes "TAG" identifier and 125 bytes tag data */
    8.69 +    if (length < 3 || SDL_memcmp(data,"TAG",3) != 0) {
    8.70 +        return SDL_FALSE;
    8.71 +    }
    8.72 +    return SDL_TRUE;
    8.73 +}
    8.74 +static __inline__ SDL_bool is_id3v2(const unsigned char *data, int length)
    8.75 +{
    8.76 +    /* ID3v2 header is 10 bytes:  http://id3.org/id3v2.4.0-structure */
    8.77 +    /* bytes 0-2: "ID3" identifier */
    8.78 +    if (length < 10 || SDL_memcmp(data,"ID3",3) != 0) {
    8.79 +        return SDL_FALSE;
    8.80 +    }
    8.81 +    /* bytes 3-4: version num (major,revision), each byte always less than 0xff. */
    8.82 +    if (data[3] == 0xff || data[4] == 0xff) {
    8.83 +        return SDL_FALSE;
    8.84 +    }
    8.85 +    /* bytes 6-9 are the ID3v2 tag size: a 32 bit 'synchsafe' integer, i.e. the
    8.86 +     * highest bit 7 in each byte zeroed.  i.e.: 7 bit information in each byte ->
    8.87 +     * effectively a 28 bit value.  */
    8.88 +    if (data[6] >= 0x80 || data[7] >= 0x80 || data[8] >= 0x80 || data[9] >= 0x80) {
    8.89 +        return SDL_FALSE;
    8.90 +    }
    8.91 +    return SDL_TRUE;
    8.92 +}
    8.93 +static __inline__ int get_id3v2_len(const unsigned char *data, int length)
    8.94 +{
    8.95 +    /* size is a 'synchsafe' integer (see above) */
    8.96 +    int size = (int)((data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9]);
    8.97 +    size += 10; /* header size */
    8.98 +    /* ID3v2 header[5] is flags (bits 4-7 only, 0-3 are zero).
    8.99 +     * bit 4 set: footer is present (a copy of the header but
   8.100 +     * with "3DI" as ident.)  */
   8.101 +    if (data[5] & 0x10) {
   8.102 +        size += 10; /* footer size */
   8.103 +    }
   8.104 +    /* optional padding (always zeroes) */
   8.105 +    while (size < length && data[size] == 0) {
   8.106 +        ++size;
   8.107 +    }
   8.108 +    return size;
   8.109 +}
   8.110 +static __inline__ SDL_bool is_apetag(const unsigned char *data, int length)
   8.111 +{
   8.112 +   /* http://wiki.hydrogenaud.io/index.php?title=APEv2_specification
   8.113 +    * Header/footer is 32 bytes: bytes 0-7 ident, bytes 8-11 version,
   8.114 +    * bytes 12-17 size. bytes 24-31 are reserved: must be all zeroes. */
   8.115 +    Uint32 v;
   8.116 +
   8.117 +    if (length < 32 || SDL_memcmp(data,"APETAGEX",8) != 0) {
   8.118 +        return SDL_FALSE;
   8.119 +    }
   8.120 +    v = (Uint32)((data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8]); /* version */
   8.121 +    if (v != 2000U && v != 1000U) {
   8.122 +        return SDL_FALSE;
   8.123 +    }
   8.124 +    v = 0; /* reserved bits : */
   8.125 +    if (SDL_memcmp(&data[24],&v,4) != 0 || SDL_memcmp(&data[28],&v,4) != 0) {
   8.126 +        return SDL_FALSE;
   8.127 +    }
   8.128 +    return SDL_TRUE;
   8.129 +}
   8.130 +static __inline__ int get_ape_len(const unsigned char *data)
   8.131 +{
   8.132 +    Uint32 flags, version;
   8.133 +    int size = (int)((data[15]<<24) | (data[14]<<16) | (data[13]<<8) | data[12]);
   8.134 +    version = (Uint32)((data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8]);
   8.135 +    flags = (Uint32)((data[23]<<24) | (data[22]<<16) | (data[21]<<8) | data[20]);
   8.136 +    if (version == 2000U && (flags & (1U<<31))) size += 32; /* header present. */
   8.137 +    return size;
   8.138 +}
   8.139 +static __inline__ int is_lyrics3tag(const unsigned char *data, int length) {
   8.140 +    /* http://id3.org/Lyrics3
   8.141 +     * http://id3.org/Lyrics3v2 */
   8.142 +    if (length < 15) return 0;
   8.143 +    if (SDL_memcmp(data+6,"LYRICS200",9) == 0) return 2; /* v2 */
   8.144 +    if (SDL_memcmp(data+6,"LYRICSEND",9) == 0) return 1; /* v1 */
   8.145 +    return 0;
   8.146 +}
   8.147 +static __inline__ int get_lyrics3v1_len(struct mp3file_t *m) {
   8.148 +    const char *p; int i, len;
   8.149 +    char buf[5104];
   8.150 +    /* needs manual search:  http://id3.org/Lyrics3 */
   8.151 +    if (m->length < 20) return -1;
   8.152 +    len = (m->length > 5109)? 5109 : m->length;
   8.153 +    MP3_RWseek(m, -len, RW_SEEK_END);
   8.154 +    MP3_RWread(m, buf, 1, (len -= 9)); /* exclude footer */
   8.155 +    /* strstr() won't work here. */
   8.156 +    for (i = len - 11, p = buf; i >= 0; --i, ++p) {
   8.157 +        if (SDL_memcmp(p, "LYRICSBEGIN", 11) == 0)
   8.158 +            break;
   8.159 +    }
   8.160 +    if (i < 0) return -1;
   8.161 +    return len - (int)(p - buf) + 9 /* footer */;
   8.162 +}
   8.163 +static __inline__ int get_lyrics3v2_len(const unsigned char *data, int length) {
   8.164 +    /* 6 bytes before the end marker is size in decimal format -
   8.165 +     * does not include the 9 bytes end marker and size field. */
   8.166 +    if (length != 6) return 0;
   8.167 +    return SDL_strtol((const char *)data, NULL, 10) + 15;
   8.168 +}
   8.169 +static __inline__ SDL_bool verify_lyrics3v2(const unsigned char *data, int length) {
   8.170 +    if (length < 11) return SDL_FALSE;
   8.171 +    if (SDL_memcmp(data,"LYRICSBEGIN",11) == 0) return SDL_TRUE;
   8.172 +    return SDL_FALSE;
   8.173 +}
   8.174 +#define MMTAG_PARANOID
   8.175 +static __inline__ SDL_bool is_musicmatch(const unsigned char *data, int length) {
   8.176 +  /* From docs/musicmatch.txt in id3lib: https://sourceforge.net/projects/id3lib/
   8.177 +     Overall tag structure:
   8.178 +
   8.179 +      +-----------------------------+
   8.180 +      |           Header            |
   8.181 +      |    (256 bytes, OPTIONAL)    |
   8.182 +      +-----------------------------+
   8.183 +      |  Image extension (4 bytes)  |
   8.184 +      +-----------------------------+
   8.185 +      |        Image binary         |
   8.186 +      |  (var. length >= 4 bytes)   |
   8.187 +      +-----------------------------+
   8.188 +      |      Unused (4 bytes)       |
   8.189 +      +-----------------------------+
   8.190 +      |  Version info (256 bytes)   |
   8.191 +      +-----------------------------+
   8.192 +      |       Audio meta-data       |
   8.193 +      | (var. length >= 7868 bytes) |
   8.194 +      +-----------------------------+
   8.195 +      |   Data offsets (20 bytes)   |
   8.196 +      +-----------------------------+
   8.197 +      |      Footer (48 bytes)      |
   8.198 +      +-----------------------------+
   8.199 +     */
   8.200 +    if (length < 48) return SDL_FALSE;
   8.201 +    /* sig: 19 bytes company name + 13 bytes space */
   8.202 +    if (SDL_memcmp(data,"Brava Software Inc.             ",32) != 0) {
   8.203 +        return SDL_FALSE;
   8.204 +    }
   8.205 +    /* 4 bytes version: x.xx */
   8.206 +    if (!SDL_isdigit(data[32]) || data[33] != '.' ||
   8.207 +        !SDL_isdigit(data[34]) ||!SDL_isdigit(data[35])) {
   8.208 +        return SDL_FALSE;
   8.209 +    }
   8.210 +    #ifdef MMTAG_PARANOID
   8.211 +    /* [36..47]: 12 bytes trailing space */
   8.212 +    for (length = 36; length < 48; ++length) {
   8.213 +        if (data[length] != ' ') return SDL_FALSE;
   8.214 +    }
   8.215 +    #endif
   8.216 +    return SDL_TRUE;
   8.217 +}
   8.218 +static __inline__ int get_musicmatch_len(struct mp3file_t *m) {
   8.219 +    const Sint32 metasizes[4] = { 7868, 7936, 8004, 8132 };
   8.220 +    const unsigned char syncstr[10] = {'1','8','2','7','3','6','4','5',0,0};
   8.221 +    unsigned char buf[256];
   8.222 +    Sint32 i, j, imgext_ofs, version_ofs;
   8.223 +    int len;
   8.224 +
   8.225 +    MP3_RWseek(m, -68, RW_SEEK_END);
   8.226 +    MP3_RWread(m, buf, 1, 20);
   8.227 +    imgext_ofs  = (Sint32)((buf[3] <<24) | (buf[2] <<16) | (buf[1] <<8) | buf[0] );
   8.228 +    version_ofs = (Sint32)((buf[15]<<24) | (buf[14]<<16) | (buf[13]<<8) | buf[12]);
   8.229 +    if (version_ofs <= imgext_ofs) return -1;
   8.230 +    if (version_ofs <= 0 || imgext_ofs <= 0) return -1;
   8.231 +    /* Try finding the version info section:
   8.232 +     * Because metadata section comes after it, and because metadata section
   8.233 +     * has different sizes across versions (format ver. <= 3.00: always 7868
   8.234 +     * bytes), we can _not_ directly calculate using deltas from the offsets
   8.235 +     * section. */
   8.236 +    for (i = 0; i < 4; ++i) {
   8.237 +    /* 48: footer, 20: offsets, 256: version info */
   8.238 +        len = metasizes[i] + 48 + 20 + 256;
   8.239 +        if (m->length < len) return -1;
   8.240 +        MP3_RWseek(m, -len, RW_SEEK_END);
   8.241 +        MP3_RWread(m, buf, 1, 256);
   8.242 +        /* [0..9]: sync string, [30..255]: 0x20 */
   8.243 +        #ifdef MMTAG_PARANOID
   8.244 +        for (j = 30; j < 256; ++j) {
   8.245 +            if (buf[j] != ' ') break;
   8.246 +        }
   8.247 +        if (j < 256) continue;
   8.248 +        #endif
   8.249 +        if (SDL_memcmp(buf, syncstr, 10) == 0) {
   8.250 +            break;
   8.251 +        }
   8.252 +    }
   8.253 +    if (i == 4) return -1; /* no luck. */
   8.254 +    #ifdef MMTAG_PARANOID
   8.255 +    /* unused section: (4 bytes of 0x00) */
   8.256 +    MP3_RWseek(m, -(len + 4), RW_SEEK_END);
   8.257 +    MP3_RWread(m, buf, 1, 4); j = 0;
   8.258 +    if (SDL_memcmp(buf, &j, 4) != 0) return -1;
   8.259 +    #endif
   8.260 +    len += (version_ofs - imgext_ofs);
   8.261 +    if (m->length < len) return -1;
   8.262 +    MP3_RWseek(m, -len, RW_SEEK_END);
   8.263 +    MP3_RWread(m, buf, 1, 8);
   8.264 +    j = (Sint32)((buf[7] <<24) | (buf[6] <<16) | (buf[5] <<8) | buf[4]);
   8.265 +    if (j < 0) return -1;
   8.266 +    /* verify image size: */
   8.267 +    /* without this, we may land at a wrong place. */
   8.268 +    if (j + 12 != version_ofs - imgext_ofs) return -1;
   8.269 +    /* try finding the optional header */
   8.270 +    if (m->length < len + 256) return len;
   8.271 +    MP3_RWseek(m, -(len + 256), RW_SEEK_END);
   8.272 +    MP3_RWread(m, buf, 1, 256);
   8.273 +    /* [0..9]: sync string, [30..255]: 0x20 */
   8.274 +    if (SDL_memcmp(buf, syncstr, 10) != 0) {
   8.275 +        return len;
   8.276 +    }
   8.277 +    #ifdef MMTAG_PARANOID
   8.278 +    for (j = 30; j < 256; ++j) {
   8.279 +        if (buf[j] != ' ') return len;
   8.280 +    }
   8.281 +    #endif
   8.282 +    return len + 256; /* header is present. */
   8.283 +}
   8.284 +
   8.285 +int mp3_skiptags(struct mp3file_t *fil)
   8.286 +{
   8.287 +    unsigned char buf[128];
   8.288 +    int len, readsize;
   8.289 +    int rc = -1;
   8.290 +
   8.291 +    readsize = MP3_RWread(fil, buf, 1, 128);
   8.292 +    if (readsize <= 0) goto fail;
   8.293 +
   8.294 +    /* ID3v2 tag is at the start */
   8.295 +    if (is_id3v2(buf, readsize)) {
   8.296 +        len = get_id3v2_len(buf, readsize);
   8.297 +        if (len >= fil->length) goto fail;
   8.298 +        fil->start += len;
   8.299 +        fil->length -= len;
   8.300 +    }
   8.301 +    /* APE tag _might_ be at the start (discouraged
   8.302 +     * but not forbidden, either.)  read the header. */
   8.303 +    else if (is_apetag(buf, readsize)) {
   8.304 +        len = get_ape_len(buf);
   8.305 +        if (len >= fil->length) goto fail;
   8.306 +        fil->start += len;
   8.307 +        fil->length -= len;
   8.308 +    }
   8.309 +
   8.310 +    /* ID3v1 tag is at the end */
   8.311 +    if (fil->length >= 128) {
   8.312 +        MP3_RWseek(fil, -128, RW_SEEK_END);
   8.313 +        readsize = MP3_RWread(fil, buf, 1, 128);
   8.314 +        if (readsize != 128) goto fail;
   8.315 +        if (is_id3v1(buf, 128)) {
   8.316 +            fil->length -= 128;
   8.317 +            /* FIXME: handle possible double-ID3v1 tags?? */
   8.318 +        }
   8.319 +    }
   8.320 +
   8.321 +    /* do we know whether ape or lyrics3 is the first?
   8.322 +     * well, we don't: we need to handle that later... */
   8.323 +
   8.324 +    /* check for the _old_ MusicMatch tag at end. */
   8.325 +    if (fil->length >= 68) {
   8.326 +        MP3_RWseek(fil, -48, RW_SEEK_END);
   8.327 +        readsize = MP3_RWread(fil, buf, 1, 48);
   8.328 +        if (readsize != 48) goto fail;
   8.329 +        if (is_musicmatch(buf, 48)) {
   8.330 +            len = get_musicmatch_len(fil);
   8.331 +            if (len < 0) goto fail;
   8.332 +            if (len >= fil->length) goto fail;
   8.333 +            fil->length -= len;
   8.334 +        }
   8.335 +    }
   8.336 +
   8.337 +    /* APE tag may be at the end: read the footer */
   8.338 +    if (fil->length >= 32) {
   8.339 +        MP3_RWseek(fil, -32, RW_SEEK_END);
   8.340 +        readsize = MP3_RWread(fil, buf, 1, 32);
   8.341 +        if (readsize != 32) goto fail;
   8.342 +        if (is_apetag(buf, 32)) {
   8.343 +            len = get_ape_len(buf);
   8.344 +            if (len >= fil->length) goto fail;
   8.345 +            fil->length -= len;
   8.346 +        }
   8.347 +    }
   8.348 +
   8.349 +    if (fil->length >= 15) {
   8.350 +        MP3_RWseek(fil, -15, RW_SEEK_END);
   8.351 +        readsize = MP3_RWread(fil, buf, 1, 15);
   8.352 +        if (readsize != 15) goto fail;
   8.353 +        len = is_lyrics3tag(buf, 15);
   8.354 +        if (len == 2) {
   8.355 +            len = get_lyrics3v2_len(buf, 6);
   8.356 +            if (len >= fil->length) goto fail;
   8.357 +            if (len < 15) goto fail;
   8.358 +            MP3_RWseek(fil, -len, RW_SEEK_END);
   8.359 +            readsize = MP3_RWread(fil, buf, 1, 11);
   8.360 +            if (readsize != 11) goto fail;
   8.361 +            if (!verify_lyrics3v2(buf, 11)) goto fail;
   8.362 +            fil->length -= len;
   8.363 +        }
   8.364 +        else if (len == 1) {
   8.365 +            len = get_lyrics3v1_len(fil);
   8.366 +            if (len < 0) goto fail;
   8.367 +            fil->length -= len;
   8.368 +        }
   8.369 +    }
   8.370 +
   8.371 +    rc = (fil->length > 0)? 0 : -1;
   8.372 +    fail:
   8.373 +    MP3_RWseek(fil, 0, RW_SEEK_SET);
   8.374 +    return rc;
   8.375 +}
   8.376 +
   8.377 +#endif /* MP3_???_MUSIC */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/mp3utils.h	Sat Dec 14 18:10:10 2019 +0300
     9.3 @@ -0,0 +1,34 @@
     9.4 +/*
     9.5 +  SDL_mixer:  An audio mixer library based on the SDL library
     9.6 +  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     9.7 +
     9.8 +  This software is provided 'as-is', without any express or implied
     9.9 +  warranty.  In no event will the authors be held liable for any damages
    9.10 +  arising from the use of this software.
    9.11 +
    9.12 +  Permission is granted to anyone to use this software for any purpose,
    9.13 +  including commercial applications, and to alter it and redistribute it
    9.14 +  freely, subject to the following restrictions:
    9.15 +
    9.16 +  1. The origin of this software must not be misrepresented; you must not
    9.17 +     claim that you wrote the original software. If you use this software
    9.18 +     in a product, an acknowledgment in the product documentation would be
    9.19 +     appreciated but is not required.
    9.20 +  2. Altered source versions must be plainly marked as such, and must not be
    9.21 +     misrepresented as being the original software.
    9.22 +  3. This notice may not be removed or altered from any source distribution.
    9.23 +*/
    9.24 +
    9.25 +#ifndef MP3UTILS_H_
    9.26 +#define MP3UTILS_H_
    9.27 +
    9.28 +struct mp3file_t {
    9.29 +  SDL_RWops *rw;
    9.30 +  int start, length, pos;
    9.31 +};
    9.32 +
    9.33 +extern int mp3_skiptags(struct mp3file_t *fil);
    9.34 +extern int MP3_RWread(struct mp3file_t *fil, void *ptr, int size, int maxnum);
    9.35 +extern int MP3_RWseek(struct mp3file_t *fil, int offset, int whence);
    9.36 +
    9.37 +#endif /* MP3UTILS_H_ */
    10.1 --- a/music_mad.c	Sun Dec 08 15:50:02 2019 +0300
    10.2 +++ b/music_mad.c	Sat Dec 14 18:10:10 2019 +0300
    10.3 @@ -25,48 +25,6 @@
    10.4  
    10.5  #include "music_mad.h"
    10.6  
    10.7 -static int
    10.8 -MAD_RWread(mad_data *music, void *ptr, int size, int maxnum) {
    10.9 -    int remaining = music->length - music->pos;
   10.10 -    int ret;
   10.11 -    maxnum *= size;
   10.12 -    if (maxnum > remaining) maxnum = remaining;
   10.13 -    ret = SDL_RWread(music->rw, ptr, 1, maxnum);
   10.14 -    if (ret > 0) music->pos += ret;
   10.15 -    return ret;
   10.16 -}
   10.17 -
   10.18 -static int
   10.19 -MAD_RWseek(mad_data *music, int offset, int whence) {
   10.20 -    int ret;
   10.21 -    switch (whence) { /* assumes a legal whence value */
   10.22 -    case RW_SEEK_CUR:
   10.23 -        offset += music->pos;
   10.24 -        break;
   10.25 -    case RW_SEEK_END:
   10.26 -        offset = music->length + offset;
   10.27 -        break;
   10.28 -    }
   10.29 -    if (offset < 0) return -1;
   10.30 -    if (offset > music->length)
   10.31 -        offset = music->length;
   10.32 -    ret = SDL_RWseek(music->rw, music->start + offset, RW_SEEK_SET);
   10.33 -    if (ret < 0) return ret;
   10.34 -    music->pos = offset;
   10.35 -    return (music->pos - music->start);
   10.36 -}
   10.37 -
   10.38 -/* SDL-1.2 doesn't have a SDL_RWsize() */
   10.39 -static int SDL12_RWsize(SDL_RWops *rw) {
   10.40 -  int pos, size;
   10.41 -  if ((pos=SDL_RWtell(rw))<0) return -1;
   10.42 -  size = SDL_RWseek(rw, 0, RW_SEEK_END);
   10.43 -  SDL_RWseek(rw, pos, RW_SEEK_SET);
   10.44 -  return size;
   10.45 -}
   10.46 -
   10.47 -static int skip_tags (mad_data *);
   10.48 -
   10.49  mad_data *
   10.50  mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer, int freerw)
   10.51  {
   10.52 @@ -74,13 +32,15 @@
   10.53  
   10.54    mp3_mad = (mad_data *)SDL_malloc(sizeof(mad_data));
   10.55    if (mp3_mad) {
   10.56 -	mp3_mad->rw = rw;
   10.57 -	mp3_mad->start = 0;
   10.58 -	mp3_mad->pos = 0;
   10.59 -	mp3_mad->length = SDL12_RWsize(rw);
   10.60 -	if (skip_tags(mp3_mad) < 0) {
   10.61 +	int pos = SDL_RWtell(rw);
   10.62 +	mp3_mad->mp3file.rw = rw;
   10.63 +	mp3_mad->mp3file.start = 0;
   10.64 +	mp3_mad->mp3file.pos = 0;
   10.65 +	mp3_mad->mp3file.length = SDL_RWseek(rw, 0, RW_SEEK_END);
   10.66 +	SDL_RWseek(rw, pos, RW_SEEK_SET);
   10.67 +	if (mp3_skiptags(&mp3_mad->mp3file) < 0) {
   10.68  	    SDL_free(mp3_mad);
   10.69 -	    Mix_SetError("music_mad: corrupt mp3 file.");
   10.70 +	    Mix_SetError("music_mad: corrupt mp3 file (bad tags.)");
   10.71  	    return NULL;
   10.72  	}
   10.73  	mp3_mad->freerw = freerw;
   10.74 @@ -106,7 +66,7 @@
   10.75    mad_synth_finish(&mp3_mad->synth);
   10.76  
   10.77    if (mp3_mad->freerw) {
   10.78 -	SDL_RWclose(mp3_mad->rw);
   10.79 +	SDL_RWclose(mp3_mad->mp3file.rw);
   10.80    }
   10.81    SDL_free(mp3_mad);
   10.82  }
   10.83 @@ -130,198 +90,6 @@
   10.84  }
   10.85  
   10.86  
   10.87 -/*************************** TAG HANDLING: ******************************/
   10.88 -
   10.89 -static __inline__ SDL_bool is_id3v1(const unsigned char *data, int length)
   10.90 -{
   10.91 -    /* http://id3.org/ID3v1 :  3 bytes "TAG" identifier and 125 bytes tag data */
   10.92 -    if (length < 3 || SDL_memcmp(data,"TAG",3) != 0) {
   10.93 -        return SDL_FALSE;
   10.94 -    }
   10.95 -    return SDL_TRUE;
   10.96 -}
   10.97 -static __inline__ SDL_bool is_id3v2(const unsigned char *data, int length)
   10.98 -{
   10.99 -    /* ID3v2 header is 10 bytes:  http://id3.org/id3v2.4.0-structure */
  10.100 -    /* bytes 0-2: "ID3" identifier */
  10.101 -    if (length < 10 || SDL_memcmp(data,"ID3",3) != 0) {
  10.102 -        return SDL_FALSE;
  10.103 -    }
  10.104 -    /* bytes 3-4: version num (major,revision), each byte always less than 0xff. */
  10.105 -    if (data[3] == 0xff || data[4] == 0xff) {
  10.106 -        return SDL_FALSE;
  10.107 -    }
  10.108 -    /* bytes 6-9 are the ID3v2 tag size: a 32 bit 'synchsafe' integer, i.e. the
  10.109 -     * highest bit 7 in each byte zeroed.  i.e.: 7 bit information in each byte ->
  10.110 -     * effectively a 28 bit value.  */
  10.111 -    if (data[6] >= 0x80 || data[7] >= 0x80 || data[8] >= 0x80 || data[9] >= 0x80) {
  10.112 -        return SDL_FALSE;
  10.113 -    }
  10.114 -    return SDL_TRUE;
  10.115 -}
  10.116 -static __inline__ int get_id3v2_len(const unsigned char *data, int length)
  10.117 -{
  10.118 -    /* size is a 'synchsafe' integer (see above) */
  10.119 -    int size = (int)((data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9]);
  10.120 -    size += 10; /* header size */
  10.121 -    /* ID3v2 header[5] is flags (bits 4-7 only, 0-3 are zero).
  10.122 -     * bit 4 set: footer is present (a copy of the header but
  10.123 -     * with "3DI" as ident.)  */
  10.124 -    if (data[5] & 0x10) {
  10.125 -        size += 10; /* footer size */
  10.126 -    }
  10.127 -    /* optional padding (always zeroes) */
  10.128 -    while (size < length && data[size] == 0) {
  10.129 -        ++size;
  10.130 -    }
  10.131 -    return size;
  10.132 -}
  10.133 -static __inline__ SDL_bool is_apetag(const unsigned char *data, int length)
  10.134 -{
  10.135 -   /* http://wiki.hydrogenaud.io/index.php?title=APEv2_specification
  10.136 -    * Header/footer is 32 bytes: bytes 0-7 ident, bytes 8-11 version,
  10.137 -    * bytes 12-17 size. bytes 24-31 are reserved: must be all zeroes. */
  10.138 -    Uint32 v;
  10.139 -
  10.140 -    if (length < 32 || SDL_memcmp(data,"APETAGEX",8) != 0) {
  10.141 -        return SDL_FALSE;
  10.142 -    }
  10.143 -    v = (data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8]; /* version */
  10.144 -    if (v != 2000U && v != 1000U) {
  10.145 -        return SDL_FALSE;
  10.146 -    }
  10.147 -    v = 0; /* reserved bits : */
  10.148 -    if (SDL_memcmp(&data[24],&v,4) != 0 || SDL_memcmp(&data[28],&v,4) != 0) {
  10.149 -        return SDL_FALSE;
  10.150 -    }
  10.151 -    return SDL_TRUE;
  10.152 -}
  10.153 -static __inline__ int get_ape_len(const unsigned char *data)
  10.154 -{
  10.155 -    Uint32 flags, version;
  10.156 -    int size = (int)((data[15]<<24) | (data[14]<<16) | (data[13]<<8) | data[12]);
  10.157 -    version = (data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8];
  10.158 -    flags = (data[23]<<24) | (data[22]<<16) | (data[21]<<8) | data[20];
  10.159 -    if (version == 2000U && (flags & (1U<<31))) size += 32; /* header present. */
  10.160 -    return size;
  10.161 -}
  10.162 -static __inline__ int is_lyrics3tag(const unsigned char *data, int length) {
  10.163 -    /* http://id3.org/Lyrics3
  10.164 -     * http://id3.org/Lyrics3v2 */
  10.165 -    if (length < 15) return 0;
  10.166 -    if (SDL_memcmp(data+6,"LYRICS200",9) == 0) return 2; /* v2 */
  10.167 -    if (SDL_memcmp(data+6,"LYRICSEND",9) == 0) return 1; /* v1 */
  10.168 -    return 0;
  10.169 -}
  10.170 -static __inline__ int get_lyrics3v1_len(mad_data *m) {
  10.171 -    const char *p; int i, len;
  10.172 -    /* needs manual search:  http://id3.org/Lyrics3 */
  10.173 -    /* this relies on the input_buffer size >= 5100 */
  10.174 -    if (m->length < 20) return -1;
  10.175 -    len = (m->length > 5109)? 5109 : m->length;
  10.176 -    MAD_RWseek(m, -len, RW_SEEK_END);
  10.177 -    MAD_RWread(m, m->input_buffer, 1, (len -= 9)); /* exclude footer */
  10.178 -    MAD_RWseek(m, 0, RW_SEEK_SET);
  10.179 -    /* strstr() won't work here. */
  10.180 -    for (i = len - 11, p = (const char*)m->input_buffer; i >= 0; --i, ++p) {
  10.181 -        if (SDL_memcmp(p, "LYRICSBEGIN", 11) == 0)
  10.182 -            break;
  10.183 -    }
  10.184 -    if (i < 0) return -1;
  10.185 -    return len - (int)(p - (const char*)m->input_buffer) + 9 /* footer */;
  10.186 -}
  10.187 -static __inline__ int get_lyrics3v2_len(const unsigned char *data, int length) {
  10.188 -    /* 6 bytes before the end marker is size in decimal format -
  10.189 -     * does not include the 9 bytes end marker and size field. */
  10.190 -    if (length != 6) return 0;
  10.191 -    return SDL_strtol((const char *)data, NULL, 10) + 15;
  10.192 -}
  10.193 -static __inline__ SDL_bool verify_lyrics3v2(const unsigned char *data, int length) {
  10.194 -    if (length < 11) return SDL_FALSE;
  10.195 -    if (SDL_memcmp(data,"LYRICSBEGIN",11) == 0) return SDL_TRUE;
  10.196 -    return SDL_FALSE;
  10.197 -}
  10.198 -
  10.199 -static int skip_tags(mad_data *music)
  10.200 -{
  10.201 -    int len, readsize;
  10.202 -
  10.203 -    readsize = MAD_RWread(music, music->input_buffer, 1, MAD_INPUT_BUFFER_SIZE);
  10.204 -    if (readsize <= 0) return -1;
  10.205 -
  10.206 -    /* ID3v2 tag is at the start */
  10.207 -    if (is_id3v2(music->input_buffer, readsize)) {
  10.208 -        len = get_id3v2_len(music->input_buffer, readsize);
  10.209 -        if (len >= music->length) return -1;
  10.210 -        music->start += len;
  10.211 -        music->length -= len;
  10.212 -        MAD_RWseek(music, 0, RW_SEEK_SET);
  10.213 -    }
  10.214 -    /* APE tag _might_ be at the start (discouraged
  10.215 -     * but not forbidden, either.)  read the header. */
  10.216 -    else if (is_apetag(music->input_buffer, readsize)) {
  10.217 -        len = get_ape_len(music->input_buffer);
  10.218 -        if (len >= music->length) return -1;
  10.219 -        music->start += len;
  10.220 -        music->length -= len;
  10.221 -        MAD_RWseek(music, 0, RW_SEEK_SET);
  10.222 -    }
  10.223 -
  10.224 -    /* ID3v1 tag is at the end */
  10.225 -    if (music->length < 128) goto ape;
  10.226 -    MAD_RWseek(music, -128, RW_SEEK_END);
  10.227 -    readsize = MAD_RWread(music, music->input_buffer, 1, 128);
  10.228 -    MAD_RWseek(music, 0, RW_SEEK_SET);
  10.229 -    if (readsize != 128) return -1;
  10.230 -    if (is_id3v1(music->input_buffer, 128)) {
  10.231 -        music->length -= 128;
  10.232 -
  10.233 -        /* FIXME: handle possible double-ID3v1 tags?? */
  10.234 -    }
  10.235 -
  10.236 -    /* do we know whether ape or lyrics3 is the first?
  10.237 -     * well, we don't: we need to handle that later... */
  10.238 -
  10.239 -    ape: /* APE tag may be at the end: read the footer */
  10.240 -    if (music->length >= 32) {
  10.241 -        MAD_RWseek(music, -32, RW_SEEK_END);
  10.242 -        readsize = MAD_RWread(music, music->input_buffer, 1, 32);
  10.243 -        MAD_RWseek(music, 0, RW_SEEK_SET);
  10.244 -        if (readsize != 32) return -1;
  10.245 -        if (is_apetag(music->input_buffer, 32)) {
  10.246 -            len = get_ape_len(music->input_buffer);
  10.247 -            if (len >= music->length) return -1;
  10.248 -            music->length -= len;
  10.249 -        }
  10.250 -    }
  10.251 -
  10.252 -    if (music->length >= 15) {
  10.253 -        MAD_RWseek(music, -15, RW_SEEK_END);
  10.254 -        readsize = MAD_RWread(music, music->input_buffer, 1, 15);
  10.255 -        MAD_RWseek(music, 0, RW_SEEK_SET);
  10.256 -        if (readsize != 15) return -1;
  10.257 -        len = is_lyrics3tag(music->input_buffer, 15);
  10.258 -        if (len == 2) {
  10.259 -            len = get_lyrics3v2_len(music->input_buffer, 6);
  10.260 -            if (len >= music->length) return -1;
  10.261 -            if (len < 15) return -1;
  10.262 -            MAD_RWseek(music, -len, RW_SEEK_END);
  10.263 -            readsize = MAD_RWread(music, music->input_buffer, 1, 11);
  10.264 -            MAD_RWseek(music, 0, RW_SEEK_SET);
  10.265 -            if (readsize != 11) return -1;
  10.266 -            if (!verify_lyrics3v2(music->input_buffer, 11)) return -1;
  10.267 -            music->length -= len;
  10.268 -        }
  10.269 -        else if (len == 1) {
  10.270 -            len = get_lyrics3v1_len(music);
  10.271 -            if (len < 0) return -1;
  10.272 -            music->length -= len;
  10.273 -        }
  10.274 -    }
  10.275 -
  10.276 -    return (music->length > 0)? 0: -1;
  10.277 -}
  10.278 -
  10.279  /* Reads the next frame from the file.  Returns true on success or
  10.280     false on failure. */
  10.281  static int
  10.282 @@ -348,7 +116,7 @@
  10.283  	}
  10.284  
  10.285  	/* Now read additional bytes from the input file. */
  10.286 -	read_size = MAD_RWread(mp3_mad, read_start, 1, read_size);
  10.287 +	read_size = MP3_RWread(&mp3_mad->mp3file, read_start, 1, read_size);
  10.288  
  10.289  	if (read_size <= 0) {
  10.290  	  if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
  10.291 @@ -539,7 +307,7 @@
  10.292  	mp3_mad->output_begin = 0;
  10.293  	mp3_mad->output_end = 0;
  10.294  
  10.295 -	MAD_RWseek(mp3_mad, 0, RW_SEEK_SET);
  10.296 +	MP3_RWseek(&mp3_mad->mp3file, 0, RW_SEEK_SET);
  10.297    }
  10.298  
  10.299    /* Now we have to skip frames until we come to the right one.
    11.1 --- a/music_mad.h	Sun Dec 08 15:50:02 2019 +0300
    11.2 +++ b/music_mad.h	Sat Dec 14 18:10:10 2019 +0300
    11.3 @@ -25,6 +25,7 @@
    11.4  #include "SDL_rwops.h"
    11.5  #include "SDL_audio.h"
    11.6  #include "SDL_mixer.h"
    11.7 +#include "mp3utils.h"
    11.8  
    11.9  #define MAD_INPUT_BUFFER_SIZE	(5*8192)
   11.10  #define MAD_OUTPUT_BUFFER_SIZE	8192
   11.11 @@ -41,8 +42,7 @@
   11.12  };
   11.13  
   11.14  typedef struct {
   11.15 -  SDL_RWops *rw;
   11.16 -  int start, length, pos;
   11.17 +  struct mp3file_t mp3file;
   11.18    int freerw;
   11.19    struct mad_stream stream;
   11.20    struct mad_frame frame;
    12.1 --- a/music_mpg.c	Sun Dec 08 15:50:02 2019 +0300
    12.2 +++ b/music_mpg.c	Sat Dec 14 18:10:10 2019 +0300
    12.3 @@ -83,12 +83,12 @@
    12.4  /* we're gonna override mpg123's I/O with these wrappers for RWops */
    12.5  static
    12.6  ssize_t rwops_read(void* p, void* dst, size_t n) {
    12.7 -    return (ssize_t)SDL_RWread((SDL_RWops*)p, dst, 1, n);
    12.8 +    return (ssize_t)MP3_RWread((struct mp3file_t *)p, dst, 1, n);
    12.9  }
   12.10  
   12.11  static
   12.12  off_t rwops_seek(void* p, off_t offset, int whence) {
   12.13 -    return (off_t)SDL_RWseek((SDL_RWops*)p, (Sint64)offset, whence);
   12.14 +    return (off_t)MP3_RWseek((struct mp3file_t *)p, (int)offset, whence);
   12.15  }
   12.16  
   12.17  static
   12.18 @@ -103,6 +103,7 @@
   12.19  mpg_new_rw(SDL_RWops *src, SDL_AudioSpec* mixer, int freesrc)
   12.20  {
   12.21      int fmt, result;
   12.22 +    int pos;
   12.23      mpg_data* m = NULL;
   12.24  
   12.25      if (!Mix_Init(MIX_INIT_MP3)) {
   12.26 @@ -117,9 +118,17 @@
   12.27  
   12.28      SDL_memset(m, 0, sizeof(mpg_data));
   12.29  
   12.30 -    m->src = src;
   12.31 +    m->mp3file.rw = src;
   12.32      m->freesrc = freesrc;
   12.33  
   12.34 +    pos = SDL_RWtell(src);
   12.35 +    m->mp3file.length = SDL_RWseek(src, 0, RW_SEEK_END);
   12.36 +    SDL_RWseek(src, pos, RW_SEEK_SET);
   12.37 +    if (mp3_skiptags(&m->mp3file) < 0) {
   12.38 +        Mix_SetError("music_mpg: corrupt mp3 file (bad tags.)");
   12.39 +        goto fail;
   12.40 +    }
   12.41 +
   12.42      m->handle = mpg123.mpg123_new(0, &result);
   12.43      if (result != MPG123_OK) {
   12.44          goto fail;
   12.45 @@ -148,7 +157,7 @@
   12.46          goto fail;
   12.47      }
   12.48  
   12.49 -    result = mpg123.mpg123_open_handle(m->handle, m->src);
   12.50 +    result = mpg123.mpg123_open_handle(m->handle, &m->mp3file);
   12.51      if (result != MPG123_OK) {
   12.52          goto fail;
   12.53      }
   12.54 @@ -188,7 +197,7 @@
   12.55      }
   12.56  
   12.57      if (m->freesrc) {
   12.58 -        SDL_RWclose(m->src);
   12.59 +        SDL_RWclose(m->mp3file.rw);
   12.60      }
   12.61  
   12.62      if (m->cvt.buf) {
    13.1 --- a/music_mpg.h	Sun Dec 08 15:50:02 2019 +0300
    13.2 +++ b/music_mpg.h	Sat Dec 14 18:10:10 2019 +0300
    13.3 @@ -22,10 +22,12 @@
    13.4  #ifdef MP3_MUSIC
    13.5  
    13.6  #include <mpg123.h>
    13.7 +#include "SDL_rwops.h"
    13.8 +#include "mp3utils.h"
    13.9  
   13.10  typedef struct
   13.11  {
   13.12 -    SDL_RWops* src;
   13.13 +    struct mp3file_t mp3file;
   13.14      int freesrc;
   13.15  
   13.16      SDL_AudioSpec mixer;
   13.17 @@ -55,4 +57,3 @@
   13.18  void mpg_volume(mpg_data* m, int volume);
   13.19  
   13.20  #endif
   13.21 -