summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-05-28 14:54:30 +0200
committerMax Kellermann <max@musicpd.org>2020-05-28 15:06:53 +0200
commit28a00472ff4812511dc161d5aae00122bdd72481 (patch)
tree28588f08527d864274b47c8057c165d5ac05d04e
parent8d540737b9aa34ef03a8000cfe88473ec8a32563 (diff)
apple/Throw: new helper library replacing osx_os_status_to_cstring()
-rw-r--r--src/apple/Throw.cxx67
-rw-r--r--src/apple/Throw.hxx45
-rw-r--r--src/output/plugins/OSXOutputPlugin.cxx104
-rw-r--r--src/output/plugins/meson.build5
4 files changed, 143 insertions, 78 deletions
diff --git a/src/apple/Throw.cxx b/src/apple/Throw.cxx
new file mode 100644
index 000000000..9f6fd7a58
--- /dev/null
+++ b/src/apple/Throw.cxx
@@ -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
diff --git a/src/apple/Throw.hxx b/src/apple/Throw.hxx
new file mode 100644
index 000000000..af4bb6932
--- /dev/null
+++ b/src/apple/Throw.hxx
@@ -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
diff --git a/src/output/plugins/OSXOutputPlugin.cxx b/src/output/plugins/OSXOutputPlugin.cxx
index 7dec3b2d3..fddf6f398 100644
--- a/src/output/plugins/OSXOutputPlugin.cxx
+++ b/src/output/plugins/OSXOutputPlugin.cxx
@@ -19,8 +19,8 @@
#include "config.h"
#include "OSXOutputPlugin.hxx"
-#include "apple/ErrorRef.hxx"
#include "apple/StringRef.hxx"
+#include "apple/Throw.hxx"
#include "../OutputAPI.hxx"
#include "mixer/MixerList.hxx"
#include "util/RuntimeError.hxx"
@@ -109,17 +109,6 @@ private:
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
osx_output_test_default_device()
{
@@ -209,11 +198,8 @@ OSXOutput::GetVolume()
&size,
&vol);
- if (status != noErr) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("unable to get volume: %s", errormsg);
- }
+ if (status != noErr)
+ Apple::ThrowOSStatus(status);
return static_cast<int>(vol * 100.0);
}
@@ -235,12 +221,8 @@ OSXOutput::SetVolume(unsigned new_volume)
size,
&vol);
- if (status != noErr) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError( "unable to set new volume %u: %s",
- new_volume, errormsg);
- }
+ if (status != noErr)
+ Apple::ThrowOSStatus(status);
}
static void
@@ -304,12 +286,9 @@ osx_output_set_channel_map(OSXOutput *oo)
0,
&desc,
&size);
- if (status != noErr) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("%s: unable to get number of output device channels: %s",
- oo->device_name, errormsg);
- }
+ if (status != noErr)
+ Apple::ThrowOSStatus(status,
+ "unable to get number of output device channels");
UInt32 num_channels = desc.mChannelsPerFrame;
std::unique_ptr<SInt32[]> channel_map(new SInt32[num_channels]);
@@ -325,11 +304,8 @@ osx_output_set_channel_map(OSXOutput *oo)
0,
channel_map.get(),
size);
- if (status != noErr) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("%s: unable to set channel map: %s", oo->device_name, errormsg);
- }
+ if (status != noErr)
+ Apple::ThrowOSStatus(status, "unable to set channel map");
}
@@ -639,12 +615,8 @@ osx_output_set_device(OSXOutput *oo)
status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
&aopa_hw_devices, 0, nullptr, &size);
- if (status != noErr) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("Unable to determine number of OS X audio devices: %s",
- errormsg);
- }
+ if (status != noErr)
+ Apple::ThrowOSStatus(status);
/* what are the available audio device IDs? */
numdevices = size / sizeof(AudioDeviceID);
@@ -652,12 +624,8 @@ osx_output_set_device(OSXOutput *oo)
status = AudioObjectGetPropertyData(kAudioObjectSystemObject,
&aopa_hw_devices, 0, nullptr,
&size, deviceids.get());
- if (status != noErr) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("Unable to determine OS X audio device IDs: %s",
- errormsg);
- }
+ if (status != noErr)
+ Apple::ThrowOSStatus(status);
/* which audio device matches oo->device_name? */
static constexpr AudioObjectPropertyAddress aopa_name{
@@ -700,12 +668,9 @@ osx_output_set_device(OSXOutput *oo)
0,
&(deviceids[i]),
sizeof(AudioDeviceID));
- if (status != noErr) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("Unable to set OS X audio output device: %s",
- errormsg);
- }
+ if (status != noErr)
+ Apple::ThrowOSStatus(status,
+ "Unable to set OS X audio output device");
oo->dev_id = deviceids[i];
FormatDebug(osx_output_domain,
@@ -756,12 +721,9 @@ OSXOutput::Enable()
throw std::runtime_error("Error finding OS X component");
OSStatus status = AudioComponentInstanceNew(comp, &au);
- if (status != noErr) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("Unable to open OS X component: %s",
- errormsg);
- }
+ if (status != noErr)
+ Apple::ThrowOSStatus(status, "Unable to open OS X component");
+
#ifdef ENABLE_DSD
pcm_export.Construct();
#endif
@@ -881,21 +843,13 @@ OSXOutput::Open(AudioFormat &audio_format)
}
status = AudioUnitInitialize(au);
- if (status != noErr) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("Unable to initialize OS X audio unit: %s",
- errormsg);
- }
+ 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) {
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("Unable to set frame size: %s",
- errormsg);
- }
+ if (status != noErr)
+ Apple::ThrowOSStatus(status, "Unable to set 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);
@@ -910,13 +864,9 @@ OSXOutput::Open(AudioFormat &audio_format)
ring_buffer = new boost::lockfree::spsc_queue<uint8_t>(ring_buffer_size);
status = AudioOutputUnitStart(au);
- if (status != 0) {
- AudioUnitUninitialize(au);
- char errormsg[1024];
- osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
- throw FormatRuntimeError("Unable to start audio output: %s",
- errormsg);
- }
+ if (status != 0)
+ Apple::ThrowOSStatus(status, "Unable to start audio output");
+
pause = false;
}
diff --git a/src/output/plugins/meson.build b/src/output/plugins/meson.build
index 4745a0ed3..b6bb13ca6 100644
--- a/src/output/plugins/meson.build
+++ b/src/output/plugins/meson.build
@@ -73,7 +73,10 @@ if enable_oss
endif
if is_darwin
- output_plugins_sources += 'OSXOutputPlugin.cxx'
+ output_plugins_sources += [
+ 'OSXOutputPlugin.cxx',
+ '../../apple/Throw.cxx',
+ ]
audiounit_dep = declare_dependency(
link_args: [
'-framework', 'AudioUnit', '-framework', 'CoreAudio', '-framework', 'CoreServices',