Commit 2b7328b4 authored by Max Kellermann's avatar Max Kellermann

output/osx: fix coding style

parent ca705e1e
...@@ -45,18 +45,19 @@ ...@@ -45,18 +45,19 @@
static constexpr unsigned MPD_OSX_BUFFER_TIME_MS = 100; static constexpr unsigned MPD_OSX_BUFFER_TIME_MS = 100;
static StringBuffer<64> static StringBuffer<64>
StreamDescriptionToString(const AudioStreamBasicDescription desc) { StreamDescriptionToString(const AudioStreamBasicDescription desc)
{
// Only convert the lpcm formats (nothing else supported / used by MPD) // Only convert the lpcm formats (nothing else supported / used by MPD)
assert(desc.mFormatID == kAudioFormatLinearPCM); assert(desc.mFormatID == kAudioFormatLinearPCM);
return StringFormat<64>("%u channel %s %sinterleaved %u-bit %s %s (%uHz)", return StringFormat<64>("%u channel %s %sinterleaved %u-bit %s %s (%uHz)",
desc.mChannelsPerFrame, desc.mChannelsPerFrame,
(desc.mFormatFlags & kAudioFormatFlagIsNonMixable) ? "" : "mixable", (desc.mFormatFlags & kAudioFormatFlagIsNonMixable) ? "" : "mixable",
(desc.mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? "non-" : "", (desc.mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? "non-" : "",
desc.mBitsPerChannel, desc.mBitsPerChannel,
(desc.mFormatFlags & kAudioFormatFlagIsFloat) ? "Float" : "SInt", (desc.mFormatFlags & kAudioFormatFlagIsFloat) ? "Float" : "SInt",
(desc.mFormatFlags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE", (desc.mFormatFlags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE",
(UInt32)desc.mSampleRate); (UInt32)desc.mSampleRate);
} }
...@@ -107,7 +108,8 @@ private: ...@@ -107,7 +108,8 @@ private:
static constexpr Domain osx_output_domain("osx_output"); static constexpr Domain osx_output_domain("osx_output");
static void static void
osx_os_status_to_cstring(OSStatus status, char *str, size_t size) { osx_os_status_to_cstring(OSStatus status, char *str, size_t size)
{
CFErrorRef cferr = CFErrorCreate(nullptr, kCFErrorDomainOSStatus, status, nullptr); CFErrorRef cferr = CFErrorCreate(nullptr, kCFErrorDomainOSStatus, status, nullptr);
CFStringRef cfstr = CFErrorCopyDescription(cferr); CFStringRef cfstr = CFErrorCopyDescription(cferr);
if (!CFStringGetCString(cfstr, str, size, kCFStringEncodingUTF8)) { if (!CFStringGetCString(cfstr, str, size, kCFStringEncodingUTF8)) {
...@@ -121,7 +123,7 @@ osx_os_status_to_cstring(OSStatus status, char *str, size_t size) { ...@@ -121,7 +123,7 @@ osx_os_status_to_cstring(OSStatus status, char *str, size_t size) {
} }
static bool static bool
osx_output_test_default_device(void) osx_output_test_default_device()
{ {
/* on a Mac, this is always the default plugin, if nothing /* on a Mac, this is always the default plugin, if nothing
else is configured */ else is configured */
...@@ -161,7 +163,7 @@ OSXOutput::Create(EventLoop &, const ConfigBlock &block) ...@@ -161,7 +163,7 @@ OSXOutput::Create(EventLoop &, const ConfigBlock &block)
AudioObjectPropertyAddress aopa; AudioObjectPropertyAddress aopa;
AudioDeviceID dev_id = kAudioDeviceUnknown; AudioDeviceID dev_id = kAudioDeviceUnknown;
UInt32 dev_id_size = sizeof(dev_id); UInt32 dev_id_size = sizeof(dev_id);
if (oo->component_subtype == kAudioUnitSubType_SystemOutput) if (oo->component_subtype == kAudioUnitSubType_SystemOutput)
// get system output dev_id if configured // get system output dev_id if configured
aopa = { aopa = {
...@@ -170,7 +172,8 @@ OSXOutput::Create(EventLoop &, const ConfigBlock &block) ...@@ -170,7 +172,8 @@ OSXOutput::Create(EventLoop &, const ConfigBlock &block)
kAudioObjectPropertyElementMaster kAudioObjectPropertyElementMaster
}; };
else else
// fallback to default device initially (can still be changed by osx_output_set_device) /* fallback to default device initially (can still be
changed by osx_output_set_device) */
aopa = { aopa = {
kAudioHardwarePropertyDefaultOutputDevice, kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeOutput, kAudioObjectPropertyScopeOutput,
...@@ -216,7 +219,8 @@ OSXOutput::GetVolume() ...@@ -216,7 +219,8 @@ OSXOutput::GetVolume()
} }
void void
OSXOutput::SetVolume(unsigned new_volume) { OSXOutput::SetVolume(unsigned new_volume)
{
Float32 vol = new_volume / 100.0; Float32 vol = new_volume / 100.0;
AudioObjectPropertyAddress aopa = { AudioObjectPropertyAddress aopa = {
.mSelector = kAudioHardwareServiceDeviceProperty_VirtualMasterVolume, .mSelector = kAudioHardwareServiceDeviceProperty_VirtualMasterVolume,
...@@ -240,11 +244,10 @@ OSXOutput::SetVolume(unsigned new_volume) { ...@@ -240,11 +244,10 @@ OSXOutput::SetVolume(unsigned new_volume) {
} }
static void static void
osx_output_parse_channel_map( osx_output_parse_channel_map(const char *device_name,
const char *device_name, const char *channel_map_str,
const char *channel_map_str, SInt32 channel_map[],
SInt32 channel_map[], UInt32 num_channels)
UInt32 num_channels)
{ {
char *endptr; char *endptr;
unsigned int inserted_channels = 0; unsigned int inserted_channels = 0;
...@@ -331,7 +334,8 @@ osx_output_set_channel_map(OSXOutput *oo) ...@@ -331,7 +334,8 @@ osx_output_set_channel_map(OSXOutput *oo)
static float static float
osx_output_score_sample_rate(Float64 destination_rate, unsigned int source_rate) { osx_output_score_sample_rate(Float64 destination_rate, unsigned source_rate)
{
float score = 0; float score = 0;
double int_portion; double int_portion;
double frac_portion = modf(source_rate / destination_rate, &int_portion); double frac_portion = modf(source_rate / destination_rate, &int_portion);
...@@ -341,24 +345,27 @@ osx_output_score_sample_rate(Float64 destination_rate, unsigned int source_rate) ...@@ -341,24 +345,27 @@ osx_output_score_sample_rate(Float64 destination_rate, unsigned int source_rate)
score += (int_portion == 1.0) ? 500 : 0; score += (int_portion == 1.0) ? 500 : 0;
if (source_rate == destination_rate) if (source_rate == destination_rate)
score += 1000; score += 1000;
else if(source_rate > destination_rate) else if (source_rate > destination_rate)
score += (int_portion > 1 && int_portion < 100) ? (100 - int_portion) / 100 * 100 : 0; score += (int_portion > 1 && int_portion < 100) ? (100 - int_portion) / 100 * 100 : 0;
else else
score += (int_portion > 1 && int_portion < 100) ? (100 + int_portion) / 100 * 100 : 0; score += (int_portion > 1 && int_portion < 100) ? (100 + int_portion) / 100 * 100 : 0;
return score; return score;
} }
static float static float
osx_output_score_format(const AudioStreamBasicDescription &format_desc, const AudioStreamBasicDescription &target_format) { osx_output_score_format(const AudioStreamBasicDescription &format_desc,
const AudioStreamBasicDescription &target_format)
{
float score = 0; float score = 0;
// Score only linear PCM formats (everything else MPD cannot use) // Score only linear PCM formats (everything else MPD cannot use)
if (format_desc.mFormatID == kAudioFormatLinearPCM) { if (format_desc.mFormatID == kAudioFormatLinearPCM) {
score += osx_output_score_sample_rate(format_desc.mSampleRate, target_format.mSampleRate); score += osx_output_score_sample_rate(format_desc.mSampleRate,
target_format.mSampleRate);
// Just choose the stream / format with the highest number of output channels // Just choose the stream / format with the highest number of output channels
score += format_desc.mChannelsPerFrame * 5; score += format_desc.mChannelsPerFrame * 5;
if (target_format.mFormatFlags == kLinearPCMFormatFlagIsFloat) { if (target_format.mFormatFlags == kLinearPCMFormatFlagIsFloat) {
// for float, prefer the highest bitdepth we have // for float, prefer the highest bitdepth we have
if (format_desc.mBitsPerChannel >= 16) if (format_desc.mBitsPerChannel >= 16)
...@@ -368,14 +375,16 @@ osx_output_score_format(const AudioStreamBasicDescription &format_desc, const Au ...@@ -368,14 +375,16 @@ osx_output_score_format(const AudioStreamBasicDescription &format_desc, const Au
score += 5; score += 5;
else if (format_desc.mBitsPerChannel > target_format.mBitsPerChannel) else if (format_desc.mBitsPerChannel > target_format.mBitsPerChannel)
score += 1; score += 1;
} }
} }
return score; return score;
} }
static Float64 static Float64
osx_output_set_device_format(AudioDeviceID dev_id, const AudioStreamBasicDescription &target_format) osx_output_set_device_format(AudioDeviceID dev_id,
const AudioStreamBasicDescription &target_format)
{ {
AudioObjectPropertyAddress aopa = { AudioObjectPropertyAddress aopa = {
kAudioDevicePropertyStreams, kAudioDevicePropertyStreams,
...@@ -384,66 +393,69 @@ osx_output_set_device_format(AudioDeviceID dev_id, const AudioStreamBasicDescrip ...@@ -384,66 +393,69 @@ osx_output_set_device_format(AudioDeviceID dev_id, const AudioStreamBasicDescrip
}; };
UInt32 property_size; UInt32 property_size;
OSStatus err = AudioObjectGetPropertyDataSize(dev_id, &aopa, 0, NULL, &property_size); OSStatus err = AudioObjectGetPropertyDataSize(dev_id, &aopa, 0, NULL, &property_size);
if (err != noErr) { if (err != noErr)
throw FormatRuntimeError("Cannot get number of streams: %d\n", err); throw FormatRuntimeError("Cannot get number of streams: %d\n", err);
}
int n_streams = property_size / sizeof(AudioStreamID);
int n_streams = property_size / sizeof(AudioStreamID); AudioStreamID streams[n_streams];
AudioStreamID streams[n_streams]; err = AudioObjectGetPropertyData(dev_id, &aopa, 0, NULL, &property_size, streams);
err = AudioObjectGetPropertyData(dev_id, &aopa, 0, NULL, &property_size, streams); if (err != noErr)
if (err != noErr) { throw FormatRuntimeError("Cannot get streams: %d\n", err);
throw FormatRuntimeError("Cannot get streams: %d\n", err);
}
bool format_found = false; bool format_found = false;
int output_stream; int output_stream;
AudioStreamBasicDescription output_format; AudioStreamBasicDescription output_format;
for (int i = 0; i < n_streams; i++) { for (int i = 0; i < n_streams; i++) {
UInt32 direction; UInt32 direction;
AudioStreamID stream = streams[i]; AudioStreamID stream = streams[i];
aopa.mSelector = kAudioStreamPropertyDirection; aopa.mSelector = kAudioStreamPropertyDirection;
property_size = sizeof(direction); property_size = sizeof(direction);
err = AudioObjectGetPropertyData(stream, err = AudioObjectGetPropertyData(stream,
&aopa, &aopa,
0, 0,
NULL, NULL,
&property_size, &property_size,
&direction); &direction);
if (err != noErr) { if (err != noErr)
throw FormatRuntimeError("Cannot get streams direction: %d\n", err); throw FormatRuntimeError("Cannot get streams direction: %d\n",
} err);
if (direction != 0) {
if (direction != 0)
continue; continue;
}
aopa.mSelector = kAudioStreamPropertyAvailablePhysicalFormats; aopa.mSelector = kAudioStreamPropertyAvailablePhysicalFormats;
err = AudioObjectGetPropertyDataSize(stream, &aopa, 0, NULL, &property_size); err = AudioObjectGetPropertyDataSize(stream, &aopa, 0, NULL,
&property_size);
if (err != noErr) if (err != noErr)
throw FormatRuntimeError("Unable to get format size s for stream %d. Error = %s", streams[i], err); throw FormatRuntimeError("Unable to get format size s for stream %d. Error = %s",
streams[i], err);
int format_count = property_size / sizeof(AudioStreamRangedDescription); const size_t format_count = property_size / sizeof(AudioStreamRangedDescription);
AudioStreamRangedDescription format_list[format_count]; AudioStreamRangedDescription format_list[format_count];
err = AudioObjectGetPropertyData(stream, &aopa, 0, NULL, &property_size, format_list); err = AudioObjectGetPropertyData(stream, &aopa, 0, NULL, &property_size, format_list);
if (err != noErr) if (err != noErr)
throw FormatRuntimeError("Unable to get available formats for stream %d. Error = %s", streams[i], err); throw FormatRuntimeError("Unable to get available formats for stream %d. Error = %s",
streams[i], err);
float output_score = 0; float output_score = 0;
for (int j = 0; j < format_count; j++) { for (size_t j = 0; j < format_count; j++) {
AudioStreamBasicDescription format_desc = format_list[j].mFormat; AudioStreamBasicDescription format_desc = format_list[j].mFormat;
std::string format_string; std::string format_string;
// for devices with kAudioStreamAnyRate // for devices with kAudioStreamAnyRate
// we use the requested samplerate here // we use the requested samplerate here
if (format_desc.mSampleRate == kAudioStreamAnyRate) if (format_desc.mSampleRate == kAudioStreamAnyRate)
format_desc.mSampleRate = target_format.mSampleRate; format_desc.mSampleRate = target_format.mSampleRate;
float score = osx_output_score_format(format_desc, target_format); float score = osx_output_score_format(format_desc, target_format);
// print all (linear pcm) formats and their rating // print all (linear pcm) formats and their rating
if(score > 0.0) if (score > 0.0)
FormatDebug(osx_output_domain, "Format: %s rated %f", StreamDescriptionToString(format_desc).c_str(), score); FormatDebug(osx_output_domain,
"Format: %s rated %f",
StreamDescriptionToString(format_desc).c_str(), score);
if (score > output_score) { if (score > output_score) {
output_score = score; output_score = score;
output_format = format_desc; output_format = format_desc;
...@@ -454,23 +466,24 @@ osx_output_set_device_format(AudioDeviceID dev_id, const AudioStreamBasicDescrip ...@@ -454,23 +466,24 @@ osx_output_set_device_format(AudioDeviceID dev_id, const AudioStreamBasicDescrip
} }
if (format_found) { if (format_found) {
aopa.mSelector = kAudioStreamPropertyPhysicalFormat; aopa.mSelector = kAudioStreamPropertyPhysicalFormat;
err = AudioObjectSetPropertyData(output_stream, err = AudioObjectSetPropertyData(output_stream,
&aopa, &aopa,
0, 0,
NULL, NULL,
sizeof(output_format), sizeof(output_format),
&output_format); &output_format);
if (err != noErr) { if (err != noErr)
throw FormatRuntimeError("Failed to change the stream format: %d\n", err); throw FormatRuntimeError("Failed to change the stream format: %d\n",
} err);
} }
return output_format.mSampleRate; return output_format.mSampleRate;
} }
static OSStatus static OSStatus
osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc, UInt32 *frame_size) osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc,
UInt32 *frame_size)
{ {
AudioValueRange value_range = {0, 0}; AudioValueRange value_range = {0, 0};
UInt32 property_size = sizeof(AudioValueRange); UInt32 property_size = sizeof(AudioValueRange);
...@@ -491,7 +504,7 @@ osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc, UInt3 ...@@ -491,7 +504,7 @@ osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc, UInt3
&buffer_frame_size, &buffer_frame_size,
sizeof(buffer_frame_size)); sizeof(buffer_frame_size));
if (err != noErr) if (err != noErr)
FormatWarning(osx_output_domain, FormatWarning(osx_output_domain,
"Failed to set maximum buffer size: %d", "Failed to set maximum buffer size: %d",
err); err);
...@@ -503,7 +516,7 @@ osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc, UInt3 ...@@ -503,7 +516,7 @@ osx_output_set_buffer_size(AudioUnit au, AudioStreamBasicDescription desc, UInt3
&buffer_frame_size, &buffer_frame_size,
&property_size); &property_size);
if (err != noErr) { if (err != noErr) {
FormatWarning(osx_output_domain, FormatWarning(osx_output_domain,
"Cannot get the buffer frame size: %d", "Cannot get the buffer frame size: %d",
err); err);
return err; return err;
...@@ -542,19 +555,21 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog) ...@@ -542,19 +555,21 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog)
err); err);
return; return;
} }
if (hog) { if (hog) {
if (hog_pid != -1) { if (hog_pid != -1) {
FormatDebug(osx_output_domain, FormatDebug(osx_output_domain,
"Device is already hogged."); "Device is already hogged.");
return; return;
} }
} else { } else {
if (hog_pid != getpid()) { if (hog_pid != getpid()) {
FormatDebug(osx_output_domain, FormatDebug(osx_output_domain,
"Device is not owned by this process."); "Device is not owned by this process.");
return; return;
} }
} }
hog_pid = hog ? getpid() : -1; hog_pid = hog ? getpid() : -1;
size = sizeof(hog_pid); size = sizeof(hog_pid);
err = AudioObjectSetPropertyData(dev_id, err = AudioObjectSetPropertyData(dev_id,
...@@ -568,9 +583,10 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog) ...@@ -568,9 +583,10 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog)
"Cannot hog the device: %d", "Cannot hog the device: %d",
err); err);
} else { } else {
FormatDebug(osx_output_domain, LogDebug(osx_output_domain,
hog_pid == -1 ? "Device is unhogged" hog_pid == -1
: "Device is hogged"); ? "Device is unhogged"
: "Device is hogged");
} }
} }
...@@ -595,8 +611,11 @@ osx_output_set_device(OSXOutput *oo) ...@@ -595,8 +611,11 @@ osx_output_set_device(OSXOutput *oo)
return; return;
/* how many audio devices are there? */ /* how many audio devices are there? */
propaddr = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; propaddr = { kAudioHardwarePropertyDevices,
status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propaddr, 0, nullptr, &size); kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster };
status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
&propaddr, 0, nullptr, &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));
throw FormatRuntimeError("Unable to determine number of OS X audio devices: %s", throw FormatRuntimeError("Unable to determine number of OS X audio devices: %s",
...@@ -606,7 +625,9 @@ osx_output_set_device(OSXOutput *oo) ...@@ -606,7 +625,9 @@ osx_output_set_device(OSXOutput *oo)
/* what are the available audio device IDs? */ /* what are the available audio device IDs? */
numdevices = size / sizeof(AudioDeviceID); numdevices = size / sizeof(AudioDeviceID);
std::unique_ptr<AudioDeviceID[]> deviceids(new AudioDeviceID[numdevices]); std::unique_ptr<AudioDeviceID[]> deviceids(new AudioDeviceID[numdevices]);
status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propaddr, 0, nullptr, &size, deviceids.get()); 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));
throw FormatRuntimeError("Unable to determine OS X audio device IDs: %s", throw FormatRuntimeError("Unable to determine OS X audio device IDs: %s",
...@@ -614,10 +635,14 @@ osx_output_set_device(OSXOutput *oo) ...@@ -614,10 +635,14 @@ osx_output_set_device(OSXOutput *oo)
} }
/* which audio device matches oo->device_name? */ /* which audio device matches oo->device_name? */
propaddr = { kAudioObjectPropertyName, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; propaddr = { kAudioObjectPropertyName,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster };
size = sizeof(CFStringRef); size = sizeof(CFStringRef);
for (i = 0; i < numdevices; i++) { for (i = 0; i < numdevices; i++) {
status = AudioObjectGetPropertyData(deviceids[i], &propaddr, 0, nullptr, &size, &cfname); status = AudioObjectGetPropertyData(deviceids[i], &propaddr,
0, nullptr,
&size, &cfname);
if (status != noErr) { if (status != noErr) {
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
throw FormatRuntimeError("Unable to determine OS X device name " throw FormatRuntimeError("Unable to determine OS X device name "
...@@ -626,7 +651,8 @@ osx_output_set_device(OSXOutput *oo) ...@@ -626,7 +651,8 @@ osx_output_set_device(OSXOutput *oo)
errormsg); errormsg);
} }
if (!CFStringGetCString(cfname, name, sizeof(name), kCFStringEncodingUTF8)) if (!CFStringGetCString(cfname, name, sizeof(name),
kCFStringEncodingUTF8))
throw std::runtime_error("Unable to convert device name from CFStringRef to char*"); throw std::runtime_error("Unable to convert device name from CFStringRef to char*");
if (strcmp(oo->device_name, name) == 0) { if (strcmp(oo->device_name, name) == 0) {
...@@ -636,10 +662,10 @@ osx_output_set_device(OSXOutput *oo) ...@@ -636,10 +662,10 @@ osx_output_set_device(OSXOutput *oo)
break; break;
} }
} }
if (i == numdevices) {
throw FormatRuntimeError("Found no audio device with name '%s' ", if (i == numdevices)
throw FormatRuntimeError("Found no audio device with name '%s' ",
oo->device_name); oo->device_name);
}
status = AudioUnitSetProperty(oo->au, status = AudioUnitSetProperty(oo->au,
kAudioOutputUnitProperty_CurrentDevice, kAudioOutputUnitProperty_CurrentDevice,
...@@ -663,13 +689,13 @@ osx_output_set_device(OSXOutput *oo) ...@@ -663,13 +689,13 @@ osx_output_set_device(OSXOutput *oo)
} }
/* /**
This function (the 'render callback' osx_render) is called by the * This function (the 'render callback' osx_render) is called by the
OS X audio subsystem (CoreAudio) to request audio data that will be * OS X audio subsystem (CoreAudio) to request audio data that will be
played by the audio hardware. This function has hard time constraints * played by the audio hardware. This function has hard time
so it cannot do IO (debug statements) or memory allocations. * constraints so it cannot do IO (debug statements) or memory
*/ * allocations.
*/
static OSStatus static OSStatus
osx_render(void *vdata, osx_render(void *vdata,
gcc_unused AudioUnitRenderActionFlags *io_action_flags, gcc_unused AudioUnitRenderActionFlags *io_action_flags,
...@@ -684,7 +710,7 @@ osx_render(void *vdata, ...@@ -684,7 +710,7 @@ osx_render(void *vdata,
buffer_list->mBuffers[0].mDataByteSize = buffer_list->mBuffers[0].mDataByteSize =
od->ring_buffer->pop((uint8_t *)buffer_list->mBuffers[0].mData, od->ring_buffer->pop((uint8_t *)buffer_list->mBuffers[0].mData,
count); count);
return noErr; return noErr;
} }
void void
...@@ -722,7 +748,7 @@ OSXOutput::Enable() ...@@ -722,7 +748,7 @@ OSXOutput::Enable()
#endif #endif
throw; throw;
} }
if (hog_device) if (hog_device)
osx_output_hog_device(dev_id, true); osx_output_hog_device(dev_id, true);
} }
...@@ -794,7 +820,9 @@ OSXOutput::Open(AudioFormat &audio_format) ...@@ -794,7 +820,9 @@ OSXOutput::Open(AudioFormat &audio_format)
Float64 sample_rate = osx_output_set_device_format(dev_id, asbd); Float64 sample_rate = osx_output_set_device_format(dev_id, asbd);
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
if(audio_format.format == SampleFormat::DSD && sample_rate != asbd.mSampleRate) { // fall back to PCM in case sample_rate cannot be synchronized if (audio_format.format == SampleFormat::DSD &&
sample_rate != asbd.mSampleRate) {
// fall back to PCM in case sample_rate cannot be synchronized
params.dop = false; params.dop = false;
audio_format.format = SampleFormat::S32; audio_format.format = SampleFormat::S32;
asbd.mBitsPerChannel = 32; asbd.mBitsPerChannel = 32;
...@@ -846,7 +874,7 @@ OSXOutput::Open(AudioFormat &audio_format) ...@@ -846,7 +874,7 @@ OSXOutput::Open(AudioFormat &audio_format)
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);
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
if (dop_enabled) { if (dop_enabled) {
pcm_export->Open(audio_format.format, audio_format.channels, params); pcm_export->Open(audio_format.format, audio_format.channels, params);
ring_buffer_size = std::max<size_t>(buffer_frame_size, ring_buffer_size = std::max<size_t>(buffer_frame_size,
MPD_OSX_BUFFER_TIME_MS * pcm_export->GetFrameSize(audio_format) * asbd.mSampleRate / 1000); MPD_OSX_BUFFER_TIME_MS * pcm_export->GetFrameSize(audio_format) * asbd.mSampleRate / 1000);
...@@ -868,7 +896,7 @@ size_t ...@@ -868,7 +896,7 @@ size_t
OSXOutput::Play(const void *chunk, size_t size) OSXOutput::Play(const void *chunk, size_t size)
{ {
assert(size > 0); assert(size > 0);
if(pause) { if (pause) {
pause = false; pause = false;
OSStatus status = AudioOutputUnitStart(au); OSStatus status = AudioOutputUnitStart(au);
if (status != 0) { if (status != 0) {
...@@ -877,7 +905,7 @@ OSXOutput::Play(const void *chunk, size_t size) ...@@ -877,7 +905,7 @@ OSXOutput::Play(const void *chunk, size_t size)
} }
} }
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
if (dop_enabled) { if (dop_enabled) {
const auto e = pcm_export->Export({chunk, size}); const auto e = pcm_export->Export({chunk, size});
/* the DoP (DSD over PCM) filter converts two frames /* the DoP (DSD over PCM) filter converts two frames
at a time and ignores the last odd frame; if there at a time and ignores the last odd frame; if there
...@@ -902,9 +930,10 @@ OSXOutput::Delay() const noexcept ...@@ -902,9 +930,10 @@ OSXOutput::Delay() const noexcept
? std::chrono::steady_clock::duration::zero() ? std::chrono::steady_clock::duration::zero()
: std::chrono::milliseconds(MPD_OSX_BUFFER_TIME_MS / 4); : std::chrono::milliseconds(MPD_OSX_BUFFER_TIME_MS / 4);
} }
bool OSXOutput::Pause() { bool OSXOutput::Pause()
if(!pause) { {
if (!pause) {
pause = true; pause = true;
AudioOutputUnitStop(au); AudioOutputUnitStop(au);
} }
......
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