Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/openal-0.0.8/src/extensions/al_ext_mp3.c @ 17

Last change on this file since 17 was 17, checked in by landauf, 16 years ago

added openal

File size: 8.3 KB
Line 
1/* -*- mode: C; tab-width:8; c-basic-offset:8 -*-
2 * vi:set ts=8:
3 *
4 * al_ext_mp3.c
5 *
6 * Temporary hack.
7 */
8#include "al_siteconfig.h"
9
10#include <AL/al.h>
11#include <stdio.h>
12#include <string.h>
13
14#include "al_ext_needed.h"
15#include "al_ext_mp3.h"
16
17#include "al_buffer.h"
18#include "al_ext.h"
19#include "alc/alc_context.h"
20
21#define MAX_MP3 64
22#define MAX_MPEG_READ 512
23
24#ifdef ENABLE_EXTENSION_AL_EXT_MP3
25
26#include <SDL/SDL.h>
27#include <smpeg.h>
28
29#ifdef OPENAL_DLOPEN_MP3
30#include <dlfcn.h>
31#endif
32
33
34/* maximum MAX_MP3 simultaneous sid/offset */
35static struct {
36        ALuint bid;
37        SMPEG *mpeg;
38} mp3bid[MAX_MP3];
39
40static struct {
41        ALuint sid;
42        ALuint offset;
43} mp3map[MAX_MP3];
44
45
46static int openal_load_smpeg_library(void);
47
48/*
49 * smpeg library functions.
50 */
51static void (*pSMPEG_enablevideo)( SMPEG* mpeg, int enable );
52static SMPEGstatus (*pSMPEG_status)( SMPEG* mpeg );
53static int (*pSMPEG_wantedSpec)( SMPEG *mpeg, SDL_AudioSpec *wanted );
54static void (*pSMPEG_enableaudio)( SMPEG* mpeg, int enable );
55static void (*pSMPEG_actualSpec)( SMPEG *mpeg, SDL_AudioSpec *spec );
56static void (*pSMPEG_rewind)( SMPEG* mpeg );
57static int (*pSMPEG_playAudio)( SMPEG *mpeg, Uint8 *stream, int len );
58static void (*pSMPEG_stop)( SMPEG* mpeg );
59static SMPEG* (*pSMPEG_new_data)(void *data, int size, SMPEG_Info* info, int sdl_audio);
60static void (*pSMPEG_play)( SMPEG* mpeg );
61static void (*pSMPEG_delete)( SMPEG* mpeg );
62
63/*
64 * smpeg library handle.
65 */
66static void * smpeg_lib_handle = NULL;
67
68static int openal_load_smpeg_library(void)
69{
70#ifdef OPENAL_DLOPEN_MP3
71        char * error = NULL;
72#endif
73   
74        if (smpeg_lib_handle != NULL)
75                return 1;  /* already loaded. */
76
77        #ifdef OPENAL_DLOPEN_MP3
78                #define OPENAL_LOAD_SMPEG_SYMBOL(x) p##x = dlsym(smpeg_lib_handle, #x); \
79                                                   error = dlerror(); \
80                                                   if (p##x == NULL) { \
81                                                           fprintf(stderr,"Could not resolve smpeg symbol %s: %s\n", #x, ((error!=NULL)?(error):("(null)"))); \
82                                                           dlclose(smpeg_lib_handle); smpeg_lib_handle = NULL; \
83                                                           return 0; }
84                dlerror(); /* clear error state */
85                smpeg_lib_handle = dlopen("libsmpeg.so", RTLD_LAZY | RTLD_GLOBAL);
86                error = dlerror();
87                if (smpeg_lib_handle == NULL) {
88                        fprintf(stderr,"Could not open smpeg library: %s\n",((error!=NULL)?(error):("(null)")));
89                        return 0;
90                }
91        #else
92                #define OPENAL_LOAD_SMPEG_SYMBOL(x) p##x = x;
93                smpeg_lib_handle = (void *) 0xF00DF00D;
94        #endif
95
96        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_enablevideo);
97        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_status);
98        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_wantedSpec);
99        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_enableaudio);
100        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_actualSpec);
101        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_rewind);
102        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_playAudio);
103        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_stop);
104        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_new_data);
105        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_play);
106        OPENAL_LOAD_SMPEG_SYMBOL(SMPEG_delete);
107
108        return 1;
109}
110
111
112#ifdef OPENAL_EXTENSION
113
114/*
115 * we are not being build into the library, therefore define the
116 * table that informs openal how to register the extensions upon
117 * dlopen.
118 */
119struct { ALubyte *name; void *addr; } alExtension_03282000 [] = {
120        AL_EXT_PAIR(alutLoadMP3_LOKI),
121        { NULL, NULL }
122};
123
124void alExtInit_03282000(void) {
125        int i;
126
127        for(i = 0; i < MAX_MP3; i++) {
128                mp3map[i].sid    = 0;
129                mp3map[i].offset = 0;
130
131                mp3bid[i].bid  = 0;
132                mp3bid[i].mpeg = NULL;
133        }
134
135        return;
136}
137
138void alExtFini_03282000(void) {
139        int i;
140
141        fprintf(stderr, "alExtFini_03282000 STUB\n");
142
143        for(i = 0; i < MAX_MP3; i++) {
144                if(mp3bid[i].mpeg != NULL) {
145                        /* Do something */
146                }
147        }
148
149        return;
150}
151
152#endif
153
154void MP3_DestroyCallback_Sid(ALuint sid);
155void MP3_DestroyCallback_Bid(ALuint bid);
156
157static int  mp3bid_get(ALuint bid, SMPEG **mpegp);
158static int  mp3bid_insert(ALuint bid, SMPEG *mpeg);
159static void mp3bid_remove(ALuint bid);
160
161static int  mp3map_get(ALuint sid, ALuint *offset);
162static int  mp3map_insert(ALuint sid);
163static void mp3map_update(int i, ALuint offset);
164static void mp3map_remove(ALuint sid);
165
166ALboolean alutLoadMP3_LOKI(ALuint bid, ALvoid *data, ALint size) {
167        static void (*palBufferi_LOKI)(ALuint, ALenum, ALint) = NULL;
168        SMPEG *newMpeg;
169        SDL_AudioSpec spec;
170
171        if(palBufferi_LOKI == NULL) {
172                palBufferi_LOKI = (void (*)(ALuint, ALenum, ALint))
173                            alGetProcAddress((const ALchar *) "alBufferi_LOKI");
174
175                if(palBufferi_LOKI == NULL) {
176                        fprintf(stderr, "Need alBufferi_LOKI\n");
177                        return AL_FALSE;
178                }
179               
180                if (!openal_load_smpeg_library())
181                        return AL_FALSE;
182
183        }
184
185        newMpeg = pSMPEG_new_data( data, size, NULL, 0 );
186
187        pSMPEG_wantedSpec( newMpeg, &spec );
188
189        _alcDCLockContext();
190
191        spec.freq     = canon_speed;
192        spec.format   = AUDIO_S16; /* FIXME */
193
194        _alcDCUnlockContext();
195
196        /* implicitly multichannel */
197        palBufferi_LOKI( bid, AL_CHANNELS, spec.channels );
198
199        pSMPEG_actualSpec( newMpeg, &spec );
200
201        /* insert new bid */
202        mp3bid_insert( bid, newMpeg );
203
204        _alBufferDataWithCallback_LOKI(bid,
205                                MP3_Callback,
206                                mp3map_remove,
207                                mp3bid_remove);
208
209        return AL_TRUE;
210}
211
212
213ALint MP3_Callback(ALuint sid,
214                ALuint bid,
215                ALshort *outdata,
216                ALenum format,
217                UNUSED(ALint freq),
218                ALint samples) {
219        int first;
220        int second;
221        SMPEG *mpeg;
222        ALuint offset;
223        int bytesRequested = samples * sizeof( ALshort );
224        int bytesPlayed;
225        int bps; /* bytes per sample */
226        int i;
227
228        if(samples > MAX_MPEG_READ) {
229                first  = MP3_Callback(sid, bid, outdata, format, freq, MAX_MPEG_READ);
230                second = MP3_Callback(sid, bid, outdata + MAX_MPEG_READ, format, freq, samples - MAX_MPEG_READ);
231                return first + second;
232
233        }
234
235        bps = _alGetBitsFromFormat( format );
236
237        /* get buffer specific information */
238        i = mp3bid_get( bid, &mpeg );
239        if(i == -1) {
240                fprintf(stderr, "No buffer id %d in data structures\n", bid);
241
242                return -1; /* weird */
243        }
244
245        /* get source specific information */
246        i = mp3map_get( sid, &offset );
247        if(i == -1) {
248                i = mp3map_insert( sid );
249
250                offset = AL_FALSE;
251
252                pSMPEG_enableaudio( mpeg, 1 );
253                pSMPEG_enablevideo( mpeg, 0 ); /* sanity check */
254        }
255
256        if( pSMPEG_status(mpeg) != SMPEG_PLAYING ) {
257                pSMPEG_play( mpeg );
258        }
259
260        memset( outdata, 0, (size_t)bytesRequested );
261
262        bytesPlayed = pSMPEG_playAudio( mpeg, (ALubyte *) outdata, bytesRequested );
263        bytesPlayed /= 2;
264
265        if(bytesPlayed < samples) {
266                pSMPEG_stop( mpeg );
267                pSMPEG_rewind( mpeg );
268
269                return bytesPlayed;
270        }
271
272        mp3map_update(i, offset + samples);
273
274        return samples;
275}
276
277static int mp3bid_get(ALuint bid, SMPEG **mpegp) {
278        int i;
279
280        for(i = 0; i < MAX_MP3; i++) {
281                if(mp3bid[i].bid == bid) {
282                        *mpegp = mp3bid[i].mpeg;
283
284                        return i;
285                }
286        }
287
288        return -1;
289}
290
291static int mp3bid_insert(ALuint bid, SMPEG *mpeg) {
292        int i;
293
294        for(i = 0; i < MAX_MP3; i++) {
295                if(mp3bid[i].bid == bid) {
296                        if(mp3bid[i].mpeg != NULL) {
297                                pSMPEG_stop( mp3bid[i].mpeg );
298                                pSMPEG_delete( mp3bid[i].mpeg );
299                                mp3bid[i].mpeg = NULL;
300                        }
301
302                        mp3bid[i].bid = 0; /* flag for next */
303                }
304
305                if(mp3bid[i].bid == 0) {
306                        mp3bid[i].bid  = bid;
307                        mp3bid[i].mpeg = mpeg;
308
309                        return i;
310                }
311        }
312
313        return 0;
314}
315
316static void mp3bid_remove( ALuint bid ) {
317        int i = 0;
318
319        for(i = 0; i < MAX_MP3; i++) {
320                if(mp3bid[i].bid == (ALuint) bid) {
321                        if(mp3bid[i].mpeg != NULL) {
322                                pSMPEG_stop( mp3bid[i].mpeg );
323                                pSMPEG_delete(mp3bid[i].mpeg);
324                                mp3bid[i].mpeg = NULL;
325                        }
326
327                        mp3bid[i].bid = 0;
328                        return;
329                }
330        }
331
332        return;
333}
334
335/* FIXME: make binary search */
336static int mp3map_get(ALuint sid, ALuint *offset) {
337        int i;
338
339        for(i = 0; i < MAX_MP3; i++) {
340                if(mp3map[i].sid == sid) {
341                        *offset = mp3map[i].offset;
342
343                        return i;
344                }
345        }
346
347        return -1;
348}
349
350/* FIXME: sorted insert for binary search */
351static int mp3map_insert(ALuint sid) {
352        int i;
353
354        for(i = 0; i < MAX_MP3; i++) {
355                if((mp3map[i].sid == 0) ||
356                   (mp3map[i].sid == sid)) {
357                        mp3map[i].sid    = sid;
358                        mp3map[i].offset  = AL_FALSE;
359
360                        return i;
361                }
362        }
363
364        return 0;
365}
366
367static void mp3map_update(int i, ALuint offset) {
368        if(i < 0) {
369                return;
370        }
371
372        if(i >= MAX_MP3) {
373                return;
374        }
375
376        mp3map[i].offset = offset;
377
378        return;
379}
380
381static void mp3map_remove(ALuint sid) {
382        int i;
383
384        for(i = 0; i < MAX_MP3; i++) {
385                if(mp3map[i].sid == sid) {
386                        mp3map[i].sid   = 0;
387                        mp3map[i].offset = AL_FALSE;
388
389                        return;
390                }
391        }
392
393        return;
394}
395
396#else
397
398/* without smpeg support, we don't do jack */
399
400#endif /* ENABLE_EXTENSION_AL_EXT_MP3 */
Note: See TracBrowser for help on using the repository browser.