/
music_mpg123.c
441 lines (380 loc) · 12.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
134
SDL_AudioStream *stream;
unsigned char *buffer;
size_t buffer_size;
} MPG123_Music;
135
136
137
138
static int MPG123_Seek(void *context, double secs);
static void MPG123_Delete(void *context);
139
140
static int mpg123_format_to_sdl(int fmt)
141
142
143
{
switch (fmt)
{
144
145
146
147
148
149
150
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;
151
152
153
}
}
154
155
/*
static const char *mpg123_format_str(int fmt)
156
157
158
159
160
161
162
163
164
{
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)
165
f(MPG123_ENC_FLOAT_32)
166
167
168
169
#undef f
}
return "unknown";
}
170
*/
171
172
static char const* mpg_err(mpg123_handle* mpg, int result)
173
174
175
{
char const* err = "unknown error";
176
if (mpg && result == MPG123_ERR) {
177
err = mpg123.mpg123_strerror(mpg);
178
} else {
179
err = mpg123.mpg123_plain_strerror(result);
180
181
182
183
184
}
return err;
}
/* we're gonna override mpg123's I/O with these wrappers for RWops */
185
186
static ssize_t rwops_read(void* p, void* dst, size_t n)
{
187
return (ssize_t)MP3_RWread((struct mp3file_t *)p, dst, 1, n);
188
189
}
190
191
static off_t rwops_seek(void* p, off_t offset, int whence)
{
192
return (off_t)MP3_RWseek((struct mp3file_t *)p, (Sint64)offset, whence);
193
194
}
195
196
static void rwops_cleanup(void* p)
{
197
198
199
200
(void)p;
/* do nothing, we will free the file later */
}
201
202
203
static int MPG123_Open(const SDL_AudioSpec *spec)
{
204
(void)spec;
205
if (mpg123.mpg123_init() != MPG123_OK) {
206
207
208
209
210
211
212
Mix_SetError("mpg123_init() failed");
return -1;
}
return 0;
}
static void *MPG123_CreateFromRW(SDL_RWops *src, int freesrc)
213
{
214
MPG123_Music *music;
215
int result;
216
217
const long *rates;
size_t i, num_rates;
218
219
220
221
222
music = (MPG123_Music*)SDL_calloc(1, sizeof(*music));
if (!music) {
return NULL;
}
223
music->mp3file.src = src;
224
225
music->volume = MIX_MAX_VOLUME;
226
227
228
229
230
231
232
233
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;
}
MP3_RWseek(&music->mp3file, 0, RW_SEEK_SET);
234
235
236
237
238
239
240
/* 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;
241
242
}
243
music->handle = mpg123.mpg123_new(0, &result);
244
if (result != MPG123_OK) {
245
246
247
MPG123_Delete(music);
Mix_SetError("mpg123_new failed");
return NULL;
248
249
}
250
result = mpg123.mpg123_replace_reader_handle(
251
music->handle,
252
rwops_read, rwops_seek, rwops_cleanup
253
);
254
if (result != MPG123_OK) {
255
256
257
MPG123_Delete(music);
Mix_SetError("mpg123_replace_reader_handle: %s", mpg_err(music->handle, result));
return NULL;
258
259
}
260
result = mpg123.mpg123_format_none(music->handle);
261
if (result != MPG123_OK) {
262
263
264
MPG123_Delete(music);
Mix_SetError("mpg123_format_none: %s", mpg_err(music->handle, result));
return NULL;
265
266
}
267
268
269
270
271
272
273
274
275
276
277
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);
278
279
}
280
result = mpg123.mpg123_open_handle(music->handle, &music->mp3file);
281
if (result != MPG123_OK) {
282
283
284
MPG123_Delete(music);
Mix_SetError("mpg123_open_handle: %s", mpg_err(music->handle, result));
return NULL;
285
286
}
287
288
music->freesrc = freesrc;
return music;
289
290
}
291
static void MPG123_SetVolume(void *context, int volume)
292
{
293
294
MPG123_Music *music = (MPG123_Music *)context;
music->volume = volume;
295
296
}
297
static int MPG123_Play(void *context, int play_count)
298
{
299
300
301
MPG123_Music *music = (MPG123_Music *)context;
music->play_count = play_count;
return MPG123_Seek(music, 0.0);
302
303
}
304
305
/* read some mp3 stream data and convert it for output */
static int MPG123_GetSome(void *context, void *data, int bytes, SDL_bool *done)
306
{
307
308
309
MPG123_Music *music = (MPG123_Music *)context;
int filled, result;
size_t amount;
310
long rate;
311
int channels, encoding, format;
312
313
314
315
316
317
if (music->stream) {
filled = SDL_AudioStreamGet(music->stream, data, bytes);
if (filled != 0) {
return filled;
}
318
319
}
320
321
322
if (!music->play_count) {
/* All done */
*done = SDL_TRUE;
323
324
325
return 0;
}
326
327
328
329
330
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;
331
}
332
break;
333
334
335
336
337
338
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;
339
}
340
/*printf("MPG123 format: %s, channels = %d, rate = %ld\n", mpg123_format_str(encoding), channels, rate);*/
341
342
343
format = mpg123_format_to_sdl(encoding);
SDL_assert(format != -1);
344
345
music->stream = SDL_NewAudioStream((SDL_AudioFormat)format, (Uint8)channels, (int)rate,
346
347
348
music_spec.format, music_spec.channels, music_spec.freq);
if (!music->stream) {
return -1;
349
}
350
351
352
353
354
355
356
357
358
359
360
361
362
363
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;
}
364
}
365
366
367
368
break;
default:
Mix_SetError("mpg123_read: %s", mpg_err(music->handle, result));
return -1;
369
}
370
371
372
373
374
375
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);
376
377
}
378
static int MPG123_Seek(void *context, double secs)
379
{
380
381
MPG123_Music *music = (MPG123_Music *)context;
off_t offset = (off_t)(music_spec.freq * secs);
382
383
384
if ((offset = mpg123.mpg123_seek(music->handle, offset, SEEK_SET)) < 0) {
return Mix_SetError("mpg123_seek: %s", mpg_err(music->handle, (int)-offset));
385
}
386
return 0;
387
388
}
389
390
static void MPG123_Delete(void *context)
{
391
MPG123_Music *music = (MPG123_Music *)context;
392
393
394
395
if (music->handle) {
mpg123.mpg123_close(music->handle);
mpg123.mpg123_delete(music->handle);
396
}
397
398
if (music->stream) {
SDL_FreeAudioStream(music->stream);
399
}
400
401
402
403
if (music->buffer) {
SDL_free(music->buffer);
}
if (music->freesrc) {
404
SDL_RWclose(music->mp3file.src);
405
406
}
SDL_free(music);
407
408
409
410
}
static void MPG123_Close(void)
{
411
mpg123.mpg123_exit();
412
413
414
415
416
417
418
419
420
421
}
Mix_MusicInterface Mix_MusicInterface_MPG123 =
{
"MPG123",
MIX_MUSIC_MPG123,
MUS_MP3,
SDL_FALSE,
SDL_FALSE,
422
MPG123_Load,
423
424
425
426
427
MPG123_Open,
MPG123_CreateFromRW,
NULL, /* CreateFromFile */
MPG123_SetVolume,
MPG123_Play,
428
NULL, /* IsPlaying */
429
430
431
432
MPG123_GetAudio,
MPG123_Seek,
NULL, /* Pause */
NULL, /* Resume */
433
NULL, /* Stop */
434
435
MPG123_Delete,
MPG123_Close,
436
MPG123_Unload
437
438
439
440
441
};
#endif /* MUSIC_MP3_MPG123 */
/* vi: set ts=4 sw=4 expandtab: */