nkeynes@964: /** nkeynes@964: * $Id$ nkeynes@964: * nkeynes@964: * The darwin core-audio audio driver nkeynes@964: * nkeynes@964: * Copyright (c) 2008 Nathan Keynes. nkeynes@964: * nkeynes@964: * This program is free software; you can redistribute it and/or modify nkeynes@964: * it under the terms of the GNU General Public License as published by nkeynes@964: * the Free Software Foundation; either version 2 of the License, or nkeynes@964: * (at your option) any later version. nkeynes@964: * nkeynes@964: * This program is distributed in the hope that it will be useful, nkeynes@964: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@964: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@964: * GNU General Public License for more details. nkeynes@964: */ nkeynes@964: #include nkeynes@964: #include nkeynes@964: #include nkeynes@964: #include "aica/audio.h" nkeynes@964: #include "lxdream.h" nkeynes@964: nkeynes@964: #define BUFFER_SIZE (sizeof(float)*2*2205) nkeynes@964: nkeynes@964: static AudioDeviceID output_device; nkeynes@964: static volatile audio_buffer_t output_buffer = NULL; nkeynes@964: static uint32_t buffer_size; nkeynes@964: nkeynes@1024: static OSStatus audio_osx_callback( AudioDeviceID inDevice, nkeynes@964: const AudioTimeStamp *inNow, nkeynes@964: const AudioBufferList *inInputData, nkeynes@964: const AudioTimeStamp *inInputTime, nkeynes@964: AudioBufferList *outOutputData, nkeynes@964: const AudioTimeStamp *inOutputTime, nkeynes@964: void *inClientData) nkeynes@964: { nkeynes@964: char *output = outOutputData->mBuffers[0].mData; nkeynes@964: int data_requested = buffer_size; nkeynes@964: nkeynes@964: while( output_buffer != NULL && data_requested > 0 ) { nkeynes@964: int copysize = output_buffer->length - output_buffer->posn; nkeynes@964: if( copysize > data_requested ) { nkeynes@964: copysize = data_requested; nkeynes@964: } nkeynes@964: memcpy( output, &output_buffer->data[output_buffer->posn], copysize ); nkeynes@964: output += copysize; nkeynes@964: data_requested -= copysize; nkeynes@964: output_buffer->posn += copysize; nkeynes@964: if( output_buffer->posn >= output_buffer->length ) { nkeynes@964: output_buffer = audio_next_read_buffer(); nkeynes@964: } nkeynes@964: } nkeynes@964: if( data_requested > 0 ) { nkeynes@964: memset( output, 0, data_requested ); nkeynes@964: } nkeynes@964: return noErr; nkeynes@964: } nkeynes@964: nkeynes@964: static gboolean audio_osx_shutdown() nkeynes@964: { nkeynes@964: AudioDeviceStop( output_device, audio_osx_callback ); nkeynes@964: AudioDeviceRemoveIOProc( output_device, audio_osx_callback ); nkeynes@964: return TRUE; nkeynes@964: } nkeynes@964: nkeynes@964: static gboolean audio_osx_init() nkeynes@964: { nkeynes@964: UInt32 size = sizeof(output_device); nkeynes@964: AudioStreamBasicDescription outputDesc; nkeynes@964: UInt32 outputDescSize = sizeof(outputDesc); nkeynes@964: nkeynes@964: if( AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, nkeynes@964: &size, &output_device) != noErr || nkeynes@964: output_device == kAudioDeviceUnknown ) { nkeynes@964: return FALSE; nkeynes@964: } nkeynes@964: nkeynes@964: if( AudioDeviceGetProperty( output_device, 1, 0, kAudioDevicePropertyStreamFormat, nkeynes@964: &outputDescSize, &outputDesc ) != noErr ) { nkeynes@964: return FALSE; nkeynes@964: } nkeynes@964: nkeynes@964: buffer_size = BUFFER_SIZE; nkeynes@964: nkeynes@964: if( AudioDeviceSetProperty( output_device, 0, 0, 0, kAudioDevicePropertyBufferSize, nkeynes@964: sizeof(buffer_size), &buffer_size ) != noErr ) { nkeynes@964: return FALSE; nkeynes@964: } nkeynes@964: nkeynes@964: AudioDeviceAddIOProc( output_device, audio_osx_callback, NULL ); nkeynes@964: return TRUE; nkeynes@964: } nkeynes@964: static gboolean audio_osx_process_buffer( audio_buffer_t buffer ) nkeynes@964: { nkeynes@964: if( output_buffer == NULL ) { nkeynes@964: output_buffer = buffer; nkeynes@964: output_buffer->posn = 0; nkeynes@964: AudioDeviceStart(output_device, audio_osx_callback); nkeynes@964: } nkeynes@964: return FALSE; nkeynes@964: } nkeynes@964: nkeynes@1024: static void audio_osx_start() nkeynes@964: { nkeynes@964: if( output_buffer != NULL ) { nkeynes@964: AudioDeviceStart(output_device, audio_osx_callback); nkeynes@964: } nkeynes@964: } nkeynes@964: nkeynes@1024: static void audio_osx_stop() nkeynes@964: { nkeynes@964: AudioDeviceStop( output_device, audio_osx_callback ); nkeynes@964: } nkeynes@964: nkeynes@964: nkeynes@1024: static struct audio_driver audio_osx_driver = { nkeynes@964: "osx", nkeynes@964: N_("OS X CoreAudio system driver"), nkeynes@1024: 1, // Preferred on OS X nkeynes@964: DEFAULT_SAMPLE_RATE, nkeynes@964: AUDIO_FMT_FLOATST, nkeynes@964: audio_osx_init, nkeynes@964: audio_osx_start, nkeynes@964: audio_osx_process_buffer, nkeynes@964: audio_osx_stop, nkeynes@964: audio_osx_shutdown}; nkeynes@964: nkeynes@1024: AUDIO_DRIVER( "osx", audio_osx_driver );