Commit f6823cc6 authored by Max Kellermann's avatar Max Kellermann

output/osx: move code to FindAudioDeviceByName()

parent 69c0f0fe
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <boost/lockfree/spsc_queue.hpp> #include <boost/lockfree/spsc_queue.hpp>
#include <memory> #include <memory>
#include <optional>
static constexpr unsigned MPD_OSX_BUFFER_TIME_MS = 100; static constexpr unsigned MPD_OSX_BUFFER_TIME_MS = 100;
...@@ -540,16 +541,36 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog) ...@@ -540,16 +541,36 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog)
} }
} }
gcc_pure
static void static bool
osx_output_set_device(OSXOutput *oo) IsAudioDeviceName(AudioDeviceID id, const char *expected_name) noexcept
{ {
OSStatus status; static constexpr AudioObjectPropertyAddress aopa_name{
UInt32 size; kAudioObjectPropertyName,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster,
};
if (oo->component_subtype != kAudioUnitSubType_HALOutput) CFStringRef cfname;
return; UInt32 size = sizeof(cfname);
if (AudioObjectGetPropertyData(id, &aopa_name,
0, nullptr,
&size, &cfname) != noErr)
return false;
const Apple::StringRef cfname_(cfname);
char actual_name[256];
if (!cfname_.GetCString(actual_name, sizeof(actual_name)))
return false;
return StringIsEqual(actual_name, expected_name);
}
static std::optional<AudioDeviceID>
FindAudioDeviceByName(const char *name)
{
/* what are the available audio device IDs? */ /* what are the available audio device IDs? */
static constexpr AudioObjectPropertyAddress aopa_hw_devices{ static constexpr AudioObjectPropertyAddress aopa_hw_devices{
kAudioHardwarePropertyDevices, kAudioHardwarePropertyDevices,
...@@ -557,60 +578,48 @@ osx_output_set_device(OSXOutput *oo) ...@@ -557,60 +578,48 @@ osx_output_set_device(OSXOutput *oo)
kAudioObjectPropertyElementMaster, kAudioObjectPropertyElementMaster,
}; };
const auto deviceids = const auto ids =
AudioObjectGetPropertyDataArray<AudioDeviceID>(kAudioObjectSystemObject, AudioObjectGetPropertyDataArray<AudioDeviceID>(kAudioObjectSystemObject,
aopa_hw_devices); aopa_hw_devices);
/* which audio device matches oo->device_name? */ for (const auto id : ids) {
static constexpr AudioObjectPropertyAddress aopa_name{ if (IsAudioDeviceName(id, name))
kAudioObjectPropertyName, return id;
kAudioObjectPropertyScopeGlobal, }
kAudioObjectPropertyElementMaster,
};
const unsigned numdevices = deviceids.size();
unsigned i;
size = sizeof(CFStringRef);
for (i = 0; i < numdevices; i++) {
CFStringRef cfname = nullptr;
status = AudioObjectGetPropertyData(deviceids[i], &aopa_name,
0, nullptr,
&size, &cfname);
if (status != noErr)
continue;
const Apple::StringRef cfname_(cfname);
char name[256]; return {};
if (!cfname_.GetCString(name, sizeof(name))) }
continue;
if (StringIsEqual(oo->device_name, name)) { static void
FormatDebug(osx_output_domain, osx_output_set_device(OSXOutput *oo)
"found matching device: ID=%u, name=%s", {
(unsigned)deviceids[i], name); if (oo->component_subtype != kAudioUnitSubType_HALOutput)
break; return;
}
}
if (i == numdevices) const auto id = FindAudioDeviceByName(oo->device_name);
if (!id.has_value())
throw FormatRuntimeError("Found no audio device with name '%s' ", throw FormatRuntimeError("Found no audio device with name '%s' ",
oo->device_name); oo->device_name);
FormatDebug(osx_output_domain,
"found matching device: ID=%u, name=%s",
(unsigned)id.value(), oo->device_name);
OSStatus status;
status = AudioUnitSetProperty(oo->au, status = AudioUnitSetProperty(oo->au,
kAudioOutputUnitProperty_CurrentDevice, kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global, kAudioUnitScope_Global,
0, 0,
&(deviceids[i]), &id.value(),
sizeof(AudioDeviceID)); sizeof(id.value()));
if (status != noErr) if (status != noErr)
Apple::ThrowOSStatus(status, Apple::ThrowOSStatus(status,
"Unable to set OS X audio output device"); "Unable to set OS X audio output device");
oo->dev_id = deviceids[i]; oo->dev_id = id.value();
FormatDebug(osx_output_domain, FormatDebug(osx_output_domain,
"set OS X audio output device ID=%u, name=%s", "set OS X audio output device ID=%u, name=%s",
(unsigned)deviceids[i], oo->device_name); (unsigned)id.value(), oo->device_name);
if (oo->channel_map) if (oo->channel_map)
osx_output_set_channel_map(oo); osx_output_set_channel_map(oo);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment