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