Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

added openal

File size: 14.9 KB
RevLine 
[17]1/* darwin_native.c
2 *
3 * Mac OS X backend for OpenAL
4 * only PowerPC target on MacOS X is supported (Darwin is not supported alone)
5 *
6 * file originally created on jan 2000 by
7 * Guillaume Borios (gborios@free.fr) and Florent Boudet (flobo@ifrance.com)
8 * to help the PineApple project (http://ios.free.fr) run on MOSX
9 *
10 * Version : Alpha 6
11 */
12
13#include <CoreAudio/CoreAudio.h>
14
15#include "backends/alc_backend.h"
16
17#include <fcntl.h>
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21
22#include "al_main.h"
23#include "al_debug.h"
24#include "al_rcvar.h"
25#include "alc/alc_context.h"
26
27/* Adding buffers improves response to temporary heavy CPU loads but increases latency... */
28
29#define buildID 12
30
31typedef struct {
32    AudioDeviceID       deviceW;                /* the device ID */
33    void *              deviceWBuffer;
34    UInt32              deviceWBufferSize;      /* Buffer size of the audio device */
35    AudioBufferList*    deviceWBufferList;
36    AudioStreamBasicDescription deviceFormat;   /* format of the default device */
37} globalVars, *globalPtr;
38
39/************************************** GLOBALS *********************************/
40
41static globalVars       libGlobals; /* my globals */
42
43static unsigned int     alWriteFormat;  /* format of data from AL*/
44static unsigned int     alWriteSpeed;   /* speed of data from AL*/
45static unsigned int     nativePreferedBuffSize;
46static void * coreAudioDestination;
47static int ratio;
48static int stillToPlay = 0;
49
50/************************************* PROTOTYPES *********************************/
51
52static void implement_me(const char *fn);
53OSStatus deviceFillingProc (AudioDeviceID  inDevice, const AudioTimeStamp*  inNow, const AudioBufferList*  inInputData, const AudioTimeStamp*  inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* inClientData);
54
55OSStatus GetAudioDevices (void **devices /*Dev IDs*/, short     *devicesAvailable /*Dev number*/);
56
57int sync_mixer_iterate( void *dummy );
58
59void playABuffer(void *realdata);
60
61/************************************** UTILITIES *********************************/
62
63static int NoPrintf( UNUSED(const char *format), ... )
64{
65        return 0;
66}
67
68/* ToDo: Use vfprintf and nuke buffer */
69static int _alDebugPrintf( const char *format, ... )
70{
71        static char formatbuf[256];
72
73        va_list ap;
74        va_start(ap, format);
75        vsnprintf(formatbuf, sizeof formatbuf, format, ap);
76        va_end(ap);
77
78        return fprintf(stderr, "%s", formatbuf);
79}
80
81static int (*DebugPrintf)( const char *format, ... ) = NoPrintf;
82
83
84static void implement_me(const char *fn)
85{
86        DebugPrintf("[darwin_native.c] : %s is not implemented.\nPlease contact gborios@free.fr for information or help.\n", fn);
87}
88
89/*********************************** OS callback proc *****************************/
90
91OSStatus deviceFillingProc (UNUSED(AudioDeviceID  inDevice), UNUSED(const AudioTimeStamp*  inNow), UNUSED(const AudioBufferList*  inInputData), UNUSED(const AudioTimeStamp*  inInputTime), AudioBufferList*  outOutputData, UNUSED(const AudioTimeStamp* inOutputTime), void* inClientData)
92{
93    coreAudioDestination = (outOutputData->mBuffers[0]).mData;
94
95    if (stillToPlay) playABuffer(NULL);
96    else sync_mixer_iterate(NULL);
97
98    return 0;
99}
100
101/************************************** HAL Routines *********************************/
102
103OSStatus GetAudioDevices (void **devices /*Dev IDs*/, short     *devicesAvailable /*Dev number*/)
104{
105#ifdef DEBUG_MAXIMUS
106    int i;
107    char        cStr[256];
108#endif
109    OSStatus    err = NULL;
110    UInt32      outSize;
111    Boolean     outWritable;
112
113    DebugPrintf("OpenAL MOSX Backend : Build %d\n",buildID);
114
115    // find out how many audio devices there are, if any
116    err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &outSize, &outWritable);
117    if (err != NULL) return (err);
118
119    // calculate the number of device available
120    *devicesAvailable = outSize / sizeof(AudioDeviceID);
121    // Bail if there aren't any devices
122    if (*devicesAvailable < 1) return (-1);
123
124    // make space for the devices we are about to get
125    if (*devices != NULL) free(*devices);
126    *devices = malloc(outSize);
127    // get an array of AudioDeviceIDs
128    err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &outSize, (void *) *devices);
129    if (err != NULL) free(*devices);
130#ifdef DEBUG_MAXIMUS
131    DebugPrintf("Found %d Audio Device(s)\n",*devicesAvailable);
132
133    for (i=0; i<*devicesAvailable;i++)
134    {
135        UInt32 ID = ((UInt32*)(*devices))[i];
136        err =  AudioDeviceGetPropertyInfo(ID, 0, 0, kAudioDevicePropertyDeviceName,  &outSize, &outWritable);
137        err = AudioDeviceGetProperty(ID, 0, 0, kAudioDevicePropertyDeviceName, &outSize, cStr);
138        DebugPrintf("Device #%d : %s",ID,cStr);
139        err = AudioDeviceGetProperty(ID, 0, 0, kAudioDevicePropertyDeviceManufacturer, &outSize, cStr);
140        DebugPrintf(" (%s)\n",cStr);
141
142    }
143#endif
144    return (err);
145}
146
147
148/************************************** INTERFACE *********************************/
149
150static void *grab_read_native(void)
151{
152    implement_me("void *grab_read_native()");
153    return NULL;
154}
155
156static void *grab_write_native(void)
157{
158    OSStatus    error = 0;
159    UInt32      count;
160    void *      devices = 0;
161    short       devicesAvailable;
162    Boolean     outWritable;
163
164    Rcvar native_debug = rc_lookup("native-backend-debug");
165    if((rc_type(native_debug) == ALRC_BOOL) &&
166       (rc_tobool(native_debug) == AL_TRUE))
167    {
168            DebugPrintf = _alDebugPrintf;
169    }
170    else
171    {
172            DebugPrintf = NoPrintf;
173    }
174
175    /* Look for audio devices */
176    error = GetAudioDevices (&devices ,&devicesAvailable);
177    if (error != 0) goto Crash;
178    libGlobals.deviceW = ((AudioDeviceID*)(devices))[0]; /* Selecting first device */
179
180    /* Getting buffer size */
181    error = AudioDeviceGetPropertyInfo(libGlobals.deviceW, 0, 0, kAudioDevicePropertyBufferSize, &count, &outWritable);
182    if (error != 0) goto Crash;
183    error = AudioDeviceGetProperty(libGlobals.deviceW, 0, 0, kAudioDevicePropertyBufferSize, &count, &libGlobals.deviceWBufferSize);
184    if (error != 0) goto Crash;
185    DebugPrintf("IOProperties : Buffersize = %d\n",
186                (int) libGlobals.deviceWBufferSize);
187
188    /* getting streams configs */
189    error = AudioDeviceGetPropertyInfo(libGlobals.deviceW, 0, 0, kAudioDevicePropertyStreamConfiguration,  &count, &outWritable);
190    if (error != 0) goto Crash;
191    {
192        libGlobals.deviceWBufferList = malloc(count);
193
194        error = AudioDeviceGetProperty(libGlobals.deviceW, 0, 0, kAudioDevicePropertyStreamConfiguration, &count, libGlobals.deviceWBufferList);
195        if (error != 0) goto Crash;
196#ifdef DEBUG_MAXIMUS
197       {
198            unsigned int i;
199            DebugPrintf("IOProperties : Buffer number = %d\n",libGlobals.deviceWBufferList->mNumberBuffers);
200            /*device->outStreamsInfo  = malloc(sizeof(StreamInfo) * device->totalOutputStreams);*/
201            for (i = 0; i < libGlobals.deviceWBufferList->mNumberBuffers; i++)
202            {
203                DebugPrintf("  Buffer %d Properties : DataByteSize = %d\n",i,libGlobals.deviceWBufferList->mBuffers[i].mDataByteSize);
204                DebugPrintf("  Buffer %d Properties : NumberChannels = %d\n",i,libGlobals.deviceWBufferList->mBuffers[i].mNumberChannels);
205                DebugPrintf("  Buffer %d Properties : Data = %d\n",i,libGlobals.deviceWBufferList->mBuffers[i].mData);
206                /*error = GetPhysicalFormatCount(device, i + 1, &device->outStreamsInfo[i].pFormatCount, false);
207                device->outStreamsInfo[i].pFormatMenuSelection = 1;
208
209                error = GetActualFormatCount(device, i + 1, &device->outStreamsInfo[i].aFormatCount, false);
210                device->outStreamsInfo[i].aFormatMenuSelection = 1;*/
211            }
212        }
213#endif
214    }
215
216    error = AudioDeviceGetPropertyInfo(libGlobals.deviceW, 0, 0, kAudioDevicePropertyStreamFormats,  &count, &outWritable);
217    if (error != 0) goto Crash;
218    error = AudioDeviceGetProperty(libGlobals.deviceW, 0, 0, kAudioDevicePropertyStreamFormats, &count, &libGlobals.deviceFormat);
219    if (error != 0) goto Crash;
220
221#ifndef DEBUG_MAXIMUS
222    DebugPrintf("IOProperties : SampleRate = %f\n",libGlobals.deviceFormat.mSampleRate);
223    DebugPrintf("IOProperties : FormatFlags = %d\n",(int)libGlobals.deviceFormat.mFormatFlags);
224    DebugPrintf("IOProperties : BytesPerPacket = %d\n",(int)libGlobals.deviceFormat.mBytesPerPacket);
225    DebugPrintf("IOProperties : FramesPerPacket = %d\n",(int)libGlobals.deviceFormat.mFramesPerPacket);
226    DebugPrintf("IOProperties : BytesPerFrame = %d\n",(int)libGlobals.deviceFormat.mBytesPerFrame);
227    DebugPrintf("IOProperties : ChannelsPerFrame = %d\n",(int)libGlobals.deviceFormat.mChannelsPerFrame);
228    DebugPrintf("IOProperties : BitsPerChannel = %d\n",(int)libGlobals.deviceFormat.mBitsPerChannel);
229#endif
230
231    error = AudioDeviceGetPropertyInfo(libGlobals.deviceW, 0, 0, kAudioDevicePropertyStreamFormat,  &count, &outWritable);
232    if (error != 0) goto Crash;
233    error = AudioDeviceGetProperty(libGlobals.deviceW, 0, 0, kAudioDevicePropertyStreamFormat, &count, &libGlobals.deviceFormat);
234    if (error != 0) goto Crash;
235
236    error = AudioDeviceAddIOProc(libGlobals.deviceW, deviceFillingProc, (void *) &libGlobals);  /* Creates the callback proc */
237    if (error != 0) goto Crash;
238
239    return &libGlobals.deviceW;
240
241Crash :
242    DebugPrintf("An error occured during void *grab_write_native()\n");
243    libGlobals.deviceW = NULL;
244    return NULL;
245}
246
247void *
248alcBackendOpenNative_( ALC_OpenMode mode )
249{
250        return mode == ALC_OPEN_INPUT_ ? grab_read_native() : grab_write_native();
251}
252
253static ALboolean set_write_native(UNUSED(void *handle),
254                                  unsigned int *bufsiz,
255                                  unsigned int *fmt,
256                                  unsigned int *speed)
257{
258    OSStatus            error = 0;
259
260    DebugPrintf("Init Speed : %d\n",*speed);
261
262    //*fmt = AL_FORMAT_STEREO16;
263    //*speed = (unsigned int)libGlobals.deviceFormat.mSampleRate;
264
265    alWriteFormat = *fmt;
266
267    /* defines what the AL buffer size should be */
268    switch(alWriteFormat)
269    {
270        case AL_FORMAT_STEREO8:*bufsiz = libGlobals.deviceWBufferSize/4;
271                                DebugPrintf("Init fmt : AL_FORMAT_STEREO8\n");
272        break;
273        case AL_FORMAT_MONO16: *bufsiz = libGlobals.deviceWBufferSize/4;
274                                DebugPrintf("Init fmt : AL_FORMAT_MONO16\n");
275        break;
276
277        case AL_FORMAT_STEREO16: *bufsiz = libGlobals.deviceWBufferSize/2;
278                                DebugPrintf("Init fmt : AL_FORMAT_STEREO16\n");
279        break;
280
281        case AL_FORMAT_MONO8: *bufsiz = libGlobals.deviceWBufferSize/8;
282                                DebugPrintf("Init fmt : AL_FORMAT_MONO8\n");
283        break;
284
285        default: break;
286    }
287    *bufsiz /= ((unsigned int)libGlobals.deviceFormat.mSampleRate) / *speed;
288
289    alWriteSpeed = *speed;
290    ratio = ((unsigned int)libGlobals.deviceFormat.mSampleRate) / *speed;
291    nativePreferedBuffSize = *bufsiz;
292
293    /* start playing sound through the device */
294    error = AudioDeviceStart(libGlobals.deviceW, deviceFillingProc);
295    if (error != 0) return NULL;
296
297    return AL_TRUE;
298}
299
300
301static ALboolean set_read_native(UNUSED(void *handle), UNUSED(unsigned int *bufsiz), UNUSED(unsigned int *fmt), UNUSED(unsigned int *speed))
302{
303    implement_me("ALboolean set_read_native()");
304    return AL_FALSE;
305}
306
307ALboolean
308alcBackendSetAttributesNative_(ALC_OpenMode mode, void *handle, ALuint *bufsiz, ALenum *fmt, ALuint *speed)
309{
310        return mode == ALC_OPEN_INPUT_ ?
311                set_read_native(handle, bufsiz, fmt, speed) :
312                set_write_native(handle, bufsiz, fmt, speed);
313}
314
315void  native_blitbuffer(void *handle, void *data, int bytes)
316{
317    stillToPlay = bytes / nativePreferedBuffSize;
318
319    if (handle == NULL) return;
320
321    if (coreAudioDestination == 0)
322    {
323        fprintf(stderr,"Something wrong happened between CoreAudio and OpenAL.\n");
324        return;
325    }
326
327    // Gyom FIXME: Is this useful?
328    assert(nativePreferedBuffSize <= bytes);
329
330    playABuffer(data);
331}
332
333void playABuffer(void *realdata)
334{
335    register unsigned int       count;
336    register Float32    *outDataPtr = coreAudioDestination;
337    register SInt16     *inDataPtr16;
338    register SInt8      *inDataPtr8;
339    static void * data;
340
341    if (realdata!=NULL) data = realdata;
342
343    inDataPtr16 = (SInt16*)(data);
344    inDataPtr8 = (SInt8*)(data);
345
346    stillToPlay--;
347
348    switch(alWriteFormat)
349    {
350        int i;
351        case AL_FORMAT_STEREO16:
352            assert(nativePreferedBuffSize <= libGlobals.deviceWBufferSize/2);
353            for (count = nativePreferedBuffSize/2; count > 0; count--)
354            {
355                for (i = ratio; i>0; i--)
356                {
357                    *outDataPtr = ((Float32)(*inDataPtr16))/32767.0;
358                    outDataPtr++;
359                }
360                inDataPtr16++;
361            }
362                data = inDataPtr16;
363                break;
364
365        case AL_FORMAT_MONO16:
366            assert(nativePreferedBuffSize <= libGlobals.deviceWBufferSize/2);
367            for (count = nativePreferedBuffSize/2; count >0; count--)
368            {
369                for (i = ratio*2; i>0; i--)
370                {
371                    *outDataPtr = ((Float32)(*inDataPtr16))/32767.0;
372                    outDataPtr++;
373                }
374                inDataPtr16++;
375            }
376                data = inDataPtr16;
377                break;
378
379        case AL_FORMAT_STEREO8:
380            assert(nativePreferedBuffSize <= libGlobals.deviceWBufferSize);
381            for (count = nativePreferedBuffSize; count >0; count--)
382            {
383                for (i = ratio; i>0; i--)
384                {
385                    *outDataPtr = ((Float32)(*inDataPtr8))/32767.0;
386                    outDataPtr++;
387                }
388                inDataPtr8++;
389            }
390                data = inDataPtr8;
391                break;
392
393        case AL_FORMAT_MONO8:
394            assert(nativePreferedBuffSize <= libGlobals.deviceWBufferSize);
395            for (count = nativePreferedBuffSize; count >0; count--)
396            {
397                for (i = ratio*2; i>0; i--)
398                {
399                    *outDataPtr = ((Float32)(*inDataPtr8))/32767.0;
400                    outDataPtr++;
401                }
402                inDataPtr8++;
403            }
404                data = inDataPtr8;
405                break;
406
407        default:
408            DebugPrintf("Format not recognized... Try again ;-)");
409            break;
410    }
411}
412
413
414
415void  release_native(void *handle)
416{
417    if (libGlobals.deviceW == *(AudioDeviceID*)handle)
418    {
419        AudioDeviceStop(libGlobals.deviceW, deviceFillingProc);
420        AudioDeviceRemoveIOProc(libGlobals.deviceW, deviceFillingProc);
421    }
422}
423
424ALfloat get_nativechannel(UNUSED(void *handle), UNUSED(ALuint channel))
425{
426    implement_me("float get_nativechannel()");
427    return 0;
428}
429
430int set_nativechannel(UNUSED(void *handle),UNUSED(ALuint channel),UNUSED(ALfloat volume))
431{
432    implement_me("int set_nativechannel()");
433    return 0;
434}
435
436void pause_nativedevice(void *handle) /* Not tested :-( */
437{
438    if (libGlobals.deviceW == *(AudioDeviceID*)handle)
439        AudioDeviceStop(libGlobals.deviceW, deviceFillingProc);
440}
441
442void resume_nativedevice(void *handle) /* Not tested :-( */
443{
444    if (libGlobals.deviceW == *(AudioDeviceID*)handle)
445        AudioDeviceStart(libGlobals.deviceW, deviceFillingProc);
446}
447
448ALsizei capture_nativedevice(UNUSED(void *handle), UNUSED(void *capture_buffer), UNUSED(int bufsiz))
449{
450    implement_me("void capture_nativedevice()");
451    return NULL;
452}
Note: See TracBrowser for help on using the repository browser.