aboutsummaryrefslogtreecommitdiffstats
path: root/src/output
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2011-12-24 15:55:35 +0100
committerMax Kellermann <max@duempel.org>2011-12-24 18:15:24 +0100
commit9179d9592d7431c9b03a8d63b4edc006dc0faa26 (patch)
tree9334b3318c19c9def15039d32606af54c7f0f2a2 /src/output
parentf2082174127ff1de3f1dbc24b98f907f8c98a57c (diff)
downloadmpd-9179d9592d7431c9b03a8d63b4edc006dc0faa26.tar.gz
mpd-9179d9592d7431c9b03a8d63b4edc006dc0faa26.tar.xz
mpd-9179d9592d7431c9b03a8d63b4edc006dc0faa26.zip
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.
Diffstat (limited to 'src/output')
-rw-r--r--src/output/osx_output_plugin.c218
1 files changed, 116 insertions, 102 deletions
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,