apple/Throw: new helper library replacing osx_os_status_to_cstring()
This commit is contained in:
parent
8d540737b9
commit
28a00472ff
67
src/apple/Throw.cxx
Normal file
67
src/apple/Throw.cxx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Throw.hxx"
|
||||||
|
#include "ErrorRef.hxx"
|
||||||
|
#include "StringRef.hxx"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Apple {
|
||||||
|
|
||||||
|
void
|
||||||
|
ThrowOSStatus(OSStatus status)
|
||||||
|
{
|
||||||
|
const Apple::ErrorRef cferr(nullptr, kCFErrorDomainOSStatus,
|
||||||
|
status, nullptr);
|
||||||
|
const Apple::StringRef cfstr(cferr.CopyDescription());
|
||||||
|
|
||||||
|
char msg[1024];
|
||||||
|
if (!cfstr.GetCString(msg, sizeof(msg)))
|
||||||
|
throw std::runtime_error("Unknown OSStatus");
|
||||||
|
|
||||||
|
throw std::runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ThrowOSStatus(OSStatus status, const char *_msg)
|
||||||
|
{
|
||||||
|
const Apple::ErrorRef cferr(nullptr, kCFErrorDomainOSStatus,
|
||||||
|
status, nullptr);
|
||||||
|
const Apple::StringRef cfstr(cferr.CopyDescription());
|
||||||
|
|
||||||
|
char msg[1024];
|
||||||
|
strcpy(msg, _msg);
|
||||||
|
size_t length = strlen(msg);
|
||||||
|
|
||||||
|
cfstr.GetCString(msg + length, sizeof(msg) - length);
|
||||||
|
throw std::runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Apple
|
45
src/apple/Throw.hxx
Normal file
45
src/apple/Throw.hxx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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_THROW_HXX
|
||||||
|
#define APPLE_THROW_HXX
|
||||||
|
|
||||||
|
#include <CoreFoundation/CFBase.h>
|
||||||
|
|
||||||
|
namespace Apple {
|
||||||
|
|
||||||
|
void
|
||||||
|
ThrowOSStatus(OSStatus status);
|
||||||
|
|
||||||
|
void
|
||||||
|
ThrowOSStatus(OSStatus status, const char *msg);
|
||||||
|
|
||||||
|
} // namespace Apple
|
||||||
|
|
||||||
|
#endif
|
@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "OSXOutputPlugin.hxx"
|
#include "OSXOutputPlugin.hxx"
|
||||||
#include "apple/ErrorRef.hxx"
|
|
||||||
#include "apple/StringRef.hxx"
|
#include "apple/StringRef.hxx"
|
||||||
|
#include "apple/Throw.hxx"
|
||||||
#include "../OutputAPI.hxx"
|
#include "../OutputAPI.hxx"
|
||||||
#include "mixer/MixerList.hxx"
|
#include "mixer/MixerList.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
@ -109,17 +109,6 @@ private:
|
|||||||
|
|
||||||
static constexpr Domain osx_output_domain("osx_output");
|
static constexpr Domain osx_output_domain("osx_output");
|
||||||
|
|
||||||
static void
|
|
||||||
osx_os_status_to_cstring(OSStatus status, char *str, size_t size)
|
|
||||||
{
|
|
||||||
Apple::ErrorRef cferr(nullptr, kCFErrorDomainOSStatus, status, nullptr);
|
|
||||||
const Apple::StringRef cfstr(cferr.CopyDescription());
|
|
||||||
if (!cfstr.GetCString(str, size)) {
|
|
||||||
/* conversion failed, return empty string */
|
|
||||||
*str = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
osx_output_test_default_device()
|
osx_output_test_default_device()
|
||||||
{
|
{
|
||||||
@ -209,11 +198,8 @@ OSXOutput::GetVolume()
|
|||||||
&size,
|
&size,
|
||||||
&vol);
|
&vol);
|
||||||
|
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status);
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
|
||||||
throw FormatRuntimeError("unable to get volume: %s", errormsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<int>(vol * 100.0);
|
return static_cast<int>(vol * 100.0);
|
||||||
}
|
}
|
||||||
@ -235,12 +221,8 @@ OSXOutput::SetVolume(unsigned new_volume)
|
|||||||
size,
|
size,
|
||||||
&vol);
|
&vol);
|
||||||
|
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status);
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
|
||||||
throw FormatRuntimeError( "unable to set new volume %u: %s",
|
|
||||||
new_volume, errormsg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -304,12 +286,9 @@ osx_output_set_channel_map(OSXOutput *oo)
|
|||||||
0,
|
0,
|
||||||
&desc,
|
&desc,
|
||||||
&size);
|
&size);
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status,
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
"unable to get number of output device channels");
|
||||||
throw FormatRuntimeError("%s: unable to get number of output device channels: %s",
|
|
||||||
oo->device_name, errormsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 num_channels = desc.mChannelsPerFrame;
|
UInt32 num_channels = desc.mChannelsPerFrame;
|
||||||
std::unique_ptr<SInt32[]> channel_map(new SInt32[num_channels]);
|
std::unique_ptr<SInt32[]> channel_map(new SInt32[num_channels]);
|
||||||
@ -325,11 +304,8 @@ osx_output_set_channel_map(OSXOutput *oo)
|
|||||||
0,
|
0,
|
||||||
channel_map.get(),
|
channel_map.get(),
|
||||||
size);
|
size);
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status, "unable to set channel map");
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
|
||||||
throw FormatRuntimeError("%s: unable to set channel map: %s", oo->device_name, errormsg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -639,12 +615,8 @@ osx_output_set_device(OSXOutput *oo)
|
|||||||
|
|
||||||
status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
|
status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
|
||||||
&aopa_hw_devices, 0, nullptr, &size);
|
&aopa_hw_devices, 0, nullptr, &size);
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status);
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
|
||||||
throw FormatRuntimeError("Unable to determine number of OS X audio devices: %s",
|
|
||||||
errormsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* what are the available audio device IDs? */
|
/* what are the available audio device IDs? */
|
||||||
numdevices = size / sizeof(AudioDeviceID);
|
numdevices = size / sizeof(AudioDeviceID);
|
||||||
@ -652,12 +624,8 @@ osx_output_set_device(OSXOutput *oo)
|
|||||||
status = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
status = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||||
&aopa_hw_devices, 0, nullptr,
|
&aopa_hw_devices, 0, nullptr,
|
||||||
&size, deviceids.get());
|
&size, deviceids.get());
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status);
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
|
||||||
throw FormatRuntimeError("Unable to determine OS X audio device IDs: %s",
|
|
||||||
errormsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* which audio device matches oo->device_name? */
|
/* which audio device matches oo->device_name? */
|
||||||
static constexpr AudioObjectPropertyAddress aopa_name{
|
static constexpr AudioObjectPropertyAddress aopa_name{
|
||||||
@ -700,12 +668,9 @@ osx_output_set_device(OSXOutput *oo)
|
|||||||
0,
|
0,
|
||||||
&(deviceids[i]),
|
&(deviceids[i]),
|
||||||
sizeof(AudioDeviceID));
|
sizeof(AudioDeviceID));
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status,
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
"Unable to set OS X audio output device");
|
||||||
throw FormatRuntimeError("Unable to set OS X audio output device: %s",
|
|
||||||
errormsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
oo->dev_id = deviceids[i];
|
oo->dev_id = deviceids[i];
|
||||||
FormatDebug(osx_output_domain,
|
FormatDebug(osx_output_domain,
|
||||||
@ -756,12 +721,9 @@ OSXOutput::Enable()
|
|||||||
throw std::runtime_error("Error finding OS X component");
|
throw std::runtime_error("Error finding OS X component");
|
||||||
|
|
||||||
OSStatus status = AudioComponentInstanceNew(comp, &au);
|
OSStatus status = AudioComponentInstanceNew(comp, &au);
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status, "Unable to open OS X component");
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
|
||||||
throw FormatRuntimeError("Unable to open OS X component: %s",
|
|
||||||
errormsg);
|
|
||||||
}
|
|
||||||
#ifdef ENABLE_DSD
|
#ifdef ENABLE_DSD
|
||||||
pcm_export.Construct();
|
pcm_export.Construct();
|
||||||
#endif
|
#endif
|
||||||
@ -881,21 +843,13 @@ OSXOutput::Open(AudioFormat &audio_format)
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = AudioUnitInitialize(au);
|
status = AudioUnitInitialize(au);
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status, "Unable to initialize OS X audio unit");
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
|
||||||
throw FormatRuntimeError("Unable to initialize OS X audio unit: %s",
|
|
||||||
errormsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 buffer_frame_size = 1;
|
UInt32 buffer_frame_size = 1;
|
||||||
status = osx_output_set_buffer_size(au, asbd, &buffer_frame_size);
|
status = osx_output_set_buffer_size(au, asbd, &buffer_frame_size);
|
||||||
if (status != noErr) {
|
if (status != noErr)
|
||||||
char errormsg[1024];
|
Apple::ThrowOSStatus(status, "Unable to set frame size");
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
|
||||||
throw FormatRuntimeError("Unable to set frame size: %s",
|
|
||||||
errormsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ring_buffer_size = std::max<size_t>(buffer_frame_size,
|
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);
|
MPD_OSX_BUFFER_TIME_MS * audio_format.GetFrameSize() * audio_format.sample_rate / 1000);
|
||||||
@ -910,13 +864,9 @@ OSXOutput::Open(AudioFormat &audio_format)
|
|||||||
ring_buffer = new boost::lockfree::spsc_queue<uint8_t>(ring_buffer_size);
|
ring_buffer = new boost::lockfree::spsc_queue<uint8_t>(ring_buffer_size);
|
||||||
|
|
||||||
status = AudioOutputUnitStart(au);
|
status = AudioOutputUnitStart(au);
|
||||||
if (status != 0) {
|
if (status != 0)
|
||||||
AudioUnitUninitialize(au);
|
Apple::ThrowOSStatus(status, "Unable to start audio output");
|
||||||
char errormsg[1024];
|
|
||||||
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
|
|
||||||
throw FormatRuntimeError("Unable to start audio output: %s",
|
|
||||||
errormsg);
|
|
||||||
}
|
|
||||||
pause = false;
|
pause = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,10 @@ if enable_oss
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if is_darwin
|
if is_darwin
|
||||||
output_plugins_sources += 'OSXOutputPlugin.cxx'
|
output_plugins_sources += [
|
||||||
|
'OSXOutputPlugin.cxx',
|
||||||
|
'../../apple/Throw.cxx',
|
||||||
|
]
|
||||||
audiounit_dep = declare_dependency(
|
audiounit_dep = declare_dependency(
|
||||||
link_args: [
|
link_args: [
|
||||||
'-framework', 'AudioUnit', '-framework', 'CoreAudio', '-framework', 'CoreServices',
|
'-framework', 'AudioUnit', '-framework', 'CoreAudio', '-framework', 'CoreServices',
|
||||||
|
Loading…
Reference in New Issue
Block a user