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>
34 #define LOC QString("CoreAudio: ")
36 #define CHANNELS_MIN 1
37 #define CHANNELS_MAX 8
45 #define OSS_STATUS(x) UInt32ToFourCC((UInt32*)&(x))
49 char* pIn = (
char*)&inVal;
50 static char fourCC[5];
61 UInt32 formatId = desc.mFormatID;
65 switch (desc.mFormatID)
67 case kAudioFormatLinearPCM:
68 str = QString(
"[%1] %2%3 Channel %4-bit %5 %6 (%7Hz) %8 Channels")
70 .arg((desc.mFormatFlags & kAudioFormatFlagIsNonMixable) ?
"" :
"Mixable ")
71 .arg(desc.mChannelsPerFrame)
72 .arg(desc.mBitsPerChannel)
73 .arg((desc.mFormatFlags & kAudioFormatFlagIsFloat) ?
"Floating Point" :
"Signed Integer")
74 .arg((desc.mFormatFlags & kAudioFormatFlagIsBigEndian) ?
"BE" :
"LE")
75 .arg((UInt32)desc.mSampleRate)
76 .arg(desc.mChannelsPerFrame);
79 str = QString(
"[%1] AC-3/DTS (%2Hz) %3 Channels")
81 .arg((UInt32)desc.mSampleRate)
82 .arg(desc.mChannelsPerFrame);
84 case kAudioFormat60958AC3:
85 str = QString(
"[%1] AC-3/DTS for S/PDIF %2 (%3Hz) %4 Channels")
87 .arg((desc.mFormatFlags & kAudioFormatFlagIsBigEndian) ?
"BE" :
"LE")
88 .arg((UInt32)desc.mSampleRate)
89 .arg(desc.mChannelsPerFrame);
92 str = QString(
"[%1]").arg(fourCC);
136 AudioStreamBasicDescription format);
163 AudioUnitRenderActionFlags *ioActionFlags,
164 const AudioTimeStamp *inTimeStamp,
166 UInt32 inNumberFrames,
167 AudioBufferList *ioData);
169 const AudioTimeStamp *inNow,
170 const void *inInputData,
171 const AudioTimeStamp *inInputTime,
172 AudioBufferList *outOutputData,
173 const AudioTimeStamp *inOutputTime,
184 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"AudioOutputCA::AudioOutputCA searching %1").arg(
m_mainDevice));
209 settings->AddSupportedRate(48000);
213 while (
int rate = settings->GetNextRate())
215 for (
auto entry : rates)
219 settings->AddSupportedRate(entry);
232 settings->AddSupportedChannels(2);
240 LOG(VB_AUDIO, LOG_INFO, QString(
"AudioOutputCA::Support %1 channels").arg(i));
242 if (i == 8 && !channels[6-1])
243 settings->AddSupportedChannels(6);
244 settings->AddSupportedChannels(i);
251 settings->setPassthrough(1);
258 bool deviceOpened =
false;
263 LOG(VB_AUDIO, LOG_INFO,
"AudioOutputCA::OpenDevice: Entering");
266 LOG(VB_AUDIO, LOG_INFO,
"AudioOutputCA::OpenDevice() Trying Digital.");
273 LOG(VB_AUDIO, LOG_INFO,
"AudioOutputCA::OpenDevice() Trying Analog.");
278 LOG(VB_AUDIO, LOG_INFO, QString(
"AudioOutputCA::OpenDevice: OpenAnalog = %1").arg(result));
285 deviceOpened = (result > 0);
290 LOG(VB_GENERAL, LOG_ERR,
"AudioOutputCA Error: Couldn't open any audio device!");
298 controlLabel +=
"MixerVolume";
307 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"CloseDevice [%1]: Entering")
315 template <
class AudioDataType>
320 AudioDataType tmpRLs;
321 AudioDataType tmpRRs;
323 for (
uint i = 0; i < frames; i++)
325 buf = buf2 = buf + 4;
350 int size,
unsigned long long timestamp)
366 if (written_size && (size > written_size))
369 memset(aubuf + written_size, 0, size - written_size);
379 UInt64 nanos = AudioConvertHostTimeToNanos(timestamp -
380 AudioGetCurrentHostTime());
385 return (written_size > 0);
390 [[maybe_unused]]
int size)
406 if (audbuf_timecode == 0ms)
418 AudioUnitRenderActionFlags *ioActionFlags,
419 const AudioTimeStamp *inTimeStamp,
420 [[maybe_unused]] UInt32 inBusNumber,
421 [[maybe_unused]] UInt32 inNumberFrames,
422 AudioBufferList *ioData)
426 if (!inst->
RenderAudio((
unsigned char *)(ioData->mBuffers[0].mData),
427 ioData->mBuffers[0].mDataByteSize,
428 inTimeStamp->mHostTime))
431 memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize);
432 *ioActionFlags = kAudioUnitRenderAction_OutputIsSilence;
443 kHALOutputParam_Volume,
444 kAudioUnitScope_Global, 0, &volume))
445 return (
int)lroundf(volume * 100.0F);
453 AudioUnitSetParameter(
d->
mOutputUnit, kHALOutputParam_Volume,
454 kAudioUnitScope_Global, 0, (volume * 0.01F), 0);
459 [[maybe_unused]]
const AudioTimeStamp *inNow,
460 [[maybe_unused]]
const void *inInputData,
461 [[maybe_unused]]
const AudioTimeStamp *inInputTime,
462 AudioBufferList *outOutputData,
463 const AudioTimeStamp *inOutputTime,
468 int index =
d->mStreamIndex;
474 if (
d->mBytesPerPacket > 0 &&
475 outOutputData->mBuffers[index].mDataByteSize >
d->mBytesPerPacket)
477 outOutputData->mBuffers[index].mDataByteSize =
d->mBytesPerPacket;
479 if (!a->
RenderAudio((
unsigned char *)(outOutputData->mBuffers[index].mData),
480 outOutputData->mBuffers[index].mDataByteSize,
481 inOutputTime->mHostTime))
484 memset(outOutputData->mBuffers[index].mData, 0,
485 outOutputData->mBuffers[index].mDataByteSize);
516 if (deviceName !=
"Default Output Device")
518 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:CoreAudioData: \"%1\" not found, using default device %2.")
522 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::CoreAudioData: device number is %1")
529 AudioDeviceID deviceID = 0;
530 AudioObjectPropertyAddress pa
532 kAudioHardwarePropertyDevices,
533 kAudioObjectPropertyScopeGlobal,
537 OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
541 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:GetPropertyDataSize: Unable to retrieve the property sizes. "
547 UInt32 deviceCount = size /
sizeof(AudioDeviceID);
548 std::vector<AudioDeviceID> devices = {};
549 devices.resize(deviceCount);
551 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
552 0,
nullptr, &size, devices.data());
555 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:GetDeviceWithName: Unable to retrieve the list of available devices. "
561 for (
const auto & dev : devices)
566 QString *name = device.
GetName();
567 if (name && *name == deviceName)
569 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::GetDeviceWithName: Found: %1").arg(*name));
583 AudioDeviceID deviceId = 0;
584 AudioObjectPropertyAddress pa
586 kAudioHardwarePropertyDefaultOutputDevice,
587 kAudioObjectPropertyScopeGlobal,
592 paramSize =
sizeof(deviceId);
593 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
594 0,
nullptr, ¶mSize, &deviceId);
596 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::GetDefaultOutputDevice: default device ID = %1").arg(deviceId));
599 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:GetDefaultOutputDevice: could not get default audio device: [%1]")
612 AudioObjectPropertyAddress pa
614 kAudioDevicePropertyStreamConfiguration,
615 kAudioDevicePropertyScopeOutput,
619 OSStatus err = AudioObjectGetPropertyDataSize(
mDeviceID, &pa,
623 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:GetTotalOutputChannels: Unable to get "
624 "size of device output channels - id: %1 Error = [%2]")
630 auto *pList = (AudioBufferList *)malloc(size);
631 err = AudioObjectGetPropertyData(
mDeviceID, &pa,
632 0,
nullptr, &size, pList);
635 for (UInt32 buffer = 0; buffer < pList->mNumberBuffers; buffer++)
636 channels += pList->mBuffers[buffer].mNumberChannels;
640 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:GetTotalOutputChannels: Unable to get "
641 "total device output channels - id: %1 Error = [%2]")
645 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::GetTotalOutputChannels: Found %1 channels in %2 buffers")
646 .arg(channels).arg(pList->mNumberBuffers));
656 AudioObjectPropertyAddress pa
658 kAudioObjectPropertyName,
659 kAudioObjectPropertyScopeGlobal,
664 UInt32 propertySize =
sizeof(CFStringRef);
665 OSStatus err = AudioObjectGetPropertyData(
mDeviceID, &pa,
666 0,
nullptr, &propertySize, &name);
669 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:AudioObjectGetPropertyData for kAudioObjectPropertyName error: [%1]")
673 char *cname =
new char[CFStringGetLength(name) + 1];
674 CFStringGetCString(name, cname, CFStringGetLength(name) + 1, kCFStringEncodingUTF8);
675 auto *qname =
new QString(cname);
683 UInt32 size =
sizeof(val);
684 AudioObjectPropertyAddress pa
686 kAudioHardwarePropertyHogModeIsAllowed,
687 kAudioObjectPropertyScopeGlobal,
691 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0,
nullptr, &size, &val);
694 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:GetAutoHogMode: Unable to get auto 'hog' mode. Error = [%1]")
703 UInt32 val = enable ? 1 : 0;
704 AudioObjectPropertyAddress pa
706 kAudioHardwarePropertyHogModeIsAllowed,
707 kAudioObjectPropertyScopeGlobal,
711 OSStatus err = AudioObjectSetPropertyData(kAudioObjectSystemObject, &pa, 0,
nullptr,
715 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:SetAutoHogMode: Unable to set auto 'hog' mode. Error = [%1]")
723 UInt32 PIDsize =
sizeof(
PID);
724 AudioObjectPropertyAddress pa
726 kAudioDevicePropertyHogMode,
727 kAudioObjectPropertyScopeGlobal,
731 OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0,
nullptr,
737 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::GetHogStatus: unable to check: [%1]")
746 AudioObjectPropertyAddress pa
748 kAudioDevicePropertyHogMode,
749 kAudioObjectPropertyScopeGlobal,
763 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::SetHogStatus: Setting 'hog' status on device %1")
765 OSStatus err = AudioObjectSetPropertyData(
mDeviceID, &pa, 0,
nullptr,
767 if (err ||
mHog != getpid())
769 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:SetHogStatus: Unable to set 'hog' status. Error = [%1]")
773 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::SetHogStatus: Successfully set 'hog' status on device %1")
781 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::SetHogStatus: Releasing 'hog' status on device %1")
784 OSStatus err = AudioObjectSetPropertyData(
mDeviceID, &pa, 0,
nullptr,
785 sizeof(hogPid), &hogPid);
786 if (err || hogPid == getpid())
788 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:SetHogStatus: Unable to release 'hog' status. Error = [%1]")
805 UInt32 mixEnable = mix ? 1 : 0;
806 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::SetMixingSupport: %1abling mixing for device %2")
807 .arg(mix ?
"En" :
"Dis")
810 AudioObjectPropertyAddress pa
812 kAudioDevicePropertySupportsMixing,
813 kAudioObjectPropertyScopeGlobal,
816 OSStatus err = AudioObjectSetPropertyData(
mDeviceID, &pa, 0,
nullptr,
817 sizeof(mixEnable), &mixEnable);
820 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:SetMixingSupport: Unable to set MixingSupport to %1. Error = [%2]")
821 .arg(mix ?
"'On'" :
"'Off'")
835 UInt32 size =
sizeof(val);
836 AudioObjectPropertyAddress pa
838 kAudioDevicePropertySupportsMixing,
839 kAudioObjectPropertyScopeGlobal,
842 OSStatus err = AudioObjectGetPropertyData(
mDeviceID, &pa, 0,
nullptr,
858 AudioObjectPropertyAddress pa
860 kAudioDevicePropertyStreams,
861 kAudioObjectPropertyScopeGlobal,
865 err = AudioObjectGetPropertyDataSize(
d, &pa,
866 0,
nullptr, &listSize);
869 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:StreamsList: could not get list size: [%1]")
877 vec.resize(listSize /
sizeof(AudioStreamID));
881 LOG(VB_GENERAL, LOG_ERR,
"CoreAudioData Error:StreamsList(): out of memory?");
885 err = AudioObjectGetPropertyData(
d, &pa,
886 0,
nullptr, &listSize, vec.data());
889 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:StreamsList: could not get list: [%1]")
903 AudioObjectPropertyAddress pa
906 kAudioStreamPropertyAvailablePhysicalFormats,
907 kAudioObjectPropertyScopeGlobal,
912 err = AudioObjectGetPropertyDataSize(s, &pa, 0,
nullptr, &listSize);
915 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:FormatsList(): couldn't get list size: [%1]")
922 vec.resize(listSize /
sizeof(AudioStreamRangedDescription));
926 LOG(VB_GENERAL, LOG_ERR,
"CoreAudioData Error:FormatsList(): out of memory?");
930 err = AudioObjectGetPropertyData(s, &pa, 0,
nullptr, &listSize, vec.data());
933 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:FormatsList: couldn't get list: [%1]")
943 8000.0, 11025.0, 12000.0,
944 16000.0, 22050.0, 24000.0,
945 32000.0, 44100.0, 48000.0,
946 64000.0, 88200.0, 96000.0,
947 128000.0, 176400.0, 192000.0 };
951 bool theAnswer =
false;
966 AudioObjectPropertyAddress pa
968 kAudioDevicePropertyAvailableNominalSampleRates,
969 kAudioObjectPropertyScopeGlobal,
974 err = AudioObjectGetPropertyDataSize(
d, &pa, 0,
nullptr, &listSize);
977 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:RatesList(): couldn't get data rate list size: [%1]")
984 ranges.resize(listSize /
sizeof(AudioValueRange));
985 finalvec.reserve(listSize /
sizeof(AudioValueRange));
989 LOG(VB_GENERAL, LOG_ERR,
"CoreAudioData Error:RatesList(): out of memory?");
993 err = AudioObjectGetPropertyData(
d, &pa, 0,
nullptr, &listSize, ranges.data());
996 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:RatesList(): couldn't get list: [%1]")
1002 UInt32 theFirstIndex;
1003 UInt32 theLastIndex = 0;
1004 for(
auto range : ranges)
1006 theFirstIndex = theLastIndex;
1014 theLastIndex = theFirstIndex;
1022 finalvec.push_back(range.mMinimum);
1024 finalvec.push_back(range.mMaximum);
1034 bool founddigital =
false;
1039 if (streams.empty())
1044 for (
auto stream : streams)
1053 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::ChannelsList: (passthru) found format: %1")
1057 chans[format.mFormat.mChannelsPerFrame-1] =
true;
1059 if (format.mFormat.mFormatID ==
'IAC3' ||
1060 format.mFormat.mFormatID == kAudioFormat60958AC3)
1066 founddigital =
true;
1074 for (
auto stream : streams)
1081 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::ChannelsList: (!founddigital) found format: %1")
1084 chans[format.mFormat.mChannelsPerFrame-1] =
true;
1093 AudioComponentDescription desc;
1094 AudioStreamBasicDescription DeviceFormat;
1095 AudioChannelLayout *layout;
1096 AudioChannelLayout new_layout;
1098 AudioObjectPropertyAddress pa
1100 kAudioHardwarePropertyDevices,
1101 kAudioObjectPropertyScopeGlobal,
1105 LOG(VB_AUDIO, LOG_INFO,
"CoreAudioData::OpenAnalog: Entering");
1107 desc.componentType = kAudioUnitType_Output;
1110 desc.componentSubType = kAudioUnitSubType_DefaultOutput;
1114 desc.componentSubType = kAudioUnitSubType_HALOutput;
1116 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
1117 desc.componentFlags = 0;
1118 desc.componentFlagsMask = 0;
1121 AudioComponent comp = AudioComponentFindNext(
nullptr, &desc);
1122 if (comp ==
nullptr)
1124 LOG(VB_GENERAL, LOG_ERR,
"CoreAudioData Error:OpenAnalog: AudioComponentFindNext failed");
1128 OSErr err = AudioComponentInstanceNew(comp, &
mOutputUnit);
1131 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:OpenAnalog: AudioComponentInstanceNew returned %1")
1138 UInt32 size_hasIO =
sizeof(hasIO);
1140 kAudioOutputUnitProperty_HasIO,
1141 kAudioUnitScope_Output,
1143 &hasIO, &size_hasIO);
1144 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::OpenAnalog: HasIO (output) = %1").arg(hasIO));
1147 UInt32 enableIO = 1;
1149 kAudioOutputUnitProperty_EnableIO,
1150 kAudioUnitScope_Global,
1152 &enableIO,
sizeof(enableIO));
1155 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:OpenAnalog: failed enabling IO: %1")
1160 kAudioOutputUnitProperty_HasIO,
1161 kAudioUnitScope_Output,
1163 &hasIO, &size_hasIO);
1164 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::HasIO = %1").arg(hasIO));
1174 kAudioOutputUnitProperty_CurrentDevice,
1175 kAudioUnitScope_Global,
1180 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:OpenAnalog: Unable to set current device to %1. Error = %2")
1187 UInt32 param_size =
sizeof(AudioStreamBasicDescription);
1190 kAudioUnitProperty_StreamFormat,
1191 kAudioUnitScope_Input,
1197 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:OpenAnalog: Unable to retrieve current stream format: [%1]")
1202 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::OpenAnalog: current format is: %1")
1206 pa.mSelector = kAudioDevicePropertyPreferredChannelLayout;
1207 err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
1208 0,
nullptr, ¶m_size);
1212 layout = (AudioChannelLayout *) malloc(param_size);
1214 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
1215 0,
nullptr, ¶m_size, layout);
1218 if(layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
1221 err = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
1222 sizeof(UInt32), &layout->mChannelBitmap,
1226 LOG(VB_GENERAL, LOG_WARNING,
"CoreAudioData Warning:OpenAnalog: Can't retrieve current channel layout");
1228 else if(layout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions )
1231 err = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
1232 sizeof(AudioChannelLayoutTag),
1233 &layout->mChannelLayoutTag,
1237 LOG(VB_GENERAL, LOG_WARNING,
"CoreAudioData Warning:OpenAnalog: Can't retrieve current channel layout");
1240 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::OpenAnalog: Layout of AUHAL has %1 channels")
1241 .arg(layout->mNumberChannelDescriptions));
1243 int channels_found = 0;
1244 for(UInt32 i = 0; i < layout->mNumberChannelDescriptions; i++)
1246 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::OpenAnalog: this is channel: %1")
1247 .arg(layout->mChannelDescriptions[i].mChannelLabel));
1249 switch( layout->mChannelDescriptions[i].mChannelLabel)
1251 case kAudioChannelLabel_Left:
1252 case kAudioChannelLabel_Right:
1253 case kAudioChannelLabel_Center:
1254 case kAudioChannelLabel_LFEScreen:
1255 case kAudioChannelLabel_LeftSurround:
1256 case kAudioChannelLabel_RightSurround:
1257 case kAudioChannelLabel_RearSurroundLeft:
1258 case kAudioChannelLabel_RearSurroundRight:
1259 case kAudioChannelLabel_CenterSurround:
1263 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::unrecognized channel form provided by driver: %1")
1264 .arg(layout->mChannelDescriptions[i].mChannelLabel));
1267 if(channels_found == 0)
1269 LOG(VB_GENERAL, LOG_WARNING,
"CoreAudioData Warning:Audio device is not configured. "
1270 "You should configure your speaker layout with "
1271 "the \"Audio Midi Setup\" utility in /Applications/"
1278 LOG(VB_GENERAL, LOG_WARNING,
"CoreAudioData Warning:this driver does not support kAudioDevicePropertyPreferredChannelLayout.");
1281 memset (&new_layout, 0,
sizeof(new_layout));
1285 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
1288 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
1292 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_5_1;
1298 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_7_1_A;
1303 kAudioUnitProperty_AudioChannelLayout,
1304 kAudioUnitScope_Input,
1306 &new_layout,
sizeof(new_layout));
1309 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:OpenAnalog: couldn't set channels layout [%1]")
1313 if(new_layout.mNumberChannelDescriptions > 0)
1314 free(new_layout.mChannelDescriptions);
1321 formatFlags = kLinearPCMFormatFlagIsSignedInteger;
1324 formatFlags = kLinearPCMFormatFlagIsFloat;
1327 formatFlags = kLinearPCMFormatFlagIsSignedInteger;
1331 AudioStreamBasicDescription conv_in_desc;
1332 memset(&conv_in_desc, 0,
sizeof(AudioStreamBasicDescription));
1334 conv_in_desc.mFormatID = kAudioFormatLinearPCM;
1335 conv_in_desc.mFormatFlags = formatFlags |
1336 kAudioFormatFlagsNativeEndian |
1337 kLinearPCMFormatFlagIsPacked;
1340 conv_in_desc.mFramesPerPacket = 1;
1343 conv_in_desc.mBitsPerChannel =
1348 kAudioUnitProperty_StreamFormat,
1349 kAudioUnitScope_Input,
1352 sizeof(AudioStreamBasicDescription));
1355 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:OpenAnalog: AudioUnitSetProperty returned [%1]")
1359 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::OpenAnalog: set format as %1")
1363 kAudioUnitProperty_StreamFormat,
1364 kAudioUnitScope_Input,
1369 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::OpenAnalog: the actual set AU format is %1")
1373 AURenderCallbackStruct input;
1375 input.inputProcRefCon =
this;
1378 kAudioUnitProperty_SetRenderCallback,
1379 kAudioUnitScope_Input,
1380 0, &input,
sizeof(input));
1383 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:OpenAnalog: AudioUnitSetProperty (callback) returned [%1]")
1390 ComponentResult res = AudioUnitInitialize(
mOutputUnit);
1393 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:OpenAnalog: AudioUnitInitialize error: [%1]")
1402 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:OpenAnalog: AudioOutputUnitStart error: [%1]")
1414 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::CloseAnalog: Entering: %1")
1421 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::CloseAnalog: AudioOutputUnitStop %1")
1427 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::CloseAnalog: AudioUnitUninitialize %1")
1431 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::CloseAnalog: CloseComponent %1")
1445 AudioStreamBasicDescription outputFormat {};
1447 LOG(VB_AUDIO, LOG_INFO,
"CoreAudioData::OpenSPDIF: Entering");
1450 if (streams.empty())
1452 LOG(VB_GENERAL, LOG_WARNING,
"CoreAudioData Warning:OpenSPDIF: Couldn't retrieve list of streams");
1456 for (
size_t i = 0; i < streams.size(); ++i)
1465 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::OpenSPDIF: Considering Physical Format: %1")
1467 if ((format.mFormat.mFormatID ==
'IAC3' ||
1468 format.mFormat.mFormatID == kAudioFormat60958AC3) &&
1471 LOG(VB_AUDIO, LOG_INFO,
"CoreAudioData::OpenSPDIF: Found digital format");
1474 outputFormat = format.mFormat;
1478 if (outputFormat.mFormatID)
1482 if (!outputFormat.mFormatID)
1484 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:OpenSPDIF: Couldn't find suitable output"));
1490 AudioObjectPropertyAddress pa
1492 kAudioStreamPropertyPhysicalFormat,
1493 kAudioObjectPropertyScopeGlobal,
1500 err = AudioObjectGetPropertyData(
mStreamID, &pa, 0,
nullptr,
1504 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:OpenSPDIF - could not retrieve the original streamformat: [%1]")
1533 err = AudioDeviceCreateIOProcID(
mDeviceID,
1538 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:OpenSPDIF: AudioDeviceCreateIOProcID failed: [%1]")
1548 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:OpenSPDIF: AudioDeviceStart failed: [%1]")
1560 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::CloseSPDIF: Entering [%1]").arg(
mDigitalInUse));;
1569 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:CloseSPDIF: AudioDeviceStop failed: [%1]")
1579 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:CloseSPDIF: AudioDeviceDestroyIOProcID failed: [%1]")
1593 AudioHardwareUnload();
1601 AudioStreamBasicDescription format)
1603 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::AudioStreamChangeFormat: %1 -> %2")
1607 AudioObjectPropertyAddress pa
1609 kAudioStreamPropertyPhysicalFormat,
1610 kAudioObjectPropertyScopeGlobal,
1613 OSStatus err = AudioObjectSetPropertyData(s, &pa, 0,
nullptr,
1614 sizeof(format), &format);
1617 LOG(VB_GENERAL, LOG_ERR, QString(
"CoreAudioData Error:AudioStreamChangeFormat couldn't set stream format: [%1]")
1631 if (streams.empty())
1634 for (
auto stream : streams)
1642 if (format.mFormat.mFormatID ==
'IAC3' ||
1643 format.mFormat.mFormatID == kAudioFormat60958AC3)
1645 LOG(VB_AUDIO, LOG_INFO,
"CoreAudioData::FindAC3Stream: found digital format");
1661 AudioObjectPropertyAddress pa
1663 kAudioHardwarePropertyDevices,
1664 kAudioObjectPropertyScopeGlobal,
1668 OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
1672 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:GetPropertyDataSize: Unable to retrieve the property sizes. "
1678 std::vector<AudioDeviceID> devices = {};
1679 devices.resize(size /
sizeof(AudioDeviceID));
1680 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
1681 0,
nullptr, &size, devices.data());
1684 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:GetPropertyData: Unable to retrieve the list of available devices. "
1690 for (
const auto & dev : devices)
1695 if (streams.empty())
1697 for (
auto stream : streams)
1704 AudioStreamBasicDescription currentFormat;
1707 AudioObjectPropertyAddress pa
1709 kAudioStreamPropertyPhysicalFormat,
1710 kAudioObjectPropertyScopeGlobal,
1716 paramSize =
sizeof(currentFormat);
1717 AudioObjectGetPropertyData(s, &pa, 0,
nullptr,
1718 ¶mSize, ¤tFormat);
1721 if (currentFormat.mFormatID ==
'IAC3' ||
1722 currentFormat.mFormatID == kAudioFormat60958AC3)
1731 if (format.mFormat.mFormatID == kAudioFormatLinearPCM)
1733 LOG(VB_AUDIO, LOG_INFO, QString(
"CoreAudioData::ResetStream: Resetting stream %1 to %2").arg(s).arg(
StreamDescriptionToString(format.mFormat)));
1734 err = AudioObjectSetPropertyData(s, &pa, 0,
nullptr,
1735 sizeof(format), &(format.mFormat));
1738 LOG(VB_GENERAL, LOG_WARNING, QString(
"CoreAudioData Warning:ResetStream: could not set physical format: [%1]")
1751 auto *devs =
new QMap<QString, QString>();
1756 AudioObjectPropertyAddress pa
1758 kAudioHardwarePropertyDevices,
1759 kAudioObjectPropertyScopeGlobal,
1763 OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa,
1767 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"GetPropertyDataSize: Unable to retrieve the property sizes. "
1773 UInt32 deviceCount = size /
sizeof(AudioDeviceID);
1774 std::vector<AudioDeviceID> devices = {};
1775 devices.resize(deviceCount);
1776 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa,
1777 0,
nullptr, &size, devices.data());
1780 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"AudioOutputCA::GetDevices: Unable to retrieve the list of "
1781 "available devices. Error [%1]")
1786 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"GetDevices: Number of devices: %1").arg(deviceCount));
1788 for (
const auto & dev : devices)
1793 QString *name = device.
GetName();
1796 devs->insert(*name, QString());