add mpg123 support
authorFranc[e]sco <lolisamurai@tfwno.gf>
Thu, 20 Jul 2017 22:03:19 +0200
changeset 757420f3b37dc95
parent 756 db4027cbc804
child 758 76033c589321
add mpg123 support
SDL_mixer.h
configure.in
dynamic_mp3.c
dynamic_mp3.h
load_mp3.c
load_mp3.h
mixer.c
music.c
music_mpg.c
music_mpg.h
     1.1 --- a/SDL_mixer.h	Thu Oct 12 21:38:45 2017 -0700
     1.2 +++ b/SDL_mixer.h	Thu Jul 20 22:03:19 2017 +0200
     1.3 @@ -123,6 +123,7 @@
     1.4      MUS_OGG,
     1.5      MUS_MP3,
     1.6      MUS_MP3_MAD,
     1.7 +    MUS_MP3_MPG,
     1.8      MUS_FLAC,
     1.9      MUS_MODPLUG
    1.10  } Mix_MusicType;
    1.11 @@ -590,8 +591,8 @@
    1.12  /* Set the current position in the music stream.
    1.13     This returns 0 if successful, or -1 if it failed or isn't implemented.
    1.14     This function is only implemented for MOD music formats (set pattern
    1.15 -   order number) and for OGG, FLAC, MP3_MAD, and MODPLUG music (set
    1.16 -   position in seconds), at the moment.
    1.17 +   order number) and for OGG, FLAC, MP3_MAD, MP3_MPG and MODPLUG music
    1.18 +   (set position in seconds), at the moment.
    1.19  */
    1.20  extern DECLSPEC int SDLCALL Mix_SetMusicPosition(double position);
    1.21  
     2.1 --- a/configure.in	Thu Oct 12 21:38:45 2017 -0700
     2.2 +++ b/configure.in	Thu Jul 20 22:03:19 2017 +0200
     2.3 @@ -643,7 +643,29 @@
     2.4      fi
     2.5  fi
     2.6  
     2.7 -if test x$have_smpeg = xyes -o x$have_libmad = xyes; then
     2.8 +AC_ARG_ENABLE(music-mp3-mpg123,
     2.9 +AC_HELP_STRING([--enable-music-mp3-mpg123], [enable MP3 music via libmpg123 [[default=no]]]),
    2.10 +                  [], [enable_music_mp3_mpg123=no])
    2.11 +if test x$enable_music_mp3 = xyes -a x$enable_music_mp3_mpg123 = xyes; then
    2.12 +    AC_MSG_CHECKING(for libmpg123 headers)
    2.13 +    have_libmpg123=no
    2.14 +    AC_TRY_COMPILE([
    2.15 +     #include "mpg123.h"
    2.16 +    ],[
    2.17 +    ],[
    2.18 +    have_libmpg123=yes
    2.19 +    ])
    2.20 +    AC_MSG_RESULT($have_libmpg123)
    2.21 +    if test x$have_libmpg123 = xyes; then
    2.22 +        SOURCES="$SOURCES $srcdir/music_mpg.c"
    2.23 +        EXTRA_CFLAGS="$EXTRA_CFLAGS -DMP3_MPG_MUSIC"
    2.24 +        EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lmpg123"
    2.25 +    else
    2.26 +        AC_MSG_WARN([*** Unable to find mpg123 library (https://www.mpg123.de)])
    2.27 +    fi
    2.28 +fi
    2.29 +
    2.30 +if test x$have_smpeg = xyes -o x$have_libmad = xyes -o x$have_libmpg123; then
    2.31  	SOURCES="$SOURCES $srcdir/*_mp3.c"
    2.32  else
    2.33      AC_MSG_WARN([MP3 support disabled])
     3.1 --- a/dynamic_mp3.c	Thu Oct 12 21:38:45 2017 -0700
     3.2 +++ b/dynamic_mp3.c	Thu Jul 20 22:03:19 2017 +0200
     3.3 @@ -178,4 +178,23 @@
     3.4  }
     3.5  #endif /* MP3_DYNAMIC */
     3.6  
     3.7 +#elif defined(MP3_MPG_MUSIC)
     3.8 +#include "mpg123.h"
     3.9 +
    3.10 +int Mix_InitMP3()
    3.11 +{
    3.12 +    int result;
    3.13 +
    3.14 +    result = mpg123_init();
    3.15 +    if (result != MPG123_OK) {
    3.16 +        return 1;
    3.17 +    }
    3.18 +
    3.19 +    return 0;
    3.20 +}
    3.21 +
    3.22 +void Mix_QuitMP3() {
    3.23 +    mpg123_exit();
    3.24 +}
    3.25 +
    3.26  #endif /* MP3_MUSIC */
     4.1 --- a/dynamic_mp3.h	Thu Oct 12 21:38:45 2017 -0700
     4.2 +++ b/dynamic_mp3.h	Thu Jul 20 22:03:19 2017 +0200
     4.3 @@ -48,6 +48,10 @@
     4.4  
     4.5  extern smpeg_loader smpeg;
     4.6  
     4.7 +#elif defined(MP3_MPG_MUSIC)
     4.8 +
     4.9 +#include "mpg123.h"
    4.10 +
    4.11  #endif /* MUSIC_MP3 */
    4.12  
    4.13  extern int Mix_InitMP3();
     5.1 --- a/load_mp3.c	Thu Oct 12 21:38:45 2017 -0700
     5.2 +++ b/load_mp3.c	Thu Jul 20 22:03:19 2017 +0200
     5.3 @@ -23,7 +23,7 @@
     5.4  
     5.5  /* $Id$ */
     5.6  
     5.7 -#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
     5.8 +#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) || defined(MP3_MPG_MUSIC)
     5.9  
    5.10  #include "SDL_mixer.h"
    5.11  
    5.12 @@ -33,6 +33,8 @@
    5.13  #include "dynamic_mp3.h"
    5.14  #elif defined(MP3_MAD_MUSIC)
    5.15  #include "music_mad.h"
    5.16 +#elif defined(MP3_MPG_MUSIC)
    5.17 +#include "music_mpg.h"
    5.18  #endif
    5.19  
    5.20  SDL_AudioSpec *Mix_LoadMP3_RW(SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
    5.21 @@ -44,6 +46,8 @@
    5.22  	SMPEG_Info info;
    5.23  #elif defined(MP3_MAD_MUSIC)
    5.24  	mad_data *mp3_mad;
    5.25 +#elif defined(MP3_MPG_MUSIC)
    5.26 +	mpg_data *mp3_mpg;
    5.27  #endif
    5.28  	long samplesize;
    5.29  	int read_len;
    5.30 @@ -75,6 +79,9 @@
    5.31  #elif defined(MP3_MAD_MUSIC)
    5.32          mp3_mad = mad_openFileRW(src, spec, freesrc);
    5.33  		err = (mp3_mad == NULL);
    5.34 +#elif defined(MP3_MPG_MUSIC)
    5.35 +		mp3_mpg = mpg_new_rw(src, spec, freesrc);
    5.36 +        err = (mp3_mpg == NULL);
    5.37  #endif
    5.38  	}
    5.39  
    5.40 @@ -116,6 +123,18 @@
    5.41  
    5.42  		mad_stop(mp3_mad);
    5.43  
    5.44 +#elif defined(MP3_MPG_MUSIC)
    5.45 +
    5.46 +		mpg_start(mp3_mpg);
    5.47 +
    5.48 +		/* read once for audio length */
    5.49 +		while ((read_len = mpg_get_samples(mp3_mpg, *audio_buf, chunk_len)) > 0)
    5.50 +		{
    5.51 +			*audio_len += read_len;
    5.52 +		}
    5.53 +
    5.54 +		mpg_stop(mp3_mpg);
    5.55 +
    5.56  #endif
    5.57  
    5.58  		err = (read_len < 0);
    5.59 @@ -146,6 +165,11 @@
    5.60  			mad_start(mp3_mad);
    5.61  			err = (*audio_len != mad_getSamples(mp3_mad, *audio_buf, *audio_len));
    5.62  			mad_stop(mp3_mad);
    5.63 +#elif defined(MP3_MPG_MUSIC)
    5.64 +			mpg_seek(mp3_mpg, 0);
    5.65 +			mpg_start(mp3_mpg);
    5.66 +			err = (*audio_len != mpg_get_samples(mp3_mpg, *audio_buf, *audio_len));
    5.67 +			mpg_stop(mp3_mpg);
    5.68  #endif
    5.69  		}
    5.70  	}
    5.71 @@ -171,6 +195,13 @@
    5.72  		/* Deleting the MP3 closed the source if desired */
    5.73  		freesrc = SDL_FALSE;
    5.74  	}
    5.75 +#elif defined(MP3_MPG_MUSIC)
    5.76 +	if (mp3_mpg)
    5.77 +	{
    5.78 +		mpg_delete(mp3_mpg); mp3_mpg = NULL;
    5.79 +		/* Deleting the MP3 closed the source if desired */
    5.80 +		freesrc = SDL_FALSE;
    5.81 +	}
    5.82  #endif
    5.83  
    5.84  	if (freesrc)
     6.1 --- a/load_mp3.h	Thu Oct 12 21:38:45 2017 -0700
     6.2 +++ b/load_mp3.h	Thu Jul 20 22:03:19 2017 +0200
     6.3 @@ -23,7 +23,7 @@
     6.4  
     6.5  /* $Id$ */
     6.6  
     6.7 -#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
     6.8 +#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) || defined(MP3_MPG_MUSIC)
     6.9  /* Don't call this directly; use Mix_LoadWAV_RW() for now. */
    6.10  SDL_AudioSpec *Mix_LoadMP3_RW (SDL_RWops *src, int freesrc,
    6.11          SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
     7.1 --- a/mixer.c	Thu Oct 12 21:38:45 2017 -0700
     7.2 +++ b/mixer.c	Thu Jul 20 22:03:19 2017 +0200
     7.3 @@ -188,7 +188,7 @@
     7.4  #endif
     7.5      }
     7.6      if (flags & MIX_INIT_MP3) {
     7.7 -#ifdef MP3_MUSIC
     7.8 +#if defined(MP3_MUSIC) || defined(MP3_MPG_MUSIC)
     7.9          if ((initialized & MIX_INIT_MP3) || Mix_InitMP3() == 0) {
    7.10              result |= MIX_INIT_MP3;
    7.11          }
    7.12 @@ -234,7 +234,7 @@
    7.13          Mix_QuitMOD();
    7.14      }
    7.15  #endif
    7.16 -#ifdef MP3_MUSIC
    7.17 +#if defined(MP3_MUSIC) || defined(MP3_MPG_MUSIC)
    7.18      if (initialized & MIX_INIT_MP3) {
    7.19          Mix_QuitMP3();
    7.20      }
    7.21 @@ -506,7 +506,7 @@
    7.22  #ifdef FLAC_MUSIC
    7.23      add_chunk_decoder("FLAC");
    7.24  #endif
    7.25 -#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
    7.26 +#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) || defined(MP3_MPG_MUSIC)
    7.27      add_chunk_decoder("MP3");
    7.28  #endif
    7.29  
    7.30 @@ -665,7 +665,7 @@
    7.31                      (Uint8 **)&chunk->abuf, &chunk->alen);
    7.32              break;
    7.33          default:
    7.34 -#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
    7.35 +#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) || defined(MP3_MPG_MUSIC)
    7.36  			if (detect_mp3((Uint8*)&magic))
    7.37  			{
    7.38  				/* note: send a copy of the mixer spec */
     8.1 --- a/music.c	Thu Oct 12 21:38:45 2017 -0700
     8.2 +++ b/music.c	Thu Jul 20 22:03:19 2017 +0200
     8.3 @@ -64,11 +64,14 @@
     8.4  #ifdef MP3_MAD_MUSIC
     8.5  #include "music_mad.h"
     8.6  #endif
     8.7 +#ifdef MP3_MPG_MUSIC
     8.8 +#include "music_mpg.h"
     8.9 +#endif
    8.10  #ifdef FLAC_MUSIC
    8.11  #include "music_flac.h"
    8.12  #endif
    8.13  
    8.14 -#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
    8.15 +#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) || defined(MP3_MPG_MUSIC)
    8.16  static SDL_AudioSpec used_mixer;
    8.17  #endif
    8.18  
    8.19 @@ -115,6 +118,9 @@
    8.20  #ifdef MP3_MAD_MUSIC
    8.21          mad_data *mp3_mad;
    8.22  #endif
    8.23 +#ifdef MP3_MPG_MUSIC
    8.24 +        mpg_data *mp3_mpg;
    8.25 +#endif
    8.26  #ifdef FLAC_MUSIC
    8.27          FLAC_music *flac;
    8.28  #endif
    8.29 @@ -333,6 +339,11 @@
    8.30                  left = mad_getSamples(music_playing->data.mp3_mad, stream, len);
    8.31                  break;
    8.32  #endif
    8.33 +#ifdef MP3_MPG_MUSIC
    8.34 +            case MUS_MP3_MPG:
    8.35 +                left = mpg_get_samples(music_playing->data.mp3_mpg, stream, len);
    8.36 +                break;
    8.37 +#endif
    8.38              default:
    8.39                  /* Unknown music type?? */
    8.40                  break;
    8.41 @@ -412,7 +423,7 @@
    8.42          add_music_decoder("FLAC");
    8.43      }
    8.44  #endif
    8.45 -#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
    8.46 +#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) || defined(MP3_MPG_MUSIC)
    8.47      /* Keep a copy of the mixer */
    8.48      used_mixer = *mixer;
    8.49      add_music_decoder("MP3");
    8.50 @@ -678,6 +689,16 @@
    8.51              Mix_SetError("Could not initialize MPEG stream.");
    8.52          }
    8.53          break;
    8.54 +#elif defined(MP3_MPG_MUSIC)
    8.55 +    case MUS_MP3:
    8.56 +        music->type = MUS_MP3_MPG;
    8.57 +        music->data.mp3_mpg = mpg_new_rw(src, &used_mixer, freesrc);
    8.58 +        if (music->data.mp3_mpg) {
    8.59 +            music->error = 0;
    8.60 +        } else {
    8.61 +            Mix_SetError("Could not initialize MPEG stream.");
    8.62 +        }
    8.63 +        break;
    8.64  #endif
    8.65  #ifdef MID_MUSIC
    8.66      case MUS_MID:
    8.67 @@ -842,6 +863,11 @@
    8.68                  mad_closeFile(music->data.mp3_mad);
    8.69                  break;
    8.70  #endif
    8.71 +#ifdef MP3_MPG_MUSIC
    8.72 +            case MUS_MP3_MPG:
    8.73 +                mpg_delete(music->data.mp3_mpg);
    8.74 +                break;
    8.75 +#endif
    8.76              default:
    8.77                  /* Unknown music type?? */
    8.78                  break;
    8.79 @@ -969,6 +995,11 @@
    8.80          mad_start(music->data.mp3_mad);
    8.81          break;
    8.82  #endif
    8.83 +#ifdef MP3_MPG_MUSIC
    8.84 +        case MUS_MP3_MPG:
    8.85 +        mpg_start(music->data.mp3_mpg);
    8.86 +        break;
    8.87 +#endif
    8.88          default:
    8.89          Mix_SetError("Can't play unknown music type");
    8.90          retval = -1;
    8.91 @@ -1086,6 +1117,11 @@
    8.92          mad_seek(music_playing->data.mp3_mad, position);
    8.93          break;
    8.94  #endif
    8.95 +#ifdef MP3_MPG_MUSIC
    8.96 +        case MUS_MP3_MPG:
    8.97 +        mpg_seek(music_playing->data.mp3_mpg, position);
    8.98 +        break;
    8.99 +#endif
   8.100          default:
   8.101          /* TODO: Implement this for other music backends */
   8.102          retval = -1;
   8.103 @@ -1188,6 +1224,11 @@
   8.104          mad_setVolume(music_playing->data.mp3_mad, volume);
   8.105          break;
   8.106  #endif
   8.107 +#ifdef MP3_MPG_MUSIC
   8.108 +        case MUS_MP3_MPG:
   8.109 +        mpg_volume(music_playing->data.mp3_mpg, volume);
   8.110 +        break;
   8.111 +#endif
   8.112          default:
   8.113          /* Unknown music type?? */
   8.114          break;
   8.115 @@ -1279,6 +1320,11 @@
   8.116          mad_stop(music_playing->data.mp3_mad);
   8.117          break;
   8.118  #endif
   8.119 +#ifdef MP3_MPG_MUSIC
   8.120 +        case MUS_MP3_MPG:
   8.121 +        mpg_stop(music_playing->data.mp3_mpg);
   8.122 +        break;
   8.123 +#endif
   8.124          default:
   8.125          /* Unknown music type?? */
   8.126          return;
   8.127 @@ -1467,6 +1513,13 @@
   8.128          }
   8.129          break;
   8.130  #endif
   8.131 +#ifdef MP3_MPG_MUSIC
   8.132 +        case MUS_MP3_MPG:
   8.133 +        if (!mpg_playing(music_playing->data.mp3_mpg)) {
   8.134 +            playing = 0;
   8.135 +        }
   8.136 +        break;
   8.137 +#endif
   8.138          default:
   8.139          playing = 0;
   8.140          break;
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/music_mpg.c	Thu Jul 20 22:03:19 2017 +0200
     9.3 @@ -0,0 +1,396 @@
     9.4 +/*
     9.5 +  SDL_mixer:    An audio mixer library based on the SDL library
     9.6 +  Copyright (C) 1997-2017 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 +#ifdef MP3_MPG_MUSIC
    9.26 +
    9.27 +#include "SDL_mixer.h"
    9.28 +#include "music_mpg.h"
    9.29 +
    9.30 +static
    9.31 +int
    9.32 +snd_format_to_mpg123(uint16_t sdl_fmt)
    9.33 +{
    9.34 +    switch (sdl_fmt)
    9.35 +    {
    9.36 +        case AUDIO_U8:     return MPG123_ENC_UNSIGNED_8;
    9.37 +        case AUDIO_U16SYS: return MPG123_ENC_UNSIGNED_16;
    9.38 +        case AUDIO_S8:     return MPG123_ENC_SIGNED_8;
    9.39 +        case AUDIO_S16SYS: return MPG123_ENC_SIGNED_16;
    9.40 +        case AUDIO_S32SYS: return MPG123_ENC_SIGNED_32;
    9.41 +    }
    9.42 +
    9.43 +    return -1;
    9.44 +}
    9.45 +
    9.46 +static
    9.47 +Uint16
    9.48 +mpg123_format_to_sdl(int fmt)
    9.49 +{
    9.50 +    switch (fmt)
    9.51 +    {
    9.52 +        case MPG123_ENC_UNSIGNED_8:  return AUDIO_U8;
    9.53 +        case MPG123_ENC_UNSIGNED_16: return AUDIO_U16SYS;
    9.54 +        case MPG123_ENC_SIGNED_8:    return AUDIO_S8;
    9.55 +        case MPG123_ENC_SIGNED_16:   return AUDIO_S16SYS;
    9.56 +        case MPG123_ENC_SIGNED_32:   return AUDIO_S32SYS;
    9.57 +    }
    9.58 +
    9.59 +    return -1;
    9.60 +}
    9.61 +
    9.62 +static
    9.63 +char const*
    9.64 +mpg123_format_str(int fmt)
    9.65 +{
    9.66 +    switch (fmt)
    9.67 +    {
    9.68 +#define f(x) case x: return #x;
    9.69 +        f(MPG123_ENC_UNSIGNED_8)
    9.70 +        f(MPG123_ENC_UNSIGNED_16)
    9.71 +        f(MPG123_ENC_SIGNED_8)
    9.72 +        f(MPG123_ENC_SIGNED_16)
    9.73 +        f(MPG123_ENC_SIGNED_32)
    9.74 +#undef f
    9.75 +    }
    9.76 +
    9.77 +    return "unknown";
    9.78 +}
    9.79 +
    9.80 +static
    9.81 +char const*
    9.82 +mpg_err(mpg123_handle* mpg, int code)
    9.83 +{
    9.84 +    char const* err = "unknown error";
    9.85 +
    9.86 +    if (mpg && code == MPG123_ERR) {
    9.87 +        err = mpg123_strerror(mpg);
    9.88 +    } else {
    9.89 +        err = mpg123_plain_strerror(code);
    9.90 +    }
    9.91 +
    9.92 +    return err;
    9.93 +}
    9.94 +
    9.95 +/* we're gonna override mpg123's I/O with these wrappers for RWops */
    9.96 +static
    9.97 +ssize_t rwops_read(void* p, void* dst, size_t n) {
    9.98 +    return (ssize_t)SDL_RWread((SDL_RWops*)p, dst, 1, n);
    9.99 +}
   9.100 +
   9.101 +static
   9.102 +off_t rwops_seek(void* p, off_t offset, int whence) {
   9.103 +    return (off_t)SDL_RWseek((SDL_RWops*)p, (Sint64)offset, whence);
   9.104 +}
   9.105 +
   9.106 +static
   9.107 +void rwops_cleanup(void* p) {
   9.108 +    (void)p;
   9.109 +    /* do nothing, we will free the file later */
   9.110 +}
   9.111 +
   9.112 +static int getsome(mpg_data* m);
   9.113 +
   9.114 +mpg_data*
   9.115 +mpg_new_rw(SDL_RWops *src, SDL_AudioSpec* mixer, int freesrc)
   9.116 +{
   9.117 +    mpg_data* m;
   9.118 +    int result;
   9.119 +    int fmt;
   9.120 +
   9.121 +    if (!Mix_Init(MIX_INIT_MP3)) {
   9.122 +        return(NULL);
   9.123 +    }
   9.124 +
   9.125 +    m = (mpg_data*)SDL_malloc(sizeof(mpg_data));
   9.126 +    if (!m) {
   9.127 +        return 0;
   9.128 +    }
   9.129 +
   9.130 +    SDL_memset(m, 0, sizeof(mpg_data));
   9.131 +
   9.132 +    m->src = src;
   9.133 +    m->freesrc = freesrc;
   9.134 +
   9.135 +    m->handle = mpg123_new(0, &result);
   9.136 +    if (result != MPG123_OK) {
   9.137 +        return 0;
   9.138 +    }
   9.139 +
   9.140 +    result = mpg123_replace_reader_handle(
   9.141 +        m->handle,
   9.142 +        rwops_read, rwops_seek, rwops_cleanup
   9.143 +    );
   9.144 +    if (result != MPG123_OK) {
   9.145 +        return 0;
   9.146 +    }
   9.147 +
   9.148 +    result = mpg123_format_none(m->handle);
   9.149 +    if (result != MPG123_OK) {
   9.150 +        return 0;
   9.151 +    }
   9.152 +
   9.153 +    fmt = snd_format_to_mpg123(mixer->format);
   9.154 +    if (fmt == -1) {
   9.155 +        return 0;
   9.156 +    }
   9.157 +
   9.158 +    result =  mpg123_format(m->handle, mixer->freq, mixer->channels, fmt);
   9.159 +    if (result != MPG123_OK) {
   9.160 +        return 0;
   9.161 +    }
   9.162 +
   9.163 +    result = mpg123_open_handle(m->handle, m->src);
   9.164 +    if (result != MPG123_OK) {
   9.165 +        return 0;
   9.166 +    }
   9.167 +
   9.168 +    m->volume = MIX_MAX_VOLUME;
   9.169 +    m->mixer = *mixer;
   9.170 +
   9.171 +    /* hacky: read until we can figure out the format then rewind */
   9.172 +    while (!m->gotformat)
   9.173 +    {
   9.174 +        if (!getsome(m)) {
   9.175 +            return 0;
   9.176 +        }
   9.177 +    }
   9.178 +
   9.179 +    /* rewind */
   9.180 +    mpg123_seek(m->handle, 0, SEEK_SET);
   9.181 +
   9.182 +    m->len_available = 0;
   9.183 +    m->snd_available = m->cvt.buf;
   9.184 +
   9.185 +    return m;
   9.186 +}
   9.187 +
   9.188 +void
   9.189 +mpg_delete(mpg_data* m)
   9.190 +{
   9.191 +    if (!m) {
   9.192 +        return;
   9.193 +    }
   9.194 +
   9.195 +    if (m->freesrc) {
   9.196 +        SDL_RWclose(m->src);
   9.197 +    }
   9.198 +
   9.199 +    if (m->cvt.buf) {
   9.200 +        SDL_free(m->cvt.buf);
   9.201 +    }
   9.202 +
   9.203 +    mpg123_close(m->handle);
   9.204 +    mpg123_delete(m->handle);
   9.205 +    SDL_free(m);
   9.206 +}
   9.207 +
   9.208 +void
   9.209 +mpg_start(mpg_data* m) {
   9.210 +    m->playing = 1;
   9.211 +}
   9.212 +
   9.213 +void
   9.214 +mpg_stop(mpg_data* m) {
   9.215 +    m->playing = 0;
   9.216 +}
   9.217 +
   9.218 +int
   9.219 +mpg_playing(mpg_data* m) {
   9.220 +    return m->playing;
   9.221 +}
   9.222 +
   9.223 +/*
   9.224 +    updates the convert struct and buffer to match the format queried from
   9.225 +    mpg123.
   9.226 +*/
   9.227 +static
   9.228 +int
   9.229 +update_format(mpg_data* m)
   9.230 +{
   9.231 +    int code;
   9.232 +    long rate;
   9.233 +    int channels, encoding;
   9.234 +    Uint16 sdlfmt;
   9.235 +    size_t bufsize;
   9.236 +
   9.237 +    m->gotformat = 1;
   9.238 +
   9.239 +    code =
   9.240 +        mpg123_getformat(
   9.241 +            m->handle,
   9.242 +            &rate, &channels, &encoding
   9.243 +        );
   9.244 +
   9.245 +    if (code != MPG123_OK) {
   9.246 +        SDL_SetError("mpg123_getformat: %s", mpg_err(m->handle, code));
   9.247 +        return 0;
   9.248 +    }
   9.249 +
   9.250 +    sdlfmt = mpg123_format_to_sdl(encoding);
   9.251 +    if (sdlfmt == (Uint16)-1)
   9.252 +    {
   9.253 +        SDL_SetError(
   9.254 +            "Format %s is not supported by SDL",
   9.255 +            mpg123_format_str(encoding)
   9.256 +        );
   9.257 +        return 0;
   9.258 +    }
   9.259 +
   9.260 +    SDL_BuildAudioCVT(
   9.261 +        &m->cvt,
   9.262 +        sdlfmt, channels, rate,
   9.263 +        m->mixer.format,
   9.264 +        m->mixer.channels,
   9.265 +        m->mixer.freq
   9.266 +    );
   9.267 +
   9.268 +    if (m->cvt.buf) {
   9.269 +        SDL_free(m->cvt.buf);
   9.270 +    }
   9.271 +
   9.272 +    bufsize = sizeof(m->buf) * m->cvt.len_mult;
   9.273 +    m->cvt.buf = SDL_malloc(bufsize);
   9.274 +
   9.275 +    if (!m->cvt.buf)
   9.276 +    {
   9.277 +        SDL_SetError("Out of memory");
   9.278 +        mpg_stop(m);
   9.279 +        return 0;
   9.280 +    }
   9.281 +
   9.282 +    return 1;
   9.283 +}
   9.284 +
   9.285 +/* read some mp3 stream data and convert it for output */
   9.286 +static
   9.287 +int
   9.288 +getsome(mpg_data* m)
   9.289 +{
   9.290 +    int code;
   9.291 +    size_t len;
   9.292 +    Uint8* data = m->buf;
   9.293 +    size_t cbdata = sizeof(m->buf);
   9.294 +    SDL_AudioCVT* cvt = &m->cvt;
   9.295 +
   9.296 +    do
   9.297 +    {
   9.298 +        code = mpg123_read(m->handle, data, sizeof(data), &len);
   9.299 +        switch (code)
   9.300 +        {
   9.301 +            case MPG123_NEW_FORMAT:
   9.302 +                if (!update_format(m)) {
   9.303 +                    return 0;
   9.304 +                }
   9.305 +                break;
   9.306 +
   9.307 +            case MPG123_DONE:
   9.308 +                mpg_stop(m);
   9.309 +            case MPG123_OK:
   9.310 +                break;
   9.311 +
   9.312 +            default:
   9.313 +                SDL_SetError("mpg123_read: %s", mpg_err(m->handle, code));
   9.314 +                return 0;
   9.315 +        }
   9.316 +    }
   9.317 +    while (len && code != MPG123_OK);
   9.318 +
   9.319 +    SDL_memcpy(cvt->buf, data, cbdata);
   9.320 +
   9.321 +    if (cvt->needed) {
   9.322 +        /* we need to convert the audio to SDL's format */
   9.323 +        cvt->len = len;
   9.324 +        SDL_ConvertAudio(cvt);
   9.325 +    }
   9.326 +
   9.327 +    else {
   9.328 +        /* no conversion needed, just copy */
   9.329 +        cvt->len_cvt = len;
   9.330 +    }
   9.331 +
   9.332 +    m->len_available = cvt->len_cvt;
   9.333 +    m->snd_available = cvt->buf;
   9.334 +
   9.335 +    return 1;
   9.336 +}
   9.337 +
   9.338 +int
   9.339 +mpg_get_samples(mpg_data* m, Uint8 *stream, int len)
   9.340 +{
   9.341 +    int mixable;
   9.342 +
   9.343 +    while (len > 0 && m->playing)
   9.344 +    {
   9.345 +        if (!m->len_available)
   9.346 +        {
   9.347 +            if (!getsome(m)) {
   9.348 +                m->playing = 0;
   9.349 +                return len;
   9.350 +            }
   9.351 +        }
   9.352 +
   9.353 +        mixable = len;
   9.354 +
   9.355 +        if (mixable > m->len_available) {
   9.356 +            mixable = m->len_available;
   9.357 +        }
   9.358 +
   9.359 +        if (m->volume == MIX_MAX_VOLUME) {
   9.360 +            SDL_memcpy(stream, m->snd_available, mixable);
   9.361 +        }
   9.362 +
   9.363 +        else
   9.364 +        {
   9.365 +            SDL_MixAudioFormat(
   9.366 +                stream,
   9.367 +                m->snd_available,
   9.368 +                m->mixer.format,
   9.369 +                mixable,
   9.370 +                m->volume
   9.371 +            );
   9.372 +        }
   9.373 +
   9.374 +        m->len_available -= mixable;
   9.375 +        m->snd_available += mixable;
   9.376 +        len -= mixable;
   9.377 +        stream += mixable;
   9.378 +    }
   9.379 +
   9.380 +    return len;
   9.381 +}
   9.382 +
   9.383 +void
   9.384 +mpg_seek(mpg_data* m, double secs)
   9.385 +{
   9.386 +    off_t offset = m->mixer.freq * secs;
   9.387 +
   9.388 +    if ((offset = mpg123_seek(m->handle, offset, SEEK_SET)) < 0) {
   9.389 +        SDL_SetError("mpg123_seek: %s", mpg_err(m->handle, -offset));
   9.390 +    }
   9.391 +}
   9.392 +
   9.393 +void
   9.394 +mpg_volume(mpg_data* m, int volume) {
   9.395 +    m->volume = volume;
   9.396 +}
   9.397 +
   9.398 +
   9.399 +#endif    /* MP3_MPG_MUSIC */
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/music_mpg.h	Thu Jul 20 22:03:19 2017 +0200
    10.3 @@ -0,0 +1,58 @@
    10.4 +/*
    10.5 +    SDL_mixer:    An audio mixer library based on the SDL library
    10.6 +    Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
    10.7 +
    10.8 +    This software is provided 'as-is', without any express or implied
    10.9 +    warranty.    In no event will the authors be held liable for any damages
   10.10 +    arising from the use of this software.
   10.11 +
   10.12 +    Permission is granted to anyone to use this software for any purpose,
   10.13 +    including commercial applications, and to alter it and redistribute it
   10.14 +    freely, subject to the following restrictions:
   10.15 +
   10.16 +    1. The origin of this software must not be misrepresented; you must not
   10.17 +         claim that you wrote the original software. If you use this software
   10.18 +         in a product, an acknowledgment in the product documentation would be
   10.19 +         appreciated but is not required.
   10.20 +    2. Altered source versions must be plainly marked as such, and must not be
   10.21 +         misrepresented as being the original software.
   10.22 +    3. This notice may not be removed or altered from any source distribution.
   10.23 +*/
   10.24 +
   10.25 +#ifdef MP3_MPG_MUSIC
   10.26 +
   10.27 +#include <mpg123.h>
   10.28 +
   10.29 +typedef struct
   10.30 +{
   10.31 +    SDL_RWops* src;
   10.32 +    int freesrc;
   10.33 +
   10.34 +    SDL_AudioSpec mixer;
   10.35 +
   10.36 +    int playing;
   10.37 +    int volume;
   10.38 +
   10.39 +    mpg123_handle* handle;
   10.40 +
   10.41 +    int gotformat;
   10.42 +    SDL_AudioCVT cvt;
   10.43 +    Uint8 buf[8192];
   10.44 +    size_t len_available;
   10.45 +    Uint8* snd_available;
   10.46 +}
   10.47 +mpg_data;
   10.48 +
   10.49 +mpg_data* mpg_new_rw(SDL_RWops *src, SDL_AudioSpec* mixer, int freesrc);
   10.50 +void mpg_delete(mpg_data* m);
   10.51 +
   10.52 +void mpg_start(mpg_data* m);
   10.53 +void mpg_stop(mpg_data* m);
   10.54 +int mpg_playing(mpg_data* m);
   10.55 +
   10.56 +int mpg_get_samples(mpg_data* m, Uint8* stream, int len);
   10.57 +void mpg_seek(mpg_data* m, double seconds);
   10.58 +void mpg_volume(mpg_data* m, int volume);
   10.59 +
   10.60 +#endif
   10.61 +