Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/openal-0.0.8/src/backends/alc_backend_sdl.c @ 17

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

added openal

File size: 6.7 KB
Line 
1/* -*- mode: C; tab-width:8; c-basic-offset:8 -*-
2 * vi:set ts=8:
3 *
4 * sdl.c
5 *
6 * SDL backend.
7 */
8#include "al_siteconfig.h"
9
10#include <AL/al.h>
11#include <stdlib.h>
12#include <string.h>
13#include <SDL.h>
14#include <SDL_audio.h>
15
16#include "al_debug.h"
17#include "al_main.h"
18#include "alc/alc_context.h"
19#include "backends/alc_backend.h"
20
21#ifdef OPENAL_DLOPEN_SDL
22#include <dlfcn.h>
23#endif
24
25
26#define DEF_SPEED       _ALC_CANON_SPEED
27#define DEF_SIZE        _ALC_DEF_BUFSIZ
28#define DEF_SAMPLES     (DEF_SIZE / 2)
29#define DEF_CHANNELS    2
30#define SDL_DEF_FMT     AUDIO_S16
31
32static struct {
33        SDL_AudioSpec spec;
34        ALboolean firstTime;
35} sdl_info;
36
37static void *ringbuffer;
38static Uint32 ringbuffersize;
39static Uint32 readOffset;
40static Uint32 writeOffset;
41
42static int openal_load_sdl_library(void);
43
44/*
45 * sdl library functions.
46 */
47static void SDLCALL (*pSDL_Delay)(Uint32 ms);
48static void SDLCALL (*pSDL_PauseAudio)(int pause_on);
49static void SDLCALL (*pSDL_CloseAudio)(void);
50static int SDLCALL (*pSDL_OpenAudio)(SDL_AudioSpec *desired, SDL_AudioSpec *obtained);
51static int SDLCALL (*pSDL_Init)(Uint32 flags);
52static char* SDLCALL (*pSDL_GetError)(void);
53static void SDLCALL (*pSDL_LockAudio)(void);
54static void SDLCALL (*pSDL_UnlockAudio)(void);
55
56/*
57 * sdl library handle.
58 */
59static void * sdl_lib_handle = NULL;
60
61static int openal_load_sdl_library(void)
62{
63#ifdef OPENAL_DLOPEN_SDL
64        char * error = NULL;
65#endif
66   
67        if (sdl_lib_handle != NULL)
68                return 1;  /* already loaded. */
69
70        #ifdef OPENAL_DLOPEN_SDL
71                #define OPENAL_LOAD_SDL_SYMBOL(x) p##x = dlsym(sdl_lib_handle, #x); \
72                                                   error = dlerror(); \
73                                                   if (p##x == NULL) { \
74                                                           fprintf(stderr,"Could not resolve SDL symbol %s: %s\n", #x, ((error!=NULL)?(error):("(null)"))); \
75                                                           dlclose(sdl_lib_handle); sdl_lib_handle = NULL; \
76                                                           return 0; }
77                dlerror(); /* clear error state */
78                sdl_lib_handle = dlopen("libSDL.so", RTLD_LAZY | RTLD_GLOBAL);
79                error = dlerror();
80                if (sdl_lib_handle == NULL) {
81                        fprintf(stderr,"Could not open SDL library: %s\n",((error!=NULL)?(error):("(null)")));
82                        return 0;
83                }
84        #else
85                #define OPENAL_LOAD_SDL_SYMBOL(x) p##x = x;
86                sdl_lib_handle = (void *) 0xF00DF00D;
87        #endif
88
89        OPENAL_LOAD_SDL_SYMBOL(SDL_Delay);
90        OPENAL_LOAD_SDL_SYMBOL(SDL_PauseAudio);
91        OPENAL_LOAD_SDL_SYMBOL(SDL_CloseAudio);
92        OPENAL_LOAD_SDL_SYMBOL(SDL_OpenAudio);
93        OPENAL_LOAD_SDL_SYMBOL(SDL_Init);
94        OPENAL_LOAD_SDL_SYMBOL(SDL_GetError);
95        OPENAL_LOAD_SDL_SYMBOL(SDL_LockAudio);
96        OPENAL_LOAD_SDL_SYMBOL(SDL_UnlockAudio);
97
98        return 1;
99}
100
101
102static void
103dummy(UNUSED(void *unused), Uint8 *stream, int len)
104{
105        memcpy_offset(stream, ringbuffer, readOffset, (size_t)len);
106        readOffset += len;
107
108        if(readOffset >= ringbuffersize) {
109                readOffset  = 0;
110                writeOffset = 0;
111        }
112}
113
114static void *
115grab_write_sdl(void)
116{
117        if (!openal_load_sdl_library())
118                return NULL;
119
120        sdl_info.spec.freq     = DEF_SPEED;
121        sdl_info.spec.channels = DEF_CHANNELS;
122        sdl_info.spec.samples  = DEF_SAMPLES;
123        sdl_info.spec.size     = DEF_SIZE;
124        sdl_info.spec.format   = SDL_DEF_FMT;
125        sdl_info.spec.callback = dummy;
126        sdl_info.firstTime     = AL_TRUE;
127
128        if(pSDL_OpenAudio(&sdl_info.spec, NULL) < 0) {
129                /* maybe we need SDL_Init? */
130                pSDL_Init(SDL_INIT_AUDIO);
131
132                if(pSDL_OpenAudio(&sdl_info.spec, NULL) < 0) {
133                        _alDebug(ALD_CONTEXT, __FILE__, __LINE__,
134                                "No SDL: %s", pSDL_GetError());
135                        return NULL;
136                }
137        }
138
139        if(ringbuffer != NULL) {
140                free(ringbuffer);
141        }
142
143        ringbuffersize = 2 * sdl_info.spec.size;
144        ringbuffer     = malloc(ringbuffersize);
145        readOffset      = 0;
146        writeOffset     = 0;
147
148        _alDebug(ALD_CONTEXT, __FILE__, __LINE__, "SDL grab audio ok");
149
150        return &sdl_info.spec;
151}
152
153static void *
154grab_read_sdl(void)
155{
156        return NULL;
157}
158
159void *
160alcBackendOpenSDL_( ALC_OpenMode mode )
161{
162        return mode == ALC_OPEN_INPUT_ ? grab_read_sdl() : grab_write_sdl();
163}
164
165void
166sdl_blitbuffer(UNUSED(void *handle), void *data, int bytes)
167{
168        if (sdl_info.firstTime == AL_TRUE) {
169                sdl_info.firstTime = AL_FALSE;
170                offset_memcpy(ringbuffer, writeOffset, data, (size_t)bytes);
171                writeOffset = bytes;
172                /* start SDL callback mojo */
173                pSDL_PauseAudio(0);
174        } else {
175                pSDL_LockAudio();
176                while(writeOffset >= ringbuffersize) {
177                        pSDL_UnlockAudio();
178                        pSDL_Delay(1);
179                        pSDL_LockAudio();
180                }
181
182                offset_memcpy(ringbuffer, writeOffset, data, (size_t)bytes);
183                writeOffset += bytes;
184
185                pSDL_UnlockAudio();
186        }
187}
188
189void
190release_sdl(UNUSED(void *handle))
191{
192        pSDL_CloseAudio();
193}
194
195static ALboolean
196set_write_sdl(UNUSED(void *handle), ALuint *bufsiz, ALenum *fmt, ALuint *speed)
197{
198        ALuint bytesPerSample   = _alGetBitsFromFormat(*fmt) >> 3;
199        ALuint channels = _alGetChannelsFromFormat(*fmt);
200
201        memset(&sdl_info, '\0', sizeof (sdl_info));
202        sdl_info.spec.freq     = *speed;
203        sdl_info.spec.channels = channels;
204        sdl_info.spec.samples  = *bufsiz / bytesPerSample;
205        sdl_info.spec.format   = _al_AL2ACFMT(*fmt);
206        sdl_info.spec.callback = dummy;
207        sdl_info.firstTime     = AL_TRUE;
208
209        pSDL_CloseAudio();
210
211        if(pSDL_OpenAudio(&sdl_info.spec, NULL) < 0) {
212                fprintf(stderr,
213                        "No SDL: %s\n", pSDL_GetError());
214
215                return AL_FALSE;
216        }
217
218        *bufsiz = sdl_info.spec.size;
219
220        if(ringbuffer != NULL) {
221                free(ringbuffer);
222        }
223
224        ringbuffersize = 2 * sdl_info.spec.size;
225        ringbuffer     = malloc(ringbuffersize);
226        readOffset      = 0;
227        writeOffset     = 0;
228
229        memset(ringbuffer, 0, ringbuffersize);
230
231        /* FIXME: should remove extraneous *channels and rely only on format */
232        *fmt      = _al_AC2ALFMT(sdl_info.spec.format, sdl_info.spec.channels);
233        *speed    = sdl_info.spec.freq;
234
235        _alDebug(ALD_CONTEXT, __FILE__, __LINE__, "set_write_sdl ok");
236
237        return AL_TRUE;
238}
239
240static ALboolean
241set_read_sdl(UNUSED(void *handle), UNUSED(ALuint *bufsiz), UNUSED(ALenum *fmt),
242             UNUSED(ALuint *speed))
243{
244        return AL_FALSE;
245}
246
247ALboolean
248alcBackendSetAttributesSDL_(ALC_OpenMode mode, void *handle, ALuint *bufsiz, ALenum *fmt, ALuint *speed)
249{
250        return mode == ALC_OPEN_INPUT_ ?
251                set_read_sdl(handle, bufsiz, fmt, speed) :
252                set_write_sdl(handle, bufsiz, fmt, speed);
253}
254
255void
256pause_sdl( UNUSED(void *handle) )
257{
258}
259
260void
261resume_sdl( UNUSED(void *handle) )
262{
263}
264
265ALsizei
266capture_sdl( UNUSED(void *handle), UNUSED(void *capture_buffer), UNUSED(int bufsiz) )
267{
268        return 0;
269}
270
271ALfloat
272get_sdlchannel( UNUSED(void *handle), UNUSED(ALuint channel) )
273{
274        return 0.0;
275}
276
277int
278set_sdlchannel( UNUSED(void *handle), UNUSED(ALuint channel), UNUSED(ALfloat volume) )
279{
280        return 0;
281}
Note: See TracBrowser for help on using the repository browser.