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