summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/apple/AudioUnit.hxx55
-rw-r--r--src/output/plugins/OSXOutputPlugin.cxx78
2 files changed, 84 insertions, 49 deletions
diff --git a/src/apple/AudioUnit.hxx b/src/apple/AudioUnit.hxx
new file mode 100644
index 000000000..bc6f72b53
--- /dev/null
+++ b/src/apple/AudioUnit.hxx
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020 Max Kellermann <max.kellermann@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef APPLE_AUDIO_UNIT_HXX
+#define APPLE_AUDIO_UNIT_HXX
+
+#include "Throw.hxx"
+
+#include <AudioUnit/AudioUnit.h>
+
+template<typename T>
+T
+AudioUnitGetPropertyT(AudioUnit inUnit, AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement)
+{
+ UInt32 size = sizeof(T);
+ T value;
+
+ OSStatus status = AudioUnitGetProperty(inUnit, inID, inScope,
+ inElement,
+ &value, &size);
+ if (status != noErr)
+ Apple::ThrowOSStatus(status);
+
+ return value;
+}
+
+#endif
diff --git a/src/output/plugins/OSXOutputPlugin.cxx b/src/output/plugins/OSXOutputPlugin.cxx
index c3c25a965..696f5acea 100644
--- a/src/output/plugins/OSXOutputPlugin.cxx
+++ b/src/output/plugins/OSXOutputPlugin.cxx
@@ -20,6 +20,7 @@
#include "config.h"
#include "OSXOutputPlugin.hxx"
#include "apple/AudioObject.hxx"
+#include "apple/AudioUnit.hxx"
#include "apple/StringRef.hxx"
#include "apple/Throw.hxx"
#include "../OutputAPI.hxx"
@@ -266,32 +267,29 @@ osx_output_parse_channel_map(const char *device_name,
device_name, num_channels);
}
+static UInt32
+AudioUnitGetChannelsPerFrame(AudioUnit inUnit)
+{
+ const auto desc = AudioUnitGetPropertyT<AudioStreamBasicDescription>(inUnit,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output,
+ 0);
+ return desc.mChannelsPerFrame;
+}
+
static void
osx_output_set_channel_map(OSXOutput *oo)
{
OSStatus status;
- AudioStreamBasicDescription desc;
- UInt32 size = sizeof(desc);
- memset(&desc, 0, size);
- status = AudioUnitGetProperty(oo->au,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output,
- 0,
- &desc,
- &size);
- if (status != noErr)
- Apple::ThrowOSStatus(status,
- "unable to get number of output device channels");
-
- UInt32 num_channels = desc.mChannelsPerFrame;
+ const UInt32 num_channels = AudioUnitGetChannelsPerFrame(oo->au);
std::unique_ptr<SInt32[]> channel_map(new SInt32[num_channels]);
osx_output_parse_channel_map(oo->device_name,
oo->channel_map,
channel_map.get(),
num_channels);
- size = num_channels * sizeof(SInt32);
+ UInt32 size = num_channels * sizeof(SInt32);
status = AudioUnitSetProperty(oo->au,
kAudioOutputUnitProperty_ChannelMap,
kAudioUnitScope_Input,
@@ -444,22 +442,16 @@ osx_output_set_device_format(AudioDeviceID dev_id,
return output_format.mSampleRate;
}
-static OSStatus
-osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc,
- UInt32 *frame_size)
+static UInt32
+osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc)
{
- AudioValueRange value_range = {0, 0};
- UInt32 property_size = sizeof(AudioValueRange);
- OSStatus err = AudioUnitGetProperty(au,
- kAudioDevicePropertyBufferFrameSizeRange,
- kAudioUnitScope_Global,
- 0,
- &value_range,
- &property_size);
- if (err != noErr)
- return err;
+ const auto value_range = AudioUnitGetPropertyT<AudioValueRange>(au,
+ kAudioDevicePropertyBufferFrameSizeRange,
+ kAudioUnitScope_Global,
+ 0);
UInt32 buffer_frame_size = value_range.mMaximum;
+ OSStatus err;
err = AudioUnitSetProperty(au,
kAudioDevicePropertyBufferFrameSize,
kAudioUnitScope_Global,
@@ -471,29 +463,20 @@ osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc,
"Failed to set maximum buffer size: %d",
err);
- property_size = sizeof(buffer_frame_size);
- err = AudioUnitGetProperty(au,
- kAudioDevicePropertyBufferFrameSize,
- kAudioUnitScope_Global,
- 0,
- &buffer_frame_size,
- &property_size);
- if (err != noErr) {
- FormatWarning(osx_output_domain,
- "Cannot get the buffer frame size: %d",
- err);
- return err;
- }
+ buffer_frame_size = AudioUnitGetPropertyT<UInt32>(au,
+ kAudioDevicePropertyBufferFrameSize,
+ kAudioUnitScope_Global,
+ 0);
buffer_frame_size *= desc.mBytesPerFrame;
// We set the frame size to a power of two integer that
// is larger than buffer_frame_size.
- while (*frame_size < buffer_frame_size + 1) {
- *frame_size <<= 1;
- }
+ UInt32 frame_size = 1;
+ while (frame_size < buffer_frame_size + 1)
+ frame_size <<= 1;
- return noErr;
+ return frame_size;
}
static void
@@ -789,10 +772,7 @@ OSXOutput::Open(AudioFormat &audio_format)
if (status != noErr)
Apple::ThrowOSStatus(status, "Unable to initialize OS X audio unit");
- UInt32 buffer_frame_size = 1;
- status = osx_output_set_buffer_size(au, asbd, &buffer_frame_size);
- if (status != noErr)
- Apple::ThrowOSStatus(status, "Unable to set frame size");
+ UInt32 buffer_frame_size = osx_output_set_buffer_size(au, asbd);
size_t ring_buffer_size = std::max<size_t>(buffer_frame_size,
MPD_OSX_BUFFER_TIME_MS * audio_format.GetFrameSize() * audio_format.sample_rate / 1000);