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>
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);
399 [[maybe_unused]]
int size)
415 if (audbuf_timecode == 0ms)
427 AudioUnitRenderActionFlags *ioActionFlags,
428 const AudioTimeStamp *inTimeStamp,
429 [[maybe_unused]] UInt32 inBusNumber,
430 [[maybe_unused]] UInt32 inNumberFrames,
431 AudioBufferList *ioData)
435 if (!inst->
RenderAudio((
unsigned char *)(ioData->mBuffers[0].mData),
436 ioData->mBuffers[0].mDataByteSize,
437 inTimeStamp->mHostTime))
440 memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize);
441 *ioActionFlags = kAudioUnitRenderAction_OutputIsSilence;
452 kHALOutputParam_Volume,
453 kAudioUnitScope_Global, 0, &volume))
454 return (
int)lroundf(volume * 100.0F);
462 AudioUnitSetParameter(
d->
mOutputUnit, kHALOutputParam_Volume,
463 kAudioUnitScope_Global, 0, (volume * 0.01F), 0);
468 [[maybe_unused]]
const AudioTimeStamp *inNow,
469 [[maybe_unused]]
const void *inInputData,
470 [[maybe_unused]]
const AudioTimeStamp *inInputTime,
471 AudioBufferList *outOutputData,
472 const AudioTimeStamp *inOutputTime,
477 int index =
d->mStreamIndex;
483 if (
d->mBytesPerPacket > 0 &&
484 outOutputData->mBuffers[index].mDataByteSize >
d->mBytesPerPacket)
486 outOutputData->mBuffers[index].mDataByteSize =
d->mBytesPerPacket;
488 if (!a->
RenderAudio((
unsigned char *)(outOutputData->mBuffers[index].mData),
489 outOutputData->mBuffers[index].mDataByteSize,
490 inOutputTime->mHostTime))
493 memset(outOutputData->mBuffers[index].mData, 0,
494 outOutputData->mBuffers[index].mDataByteSize);
525 if (deviceName !=
"Default Output Device")
527 Warn(QString(
"CoreAudioData: \"%1\" not found, using default device %2.")
531 Debug(QString(
"CoreAudioData: device number is %1")
538 AudioDeviceID deviceID = 0;
539 AudioObjectPropertyAddress pa
541 kAudioHardwarePropertyDevices,
542 kAudioObjectPropertyScopeGlobal,
546 OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
550 Warn(QString(
"GetPropertyDataSize: Unable to retrieve the property sizes. "
556 UInt32 deviceCount = size /
sizeof(AudioDeviceID);
557 std::vector<AudioDeviceID> devices = {};
558 devices.resize(deviceCount);
560 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
561 0,
nullptr, &size, devices.data());
564 Warn(QString(
"GetDeviceWithName: Unable to retrieve the list of available devices. "
570 for (
const auto & dev : devices)
575 QString *name = device.
GetName();
576 if (name && *name == deviceName)
578 Debug(QString(
"GetDeviceWithName: Found: %1").arg(*name));
592 AudioDeviceID deviceId = 0;
593 AudioObjectPropertyAddress pa
595 kAudioHardwarePropertyDefaultOutputDevice,
596 kAudioObjectPropertyScopeGlobal,
601 paramSize =
sizeof(deviceId);
602 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
603 0,
nullptr, ¶mSize, &deviceId);
605 Debug(QString(
"GetDefaultOutputDevice: default device ID = %1").arg(deviceId));
608 Warn(QString(
"GetDefaultOutputDevice: could not get default audio device: [%1]")
621 AudioObjectPropertyAddress pa
623 kAudioDevicePropertyStreamConfiguration,
624 kAudioDevicePropertyScopeOutput,
628 OSStatus err = AudioObjectGetPropertyDataSize(
mDeviceID, &pa,
632 Warn(QString(
"GetTotalOutputChannels: Unable to get "
633 "size of device output channels - id: %1 Error = [%2]")
639 auto *pList = (AudioBufferList *)malloc(size);
640 err = AudioObjectGetPropertyData(
mDeviceID, &pa,
641 0,
nullptr, &size, pList);
644 for (UInt32 buffer = 0; buffer < pList->mNumberBuffers; buffer++)
645 channels += pList->mBuffers[buffer].mNumberChannels;
649 Warn(QString(
"GetTotalOutputChannels: Unable to get "
650 "total device output channels - id: %1 Error = [%2]")
654 Debug(QString(
"GetTotalOutputChannels: Found %1 channels in %2 buffers")
655 .arg(channels).arg(pList->mNumberBuffers));
665 AudioObjectPropertyAddress pa
667 kAudioObjectPropertyName,
668 kAudioObjectPropertyScopeGlobal,
673 UInt32 propertySize =
sizeof(CFStringRef);
674 OSStatus err = AudioObjectGetPropertyData(
mDeviceID, &pa,
675 0,
nullptr, &propertySize, &name);
678 Error(QString(
"AudioObjectGetPropertyData for kAudioObjectPropertyName error: [%1]")
682 char *cname =
new char[CFStringGetLength(name) + 1];
683 CFStringGetCString(name, cname, CFStringGetLength(name) + 1, kCFStringEncodingUTF8);
684 auto *qname =
new QString(cname);
692 UInt32 size =
sizeof(val);
693 AudioObjectPropertyAddress pa
695 kAudioHardwarePropertyHogModeIsAllowed,
696 kAudioObjectPropertyScopeGlobal,
700 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0,
nullptr, &size, &val);
703 Warn(QString(
"GetAutoHogMode: Unable to get auto 'hog' mode. Error = [%1]")
712 UInt32 val = enable ? 1 : 0;
713 AudioObjectPropertyAddress pa
715 kAudioHardwarePropertyHogModeIsAllowed,
716 kAudioObjectPropertyScopeGlobal,
720 OSStatus err = AudioObjectSetPropertyData(kAudioObjectSystemObject, &pa, 0,
nullptr,
724 Warn(QString(
"SetAutoHogMode: Unable to set auto 'hog' mode. Error = [%1]")
732 UInt32 PIDsize =
sizeof(
PID);
733 AudioObjectPropertyAddress pa
735 kAudioDevicePropertyHogMode,
736 kAudioObjectPropertyScopeGlobal,
740 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0,
nullptr,
746 Debug(QString(
"GetHogStatus: unable to check: [%1]")
755 AudioObjectPropertyAddress pa
757 kAudioDevicePropertyHogMode,
758 kAudioObjectPropertyScopeGlobal,
772 Debug(QString(
"SetHogStatus: Setting 'hog' status on device %1")
774 OSStatus err = AudioObjectSetPropertyData(
mDeviceID, &pa, 0,
nullptr,
776 if (err ||
mHog != getpid())
778 Warn(QString(
"SetHogStatus: Unable to set 'hog' status. Error = [%1]")
782 Debug(QString(
"SetHogStatus: Successfully set 'hog' status on device %1")
790 Debug(QString(
"SetHogStatus: Releasing 'hog' status on device %1")
793 OSStatus err = AudioObjectSetPropertyData(
mDeviceID, &pa, 0,
nullptr,
794 sizeof(hogPid), &hogPid);
795 if (err || hogPid == getpid())
797 Warn(QString(
"SetHogStatus: Unable to release 'hog' status. Error = [%1]")
814 UInt32 mixEnable = mix ? 1 : 0;
815 Debug(QString(
"SetMixingSupport: %1abling mixing for device %2")
816 .arg(mix ?
"En" :
"Dis")
819 AudioObjectPropertyAddress pa
821 kAudioDevicePropertySupportsMixing,
822 kAudioObjectPropertyScopeGlobal,
825 OSStatus err = AudioObjectSetPropertyData(
mDeviceID, &pa, 0,
nullptr,
826 sizeof(mixEnable), &mixEnable);
829 Warn(QString(
"SetMixingSupport: Unable to set MixingSupport to %1. Error = [%2]")
830 .arg(mix ?
"'On'" :
"'Off'")
844 UInt32 size =
sizeof(val);
845 AudioObjectPropertyAddress pa
847 kAudioDevicePropertySupportsMixing,
848 kAudioObjectPropertyScopeGlobal,
851 OSStatus err = AudioObjectGetPropertyData(
mDeviceID, &pa, 0,
nullptr,
867 AudioObjectPropertyAddress pa
869 kAudioDevicePropertyStreams,
870 kAudioObjectPropertyScopeGlobal,
874 err = AudioObjectGetPropertyDataSize(
d, &pa,
875 0,
nullptr, &listSize);
878 Error(QString(
"StreamsList: could not get list size: [%1]")
886 vec.resize(listSize /
sizeof(AudioStreamID));
890 Error(
"StreamsList(): out of memory?");
894 err = AudioObjectGetPropertyData(
d, &pa,
895 0,
nullptr, &listSize, vec.data());
898 Error(QString(
"StreamsList: could not get list: [%1]")
912 AudioObjectPropertyAddress pa
915 kAudioStreamPropertyAvailablePhysicalFormats,
916 kAudioObjectPropertyScopeGlobal,
921 err = AudioObjectGetPropertyDataSize(s, &pa, 0,
nullptr, &listSize);
924 Warn(QString(
"FormatsList(): couldn't get list size: [%1]")
931 vec.resize(listSize /
sizeof(AudioStreamRangedDescription));
935 Error(
"FormatsList(): out of memory?");
939 err = AudioObjectGetPropertyData(s, &pa, 0,
nullptr, &listSize, vec.data());
942 Warn(QString(
"FormatsList: couldn't get list: [%1]")
952 8000.0, 11025.0, 12000.0,
953 16000.0, 22050.0, 24000.0,
954 32000.0, 44100.0, 48000.0,
955 64000.0, 88200.0, 96000.0,
956 128000.0, 176400.0, 192000.0 };
960 bool theAnswer =
false;
975 AudioObjectPropertyAddress pa
977 kAudioDevicePropertyAvailableNominalSampleRates,
978 kAudioObjectPropertyScopeGlobal,
983 err = AudioObjectGetPropertyDataSize(
d, &pa, 0,
nullptr, &listSize);
986 Warn(QString(
"RatesList(): couldn't get data rate list size: [%1]")
993 ranges.resize(listSize /
sizeof(AudioValueRange));
994 finalvec.reserve(listSize /
sizeof(AudioValueRange));
998 Error(
"RatesList(): out of memory?");
1002 err = AudioObjectGetPropertyData(
d, &pa, 0,
nullptr, &listSize, ranges.data());
1005 Warn(QString(
"RatesList(): couldn't get list: [%1]")
1011 UInt32 theFirstIndex;
1012 UInt32 theLastIndex = 0;
1013 for(
auto range : ranges)
1015 theFirstIndex = theLastIndex;
1023 theLastIndex = theFirstIndex;
1031 finalvec.push_back(range.mMinimum);
1033 finalvec.push_back(range.mMaximum);
1043 bool founddigital =
false;
1048 if (streams.empty())
1053 for (
auto stream : streams)
1062 Debug(QString(
"ChannelsList: (passthru) found format: %1")
1066 chans[format.mFormat.mChannelsPerFrame-1] =
true;
1068 if (format.mFormat.mFormatID ==
'IAC3' ||
1069 format.mFormat.mFormatID == kAudioFormat60958AC3)
1075 founddigital =
true;
1083 for (
auto stream : streams)
1090 Debug(QString(
"ChannelsList: (!founddigital) found format: %1")
1093 chans[format.mFormat.mChannelsPerFrame-1] =
true;
1102 AudioComponentDescription desc;
1103 AudioStreamBasicDescription DeviceFormat;
1104 AudioChannelLayout *layout;
1105 AudioChannelLayout new_layout;
1107 AudioObjectPropertyAddress pa
1109 kAudioHardwarePropertyDevices,
1110 kAudioObjectPropertyScopeGlobal,
1114 Debug(
"OpenAnalog: Entering");
1116 desc.componentType = kAudioUnitType_Output;
1119 desc.componentSubType = kAudioUnitSubType_DefaultOutput;
1123 desc.componentSubType = kAudioUnitSubType_HALOutput;
1125 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
1126 desc.componentFlags = 0;
1127 desc.componentFlagsMask = 0;
1130 AudioComponent comp = AudioComponentFindNext(
nullptr, &desc);
1131 if (comp ==
nullptr)
1133 Error(
"OpenAnalog: AudioComponentFindNext failed");
1137 OSErr err = AudioComponentInstanceNew(comp, &
mOutputUnit);
1140 Error(QString(
"OpenAnalog: AudioComponentInstanceNew returned %1")
1147 UInt32 size_hasIO =
sizeof(hasIO);
1149 kAudioOutputUnitProperty_HasIO,
1150 kAudioUnitScope_Output,
1152 &hasIO, &size_hasIO);
1153 Debug(QString(
"OpenAnalog: HasIO (output) = %1").arg(hasIO));
1156 UInt32 enableIO = 1;
1158 kAudioOutputUnitProperty_EnableIO,
1159 kAudioUnitScope_Global,
1161 &enableIO,
sizeof(enableIO));
1164 Warn(QString(
"OpenAnalog: failed enabling IO: %1")
1169 kAudioOutputUnitProperty_HasIO,
1170 kAudioUnitScope_Output,
1172 &hasIO, &size_hasIO);
1173 Debug(QString(
"HasIO = %1").arg(hasIO));
1183 kAudioOutputUnitProperty_CurrentDevice,
1184 kAudioUnitScope_Global,
1189 Error(QString(
"OpenAnalog: Unable to set current device to %1. Error = %2")
1196 UInt32 param_size =
sizeof(AudioStreamBasicDescription);
1199 kAudioUnitProperty_StreamFormat,
1200 kAudioUnitScope_Input,
1206 Warn(QString(
"OpenAnalog: Unable to retrieve current stream format: [%1]")
1211 Debug(QString(
"OpenAnalog: current format is: %1")
1215 pa.mSelector = kAudioDevicePropertyPreferredChannelLayout;
1216 err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
1217 0,
nullptr, ¶m_size);
1221 layout = (AudioChannelLayout *) malloc(param_size);
1223 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
1224 0,
nullptr, ¶m_size, layout);
1227 if(layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
1230 err = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
1231 sizeof(UInt32), &layout->mChannelBitmap,
1235 Warn(
"OpenAnalog: Can't retrieve current channel layout");
1237 else if(layout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions )
1240 err = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
1241 sizeof(AudioChannelLayoutTag),
1242 &layout->mChannelLayoutTag,
1246 Warn(
"OpenAnalog: Can't retrieve current channel layout");
1249 Debug(QString(
"OpenAnalog: Layout of AUHAL has %1 channels")
1250 .arg(layout->mNumberChannelDescriptions));
1252 int channels_found = 0;
1253 for(UInt32 i = 0; i < layout->mNumberChannelDescriptions; i++)
1255 Debug(QString(
"OpenAnalog: this is channel: %1")
1256 .arg(layout->mChannelDescriptions[i].mChannelLabel));
1258 switch( layout->mChannelDescriptions[i].mChannelLabel)
1260 case kAudioChannelLabel_Left:
1261 case kAudioChannelLabel_Right:
1262 case kAudioChannelLabel_Center:
1263 case kAudioChannelLabel_LFEScreen:
1264 case kAudioChannelLabel_LeftSurround:
1265 case kAudioChannelLabel_RightSurround:
1266 case kAudioChannelLabel_RearSurroundLeft:
1267 case kAudioChannelLabel_RearSurroundRight:
1268 case kAudioChannelLabel_CenterSurround:
1272 Debug(QString(
"unrecognized channel form provided by driver: %1")
1273 .arg(layout->mChannelDescriptions[i].mChannelLabel));
1276 if(channels_found == 0)
1278 Warn(
"Audio device is not configured. "
1279 "You should configure your speaker layout with "
1280 "the \"Audio Midi Setup\" utility in /Applications/"
1287 Warn(
"this driver does not support kAudioDevicePropertyPreferredChannelLayout.");
1290 memset (&new_layout, 0,
sizeof(new_layout));
1294 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
1297 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
1301 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_5_1;
1307 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_7_1_A;
1312 kAudioUnitProperty_AudioChannelLayout,
1313 kAudioUnitScope_Input,
1315 &new_layout,
sizeof(new_layout));
1318 Warn(QString(
"OpenAnalog: couldn't set channels layout [%1]")
1322 if(new_layout.mNumberChannelDescriptions > 0)
1323 free(new_layout.mChannelDescriptions);
1330 formatFlags = kLinearPCMFormatFlagIsSignedInteger;
1333 formatFlags = kLinearPCMFormatFlagIsFloat;
1336 formatFlags = kLinearPCMFormatFlagIsSignedInteger;
1340 AudioStreamBasicDescription conv_in_desc;
1341 memset(&conv_in_desc, 0,
sizeof(AudioStreamBasicDescription));
1343 conv_in_desc.mFormatID = kAudioFormatLinearPCM;
1344 conv_in_desc.mFormatFlags = formatFlags |
1345 kAudioFormatFlagsNativeEndian |
1346 kLinearPCMFormatFlagIsPacked;
1349 conv_in_desc.mFramesPerPacket = 1;
1352 conv_in_desc.mBitsPerChannel =
1357 kAudioUnitProperty_StreamFormat,
1358 kAudioUnitScope_Input,
1361 sizeof(AudioStreamBasicDescription));
1364 Error(QString(
"OpenAnalog: AudioUnitSetProperty returned [%1]")
1368 Debug(QString(
"OpenAnalog: set format as %1")
1372 kAudioUnitProperty_StreamFormat,
1373 kAudioUnitScope_Input,
1378 Debug(QString(
"OpenAnalog: the actual set AU format is %1")
1382 AURenderCallbackStruct input;
1384 input.inputProcRefCon =
this;
1387 kAudioUnitProperty_SetRenderCallback,
1388 kAudioUnitScope_Input,
1389 0, &input,
sizeof(input));
1392 Error(QString(
"OpenAnalog: AudioUnitSetProperty (callback) returned [%1]")
1399 ComponentResult res = AudioUnitInitialize(
mOutputUnit);
1402 Error(QString(
"OpenAnalog: AudioUnitInitialize error: [%1]")
1411 Error(QString(
"OpenAnalog: AudioOutputUnitStart error: [%1]")
1423 Debug(QString(
"CloseAnalog: Entering: %1")
1430 Debug(QString(
"CloseAnalog: AudioOutputUnitStop %1")
1436 Debug(QString(
"CloseAnalog: AudioUnitUninitialize %1")
1440 Debug(QString(
"CloseAnalog: CloseComponent %1")
1454 AudioStreamBasicDescription outputFormat {};
1456 Debug(
"OpenSPDIF: Entering");
1459 if (streams.empty())
1461 Warn(
"OpenSPDIF: Couldn't retrieve list of streams");
1465 for (
size_t i = 0; i < streams.size(); ++i)
1474 Debug(QString(
"OpenSPDIF: Considering Physical Format: %1")
1476 if ((format.mFormat.mFormatID ==
'IAC3' ||
1477 format.mFormat.mFormatID == kAudioFormat60958AC3) &&
1480 Debug(
"OpenSPDIF: Found digital format");
1483 outputFormat = format.mFormat;
1487 if (outputFormat.mFormatID)
1491 if (!outputFormat.mFormatID)
1493 Error(QString(
"OpenSPDIF: Couldn't find suitable output"));
1499 AudioObjectPropertyAddress pa
1501 kAudioStreamPropertyPhysicalFormat,
1502 kAudioObjectPropertyScopeGlobal,
1509 err = AudioObjectGetPropertyData(
mStreamID, &pa, 0,
nullptr,
1513 Warn(QString(
"OpenSPDIF - could not retrieve the original streamformat: [%1]")
1542 err = AudioDeviceCreateIOProcID(
mDeviceID,
1547 Error(QString(
"OpenSPDIF: AudioDeviceCreateIOProcID failed: [%1]")
1557 Error(QString(
"OpenSPDIF: AudioDeviceStart failed: [%1]")
1578 Error(QString(
"CloseSPDIF: AudioDeviceStop failed: [%1]")
1588 Error(QString(
"CloseSPDIF: AudioDeviceDestroyIOProcID failed: [%1]")
1602 AudioHardwareUnload();
1610 AudioStreamBasicDescription format)
1612 Debug(QString(
"AudioStreamChangeFormat: %1 -> %2")
1616 AudioObjectPropertyAddress pa
1618 kAudioStreamPropertyPhysicalFormat,
1619 kAudioObjectPropertyScopeGlobal,
1622 OSStatus err = AudioObjectSetPropertyData(s, &pa, 0,
nullptr,
1623 sizeof(format), &format);
1626 Error(QString(
"AudioStreamChangeFormat couldn't set stream format: [%1]")
1640 if (streams.empty())
1643 for (
auto stream : streams)
1651 if (format.mFormat.mFormatID ==
'IAC3' ||
1652 format.mFormat.mFormatID == kAudioFormat60958AC3)
1654 Debug(
"FindAC3Stream: found digital format");
1670 AudioObjectPropertyAddress pa
1672 kAudioHardwarePropertyDevices,
1673 kAudioObjectPropertyScopeGlobal,
1677 OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
1681 Warn(QString(
"GetPropertyDataSize: Unable to retrieve the property sizes. "
1687 std::vector<AudioDeviceID> devices = {};
1688 devices.resize(size /
sizeof(AudioDeviceID));
1689 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
1690 0,
nullptr, &size, devices.data());
1693 Warn(QString(
"GetPropertyData: Unable to retrieve the list of available devices. "
1699 for (
const auto & dev : devices)
1704 if (streams.empty())
1706 for (
auto stream : streams)
1713 AudioStreamBasicDescription currentFormat;
1716 AudioObjectPropertyAddress pa
1718 kAudioStreamPropertyPhysicalFormat,
1719 kAudioObjectPropertyScopeGlobal,
1725 paramSize =
sizeof(currentFormat);
1726 AudioObjectGetPropertyData(s, &pa, 0,
nullptr,
1727 ¶mSize, ¤tFormat);
1730 if (currentFormat.mFormatID ==
'IAC3' ||
1731 currentFormat.mFormatID == kAudioFormat60958AC3)
1740 if (format.mFormat.mFormatID == kAudioFormatLinearPCM)
1743 err = AudioObjectSetPropertyData(s, &pa, 0,
nullptr,
1744 sizeof(format), &(format.mFormat));
1747 Warn(QString(
"ResetStream: could not set physical format: [%1]")
1760 auto *devs =
new QMap<QString, QString>();
1765 AudioObjectPropertyAddress pa
1767 kAudioHardwarePropertyDevices,
1768 kAudioObjectPropertyScopeGlobal,
1772 OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
1776 VBAUDIO(QString(
"GetPropertyDataSize: Unable to retrieve the property sizes. "
1782 UInt32 deviceCount = size /
sizeof(AudioDeviceID);
1783 std::vector<AudioDeviceID> devices = {};
1784 devices.resize(deviceCount);
1785 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
1786 0,
nullptr, &size, devices.data());
1789 VBAUDIO(QString(
"AudioOutputCA::GetDevices: Unable to retrieve the list of "
1790 "available devices. Error [%1]")
1795 VBAUDIO(QString(
"GetDevices: Number of devices: %1").arg(deviceCount));
1797 for (
const auto & dev : devices)
1802 QString *name = device.
GetName();
1805 devs->insert(*name, QString());