diff options
-rw-r--r-- | src/apple/AudioUnit.hxx | 55 | ||||
-rw-r--r-- | src/output/plugins/OSXOutputPlugin.cxx | 78 |
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); |