music_mpg123.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 26 Oct 2018 11:04:13 -0700
changeset 915 2e274cefe1db
parent 848 3907db698eb5
child 926 d6c9518fb5ee
permissions -rw-r--r--
Updated to version 2.0.4
     1 /*
     2   SDL_mixer:    An audio mixer library based on the SDL library
     3   Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.    In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14        claim that you wrote the original software. If you use this software
    15        in a product, an acknowledgment in the product documentation would be
    16        appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18        misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 /* This file supports playing MP3 files with mpg123 */
    23 
    24 #ifdef MUSIC_MP3_MPG123
    25 
    26 #include <stdio.h>      // For SEEK_SET
    27 
    28 #include "SDL_assert.h"
    29 #include "SDL_loadso.h"
    30 
    31 #include "music_mpg123.h"
    32 
    33 #include <mpg123.h>
    34 
    35 
    36 typedef struct {
    37     int loaded;
    38     void *handle;
    39 
    40     int (*mpg123_close)(mpg123_handle *mh);
    41     void (*mpg123_delete)(mpg123_handle *mh);
    42     void (*mpg123_exit)(void);
    43     int (*mpg123_format)( mpg123_handle *mh, long rate, int channels, int encodings );
    44     int (*mpg123_format_none)(mpg123_handle *mh);
    45     int (*mpg123_getformat)( mpg123_handle *mh, long *rate, int *channels, int *encoding );
    46     int (*mpg123_init)(void);
    47     mpg123_handle *(*mpg123_new)(const char* decoder, int *error);
    48     int (*mpg123_open_handle)(mpg123_handle *mh, void *iohandle);
    49     const char* (*mpg123_plain_strerror)(int errcode);
    50     void (*mpg123_rates)(const long **list, size_t *number);
    51     int (*mpg123_read)(mpg123_handle *mh, unsigned char *outmemory, size_t outmemsize, size_t *done );
    52     int (*mpg123_replace_reader_handle)( mpg123_handle *mh, ssize_t (*r_read) (void *, void *, size_t), off_t (*r_lseek)(void *, off_t, int), void (*cleanup)(void*) );
    53     off_t (*mpg123_seek)( mpg123_handle *mh, off_t sampleoff, int whence );
    54     const char* (*mpg123_strerror)(mpg123_handle *mh);
    55 } mpg123_loader;
    56 
    57 static mpg123_loader mpg123 = {
    58     0, NULL
    59 };
    60 
    61 #ifdef MPG123_DYNAMIC
    62 #define FUNCTION_LOADER(FUNC, SIG) \
    63     mpg123.FUNC = (SIG) SDL_LoadFunction(mpg123.handle, #FUNC); \
    64     if (mpg123.FUNC == NULL) { SDL_UnloadObject(mpg123.handle); return -1; }
    65 #else
    66 #define FUNCTION_LOADER(FUNC, SIG) \
    67     mpg123.FUNC = FUNC;
    68 #endif
    69 
    70 static int MPG123_Load(void)
    71 {
    72     if (mpg123.loaded == 0) {
    73 #ifdef MPG123_DYNAMIC
    74         mpg123.handle = SDL_LoadObject(MPG123_DYNAMIC);
    75         if (mpg123.handle == NULL) {
    76             return -1;
    77         }
    78 #elif defined(__MACOSX__)
    79         extern int mpg123_init(void) __attribute__((weak_import));
    80         if (mpg123_init == NULL)
    81         {
    82             /* Missing weakly linked framework */
    83             Mix_SetError("Missing mpg123.framework");
    84             return -1;
    85         }
    86 #endif
    87         FUNCTION_LOADER(mpg123_close, int (*)(mpg123_handle *mh))
    88         FUNCTION_LOADER(mpg123_delete, void (*)(mpg123_handle *mh))
    89         FUNCTION_LOADER(mpg123_exit, void (*)(void))
    90         FUNCTION_LOADER(mpg123_format, int (*)( mpg123_handle *mh, long rate, int channels, int encodings ))
    91         FUNCTION_LOADER(mpg123_format_none, int (*)(mpg123_handle *mh))
    92         FUNCTION_LOADER(mpg123_getformat, int (*)( mpg123_handle *mh, long *rate, int *channels, int *encoding ))
    93         FUNCTION_LOADER(mpg123_init, int (*)(void))
    94         FUNCTION_LOADER(mpg123_new, mpg123_handle *(*)(const char* decoder, int *error))
    95         FUNCTION_LOADER(mpg123_open_handle, int (*)(mpg123_handle *mh, void *iohandle))
    96         FUNCTION_LOADER(mpg123_plain_strerror, const char* (*)(int errcode))
    97         FUNCTION_LOADER(mpg123_rates, void (*)(const long **list, size_t *number));
    98         FUNCTION_LOADER(mpg123_read, int (*)(mpg123_handle *mh, unsigned char *outmemory, size_t outmemsize, size_t *done ))
    99         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*) ))
   100         FUNCTION_LOADER(mpg123_seek, off_t (*)( mpg123_handle *mh, off_t sampleoff, int whence ))
   101         FUNCTION_LOADER(mpg123_strerror, const char* (*)(mpg123_handle *mh))
   102     }
   103     ++mpg123.loaded;
   104 
   105     return 0;
   106 }
   107 
   108 static void MPG123_Unload(void)
   109 {
   110     if (mpg123.loaded == 0) {
   111         return;
   112     }
   113     if (mpg123.loaded == 1) {
   114 #ifdef MPG123_DYNAMIC
   115         SDL_UnloadObject(mpg123.handle);
   116 #endif
   117     }
   118     --mpg123.loaded;
   119 }
   120 
   121 
   122 typedef struct
   123 {
   124     int play_count;
   125     SDL_RWops* src;
   126     int freesrc;
   127     int volume;
   128 
   129     mpg123_handle* handle;
   130     SDL_AudioStream *stream;
   131     unsigned char *buffer;
   132     size_t buffer_size;
   133 } MPG123_Music;
   134 
   135 
   136 static int MPG123_Seek(void *context, double secs);
   137 static void MPG123_Delete(void *context);
   138 
   139 static int mpg123_format_to_sdl(int fmt)
   140 {
   141     switch (fmt)
   142     {
   143         case MPG123_ENC_SIGNED_8:       return AUDIO_S8;
   144         case MPG123_ENC_UNSIGNED_8:     return AUDIO_U8;
   145         case MPG123_ENC_SIGNED_16:      return AUDIO_S16SYS;
   146         case MPG123_ENC_UNSIGNED_16:    return AUDIO_U16SYS;
   147         case MPG123_ENC_SIGNED_32:      return AUDIO_S32SYS;
   148         case MPG123_ENC_FLOAT_32:       return AUDIO_F32SYS;
   149         default:                        return -1;
   150     }
   151 }
   152 
   153 /*
   154 static const char *mpg123_format_str(int fmt)
   155 {
   156     switch (fmt)
   157     {
   158 #define f(x) case x: return #x;
   159         f(MPG123_ENC_UNSIGNED_8)
   160         f(MPG123_ENC_UNSIGNED_16)
   161         f(MPG123_ENC_SIGNED_8)
   162         f(MPG123_ENC_SIGNED_16)
   163         f(MPG123_ENC_SIGNED_32)
   164         f(MPG123_ENC_FLOAT_32)
   165 #undef f
   166     }
   167     return "unknown";
   168 }
   169 */
   170 
   171 static char const* mpg_err(mpg123_handle* mpg, int result)
   172 {
   173     char const* err = "unknown error";
   174 
   175     if (mpg && result == MPG123_ERR) {
   176         err = mpg123.mpg123_strerror(mpg);
   177     } else {
   178         err = mpg123.mpg123_plain_strerror(result);
   179     }
   180     return err;
   181 }
   182 
   183 /* we're gonna override mpg123's I/O with these wrappers for RWops */
   184 static ssize_t rwops_read(void* p, void* dst, size_t n)
   185 {
   186     return (ssize_t)SDL_RWread((SDL_RWops*)p, dst, 1, n);
   187 }
   188 
   189 static off_t rwops_seek(void* p, off_t offset, int whence)
   190 {
   191     return (off_t)SDL_RWseek((SDL_RWops*)p, (Sint64)offset, whence);
   192 }
   193 
   194 static void rwops_cleanup(void* p)
   195 {
   196     (void)p;
   197     /* do nothing, we will free the file later */
   198 }
   199 
   200 
   201 static int MPG123_Open(const SDL_AudioSpec *spec)
   202 {
   203     if (mpg123.mpg123_init() != MPG123_OK) {
   204         Mix_SetError("mpg123_init() failed");
   205         return -1;
   206     }
   207     return 0;
   208 }
   209 
   210 static void *MPG123_CreateFromRW(SDL_RWops *src, int freesrc)
   211 {
   212     MPG123_Music *music;
   213     int result;
   214     const long *rates;
   215     size_t i, num_rates;
   216 
   217     music = (MPG123_Music*)SDL_calloc(1, sizeof(*music));
   218     if (!music) {
   219         return NULL;
   220     }
   221     music->src = src;
   222     music->volume = MIX_MAX_VOLUME;
   223 
   224     /* Just assume 16-bit 2 channel audio for now */
   225     music->buffer_size = music_spec.samples * sizeof(Sint16) * 2;
   226     music->buffer = (unsigned char *)SDL_malloc(music->buffer_size);
   227     if (!music->buffer) {
   228         MPG123_Delete(music);
   229         SDL_OutOfMemory();
   230         return NULL;
   231     }
   232 
   233     music->handle = mpg123.mpg123_new(0, &result);
   234     if (result != MPG123_OK) {
   235         MPG123_Delete(music);
   236         Mix_SetError("mpg123_new failed");
   237         return NULL;
   238     }
   239 
   240     result = mpg123.mpg123_replace_reader_handle(
   241         music->handle,
   242         rwops_read, rwops_seek, rwops_cleanup
   243     );
   244     if (result != MPG123_OK) {
   245         MPG123_Delete(music);
   246         Mix_SetError("mpg123_replace_reader_handle: %s", mpg_err(music->handle, result));
   247         return NULL;
   248     }
   249 
   250     result = mpg123.mpg123_format_none(music->handle);
   251     if (result != MPG123_OK) {
   252         MPG123_Delete(music);
   253         Mix_SetError("mpg123_format_none: %s", mpg_err(music->handle, result));
   254         return NULL;
   255     }
   256 
   257     mpg123.mpg123_rates(&rates, &num_rates);
   258     for (i = 0; i < num_rates; ++i) {
   259         const int channels = (MPG123_MONO|MPG123_STEREO);
   260         const int formats = (MPG123_ENC_SIGNED_8 |
   261                              MPG123_ENC_UNSIGNED_8 |
   262                              MPG123_ENC_SIGNED_16 |
   263                              MPG123_ENC_UNSIGNED_16 |
   264                              MPG123_ENC_SIGNED_32 |
   265                              MPG123_ENC_FLOAT_32);
   266 
   267         mpg123.mpg123_format(music->handle, rates[i], channels, formats);
   268     }
   269 
   270     result = mpg123.mpg123_open_handle(music->handle, music->src);
   271     if (result != MPG123_OK) {
   272         MPG123_Delete(music);
   273         Mix_SetError("mpg123_open_handle: %s", mpg_err(music->handle, result));
   274         return NULL;
   275     }
   276 
   277     music->freesrc = freesrc;
   278     return music;
   279 }
   280 
   281 static void MPG123_SetVolume(void *context, int volume)
   282 {
   283     MPG123_Music *music = (MPG123_Music *)context;
   284     music->volume = volume;
   285 }
   286 
   287 static int MPG123_Play(void *context, int play_count)
   288 {
   289     MPG123_Music *music = (MPG123_Music *)context;
   290     music->play_count = play_count;
   291     return MPG123_Seek(music, 0.0);
   292 }
   293 
   294 /* read some mp3 stream data and convert it for output */
   295 static int MPG123_GetSome(void *context, void *data, int bytes, SDL_bool *done)
   296 {
   297     MPG123_Music *music = (MPG123_Music *)context;
   298     int filled, result;
   299     size_t amount;
   300     long rate;
   301     int channels, encoding, format;
   302 
   303     if (music->stream) {
   304         filled = SDL_AudioStreamGet(music->stream, data, bytes);
   305         if (filled != 0) {
   306             return filled;
   307         }
   308     }
   309 
   310     if (!music->play_count) {
   311         /* All done */
   312         *done = SDL_TRUE;
   313         return 0;
   314     }
   315 
   316     result = mpg123.mpg123_read(music->handle, music->buffer, music->buffer_size, &amount);
   317     switch (result) {
   318     case MPG123_OK:
   319         if (SDL_AudioStreamPut(music->stream, music->buffer, (int)amount) < 0) {
   320             return -1;
   321         }
   322         break;
   323 
   324     case MPG123_NEW_FORMAT:
   325         result = mpg123.mpg123_getformat(music->handle, &rate, &channels, &encoding);
   326         if (result != MPG123_OK) {
   327             Mix_SetError("mpg123_getformat: %s", mpg_err(music->handle, result));
   328             return -1;
   329         }
   330 /*printf("MPG123 format: %s, channels = %d, rate = %ld\n", mpg123_format_str(encoding), channels, rate);*/
   331 
   332         format = mpg123_format_to_sdl(encoding);
   333         SDL_assert(format != -1);
   334 
   335         music->stream = SDL_NewAudioStream(format, channels, (int)rate,
   336                                            music_spec.format, music_spec.channels, music_spec.freq);
   337         if (!music->stream) {
   338             return -1;
   339         }
   340         break;
   341 
   342     case MPG123_DONE:
   343         if (music->play_count == 1) {
   344             music->play_count = 0;
   345             SDL_AudioStreamFlush(music->stream);
   346         } else {
   347             int play_count = -1;
   348             if (music->play_count > 0) {
   349                 play_count = (music->play_count - 1);
   350             }
   351             if (MPG123_Play(music, play_count) < 0) {
   352                 return -1;
   353             }
   354         }
   355         break;
   356     default:
   357         Mix_SetError("mpg123_read: %s", mpg_err(music->handle, result));
   358         return -1;
   359     }
   360     return 0;
   361 }
   362 static int MPG123_GetAudio(void *context, void *data, int bytes)
   363 {
   364     MPG123_Music *music = (MPG123_Music *)context;
   365     return music_pcm_getaudio(context, data, bytes, music->volume, MPG123_GetSome);
   366 }
   367 
   368 static int MPG123_Seek(void *context, double secs)
   369 {
   370     MPG123_Music *music = (MPG123_Music *)context;
   371     off_t offset = (off_t)(music_spec.freq * secs);
   372 
   373     if ((offset = mpg123.mpg123_seek(music->handle, offset, SEEK_SET)) < 0) {
   374         return Mix_SetError("mpg123_seek: %s", mpg_err(music->handle, (int)-offset));
   375     }
   376     return 0;
   377 }
   378 
   379 static void MPG123_Delete(void *context)
   380 {
   381     MPG123_Music *music = (MPG123_Music *)context;
   382 
   383     if (music->handle) {
   384         mpg123.mpg123_close(music->handle);
   385         mpg123.mpg123_delete(music->handle);
   386     }
   387     if (music->stream) {
   388         SDL_FreeAudioStream(music->stream);
   389     }
   390     if (music->buffer) {
   391         SDL_free(music->buffer);
   392     }
   393     if (music->freesrc) {
   394         SDL_RWclose(music->src);
   395     }
   396     SDL_free(music);
   397 }
   398 
   399 static void MPG123_Close(void)
   400 {
   401     mpg123.mpg123_exit();
   402 }
   403 
   404 Mix_MusicInterface Mix_MusicInterface_MPG123 =
   405 {
   406     "MPG123",
   407     MIX_MUSIC_MPG123,
   408     MUS_MP3,
   409     SDL_FALSE,
   410     SDL_FALSE,
   411 
   412     MPG123_Load,
   413     MPG123_Open,
   414     MPG123_CreateFromRW,
   415     NULL,   /* CreateFromFile */
   416     MPG123_SetVolume,
   417     MPG123_Play,
   418     NULL,   /* IsPlaying */
   419     MPG123_GetAudio,
   420     MPG123_Seek,
   421     NULL,   /* Pause */
   422     NULL,   /* Resume */
   423     NULL,   /* Stop */
   424     MPG123_Delete,
   425     MPG123_Close,
   426     MPG123_Unload
   427 };
   428 
   429 #endif /* MUSIC_MP3_MPG123 */
   430 
   431 /* vi: set ts=4 sw=4 expandtab: */