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