From 9179d9592d7431c9b03a8d63b4edc006dc0faa26 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 24 Dec 2011 15:55:35 +0100 Subject: output/osx: allocate the device in enable() Keep the device open as long as the output is enabled, but initialize it only when playback starts. --- src/output/osx_output_plugin.c | 218 ++++++++++++++++++++++------------------- 1 file changed, 116 insertions(+), 102 deletions(-) (limited to 'src/output/osx_output_plugin.c') diff --git a/src/output/osx_output_plugin.c b/src/output/osx_output_plugin.c index 93f784a48..550729406 100644 --- a/src/output/osx_output_plugin.c +++ b/src/output/osx_output_plugin.c @@ -114,72 +114,6 @@ osx_output_finish(struct audio_output *ao) g_free(od); } -static void -osx_output_cancel(struct audio_output *ao) -{ - struct osx_output *od = (struct osx_output *)ao; - - g_mutex_lock(od->mutex); - od->len = 0; - g_mutex_unlock(od->mutex); -} - -static void -osx_output_close(struct audio_output *ao) -{ - struct osx_output *od = (struct osx_output *)ao; - - AudioOutputUnitStop(od->au); - AudioUnitUninitialize(od->au); - CloseComponent(od->au); -} - -static OSStatus -osx_render(void *vdata, - G_GNUC_UNUSED AudioUnitRenderActionFlags *io_action_flags, - G_GNUC_UNUSED const AudioTimeStamp *in_timestamp, - G_GNUC_UNUSED UInt32 in_bus_number, - G_GNUC_UNUSED UInt32 in_number_frames, - AudioBufferList *buffer_list) -{ - struct osx_output *od = (struct osx_output *) vdata; - AudioBuffer *buffer = &buffer_list->mBuffers[0]; - size_t buffer_size = buffer->mDataByteSize; - size_t bytes_to_copy; - size_t trailer_length; - size_t dest_pos = 0; - - g_mutex_lock(od->mutex); - - bytes_to_copy = MIN(od->len, buffer_size); - od->len -= bytes_to_copy; - - trailer_length = od->buffer_size - od->pos; - if (bytes_to_copy > trailer_length) { - memcpy((unsigned char*)buffer->mData + dest_pos, - od->buffer + od->pos, trailer_length); - od->pos = 0; - dest_pos += trailer_length; - bytes_to_copy -= trailer_length; - } - - memcpy((unsigned char*)buffer->mData + dest_pos, - od->buffer + od->pos, bytes_to_copy); - od->pos += bytes_to_copy; - - if (od->pos >= od->buffer_size) - od->pos = 0; - - g_cond_signal(od->condition); - g_mutex_unlock(od->mutex); - - if (bytes_to_copy < buffer_size) - memset((unsigned char*)buffer->mData + bytes_to_copy, 0, - buffer_size - bytes_to_copy); - - return 0; -} - static bool osx_output_set_device(struct osx_output *oo, GError **error) { @@ -269,65 +203,135 @@ done: return ret; } +static OSStatus +osx_render(void *vdata, + G_GNUC_UNUSED AudioUnitRenderActionFlags *io_action_flags, + G_GNUC_UNUSED const AudioTimeStamp *in_timestamp, + G_GNUC_UNUSED UInt32 in_bus_number, + G_GNUC_UNUSED UInt32 in_number_frames, + AudioBufferList *buffer_list) +{ + struct osx_output *od = (struct osx_output *) vdata; + AudioBuffer *buffer = &buffer_list->mBuffers[0]; + size_t buffer_size = buffer->mDataByteSize; + size_t bytes_to_copy; + size_t trailer_length; + size_t dest_pos = 0; + + g_mutex_lock(od->mutex); + + bytes_to_copy = MIN(od->len, buffer_size); + od->len -= bytes_to_copy; + + trailer_length = od->buffer_size - od->pos; + if (bytes_to_copy > trailer_length) { + memcpy((unsigned char*)buffer->mData + dest_pos, + od->buffer + od->pos, trailer_length); + od->pos = 0; + dest_pos += trailer_length; + bytes_to_copy -= trailer_length; + } + + memcpy((unsigned char*)buffer->mData + dest_pos, + od->buffer + od->pos, bytes_to_copy); + od->pos += bytes_to_copy; + + if (od->pos >= od->buffer_size) + od->pos = 0; + + g_cond_signal(od->condition); + g_mutex_unlock(od->mutex); + + if (bytes_to_copy < buffer_size) + memset((unsigned char*)buffer->mData + bytes_to_copy, 0, + buffer_size - bytes_to_copy); + + return 0; +} + static bool -osx_output_open(struct audio_output *ao, struct audio_format *audio_format, GError **error) +osx_output_enable(struct audio_output *ao, GError **error_r) { - struct osx_output *od = (struct osx_output *)ao; - ComponentDescription desc; - Component comp; - AURenderCallbackStruct callback; - AudioStreamBasicDescription stream_description; - OSStatus status; - ComponentResult result; + struct osx_output *oo = (struct osx_output *)ao; + ComponentDescription desc; desc.componentType = kAudioUnitType_Output; - desc.componentSubType = od->component_subtype; + desc.componentSubType = oo->component_subtype; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; - comp = FindNextComponent(NULL, &desc); + Component comp = FindNextComponent(NULL, &desc); if (comp == 0) { - g_set_error(error, osx_output_quark(), 0, + g_set_error(error_r, osx_output_quark(), 0, "Error finding OS X component"); return false; } - status = OpenAComponent(comp, &od->au); + OSStatus status = OpenAComponent(comp, &oo->au); if (status != noErr) { - g_set_error(error, osx_output_quark(), status, + g_set_error(error_r, osx_output_quark(), status, "Unable to open OS X component: %s", GetMacOSStatusCommentString(status)); return false; } - status = AudioUnitInitialize(od->au); - if (status != noErr) { - CloseComponent(od->au); - g_set_error(error, osx_output_quark(), status, - "Unable to initialize OS X audio unit: %s", - GetMacOSStatusCommentString(status)); + if (!osx_output_set_device(oo, error_r)) { + CloseComponent(oo->au); return false; } - if (!osx_output_set_device(od, error)) - return false; - + AURenderCallbackStruct callback; callback.inputProc = osx_render; - callback.inputProcRefCon = od; + callback.inputProcRefCon = oo; - result = AudioUnitSetProperty(od->au, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, 0, - &callback, sizeof(callback)); + ComponentResult result = + AudioUnitSetProperty(oo->au, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, 0, + &callback, sizeof(callback)); if (result != noErr) { - AudioUnitUninitialize(od->au); - CloseComponent(od->au); - g_set_error(error, osx_output_quark(), result, + g_set_error(error_r, osx_output_quark(), result, "unable to set callback for OS X audio unit"); return false; } + return true; +} + +static void +osx_output_disable(struct audio_output *ao) +{ + struct osx_output *oo = (struct osx_output *)ao; + + CloseComponent(oo->au); +} + +static void +osx_output_cancel(struct audio_output *ao) +{ + struct osx_output *od = (struct osx_output *)ao; + + g_mutex_lock(od->mutex); + od->len = 0; + g_mutex_unlock(od->mutex); +} + +static void +osx_output_close(struct audio_output *ao) +{ + struct osx_output *od = (struct osx_output *)ao; + + AudioOutputUnitStop(od->au); + AudioUnitUninitialize(od->au); +} + +static bool +osx_output_open(struct audio_output *ao, struct audio_format *audio_format, GError **error) +{ + struct osx_output *od = (struct osx_output *)ao; + + AudioStreamBasicDescription stream_description; stream_description.mSampleRate = audio_format->sample_rate; stream_description.mFormatID = kAudioFormatLinearPCM; stream_description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; @@ -357,18 +361,25 @@ osx_output_open(struct audio_output *ao, struct audio_format *audio_format, GErr stream_description.mBytesPerFrame = stream_description.mBytesPerPacket; stream_description.mChannelsPerFrame = audio_format->channels; - result = AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, 0, - &stream_description, - sizeof(stream_description)); + ComponentResult result = + AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, 0, + &stream_description, + sizeof(stream_description)); if (result != noErr) { - AudioUnitUninitialize(od->au); - CloseComponent(od->au); g_set_error(error, osx_output_quark(), result, "Unable to set format on OS X device"); return false; } + OSStatus status = AudioUnitInitialize(od->au); + if (status != noErr) { + g_set_error(error, osx_output_quark(), status, + "Unable to initialize OS X audio unit: %s", + GetMacOSStatusCommentString(status)); + return false; + } + /* create a buffer of 1s */ od->buffer_size = (audio_format->sample_rate) * audio_format_frame_size(audio_format); @@ -379,6 +390,7 @@ osx_output_open(struct audio_output *ao, struct audio_format *audio_format, GErr status = AudioOutputUnitStart(od->au); if (status != 0) { + AudioUnitUninitialize(od->au); g_set_error(error, osx_output_quark(), status, "unable to start audio output: %s", GetMacOSStatusCommentString(status)); @@ -427,6 +439,8 @@ const struct audio_output_plugin osx_output_plugin = { .test_default_device = osx_output_test_default_device, .init = osx_output_init, .finish = osx_output_finish, + .enable = osx_output_enable, + .disable = osx_output_disable, .open = osx_output_open, .close = osx_output_close, .play = osx_output_play, -- cgit v1.2.3