output/osx: use std::unique_ptr

Eliminate all those "goto"s and make the function exception-safe.
This commit is contained in:
Max Kellermann 2016-11-09 11:46:32 +01:00
parent 5c075210d6
commit 10f62db9fd

View File

@ -33,6 +33,8 @@
#include <CoreServices/CoreServices.h> #include <CoreServices/CoreServices.h>
#include <boost/lockfree/spsc_queue.hpp> #include <boost/lockfree/spsc_queue.hpp>
#include <memory>
struct OSXOutput { struct OSXOutput {
AudioOutput base; AudioOutput base;
@ -206,10 +208,8 @@ osx_output_set_channel_map(OSXOutput *oo, Error &error)
{ {
AudioStreamBasicDescription desc; AudioStreamBasicDescription desc;
OSStatus status; OSStatus status;
SInt32 *channel_map = nullptr;
UInt32 size, num_channels; UInt32 size, num_channels;
char errormsg[1024]; char errormsg[1024];
bool ret = true;
size = sizeof(desc); size = sizeof(desc);
memset(&desc, 0, size); memset(&desc, 0, size);
@ -224,20 +224,18 @@ osx_output_set_channel_map(OSXOutput *oo, Error &error)
error.Format(osx_output_domain, status, error.Format(osx_output_domain, status,
"%s: unable to get number of output device channels: %s", "%s: unable to get number of output device channels: %s",
oo->device_name, errormsg); oo->device_name, errormsg);
ret = false; return false;
goto done;
} }
num_channels = desc.mChannelsPerFrame; num_channels = desc.mChannelsPerFrame;
channel_map = new SInt32[num_channels]; std::unique_ptr<SInt32[]> channel_map(new SInt32[num_channels]);
if (!osx_output_parse_channel_map(oo->device_name, if (!osx_output_parse_channel_map(oo->device_name,
oo->channel_map, oo->channel_map,
channel_map, channel_map.get(),
num_channels, num_channels,
error) error)
) { ) {
ret = false; return false;
goto done;
} }
size = num_channels * sizeof(SInt32); size = num_channels * sizeof(SInt32);
@ -245,19 +243,16 @@ osx_output_set_channel_map(OSXOutput *oo, Error &error)
kAudioOutputUnitProperty_ChannelMap, kAudioOutputUnitProperty_ChannelMap,
kAudioUnitScope_Input, kAudioUnitScope_Input,
0, 0,
channel_map, channel_map.get(),
size); size);
if (status != noErr) { if (status != noErr) {
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
error.Format(osx_output_domain, status, error.Format(osx_output_domain, status,
"%s: unable to set channel map: %s", oo->device_name, errormsg); "%s: unable to set channel map: %s", oo->device_name, errormsg);
ret = false; return false;
goto done;
} }
done: return true;
delete[] channel_map;
return ret;
} }
static void static void
@ -436,10 +431,8 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog)
static bool static bool
osx_output_set_device(OSXOutput *oo, Error &error) osx_output_set_device(OSXOutput *oo, Error &error)
{ {
bool ret = true;
OSStatus status; OSStatus status;
UInt32 size, numdevices; UInt32 size, numdevices;
AudioDeviceID *deviceids = nullptr;
AudioObjectPropertyAddress propaddr; AudioObjectPropertyAddress propaddr;
CFStringRef cfname = nullptr; CFStringRef cfname = nullptr;
char errormsg[1024]; char errormsg[1024];
@ -452,7 +445,7 @@ osx_output_set_device(OSXOutput *oo, Error &error)
}; };
if (oo->component_subtype != kAudioUnitSubType_HALOutput) if (oo->component_subtype != kAudioUnitSubType_HALOutput)
goto done; return true;
/* how many audio devices are there? */ /* how many audio devices are there? */
propaddr = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; propaddr = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
@ -462,21 +455,19 @@ osx_output_set_device(OSXOutput *oo, Error &error)
error.Format(osx_output_domain, status, error.Format(osx_output_domain, status,
"Unable to determine number of OS X audio devices: %s", "Unable to determine number of OS X audio devices: %s",
errormsg); errormsg);
ret = false; return false;
goto done;
} }
/* what are the available audio device IDs? */ /* what are the available audio device IDs? */
numdevices = size / sizeof(AudioDeviceID); numdevices = size / sizeof(AudioDeviceID);
deviceids = new AudioDeviceID[numdevices]; std::unique_ptr<AudioDeviceID[]> deviceids(new AudioDeviceID[numdevices]);
status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propaddr, 0, nullptr, &size, deviceids); status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propaddr, 0, nullptr, &size, deviceids.get());
if (status != noErr) { if (status != noErr) {
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
error.Format(osx_output_domain, status, error.Format(osx_output_domain, status,
"Unable to determine OS X audio device IDs: %s", "Unable to determine OS X audio device IDs: %s",
errormsg); errormsg);
ret = false; return false;
goto done;
} }
/* which audio device matches oo->device_name? */ /* which audio device matches oo->device_name? */
@ -491,14 +482,12 @@ osx_output_set_device(OSXOutput *oo, Error &error)
"(device %u): %s", "(device %u): %s",
(unsigned int) deviceids[i], (unsigned int) deviceids[i],
errormsg); errormsg);
ret = false; return false;
goto done;
} }
if (!CFStringGetCString(cfname, name, sizeof(name), kCFStringEncodingUTF8)) { if (!CFStringGetCString(cfname, name, sizeof(name), kCFStringEncodingUTF8)) {
error.Set(osx_output_domain, "Unable to convert device name from CFStringRef to char*"); error.Set(osx_output_domain, "Unable to convert device name from CFStringRef to char*");
ret = false; return false;
goto done;
} }
if (strcmp(oo->device_name, name) == 0) { if (strcmp(oo->device_name, name) == 0) {
@ -513,7 +502,7 @@ osx_output_set_device(OSXOutput *oo, Error &error)
"Found no audio device with name '%s' " "Found no audio device with name '%s' "
"(will use default audio device)", "(will use default audio device)",
oo->device_name); oo->device_name);
goto done; return true;
} }
status = AudioUnitSetProperty(oo->au, status = AudioUnitSetProperty(oo->au,
@ -527,8 +516,7 @@ osx_output_set_device(OSXOutput *oo, Error &error)
error.Format(osx_output_domain, status, error.Format(osx_output_domain, status,
"Unable to set OS X audio output device: %s", "Unable to set OS X audio output device: %s",
errormsg); errormsg);
ret = false; return false;
goto done;
} }
oo->dev_id = deviceids[i]; oo->dev_id = deviceids[i];
@ -536,14 +524,10 @@ osx_output_set_device(OSXOutput *oo, Error &error)
"set OS X audio output device ID=%u, name=%s", "set OS X audio output device ID=%u, name=%s",
(unsigned)deviceids[i], name); (unsigned)deviceids[i], name);
if (oo->channel_map && !osx_output_set_channel_map(oo, error)) { if (oo->channel_map && !osx_output_set_channel_map(oo, error))
ret = false; return false;
goto done;
}
done: return true;
delete[] deviceids;
return ret;
} }