15 #include <SoundTouch.h>
20 #include <CoreServices/CoreServices.h>
21 #include <CoreAudio/CoreAudio.h>
22 #include <AudioUnit/AudioUnit.h>
23 #include <AudioToolbox/AudioFormat.h>
24 #include <AvailabilityMacros.h>
29 #if !defined(MAC_OS_VERSION_12_0)
30 #define kAudioObjectPropertyElementMain kAudioObjectPropertyElementMaster
33 #define LOC QString("CoreAudio: ")
35 #define CHANNELS_MIN 1
36 #define CHANNELS_MAX 8
44 #define OSS_STATUS(x) UInt32ToFourCC((UInt32*)&(x))
48 char* pIn = (
char*)&inVal;
49 static char fourCC[5];
60 UInt32 formatId = desc.mFormatID;
64 switch (desc.mFormatID)
66 case kAudioFormatLinearPCM:
67 str = QString(
"[%1] %2%3 Channel %4-bit %5 %6 (%7Hz) %8 Channels")
69 .arg((desc.mFormatFlags & kAudioFormatFlagIsNonMixable) ?
"" :
"Mixable ")
70 .arg(desc.mChannelsPerFrame)
71 .arg(desc.mBitsPerChannel)
72 .arg((desc.mFormatFlags & kAudioFormatFlagIsFloat) ?
"Floating Point" :
"Signed Integer")
73 .arg((desc.mFormatFlags & kAudioFormatFlagIsBigEndian) ?
"BE" :
"LE")
74 .arg((UInt32)desc.mSampleRate)
75 .arg(desc.mChannelsPerFrame);
78 str = QString(
"[%1] AC-3/DTS (%2Hz) %3 Channels")
80 .arg((UInt32)desc.mSampleRate)
81 .arg(desc.mChannelsPerFrame);
83 case kAudioFormat60958AC3:
84 str = QString(
"[%1] AC-3/DTS for S/PDIF %2 (%3Hz) %4 Channels")
86 .arg((desc.mFormatFlags & kAudioFormatFlagIsBigEndian) ?
"BE" :
"LE")
87 .arg((UInt32)desc.mSampleRate)
88 .arg(desc.mChannelsPerFrame);
91 str = QString(
"[%1]").arg(fourCC);
135 AudioStreamBasicDescription format);
138 static void Debug(
const QString& msg)
139 {
LOG(VB_AUDIO, LOG_INFO,
"CoreAudioData::" + msg); }
141 static void Error(
const QString& msg)
142 {
LOG(VB_GENERAL, LOG_ERR,
"CoreAudioData Error:" + msg); }
144 static void Warn (
const QString& msg)
145 {
LOG(VB_GENERAL, LOG_WARNING,
"CoreAudioData Warning:" + msg); }
172 AudioUnitRenderActionFlags *ioActionFlags,
173 const AudioTimeStamp *inTimeStamp,
175 UInt32 inNumberFrames,
176 AudioBufferList *ioData);
178 const AudioTimeStamp *inNow,
179 const void *inInputData,
180 const AudioTimeStamp *inInputTime,
181 AudioBufferList *outOutputData,
182 const AudioTimeStamp *inOutputTime,
218 settings->AddSupportedRate(48000);
222 while (
int rate = settings->GetNextRate())
224 for (
auto entry : rates)
228 settings->AddSupportedRate(entry);
241 settings->AddSupportedChannels(2);
249 Debug(QString(
"Support %1 channels").arg(i));
251 if (i == 8 && !channels[6-1])
252 settings->AddSupportedChannels(6);
253 settings->AddSupportedChannels(i);
260 settings->setPassthrough(1);
267 bool deviceOpened =
false;
272 Debug(
"OpenDevice: Entering");
275 Debug(
"OpenDevice() Trying Digital.");
282 Debug(
"OpenDevice() Trying Analog.");
287 Debug(QString(
"OpenDevice: OpenAnalog = %1").arg(result));
294 deviceOpened = (result > 0);
299 Error(
"Couldn't open any audio device!");
307 controlLabel +=
"MixerVolume";
316 VBAUDIO(QString(
"CloseDevice [%1]: Entering")
324 template <
class AudioDataType>
329 AudioDataType tmpRLs;
330 AudioDataType tmpRRs;
332 for (
uint i = 0; i < frames; i++)
334 buf = buf2 = buf + 4;
359 int size,
unsigned long long timestamp)
375 if (written_size && (size > written_size))
378 memset(aubuf + written_size, 0, size - written_size);
388 UInt64 nanos = AudioConvertHostTimeToNanos(timestamp -
389 AudioGetCurrentHostTime());
394 return (written_size > 0);
416 if (audbuf_timecode == 0ms)
428 AudioUnitRenderActionFlags *ioActionFlags,
429 const AudioTimeStamp *inTimeStamp,
431 UInt32 inNumberFrames,
432 AudioBufferList *ioData)
435 (void)inNumberFrames;
439 if (!inst->
RenderAudio((
unsigned char *)(ioData->mBuffers[0].mData),
440 ioData->mBuffers[0].mDataByteSize,
441 inTimeStamp->mHostTime))
444 memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize);
445 *ioActionFlags = kAudioUnitRenderAction_OutputIsSilence;
457 kHALOutputParam_Volume,
458 kAudioUnitScope_Global, 0, &volume))
459 return (
int)lroundf(volume * 100.0F);
468 AudioUnitSetParameter(
d->
mOutputUnit, kHALOutputParam_Volume,
469 kAudioUnitScope_Global, 0, (volume * 0.01F), 0);
474 const AudioTimeStamp *inNow,
475 const void *inInputData,
476 const AudioTimeStamp *inInputTime,
477 AudioBufferList *outOutputData,
478 const AudioTimeStamp *inOutputTime,
483 int index =
d->mStreamIndex;
494 if (
d->mBytesPerPacket > 0 &&
495 outOutputData->mBuffers[index].mDataByteSize >
d->mBytesPerPacket)
497 outOutputData->mBuffers[index].mDataByteSize =
d->mBytesPerPacket;
499 if (!a->
RenderAudio((
unsigned char *)(outOutputData->mBuffers[index].mData),
500 outOutputData->mBuffers[index].mDataByteSize,
501 inOutputTime->mHostTime))
504 memset(outOutputData->mBuffers[index].mData, 0,
505 outOutputData->mBuffers[index].mDataByteSize);
536 if (deviceName !=
"Default Output Device")
538 Warn(QString(
"CoreAudioData: \"%1\" not found, using default device %2.")
542 Debug(QString(
"CoreAudioData: device number is %1")
549 AudioDeviceID deviceID = 0;
550 AudioObjectPropertyAddress pa
552 kAudioHardwarePropertyDevices,
553 kAudioObjectPropertyScopeGlobal,
557 OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
561 Warn(QString(
"GetPropertyDataSize: Unable to retrieve the property sizes. "
567 UInt32 deviceCount = size /
sizeof(AudioDeviceID);
568 std::vector<AudioDeviceID> devices = {};
569 devices.resize(deviceCount);
571 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
572 0,
nullptr, &size, devices.data());
575 Warn(QString(
"GetDeviceWithName: Unable to retrieve the list of available devices. "
581 for (
const auto & dev : devices)
586 QString *name = device.
GetName();
587 if (name && *name == deviceName)
589 Debug(QString(
"GetDeviceWithName: Found: %1").arg(*name));
603 AudioDeviceID deviceId = 0;
604 AudioObjectPropertyAddress pa
606 kAudioHardwarePropertyDefaultOutputDevice,
607 kAudioObjectPropertyScopeGlobal,
612 paramSize =
sizeof(deviceId);
613 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
614 0,
nullptr, ¶mSize, &deviceId);
616 Debug(QString(
"GetDefaultOutputDevice: default device ID = %1").arg(deviceId));
619 Warn(QString(
"GetDefaultOutputDevice: could not get default audio device: [%1]")
632 AudioObjectPropertyAddress pa
634 kAudioDevicePropertyStreamConfiguration,
635 kAudioDevicePropertyScopeOutput,
639 OSStatus err = AudioObjectGetPropertyDataSize(
mDeviceID, &pa,
643 Warn(QString(
"GetTotalOutputChannels: Unable to get "
644 "size of device output channels - id: %1 Error = [%2]")
650 auto *pList = (AudioBufferList *)malloc(size);
651 err = AudioObjectGetPropertyData(
mDeviceID, &pa,
652 0,
nullptr, &size, pList);
655 for (UInt32 buffer = 0; buffer < pList->mNumberBuffers; buffer++)
656 channels += pList->mBuffers[buffer].mNumberChannels;
660 Warn(QString(
"GetTotalOutputChannels: Unable to get "
661 "total device output channels - id: %1 Error = [%2]")
665 Debug(QString(
"GetTotalOutputChannels: Found %1 channels in %2 buffers")
666 .arg(channels).arg(pList->mNumberBuffers));
676 AudioObjectPropertyAddress pa
678 kAudioObjectPropertyName,
679 kAudioObjectPropertyScopeGlobal,
684 UInt32 propertySize =
sizeof(CFStringRef);
685 OSStatus err = AudioObjectGetPropertyData(
mDeviceID, &pa,
686 0,
nullptr, &propertySize, &name);
689 Error(QString(
"AudioObjectGetPropertyData for kAudioObjectPropertyName error: [%1]")
693 char *cname =
new char[CFStringGetLength(name) + 1];
694 CFStringGetCString(name, cname, CFStringGetLength(name) + 1, kCFStringEncodingUTF8);
695 auto *qname =
new QString(cname);
703 UInt32 size =
sizeof(val);
704 AudioObjectPropertyAddress pa
706 kAudioHardwarePropertyHogModeIsAllowed,
707 kAudioObjectPropertyScopeGlobal,
711 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0,
nullptr, &size, &val);
714 Warn(QString(
"GetAutoHogMode: Unable to get auto 'hog' mode. Error = [%1]")
723 UInt32 val = enable ? 1 : 0;
724 AudioObjectPropertyAddress pa
726 kAudioHardwarePropertyHogModeIsAllowed,
727 kAudioObjectPropertyScopeGlobal,
731 OSStatus err = AudioObjectSetPropertyData(kAudioObjectSystemObject, &pa, 0,
nullptr,
735 Warn(QString(
"SetAutoHogMode: Unable to set auto 'hog' mode. Error = [%1]")
743 UInt32 PIDsize =
sizeof(
PID);
744 AudioObjectPropertyAddress pa
746 kAudioDevicePropertyHogMode,
747 kAudioObjectPropertyScopeGlobal,
751 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0,
nullptr,
757 Debug(QString(
"GetHogStatus: unable to check: [%1]")
766 AudioObjectPropertyAddress pa
768 kAudioDevicePropertyHogMode,
769 kAudioObjectPropertyScopeGlobal,
783 Debug(QString(
"SetHogStatus: Setting 'hog' status on device %1")
785 OSStatus err = AudioObjectSetPropertyData(
mDeviceID, &pa, 0,
nullptr,
787 if (err ||
mHog != getpid())
789 Warn(QString(
"SetHogStatus: Unable to set 'hog' status. Error = [%1]")
793 Debug(QString(
"SetHogStatus: Successfully set 'hog' status on device %1")
801 Debug(QString(
"SetHogStatus: Releasing 'hog' status on device %1")
804 OSStatus err = AudioObjectSetPropertyData(
mDeviceID, &pa, 0,
nullptr,
805 sizeof(hogPid), &hogPid);
806 if (err || hogPid == getpid())
808 Warn(QString(
"SetHogStatus: Unable to release 'hog' status. Error = [%1]")
825 UInt32 mixEnable = mix ? 1 : 0;
826 Debug(QString(
"SetMixingSupport: %1abling mixing for device %2")
827 .arg(mix ?
"En" :
"Dis")
830 AudioObjectPropertyAddress pa
832 kAudioDevicePropertySupportsMixing,
833 kAudioObjectPropertyScopeGlobal,
836 OSStatus err = AudioObjectSetPropertyData(
mDeviceID, &pa, 0,
nullptr,
837 sizeof(mixEnable), &mixEnable);
840 Warn(QString(
"SetMixingSupport: Unable to set MixingSupport to %1. Error = [%2]")
841 .arg(mix ?
"'On'" :
"'Off'")
855 UInt32 size =
sizeof(val);
856 AudioObjectPropertyAddress pa
858 kAudioDevicePropertySupportsMixing,
859 kAudioObjectPropertyScopeGlobal,
862 OSStatus err = AudioObjectGetPropertyData(
mDeviceID, &pa, 0,
nullptr,
878 AudioObjectPropertyAddress pa
880 kAudioDevicePropertyStreams,
881 kAudioObjectPropertyScopeGlobal,
885 err = AudioObjectGetPropertyDataSize(
d, &pa,
886 0,
nullptr, &listSize);
889 Error(QString(
"StreamsList: could not get list size: [%1]")
897 vec.resize(listSize /
sizeof(AudioStreamID));
901 Error(
"StreamsList(): out of memory?");
905 err = AudioObjectGetPropertyData(
d, &pa,
906 0,
nullptr, &listSize, vec.data());
909 Error(QString(
"StreamsList: could not get list: [%1]")
923 AudioObjectPropertyAddress pa
926 kAudioStreamPropertyAvailablePhysicalFormats,
927 kAudioObjectPropertyScopeGlobal,
932 err = AudioObjectGetPropertyDataSize(s, &pa, 0,
nullptr, &listSize);
935 Warn(QString(
"FormatsList(): couldn't get list size: [%1]")
942 vec.resize(listSize /
sizeof(AudioStreamRangedDescription));
946 Error(
"FormatsList(): out of memory?");
950 err = AudioObjectGetPropertyData(s, &pa, 0,
nullptr, &listSize, vec.data());
953 Warn(QString(
"FormatsList: couldn't get list: [%1]")
963 8000.0, 11025.0, 12000.0,
964 16000.0, 22050.0, 24000.0,
965 32000.0, 44100.0, 48000.0,
966 64000.0, 88200.0, 96000.0,
967 128000.0, 176400.0, 192000.0 };
971 bool theAnswer =
false;
986 AudioObjectPropertyAddress pa
988 kAudioDevicePropertyAvailableNominalSampleRates,
989 kAudioObjectPropertyScopeGlobal,
994 err = AudioObjectGetPropertyDataSize(
d, &pa, 0,
nullptr, &listSize);
997 Warn(QString(
"RatesList(): couldn't get data rate list size: [%1]")
1004 ranges.resize(listSize /
sizeof(AudioValueRange));
1005 finalvec.reserve(listSize /
sizeof(AudioValueRange));
1009 Error(
"RatesList(): out of memory?");
1013 err = AudioObjectGetPropertyData(
d, &pa, 0,
nullptr, &listSize, ranges.data());
1016 Warn(QString(
"RatesList(): couldn't get list: [%1]")
1022 UInt32 theFirstIndex;
1023 UInt32 theLastIndex = 0;
1024 for(
auto range : ranges)
1026 theFirstIndex = theLastIndex;
1034 theLastIndex = theFirstIndex;
1042 finalvec.push_back(range.mMinimum);
1044 finalvec.push_back(range.mMaximum);
1054 bool founddigital =
false;
1059 if (streams.empty())
1064 for (
auto stream : streams)
1073 Debug(QString(
"ChannelsList: (passthru) found format: %1")
1077 chans[format.mFormat.mChannelsPerFrame-1] =
true;
1079 if (format.mFormat.mFormatID ==
'IAC3' ||
1080 format.mFormat.mFormatID == kAudioFormat60958AC3)
1086 founddigital =
true;
1094 for (
auto stream : streams)
1101 Debug(QString(
"ChannelsList: (!founddigital) found format: %1")
1104 chans[format.mFormat.mChannelsPerFrame-1] =
true;
1113 AudioComponentDescription desc;
1114 AudioStreamBasicDescription DeviceFormat;
1115 AudioChannelLayout *layout;
1116 AudioChannelLayout new_layout;
1118 AudioObjectPropertyAddress pa
1120 kAudioHardwarePropertyDevices,
1121 kAudioObjectPropertyScopeGlobal,
1125 Debug(
"OpenAnalog: Entering");
1127 desc.componentType = kAudioUnitType_Output;
1130 desc.componentSubType = kAudioUnitSubType_DefaultOutput;
1134 desc.componentSubType = kAudioUnitSubType_HALOutput;
1136 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
1137 desc.componentFlags = 0;
1138 desc.componentFlagsMask = 0;
1141 AudioComponent comp = AudioComponentFindNext(
nullptr, &desc);
1142 if (comp ==
nullptr)
1144 Error(
"OpenAnalog: AudioComponentFindNext failed");
1148 OSErr err = AudioComponentInstanceNew(comp, &
mOutputUnit);
1151 Error(QString(
"OpenAnalog: AudioComponentInstanceNew returned %1")
1158 UInt32 size_hasIO =
sizeof(hasIO);
1160 kAudioOutputUnitProperty_HasIO,
1161 kAudioUnitScope_Output,
1163 &hasIO, &size_hasIO);
1164 Debug(QString(
"OpenAnalog: HasIO (output) = %1").arg(hasIO));
1167 UInt32 enableIO = 1;
1169 kAudioOutputUnitProperty_EnableIO,
1170 kAudioUnitScope_Global,
1172 &enableIO,
sizeof(enableIO));
1175 Warn(QString(
"OpenAnalog: failed enabling IO: %1")
1180 kAudioOutputUnitProperty_HasIO,
1181 kAudioUnitScope_Output,
1183 &hasIO, &size_hasIO);
1184 Debug(QString(
"HasIO = %1").arg(hasIO));
1194 kAudioOutputUnitProperty_CurrentDevice,
1195 kAudioUnitScope_Global,
1200 Error(QString(
"OpenAnalog: Unable to set current device to %1. Error = %2")
1207 UInt32 param_size =
sizeof(AudioStreamBasicDescription);
1210 kAudioUnitProperty_StreamFormat,
1211 kAudioUnitScope_Input,
1217 Warn(QString(
"OpenAnalog: Unable to retrieve current stream format: [%1]")
1222 Debug(QString(
"OpenAnalog: current format is: %1")
1226 pa.mSelector = kAudioDevicePropertyPreferredChannelLayout;
1227 err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
1228 0,
nullptr, ¶m_size);
1232 layout = (AudioChannelLayout *) malloc(param_size);
1234 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
1235 0,
nullptr, ¶m_size, layout);
1238 if(layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
1241 err = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
1242 sizeof(UInt32), &layout->mChannelBitmap,
1246 Warn(
"OpenAnalog: Can't retrieve current channel layout");
1248 else if(layout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions )
1251 err = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
1252 sizeof(AudioChannelLayoutTag),
1253 &layout->mChannelLayoutTag,
1257 Warn(
"OpenAnalog: Can't retrieve current channel layout");
1260 Debug(QString(
"OpenAnalog: Layout of AUHAL has %1 channels")
1261 .arg(layout->mNumberChannelDescriptions));
1263 int channels_found = 0;
1264 for(UInt32 i = 0; i < layout->mNumberChannelDescriptions; i++)
1266 Debug(QString(
"OpenAnalog: this is channel: %1")
1267 .arg(layout->mChannelDescriptions[i].mChannelLabel));
1269 switch( layout->mChannelDescriptions[i].mChannelLabel)
1271 case kAudioChannelLabel_Left:
1272 case kAudioChannelLabel_Right:
1273 case kAudioChannelLabel_Center:
1274 case kAudioChannelLabel_LFEScreen:
1275 case kAudioChannelLabel_LeftSurround:
1276 case kAudioChannelLabel_RightSurround:
1277 case kAudioChannelLabel_RearSurroundLeft:
1278 case kAudioChannelLabel_RearSurroundRight:
1279 case kAudioChannelLabel_CenterSurround:
1283 Debug(QString(
"unrecognized channel form provided by driver: %1")
1284 .arg(layout->mChannelDescriptions[i].mChannelLabel));
1287 if(channels_found == 0)
1289 Warn(
"Audio device is not configured. "
1290 "You should configure your speaker layout with "
1291 "the \"Audio Midi Setup\" utility in /Applications/"
1298 Warn(
"this driver does not support kAudioDevicePropertyPreferredChannelLayout.");
1301 memset (&new_layout, 0,
sizeof(new_layout));
1305 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
1308 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
1312 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_5_1;
1318 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_7_1_A;
1323 kAudioUnitProperty_AudioChannelLayout,
1324 kAudioUnitScope_Input,
1326 &new_layout,
sizeof(new_layout));
1329 Warn(QString(
"OpenAnalog: couldn't set channels layout [%1]")
1333 if(new_layout.mNumberChannelDescriptions > 0)
1334 free(new_layout.mChannelDescriptions);
1341 formatFlags = kLinearPCMFormatFlagIsSignedInteger;
1344 formatFlags = kLinearPCMFormatFlagIsFloat;
1347 formatFlags = kLinearPCMFormatFlagIsSignedInteger;
1351 AudioStreamBasicDescription conv_in_desc;
1352 memset(&conv_in_desc, 0,
sizeof(AudioStreamBasicDescription));
1354 conv_in_desc.mFormatID = kAudioFormatLinearPCM;
1355 conv_in_desc.mFormatFlags = formatFlags |
1356 kAudioFormatFlagsNativeEndian |
1357 kLinearPCMFormatFlagIsPacked;
1360 conv_in_desc.mFramesPerPacket = 1;
1363 conv_in_desc.mBitsPerChannel =
1368 kAudioUnitProperty_StreamFormat,
1369 kAudioUnitScope_Input,
1372 sizeof(AudioStreamBasicDescription));
1375 Error(QString(
"OpenAnalog: AudioUnitSetProperty returned [%1]")
1379 Debug(QString(
"OpenAnalog: set format as %1")
1383 kAudioUnitProperty_StreamFormat,
1384 kAudioUnitScope_Input,
1389 Debug(QString(
"OpenAnalog: the actual set AU format is %1")
1393 AURenderCallbackStruct input;
1395 input.inputProcRefCon =
this;
1398 kAudioUnitProperty_SetRenderCallback,
1399 kAudioUnitScope_Input,
1400 0, &input,
sizeof(input));
1403 Error(QString(
"OpenAnalog: AudioUnitSetProperty (callback) returned [%1]")
1410 ComponentResult res = AudioUnitInitialize(
mOutputUnit);
1413 Error(QString(
"OpenAnalog: AudioUnitInitialize error: [%1]")
1422 Error(QString(
"OpenAnalog: AudioOutputUnitStart error: [%1]")
1434 Debug(QString(
"CloseAnalog: Entering: %1")
1441 Debug(QString(
"CloseAnalog: AudioOutputUnitStop %1")
1447 Debug(QString(
"CloseAnalog: AudioUnitUninitialize %1")
1451 Debug(QString(
"CloseAnalog: CloseComponent %1")
1465 AudioStreamBasicDescription outputFormat {};
1467 Debug(
"OpenSPDIF: Entering");
1470 if (streams.empty())
1472 Warn(
"OpenSPDIF: Couldn't retrieve list of streams");
1476 for (
size_t i = 0; i < streams.size(); ++i)
1485 Debug(QString(
"OpenSPDIF: Considering Physical Format: %1")
1487 if ((format.mFormat.mFormatID ==
'IAC3' ||
1488 format.mFormat.mFormatID == kAudioFormat60958AC3) &&
1491 Debug(
"OpenSPDIF: Found digital format");
1494 outputFormat = format.mFormat;
1498 if (outputFormat.mFormatID)
1502 if (!outputFormat.mFormatID)
1504 Error(QString(
"OpenSPDIF: Couldn't find suitable output"));
1510 AudioObjectPropertyAddress pa
1512 kAudioStreamPropertyPhysicalFormat,
1513 kAudioObjectPropertyScopeGlobal,
1520 err = AudioObjectGetPropertyData(
mStreamID, &pa, 0,
nullptr,
1524 Warn(QString(
"OpenSPDIF - could not retrieve the original streamformat: [%1]")
1553 err = AudioDeviceCreateIOProcID(
mDeviceID,
1558 Error(QString(
"OpenSPDIF: AudioDeviceCreateIOProcID failed: [%1]")
1568 Error(QString(
"OpenSPDIF: AudioDeviceStart failed: [%1]")
1589 Error(QString(
"CloseSPDIF: AudioDeviceStop failed: [%1]")
1599 Error(QString(
"CloseSPDIF: AudioDeviceDestroyIOProcID failed: [%1]")
1613 AudioHardwareUnload();
1621 AudioStreamBasicDescription format)
1623 Debug(QString(
"AudioStreamChangeFormat: %1 -> %2")
1627 AudioObjectPropertyAddress pa
1629 kAudioStreamPropertyPhysicalFormat,
1630 kAudioObjectPropertyScopeGlobal,
1633 OSStatus err = AudioObjectSetPropertyData(s, &pa, 0,
nullptr,
1634 sizeof(format), &format);
1637 Error(QString(
"AudioStreamChangeFormat couldn't set stream format: [%1]")
1651 if (streams.empty())
1654 for (
auto stream : streams)
1662 if (format.mFormat.mFormatID ==
'IAC3' ||
1663 format.mFormat.mFormatID == kAudioFormat60958AC3)
1665 Debug(
"FindAC3Stream: found digital format");
1681 AudioObjectPropertyAddress pa
1683 kAudioHardwarePropertyDevices,
1684 kAudioObjectPropertyScopeGlobal,
1688 OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
1692 Warn(QString(
"GetPropertyDataSize: Unable to retrieve the property sizes. "
1698 std::vector<AudioDeviceID> devices = {};
1699 devices.resize(size /
sizeof(AudioDeviceID));
1700 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
1701 0,
nullptr, &size, devices.data());
1704 Warn(QString(
"GetPropertyData: Unable to retrieve the list of available devices. "
1710 for (
const auto & dev : devices)
1715 if (streams.empty())
1717 for (
auto stream : streams)
1724 AudioStreamBasicDescription currentFormat;
1727 AudioObjectPropertyAddress pa
1729 kAudioStreamPropertyPhysicalFormat,
1730 kAudioObjectPropertyScopeGlobal,
1736 paramSize =
sizeof(currentFormat);
1737 AudioObjectGetPropertyData(s, &pa, 0,
nullptr,
1738 ¶mSize, ¤tFormat);
1741 if (currentFormat.mFormatID ==
'IAC3' ||
1742 currentFormat.mFormatID == kAudioFormat60958AC3)
1751 if (format.mFormat.mFormatID == kAudioFormatLinearPCM)
1754 err = AudioObjectSetPropertyData(s, &pa, 0,
nullptr,
1755 sizeof(format), &(format.mFormat));
1758 Warn(QString(
"ResetStream: could not set physical format: [%1]")
1771 auto *devs =
new QMap<QString, QString>();
1776 AudioObjectPropertyAddress pa
1778 kAudioHardwarePropertyDevices,
1779 kAudioObjectPropertyScopeGlobal,
1783 OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
1787 VBAUDIO(QString(
"GetPropertyDataSize: Unable to retrieve the property sizes. "
1793 UInt32 deviceCount = size /
sizeof(AudioDeviceID);
1794 std::vector<AudioDeviceID> devices = {};
1795 devices.resize(deviceCount);
1796 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
1797 0,
nullptr, &size, devices.data());
1800 VBAUDIO(QString(
"AudioOutputCA::GetDevices: Unable to retrieve the list of "
1801 "available devices. Error [%1]")
1806 VBAUDIO(QString(
"GetDevices: Number of devices: %1").arg(deviceCount));
1808 for (
const auto & dev : devices)
1813 QString *name = device.
GetName();
1816 devs->insert(*name, QString());