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 
MPG123_Load(void)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 
MPG123_Unload(void)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 
mpg123_format_to_sdl(int fmt)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 
mpg_err(mpg123_handle * mpg,int result)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 */
rwops_read(void * p,void * dst,size_t n)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 
rwops_seek(void * p,off_t offset,int whence)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 
rwops_cleanup(void * p)194 static void rwops_cleanup(void* p)
195 {
196     (void)p;
197     /* do nothing, we will free the file later */
198 }
199 
200 
MPG123_Open(const SDL_AudioSpec * spec)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 
MPG123_CreateFromRW(SDL_RWops * src,int freesrc)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 
MPG123_SetVolume(void * context,int volume)281 static void MPG123_SetVolume(void *context, int volume)
282 {
283     MPG123_Music *music = (MPG123_Music *)context;
284     music->volume = volume;
285 }
286 
MPG123_Play(void * context,int play_count)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 */
MPG123_GetSome(void * context,void * data,int bytes,SDL_bool * done)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 }
MPG123_GetAudio(void * context,void * data,int bytes)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 
MPG123_Seek(void * context,double secs)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 
MPG123_Delete(void * context)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 
MPG123_Close(void)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: */
432