20 #include "JackCoreAudioDriver.h"
21 #include "JackEngineControl.h"
22 #include "JackMachThread.h"
23 #include "JackGraphManager.h"
24 #include "JackError.h"
25 #include "JackClientControl.h"
26 #include "JackDriverLoader.h"
27 #include "JackGlobals.h"
28 #include "JackTools.h"
29 #include "JackCompilerDeps.h"
30 #include "JackLockedEngine.h"
34 #include <CoreServices/CoreServices.h>
35 #include <CoreFoundation/CFNumber.h>
40 static void Print4CharCode(
const char* msg,
long c)
42 UInt32 __4CC_number = (c);
44 *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number);
46 jack_log(
"%s'%s'", (msg), __4CC_string);
49 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
51 jack_log(
"- - - - - - - - - - - - - - - - - - - -");
52 jack_log(
" Sample Rate:%f", inDesc->mSampleRate);
53 jack_log(
" Format ID:%.*s", (
int)
sizeof(inDesc->mFormatID), (
char*)&inDesc->mFormatID);
54 jack_log(
" Format Flags:%lX", inDesc->mFormatFlags);
55 jack_log(
" Bytes per Packet:%ld", inDesc->mBytesPerPacket);
56 jack_log(
" Frames per Packet:%ld", inDesc->mFramesPerPacket);
57 jack_log(
" Bytes per Frame:%ld", inDesc->mBytesPerFrame);
58 jack_log(
" Channels per Frame:%ld", inDesc->mChannelsPerFrame);
59 jack_log(
" Bits per Channel:%ld", inDesc->mBitsPerChannel);
60 jack_log(
"- - - - - - - - - - - - - - - - - - - -");
63 static void printError(OSStatus err)
66 case kAudioHardwareNoError:
67 jack_log(
"error code : kAudioHardwareNoError");
69 case kAudioConverterErr_FormatNotSupported:
70 jack_log(
"error code : kAudioConverterErr_FormatNotSupported");
72 case kAudioConverterErr_OperationNotSupported:
73 jack_log(
"error code : kAudioConverterErr_OperationNotSupported");
75 case kAudioConverterErr_PropertyNotSupported:
76 jack_log(
"error code : kAudioConverterErr_PropertyNotSupported");
78 case kAudioConverterErr_InvalidInputSize:
79 jack_log(
"error code : kAudioConverterErr_InvalidInputSize");
81 case kAudioConverterErr_InvalidOutputSize:
82 jack_log(
"error code : kAudioConverterErr_InvalidOutputSize");
84 case kAudioConverterErr_UnspecifiedError:
85 jack_log(
"error code : kAudioConverterErr_UnspecifiedError");
87 case kAudioConverterErr_BadPropertySizeError:
88 jack_log(
"error code : kAudioConverterErr_BadPropertySizeError");
90 case kAudioConverterErr_RequiresPacketDescriptionsError:
91 jack_log(
"error code : kAudioConverterErr_RequiresPacketDescriptionsError");
93 case kAudioConverterErr_InputSampleRateOutOfRange:
94 jack_log(
"error code : kAudioConverterErr_InputSampleRateOutOfRange");
96 case kAudioConverterErr_OutputSampleRateOutOfRange:
97 jack_log(
"error code : kAudioConverterErr_OutputSampleRateOutOfRange");
99 case kAudioHardwareNotRunningError:
100 jack_log(
"error code : kAudioHardwareNotRunningError");
102 case kAudioHardwareUnknownPropertyError:
103 jack_log(
"error code : kAudioHardwareUnknownPropertyError");
105 case kAudioHardwareIllegalOperationError:
106 jack_log(
"error code : kAudioHardwareIllegalOperationError");
108 case kAudioHardwareBadDeviceError:
109 jack_log(
"error code : kAudioHardwareBadDeviceError");
111 case kAudioHardwareBadStreamError:
112 jack_log(
"error code : kAudioHardwareBadStreamError");
114 case kAudioDeviceUnsupportedFormatError:
115 jack_log(
"error code : kAudioDeviceUnsupportedFormatError");
117 case kAudioDevicePermissionsError:
118 jack_log(
"error code : kAudioDevicePermissionsError");
120 case kAudioHardwareBadObjectError:
121 jack_log(
"error code : kAudioHardwareBadObjectError");
123 case kAudioHardwareUnsupportedOperationError:
124 jack_log(
"error code : kAudioHardwareUnsupportedOperationError");
127 Print4CharCode(
"error code : unknown", err);
132 static bool CheckAvailableDeviceName(
const char* device_name, AudioDeviceID* device_id)
139 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
144 deviceNum = size /
sizeof(AudioDeviceID);
145 AudioDeviceID devices[deviceNum];
147 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
152 for (i = 0; i < deviceNum; i++) {
153 char device_name_aux[256];
156 err = AudioDeviceGetProperty(devices[i], 0,
false, kAudioDevicePropertyDeviceName, &size, device_name_aux);
161 if (strcmp(device_name_aux, device_name) == 0) {
162 *device_id = devices[i];
171 static bool CheckAvailableDevice(AudioDeviceID device_id)
178 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
183 deviceNum = size /
sizeof(AudioDeviceID);
184 AudioDeviceID devices[deviceNum];
186 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
191 for (i = 0; i < deviceNum; i++) {
192 if (device_id == devices[i]) {
202 static OSStatus DisplayDeviceNames()
210 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
215 deviceNum = size /
sizeof(AudioDeviceID);
216 AudioDeviceID devices[deviceNum];
218 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
223 for (i = 0; i < deviceNum; i++) {
224 char device_name[256];
225 char internal_name[256];
227 size =
sizeof(CFStringRef);
229 err = AudioDeviceGetProperty(devices[i], 0,
false, kAudioDevicePropertyDeviceUID, &size, &UIname);
231 CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
237 err = AudioDeviceGetProperty(devices[i], 0,
false, kAudioDevicePropertyDeviceName, &size, device_name);
242 jack_info(
"Device ID = \'%d\' name = \'%s\', internal name = \'%s\' (to be used as -C, -P, or -d parameter)", devices[i], device_name, internal_name);
248 if (UIname != NULL) {
254 static CFStringRef GetDeviceName(AudioDeviceID
id)
256 UInt32 size =
sizeof(CFStringRef);
258 OSStatus err = AudioDeviceGetProperty(
id, 0,
false, kAudioDevicePropertyDeviceUID, &size, &UIname);
259 return (err == noErr) ? UIname : NULL;
262 static void ParseChannelList(
const string& list, vector<int>& result)
264 stringstream ss(list);
268 while (ss >> token) {
272 result.push_back(chan);
276 OSStatus JackCoreAudioDriver::Render(
void* inRefCon,
277 AudioUnitRenderActionFlags* ioActionFlags,
278 const AudioTimeStamp* inTimeStamp,
280 UInt32 inNumberFrames,
281 AudioBufferList* ioData)
283 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon;
284 driver->fActionFags = ioActionFlags;
285 driver->fCurrentTime = inTimeStamp;
286 driver->fDriverOutputData = ioData;
289 if (set_threaded_log_function()) {
291 jack_log(
"set_threaded_log_function");
292 JackMachThread::GetParams(pthread_self(), &driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint);
294 if (driver->fComputationGrain > 0) {
295 jack_log(
"JackCoreAudioDriver::Render : RT thread computation setup to %d percent of period",
int(driver->fComputationGrain * 100));
296 driver->fEngineControl->fComputation = driver->fEngineControl->fPeriod * driver->fComputationGrain;
301 driver->fState =
true;
303 driver->CycleTakeBeginTime();
305 if (driver->Process() < 0) {
306 jack_error(
"Process error, stopping driver.");
307 driver->NotifyFailure(JackBackendError,
"Process error, stopping driver.");
309 kill(JackTools::GetPID(), SIGINT);
310 return kAudioHardwareUnsupportedOperationError;
316 int JackCoreAudioDriver::Read()
318 if (fCaptureChannels > 0) {
319 return (AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData) == noErr) ? 0 : -1;
325 int JackCoreAudioDriver::Write()
327 for (
int i = 0; i < fPlaybackChannels; i++) {
328 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
329 jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
330 int size =
sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
331 memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
333 if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
334 memcpy(GetMonitorBuffer(i), buffer, size);
337 memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0,
sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
343 OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
346 AudioDevicePropertyID inPropertyID,
349 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
351 switch (inPropertyID) {
353 case kAudioDevicePropertyNominalSampleRate: {
354 jack_log(
"JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
356 Float64 tmp_sample_rate;
357 UInt32 outSize =
sizeof(Float64);
358 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
363 jack_log(
"SRNotificationCallback : checked sample rate = %f", tmp_sample_rate);
365 driver->fState =
true;
373 OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
376 AudioDevicePropertyID inPropertyID,
379 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
381 switch (inPropertyID) {
383 case kAudioDevicePropertyBufferFrameSize: {
384 jack_log(
"JackCoreAudioDriver::BSNotificationCallback kAudioDevicePropertyBufferFrameSize");
386 UInt32 tmp_buffer_size;
387 UInt32 outSize =
sizeof(UInt32);
388 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
393 jack_log(
"BSNotificationCallback : checked buffer size = %d", tmp_buffer_size);
395 driver->fState =
true;
404 OSStatus JackCoreAudioDriver::AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID,
void* inClientData)
406 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
408 switch (inPropertyID) {
410 case kAudioHardwarePropertyDevices: {
411 jack_log(
"JackCoreAudioDriver::AudioHardwareNotificationCallback kAudioHardwarePropertyDevices");
412 DisplayDeviceNames();
413 AudioDeviceID captureID, playbackID;
414 if (CheckAvailableDevice(driver->fDeviceID) ||
415 (CheckAvailableDeviceName(driver->fCaptureUID, &captureID)
416 && CheckAvailableDeviceName(driver->fPlaybackUID, &playbackID))) {
427 OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
430 AudioDevicePropertyID inPropertyID,
433 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
435 switch (inPropertyID) {
437 case kAudioDevicePropertyDeviceIsRunning: {
438 UInt32 isrunning = 0;
439 UInt32 outsize =
sizeof(UInt32);
440 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsRunning, &outsize, &isrunning) == noErr) {
441 jack_log(
"JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsRunning = %d", isrunning);
446 case kAudioDevicePropertyDeviceIsAlive: {
448 UInt32 outsize =
sizeof(UInt32);
449 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsAlive, &outsize, &isalive) == noErr) {
450 jack_log(
"JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsAlive = %d", isalive);
455 case kAudioDevicePropertyDeviceHasChanged: {
456 UInt32 hachanged = 0;
457 UInt32 outsize =
sizeof(UInt32);
458 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceHasChanged, &outsize, &hachanged) == noErr) {
459 jack_log(
"JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceHasChanged = %d", hachanged);
464 case kAudioDeviceProcessorOverload: {
465 jack_error(
"JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload");
466 jack_time_t cur_time = GetMicroSeconds();
467 driver->NotifyXRun(cur_time,
float(cur_time - driver->fBeginDateUst));
471 case kAudioDevicePropertyStreamConfiguration: {
472 jack_error(
"Cannot handle kAudioDevicePropertyStreamConfiguration : server will quit...");
473 driver->NotifyFailure(JackBackendError,
"Another application has changed the device configuration.");
474 driver->CloseAUHAL();
475 kill(JackTools::GetPID(), SIGINT);
476 return kAudioHardwareUnsupportedOperationError;
479 case kAudioDevicePropertyNominalSampleRate: {
480 Float64 sample_rate = 0;
481 UInt32 outsize =
sizeof(Float64);
482 OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
484 return kAudioHardwareUnsupportedOperationError;
487 char device_name[256];
488 const char* digidesign_name =
"Digidesign";
489 driver->GetDeviceNameFromID(driver->fDeviceID, device_name);
491 if (sample_rate != driver->fEngineControl->fSampleRate) {
494 if (strncmp(device_name, digidesign_name, 10) == 0) {
496 jack_log(
"Digidesign HW = %s", device_name);
499 sample_rate = driver->fEngineControl->fSampleRate;
500 err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sample_rate);
502 jack_error(
"Cannot set sample rate = %f", sample_rate);
505 jack_log(
"Set sample rate = %f", sample_rate);
509 outsize =
sizeof(Float64);
510 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
515 jack_log(
"Checked sample rate = %f", sample_rate);
520 driver->NotifyFailure(JackBackendError,
"Another application has changed the sample rate.");
521 driver->CloseAUHAL();
522 kill(JackTools::GetPID(), SIGINT);
523 return kAudioHardwareUnsupportedOperationError;
532 OSStatus JackCoreAudioDriver::GetDeviceIDFromUID(
const char* UID, AudioDeviceID*
id)
534 UInt32 size =
sizeof(AudioValueTranslation);
535 CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
536 AudioValueTranslation value = { &inIUD,
sizeof(CFStringRef),
id,
sizeof(AudioDeviceID) };
539 return kAudioHardwareUnspecifiedError;
541 OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
543 jack_log(
"GetDeviceIDFromUID %s %ld", UID, *
id);
544 return (*
id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
548 OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID*
id)
551 UInt32 theSize =
sizeof(UInt32);
552 AudioDeviceID inDefault;
553 AudioDeviceID outDefault;
555 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
559 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
563 jack_log(
"GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
566 if (inDefault != outDefault) {
567 jack_error(
"Default input and output devices are not the same !!");
568 return kAudioHardwareBadDeviceError;
569 }
else if (inDefault == 0) {
570 jack_error(
"Default input and output devices are null !!");
571 return kAudioHardwareBadDeviceError;
578 OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID*
id)
581 UInt32 theSize =
sizeof(UInt32);
582 AudioDeviceID inDefault;
584 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
588 if (inDefault == 0) {
589 jack_error(
"Error: default input device is 0, please select a correct one !!");
592 jack_log(
"GetDefaultInputDevice: input = %ld ", inDefault);
597 OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID*
id)
600 UInt32 theSize =
sizeof(UInt32);
601 AudioDeviceID outDefault;
603 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
607 if (outDefault == 0) {
608 jack_error(
"Error: default output device is 0, please select a correct one !!");
611 jack_log(
"GetDefaultOutputDevice: output = %ld", outDefault);
616 OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID
id,
char* name)
619 return AudioDeviceGetProperty(
id, 0,
false, kAudioDevicePropertyDeviceName, &size, name);
622 OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device,
int& channelCount,
bool isInput)
624 OSStatus err = noErr;
629 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
631 int stream_count = outSize /
sizeof(AudioBufferList);
632 AudioBufferList bufferList[stream_count];
633 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
635 for (uint i = 0; i < bufferList->mNumberBuffers; i++) {
636 channelCount += bufferList->mBuffers[i].mNumberChannels;
644 OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device,
bool isInput, vector<int>& latencies)
646 OSStatus err = noErr;
647 UInt32 outSize1, outSize2, outSize3;
650 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable);
652 int stream_count = outSize1 /
sizeof(UInt32);
653 AudioStreamID streamIDs[stream_count];
654 AudioBufferList bufferList[stream_count];
655 UInt32 streamLatency;
656 outSize2 =
sizeof(UInt32);
658 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs);
660 jack_error(
"GetStreamLatencies kAudioDevicePropertyStreams err = %d", err);
664 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable);
666 jack_error(
"GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
670 for (
int i = 0; i < stream_count; i++) {
671 err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency);
673 jack_error(
"GetStreamLatencies kAudioStreamPropertyLatency err = %d", err);
676 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList);
678 jack_error(
"GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
682 for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) {
683 latencies.push_back(streamLatency);
690 JackCoreAudioDriver::JackCoreAudioDriver(
const char* name,
const char* alias, JackLockedEngine* engine, JackSynchro* table)
691 : JackAudioDriver(name, alias, engine, table),
692 fJackInputData(NULL),
693 fDriverOutputData(NULL),
698 fComputationGrain(-1.f),
699 fClockDriftCompensate(false)
702 JackCoreAudioDriver::~JackCoreAudioDriver()
705 OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
707 OSStatus osErr = noErr;
708 AudioObjectPropertyAddress pluginAOPA;
709 pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
710 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
711 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
716 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
717 if (osErr != noErr) {
718 jack_error(
"JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
723 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
724 if (osErr != noErr) {
725 jack_error(
"JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error");
735 OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
737 OSStatus err = noErr;
738 AudioObjectID sub_device[32];
739 UInt32 outSize =
sizeof(sub_device);
741 err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
742 vector<AudioDeviceID> captureDeviceIDArray;
745 jack_log(
"Input device does not have subdevices");
746 captureDeviceIDArray.push_back(captureDeviceID);
748 int num_devices = outSize /
sizeof(AudioObjectID);
749 jack_log(
"Input device has %d subdevices", num_devices);
750 for (
int i = 0; i < num_devices; i++) {
751 captureDeviceIDArray.push_back(sub_device[i]);
755 err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
756 vector<AudioDeviceID> playbackDeviceIDArray;
759 jack_log(
"Output device does not have subdevices");
760 playbackDeviceIDArray.push_back(playbackDeviceID);
762 int num_devices = outSize /
sizeof(AudioObjectID);
763 jack_log(
"Output device has %d subdevices", num_devices);
764 for (
int i = 0; i < num_devices; i++) {
765 playbackDeviceIDArray.push_back(sub_device[i]);
769 return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
772 OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
774 OSStatus osErr = noErr;
780 AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
781 AudioObjectPropertyAddress theAddressDrift = { kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
782 UInt32 theQualifierDataSize =
sizeof(AudioObjectID);
783 AudioClassID inClass = kAudioSubDeviceClassID;
784 void* theQualifierData = &inClass;
785 UInt32 subDevicesNum = 0;
790 UInt32 keptclockdomain = 0;
791 UInt32 clockdomain = 0;
792 outSize =
sizeof(UInt32);
793 bool need_clock_drift_compensation =
false;
795 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
796 if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
797 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device");
800 osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
802 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
805 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
806 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain);
807 if (clockdomain != 0 && clockdomain != keptclockdomain) {
808 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
809 need_clock_drift_compensation =
true;
815 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
816 if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
817 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device");
820 osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
822 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
825 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
826 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain);
827 if (clockdomain != 0 && clockdomain != keptclockdomain) {
828 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
829 need_clock_drift_compensation =
true;
836 if (keptclockdomain == 0) {
837 need_clock_drift_compensation =
true;
844 char device_name[256];
845 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
846 GetDeviceNameFromID(captureDeviceID[i], device_name);
847 jack_info(
"Separated input = '%s' ", device_name);
850 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
851 GetDeviceNameFromID(playbackDeviceID[i], device_name);
852 jack_info(
"Separated output = '%s' ", device_name);
855 osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
856 if (osErr != noErr) {
857 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
862 AudioValueTranslation pluginAVT;
864 CFStringRef inBundleRef = CFSTR(
"com.apple.audio.CoreAudio");
866 pluginAVT.mInputData = &inBundleRef;
867 pluginAVT.mInputDataSize =
sizeof(inBundleRef);
868 pluginAVT.mOutputData = &fPluginID;
869 pluginAVT.mOutputDataSize =
sizeof(fPluginID);
871 osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
872 if (osErr != noErr) {
873 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
882 CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
884 CFStringRef AggregateDeviceNameRef = CFSTR(
"JackDuplex");
885 CFStringRef AggregateDeviceUIDRef = CFSTR(
"com.grame.JackDuplex");
888 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
891 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
895 CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
898 Gestalt(gestaltSystemVersion, &system);
900 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
903 if (system < 0x00001054) {
904 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
906 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
907 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
911 CFMutableArrayRef subDevicesArrayClock = NULL;
954 CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
956 vector<CFStringRef> captureDeviceUID;
957 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
958 CFStringRef ref = GetDeviceName(captureDeviceID[i]);
962 captureDeviceUID.push_back(ref);
964 CFArrayAppendValue(subDevicesArray, ref);
967 vector<CFStringRef> playbackDeviceUID;
968 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
969 CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
973 playbackDeviceUID.push_back(ref);
975 CFArrayAppendValue(subDevicesArray, ref);
982 AudioObjectPropertyAddress pluginAOPA;
983 pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
984 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
985 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
988 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
989 if (osErr != noErr) {
990 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyDataSize error");
995 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA,
sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
996 if (osErr != noErr) {
997 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error");
1004 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1,
false);
1010 pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList;
1011 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1012 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1013 outDataSize =
sizeof(CFMutableArrayRef);
1014 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
1015 if (osErr != noErr) {
1016 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error");
1022 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1,
false);
1030 pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
1031 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1032 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1033 outDataSize =
sizeof(CFStringRef);
1034 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]);
1035 if (osErr != noErr) {
1036 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for master device error");
1042 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1,
false);
1047 if (fClockDriftCompensate) {
1048 if (need_clock_drift_compensation) {
1049 jack_info(
"Clock drift compensation activated...");
1052 osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
1053 if (osErr != noErr) {
1054 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
1059 subDevicesNum = outSize /
sizeof(AudioObjectID);
1060 jack_info(
"JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum);
1061 AudioObjectID subDevices[subDevicesNum];
1062 outSize =
sizeof(subDevices);
1064 osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
1065 if (osErr != noErr) {
1066 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
1071 for (UInt32 index = 0; index < subDevicesNum; ++index) {
1072 UInt32 theDriftCompensationValue = 1;
1073 osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL,
sizeof(UInt32), &theDriftCompensationValue);
1074 if (osErr != noErr) {
1075 jack_error(
"JackCoreAudioDriver::CreateAggregateDevice kAudioSubDevicePropertyDriftCompensation error");
1080 jack_info(
"Clock drift compensation was asked but is not needed (devices use the same clock domain)");
1085 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1,
false);
1092 CFRelease(AggregateDeviceNumberRef);
1095 CFRelease(aggDeviceDict);
1096 CFRelease(subDevicesArray);
1098 if (subDevicesArrayClock) {
1099 CFRelease(subDevicesArrayClock);
1103 for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
1104 CFRelease(captureDeviceUID[i]);
1107 for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
1108 CFRelease(playbackDeviceUID[i]);
1111 jack_log(
"New aggregate device %ld", *outAggregateDevice);
1115 DestroyAggregateDevice();
1119 int JackCoreAudioDriver::SetupDevices(
const char* capture_driver_uid,
1120 const char* playback_driver_uid,
1121 char* capture_driver_name,
1122 char* playback_driver_name,
1123 jack_nframes_t samplerate)
1125 capture_driver_name[0] = 0;
1126 playback_driver_name[0] = 0;
1129 if (strcmp(capture_driver_uid,
"") != 0 && strcmp(playback_driver_uid,
"") != 0) {
1130 jack_log(
"JackCoreAudioDriver::Open duplex");
1133 if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
1135 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
1136 jack_log(
"Will take default in/out");
1137 if (GetDefaultDevice(&fDeviceID) != noErr) {
1142 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
1143 jack_error(
"Cannot get device name from device ID");
1150 AudioDeviceID captureID, playbackID;
1152 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
1153 jack_log(
"Will take default input");
1154 if (GetDefaultInputDevice(&captureID) != noErr) {
1155 jack_error(
"Cannot open default input device");
1160 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
1161 jack_log(
"Will take default output");
1162 if (GetDefaultOutputDevice(&playbackID) != noErr) {
1163 jack_error(
"Cannot open default output device");
1168 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1172 GetDeviceNameFromID(captureID, fCaptureUID);
1173 GetDeviceNameFromID(playbackID, fPlaybackUID);
1177 }
else if (strcmp(capture_driver_uid,
"") != 0) {
1178 jack_log(
"JackCoreAudioDriver::Open capture only");
1179 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
1180 jack_log(
"Will take default input");
1181 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
1182 jack_error(
"Cannot open default input device");
1186 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
1187 jack_error(
"Cannot get device name from device ID");
1192 }
else if (strcmp(playback_driver_uid,
"") != 0) {
1193 jack_log(
"JackCoreAudioDriver::Open playback only");
1194 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
1195 jack_log(
"Will take default output");
1196 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
1197 jack_error(
"Cannot open default output device");
1201 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
1202 jack_error(
"Cannot get device name from device ID");
1208 jack_log(
"JackCoreAudioDriver::Open default driver");
1209 if (GetDefaultDevice(&fDeviceID) != noErr) {
1210 jack_error(
"Cannot open default device in duplex mode, so aggregate default input and default output");
1213 AudioDeviceID captureID, playbackID;
1215 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
1216 jack_log(
"Will take default input");
1217 if (GetDefaultInputDevice(&captureID) != noErr) {
1218 jack_error(
"Cannot open default input device");
1223 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
1224 jack_log(
"Will take default output");
1225 if (GetDefaultOutputDevice(&playbackID) != noErr) {
1226 jack_error(
"Cannot open default output device");
1231 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1235 GetDeviceNameFromID(captureID, fCaptureUID);
1236 GetDeviceNameFromID(playbackID, fPlaybackUID);
1242 jack_info(
"Device = %ld has been hogged", fDeviceID);
1252 int JackCoreAudioDriver::SetupChannels(
bool capturing,
bool playing,
int& inchannels,
int& outchannels,
int& in_nChannels,
int& out_nChannels,
bool strict)
1254 OSStatus err = noErr;
1257 err = GetTotalChannels(fDeviceID, in_nChannels,
true);
1259 jack_error(
"Cannot get input channel number");
1263 jack_log(
"Max input channels : %d", in_nChannels);
1268 err = GetTotalChannels(fDeviceID, out_nChannels,
false);
1270 jack_error(
"Cannot get output channel number");
1274 jack_log(
"Max output channels : %d", out_nChannels);
1278 if (inchannels > in_nChannels) {
1279 jack_error(
"This device hasn't required input channels inchannels = %d in_nChannels = %d", inchannels, in_nChannels);
1285 if (outchannels > out_nChannels) {
1286 jack_error(
"This device hasn't required output channels outchannels = %d out_nChannels = %d", outchannels, out_nChannels);
1292 if (inchannels == -1) {
1293 jack_log(
"Setup max in channels = %d", in_nChannels);
1294 inchannels = in_nChannels;
1297 if (outchannels == -1) {
1298 jack_log(
"Setup max out channels = %d", out_nChannels);
1299 outchannels = out_nChannels;
1305 int JackCoreAudioDriver::SetupBufferSize(jack_nframes_t buffer_size)
1308 OSStatus err = noErr;
1309 UInt32 tmp_buffer_size = buffer_size;
1310 UInt32 outSize =
sizeof(UInt32);
1312 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
1314 jack_error(
"Cannot get buffer size %ld", buffer_size);
1318 jack_log(
"Current buffer size = %ld", tmp_buffer_size);
1322 if (buffer_size != tmp_buffer_size) {
1323 tmp_buffer_size = buffer_size;
1326 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback,
this);
1328 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyBufferFrameSize");
1337 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, outSize, &tmp_buffer_size);
1339 jack_error(
"Cannot set buffer size = %ld", tmp_buffer_size);
1344 while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1346 jack_log(
"Wait count = %d", count);
1349 if (count >= WAIT_NOTIFICATION_COUNTER) {
1350 jack_error(
"Did not get buffer size notification...");
1355 outSize =
sizeof(UInt32);
1356 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
1358 jack_error(
"Cannot get current buffer size");
1361 jack_log(
"Checked buffer size = %ld", tmp_buffer_size);
1365 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1373 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1378 int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t sample_rate)
1380 return SetupSampleRateAux(fDeviceID, sample_rate);
1383 int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t sample_rate)
1385 OSStatus err = noErr;
1387 Float64 tmp_sample_rate;
1390 outSize =
sizeof(Float64);
1391 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
1393 jack_error(
"Cannot get current sample rate");
1397 jack_log(
"Current sample rate = %f", tmp_sample_rate);
1401 if (sample_rate != (jack_nframes_t)tmp_sample_rate) {
1402 tmp_sample_rate = (Float64)sample_rate;
1405 err = AudioDeviceAddPropertyListener(inDevice, 0,
true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback,
this);
1407 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
1416 err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &tmp_sample_rate);
1418 jack_error(
"Cannot set sample rate = %ld", sample_rate);
1423 while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1425 jack_log(
"Wait count = %d", count);
1428 if (count >= WAIT_NOTIFICATION_COUNTER) {
1429 jack_error(
"Did not get sample rate notification...");
1434 outSize =
sizeof(Float64);
1435 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
1437 jack_error(
"Cannot get current sample rate");
1440 jack_log(
"Checked sample rate = %f", tmp_sample_rate);
1444 AudioDeviceRemovePropertyListener(inDevice, 0,
true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1452 AudioDeviceRemovePropertyListener(inDevice, 0,
true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1456 int JackCoreAudioDriver::OpenAUHAL(
bool capturing,
1462 const vector<int>& chan_in_list,
1463 const vector<int>& chan_out_list,
1464 jack_nframes_t buffer_size,
1465 jack_nframes_t sample_rate)
1467 ComponentResult err1;
1469 AudioStreamBasicDescription srcFormat, dstFormat;
1470 AudioDeviceID currAudioDeviceID;
1473 jack_log(
"OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d chan_in_list = %d chan_out_list = %d",
1474 capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, chan_in_list.size(), chan_out_list.size());
1476 if (inchannels == 0 && outchannels == 0) {
1477 jack_error(
"No input and output channels...");
1482 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
1483 Component HALOutput = FindNextComponent(NULL, &cd);
1485 err1 = OpenAComponent(HALOutput, &fAUHAL);
1486 if (err1 != noErr) {
1492 err1 = AudioUnitInitialize(fAUHAL);
1493 if (err1 != noErr) {
1500 if (capturing && inchannels > 0) {
1508 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO,
sizeof(enableIO));
1509 if (err1 != noErr) {
1510 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
1515 if (playing && outchannels > 0) {
1520 jack_log(
"Setup AUHAL output off");
1523 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO,
sizeof(enableIO));
1524 if (err1 != noErr) {
1525 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
1530 size =
sizeof(AudioDeviceID);
1531 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
1532 if (err1 != noErr) {
1533 jack_error(
"Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
1537 jack_log(
"AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
1541 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID,
sizeof(AudioDeviceID));
1542 if (err1 != noErr) {
1543 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
1549 if (capturing && inchannels > 0) {
1550 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size,
sizeof(UInt32));
1551 if (err1 != noErr) {
1552 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
1558 if (playing && outchannels > 0) {
1559 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size,
sizeof(UInt32));
1560 if (err1 != noErr) {
1561 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
1568 if (capturing && inchannels > 0 && inchannels <= in_nChannels) {
1569 SInt32 chanArr[in_nChannels];
1570 for (
int i = 0; i < in_nChannels; i++) {
1574 if (chan_in_list.size() > 0) {
1575 for (uint i = 0; i < chan_in_list.size(); i++) {
1576 int chan = chan_in_list[i];
1577 if (chan < out_nChannels) {
1580 jack_info(
"Input channel = %d ==> JACK input port = %d", chan, i);
1582 jack_info(
"Error input channel number is incorrect : %d", chan);
1587 for (
int i = 0; i < inchannels; i++) {
1589 jack_info(
"Input channel = %d ==> JACK input port = %d", chanArr[i], i);
1593 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr,
sizeof(SInt32) * in_nChannels);
1594 if (err1 != noErr) {
1595 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for input");
1602 if (playing && outchannels > 0 && outchannels <= out_nChannels) {
1603 SInt32 chanArr[out_nChannels];
1604 for (
int i = 0; i < out_nChannels; i++) {
1608 if (chan_out_list.size() > 0) {
1609 for (uint i = 0; i < chan_out_list.size(); i++) {
1610 int chan = chan_out_list[i];
1611 if (chan < out_nChannels) {
1614 jack_info(
"JACK output port = %d ==> output channel = %d", i, chan);
1616 jack_info(
"Error output channel number is incorrect : %d", chan);
1621 for (
int i = 0; i < outchannels; i++) {
1623 jack_info(
"JACK output port = %d ==> output channel = %d", i, chanArr[i]);
1627 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr,
sizeof(SInt32) * out_nChannels);
1628 if (err1 != noErr) {
1629 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for output");
1636 if (capturing && inchannels > 0) {
1638 size =
sizeof(AudioStreamBasicDescription);
1639 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &size);
1640 if (err1 != noErr) {
1641 jack_error(
"Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
1645 PrintStreamDesc(&srcFormat);
1647 jack_log(
"Setup AUHAL input stream converter SR = %ld", sample_rate);
1648 srcFormat.mSampleRate = sample_rate;
1649 srcFormat.mFormatID = kAudioFormatLinearPCM;
1650 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1651 srcFormat.mBytesPerPacket =
sizeof(jack_default_audio_sample_t);
1652 srcFormat.mFramesPerPacket = 1;
1653 srcFormat.mBytesPerFrame =
sizeof(jack_default_audio_sample_t);
1654 srcFormat.mChannelsPerFrame = inchannels;
1655 srcFormat.mBitsPerChannel = 32;
1656 PrintStreamDesc(&srcFormat);
1658 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat,
sizeof(AudioStreamBasicDescription));
1659 if (err1 != noErr) {
1660 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
1666 if (playing && outchannels > 0) {
1668 size =
sizeof(AudioStreamBasicDescription);
1669 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &size);
1670 if (err1 != noErr) {
1671 jack_error(
"Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
1675 PrintStreamDesc(&dstFormat);
1677 jack_log(
"Setup AUHAL output stream converter SR = %ld", sample_rate);
1678 dstFormat.mSampleRate = sample_rate;
1679 dstFormat.mFormatID = kAudioFormatLinearPCM;
1680 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1681 dstFormat.mBytesPerPacket =
sizeof(jack_default_audio_sample_t);
1682 dstFormat.mFramesPerPacket = 1;
1683 dstFormat.mBytesPerFrame =
sizeof(jack_default_audio_sample_t);
1684 dstFormat.mChannelsPerFrame = outchannels;
1685 dstFormat.mBitsPerChannel = 32;
1686 PrintStreamDesc(&dstFormat);
1688 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat,
sizeof(AudioStreamBasicDescription));
1689 if (err1 != noErr) {
1690 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
1697 if (inchannels > 0 && outchannels == 0) {
1698 AURenderCallbackStruct output;
1699 output.inputProc = Render;
1700 output.inputProcRefCon =
this;
1701 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output,
sizeof(output));
1702 if (err1 != noErr) {
1703 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
1708 AURenderCallbackStruct output;
1709 output.inputProc = Render;
1710 output.inputProcRefCon =
this;
1711 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output,
sizeof(output));
1712 if (err1 != noErr) {
1713 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
1726 int JackCoreAudioDriver::SetupBuffers(
int inchannels)
1729 fJackInputData = (AudioBufferList*)malloc(
sizeof(UInt32) + inchannels *
sizeof(AudioBuffer));
1730 fJackInputData->mNumberBuffers = inchannels;
1731 for (
int i = 0; i < inchannels; i++) {
1732 fJackInputData->mBuffers[i].mNumberChannels = 1;
1733 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize *
sizeof(jack_default_audio_sample_t);
1738 void JackCoreAudioDriver::DisposeBuffers()
1740 if (fJackInputData) {
1741 free(fJackInputData);
1746 void JackCoreAudioDriver::CloseAUHAL()
1748 AudioOutputUnitStop(fAUHAL);
1749 AudioUnitUninitialize(fAUHAL);
1750 CloseComponent(fAUHAL);
1753 int JackCoreAudioDriver::AddListeners()
1755 OSStatus err = noErr;
1758 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDeviceProcessorOverload, DeviceNotificationCallback,
this);
1760 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
1765 err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback,
this);
1767 jack_error(
"Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
1772 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback,
this);
1774 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
1779 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback,
this);
1781 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
1786 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback,
this);
1788 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsAlive");
1793 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback,
this);
1795 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceHasChanged");
1800 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback,
this);
1802 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
1807 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback,
this);
1809 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
1814 if (!fEngineControl->fSyncMode && fIOUsage != 1.f) {
1815 UInt32 outSize =
sizeof(float);
1816 err = AudioDeviceSetProperty(fDeviceID, NULL, 0,
false, kAudioDevicePropertyIOCycleUsage, outSize, &fIOUsage);
1818 jack_error(
"Error calling AudioDeviceSetProperty kAudioDevicePropertyIOCycleUsage");
1826 void JackCoreAudioDriver::RemoveListeners()
1828 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
1829 AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback);
1830 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
1831 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
1832 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback);
1833 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback);
1834 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
1835 AudioDeviceRemovePropertyListener(fDeviceID, 0,
false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
1838 int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
1839 jack_nframes_t sample_rate,
1844 const char* chan_in_list,
1845 const char* chan_out_list,
1847 const char* capture_driver_uid,
1848 const char* playback_driver_uid,
1849 jack_nframes_t capture_latency,
1850 jack_nframes_t playback_latency,
1851 int async_output_latency,
1852 int computation_grain,
1856 int in_nChannels = 0;
1857 int out_nChannels = 0;
1858 char capture_driver_name[256];
1859 char playback_driver_name[256];
1861 fCaptureLatency = capture_latency;
1862 fPlaybackLatency = playback_latency;
1863 fIOUsage = float(async_output_latency) / 100.f;
1864 fComputationGrain = float(computation_grain) / 100.f;
1866 fClockDriftCompensate = clock_drift;
1870 Gestalt(gestaltSystemVersionMajor, &major);
1871 Gestalt(gestaltSystemVersionMinor, &minor);
1873 vector<int> parsed_chan_in_list;
1874 vector<int> parsed_chan_out_list;
1876 ParseChannelList(chan_in_list, parsed_chan_in_list);
1877 if (parsed_chan_in_list.size() > 0) {
1878 jack_info(
"Explicit input channel list size = %d", parsed_chan_in_list.size());
1879 inchannels = parsed_chan_in_list.size();
1882 ParseChannelList(chan_out_list, parsed_chan_out_list);
1883 if (parsed_chan_out_list.size() > 0) {
1884 jack_info(
"Explicit output channel list size = %d", parsed_chan_out_list.size());
1885 outchannels = parsed_chan_out_list.size();
1889 if (major == 10 && minor >= 6) {
1890 CFRunLoopRef theRunLoop = NULL;
1891 AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
1892 OSStatus osErr = AudioObjectSetPropertyData (kAudioObjectSystemObject, &theAddress, 0, NULL,
sizeof(CFRunLoopRef), &theRunLoop);
1893 if (osErr != noErr) {
1894 jack_error(
"JackCoreAudioDriver::Open kAudioHardwarePropertyRunLoop error");
1899 if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate) < 0) {
1904 if (JackAudioDriver::Open(buffer_size, sample_rate,
1906 inchannels, outchannels,
1908 capture_driver_name,
1909 playback_driver_name,
1911 playback_latency) != 0) {
1915 if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels,
true) < 0) {
1919 if (SetupBufferSize(buffer_size) < 0) {
1923 if (SetupSampleRate(sample_rate) < 0) {
1927 if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) {
1931 if (capturing && inchannels > 0) {
1932 if (SetupBuffers(inchannels) < 0) {
1937 if (AddListeners() < 0) {
1942 fCaptureChannels = inchannels;
1943 fPlaybackChannels = outchannels;
1951 int JackCoreAudioDriver::Close()
1953 jack_log(
"JackCoreAudioDriver::Close");
1956 int res = JackAudioDriver::Close();
1961 DestroyAggregateDevice();
1965 void JackCoreAudioDriver::UpdateLatencies()
1974 size =
sizeof(UInt32);
1977 err = AudioDeviceGetProperty(fDeviceID, 0,
true, kAudioDevicePropertyLatency, &size, &value1);
1979 jack_error(
"AudioDeviceGetProperty kAudioDevicePropertyLatency error");
1981 err = AudioDeviceGetProperty(fDeviceID, 0,
true, kAudioDevicePropertySafetyOffset, &size, &value2);
1983 jack_error(
"AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
1986 input_range.
min = input_range.
max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
1989 vector<int> input_latencies;
1990 err = GetStreamLatencies(fDeviceID,
true, input_latencies);
1992 for (
int i = 0; i < fCaptureChannels; i++) {
1994 input_range.
min += input_latencies[i];
1995 input_range.
max += input_latencies[i];
1997 fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
2001 size =
sizeof(UInt32);
2004 err = AudioDeviceGetProperty(fDeviceID, 0,
false, kAudioDevicePropertyLatency, &size, &value1);
2006 jack_error(
"AudioDeviceGetProperty kAudioDevicePropertyLatency error");
2008 err = AudioDeviceGetProperty(fDeviceID, 0,
false, kAudioDevicePropertySafetyOffset, &size, &value2);
2010 jack_error(
"AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
2014 vector<int> output_latencies;
2015 err = GetStreamLatencies(fDeviceID,
false, output_latencies);
2018 output_range.
min = output_range.
max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode)
2019 ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency;
2021 for (
int i = 0; i < fPlaybackChannels; i++) {
2023 output_range.
min += output_latencies[i];
2024 output_range.
max += output_latencies[i];
2026 fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
2029 if (fWithMonitorPorts) {
2030 monitor_range.
min = monitor_range.
max = fEngineControl->fBufferSize;
2031 fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
2036 int JackCoreAudioDriver::Attach()
2040 jack_port_id_t port_index;
2043 char channel_name[64];
2044 char name[REAL_JACK_PORT_NAME_SIZE];
2045 char alias[REAL_JACK_PORT_NAME_SIZE];
2047 jack_log(
"JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
2049 for (
int i = 0; i < fCaptureChannels; i++) {
2051 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1,
true, kAudioDevicePropertyChannelName, &size, &isWritable);
2053 jack_log(
"AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
2055 if (err == noErr && size > 0) {
2056 err = AudioDeviceGetProperty(fDeviceID, i + 1,
true, kAudioDevicePropertyChannelName, &size, channel_name);
2058 jack_log(
"AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
2060 snprintf(alias,
sizeof(alias),
"%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
2062 snprintf(alias,
sizeof(alias),
"%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
2065 snprintf(name,
sizeof(name),
"%s:capture_%d", fClientControl.fName, i + 1);
2067 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
2068 jack_error(
"Cannot register port for %s", name);
2072 port = fGraphManager->GetPort(port_index);
2073 port->SetAlias(alias);
2074 fCapturePortList[i] = port_index;
2077 for (
int i = 0; i < fPlaybackChannels; i++) {
2079 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1,
false, kAudioDevicePropertyChannelName, &size, &isWritable);
2081 jack_log(
"AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
2083 if (err == noErr && size > 0) {
2084 err = AudioDeviceGetProperty(fDeviceID, i + 1,
false, kAudioDevicePropertyChannelName, &size, channel_name);
2086 jack_log(
"AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
2088 snprintf(alias,
sizeof(alias),
"%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
2090 snprintf(alias,
sizeof(alias),
"%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
2093 snprintf(name,
sizeof(name),
"%s:playback_%d", fClientControl.fName, i + 1);
2095 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
2096 jack_error(
"Cannot register port for %s", name);
2100 port = fGraphManager->GetPort(port_index);
2101 port->SetAlias(alias);
2102 fPlaybackPortList[i] = port_index;
2105 if (fWithMonitorPorts) {
2107 snprintf(name,
sizeof(name),
"%s:monitor_%u", fClientControl.fName, i + 1);
2108 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
2109 jack_error(
"Cannot register monitor port for %s", name);
2112 fMonitorPortList[i] = port_index;
2120 for (
int i = 0; i < fCaptureChannels; i++) {
2121 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
2127 int JackCoreAudioDriver::Start()
2129 jack_log(
"JackCoreAudioDriver::Start");
2130 if (JackAudioDriver::Start() == 0) {
2136 OSStatus err = AudioOutputUnitStart(fAUHAL);
2139 while (!fState && count++ < WAIT_COUNTER) {
2141 jack_log(
"JackCoreAudioDriver::Start wait count = %d", count);
2144 if (count < WAIT_COUNTER) {
2145 jack_info(
"CoreAudio driver is running...");
2149 jack_error(
"CoreAudio driver cannot start...");
2151 JackAudioDriver::Stop();
2156 int JackCoreAudioDriver::Stop()
2158 jack_log(
"JackCoreAudioDriver::Stop");
2159 int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
2160 if (JackAudioDriver::Stop() < 0) {
2166 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
2168 if (SetupBufferSize(buffer_size) < 0) {
2172 JackAudioDriver::SetBufferSize(buffer_size);
2178 for (
int i = 0; i < fCaptureChannels; i++) {
2179 fJackInputData->mBuffers[i].mNumberChannels = 1;
2180 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize *
sizeof(jack_default_audio_sample_t);
2181 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
2187 bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID,
bool isInput)
2192 UInt32 propSize =
sizeof(hog_pid);
2193 err = AudioDeviceGetProperty(deviceID, 0, isInput, kAudioDevicePropertyHogMode, &propSize, &hog_pid);
2199 if (hog_pid != getpid()) {
2201 err = AudioDeviceSetProperty(deviceID, 0, 0, isInput, kAudioDevicePropertyHogMode, propSize, &hog_pid);
2203 jack_error(
"Can't hog device = %d because it's being hogged by another program or cannot be hogged", deviceID);
2211 bool JackCoreAudioDriver::TakeHog()
2213 OSStatus err = noErr;
2214 AudioObjectID sub_device[32];
2215 UInt32 outSize =
sizeof(sub_device);
2216 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
2219 jack_log(
"Device does not have subdevices");
2220 return TakeHogAux(fDeviceID,
true);
2222 int num_devices = outSize /
sizeof(AudioObjectID);
2223 jack_log(
"Device does has %d subdevices", num_devices);
2224 for (
int i = 0; i < num_devices; i++) {
2225 if (!TakeHogAux(sub_device[i],
true)) {
2233 bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
2235 UInt32 deviceType, outSize =
sizeof(UInt32);
2236 OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
2239 jack_log(
"JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
2242 return (deviceType == kAudioDeviceTransportTypeAggregate);
2261 desc = jack_driver_descriptor_construct(
"coreaudio", JackDriverMaster,
"Apple CoreAudio API based audio backend", &filler);
2264 jack_driver_descriptor_add_parameter(desc, &filler,
"channels",
'c', JackDriverParamInt, &value, NULL,
"Maximum number of channels",
"Maximum number of channels. If -1, max possible number of channels will be used");
2265 jack_driver_descriptor_add_parameter(desc, &filler,
"in-channels",
'i', JackDriverParamInt, &value, NULL,
"Maximum number of input channels",
"Maximum number of input channels. If -1, max possible number of input channels will be used");
2266 jack_driver_descriptor_add_parameter(desc, &filler,
"out-channels",
'o', JackDriverParamInt, &value, NULL,
"Maximum number of output channels",
"Maximum number of output channels. If -1, max possible number of output channels will be used");
2269 jack_driver_descriptor_add_parameter(desc, &filler,
"input-list",
'n', JackDriverParamString, &value, NULL,
"Input channel list",
"List of input channel number to be opened");
2270 jack_driver_descriptor_add_parameter(desc, &filler,
"output-list",
'N', JackDriverParamString, &value, NULL,
"Output channel list",
"List of output channel number to be opened");
2273 jack_driver_descriptor_add_parameter(desc, &filler,
"capture",
'C', JackDriverParamString, &value, NULL,
"Input CoreAudio device name", NULL);
2274 jack_driver_descriptor_add_parameter(desc, &filler,
"playback",
'P', JackDriverParamString, &value, NULL,
"Output CoreAudio device name", NULL);
2277 jack_driver_descriptor_add_parameter(desc, &filler,
"monitor",
'm', JackDriverParamBool, &value, NULL,
"Provide monitor ports for the output", NULL);
2280 jack_driver_descriptor_add_parameter(desc, &filler,
"duplex",
'D', JackDriverParamBool, &value, NULL,
"Provide both capture and playback ports", NULL);
2283 jack_driver_descriptor_add_parameter(desc, &filler,
"rate",
'r', JackDriverParamUInt, &value, NULL,
"Sample rate", NULL);
2286 jack_driver_descriptor_add_parameter(desc, &filler,
"period",
'p', JackDriverParamUInt, &value, NULL,
"Frames per period", NULL);
2289 jack_driver_descriptor_add_parameter(desc, &filler,
"device",
'd', JackDriverParamString, &value, NULL,
"CoreAudio device name", NULL);
2292 jack_driver_descriptor_add_parameter(desc, &filler,
"input-latency",
'I', JackDriverParamUInt, &value, NULL,
"Extra input latency (frames)", NULL);
2293 jack_driver_descriptor_add_parameter(desc, &filler,
"output-latency",
'O', JackDriverParamUInt, &value, NULL,
"Extra output latency (frames)", NULL);
2296 jack_driver_descriptor_add_parameter(desc, &filler,
"list-devices",
'l', JackDriverParamBool, &value, NULL,
"Display available CoreAudio devices", NULL);
2299 jack_driver_descriptor_add_parameter(desc, &filler,
"hog",
'H', JackDriverParamBool, &value, NULL,
"Take exclusive access of the audio device", NULL);
2302 jack_driver_descriptor_add_parameter(desc, &filler,
"async-latency",
'L', JackDriverParamUInt, &value, NULL,
"Extra output latency in asynchronous mode (percent)", NULL);
2305 jack_driver_descriptor_add_parameter(desc, &filler,
"grain",
'G', JackDriverParamUInt, &value, NULL,
"Computation grain in RT thread (percent)", NULL);
2308 jack_driver_descriptor_add_parameter(desc, &filler,
"clock-drift",
's', JackDriverParamBool, &value, NULL,
"Clock drift compensation",
"Whether to compensate clock drift in dynamically created aggregate device");
2315 jack_nframes_t srate = 44100;
2316 jack_nframes_t frames_per_interrupt = 256;
2317 bool capture =
false;
2318 bool playback =
false;
2321 const char* chan_in_list =
"";
2322 const char* chan_out_list =
"";
2323 bool monitor =
false;
2324 const char* capture_driver_uid =
"";
2325 const char* playback_driver_uid =
"";
2328 jack_nframes_t systemic_input_latency = 0;
2329 jack_nframes_t systemic_output_latency = 0;
2330 int async_output_latency = 100;
2331 int computation_grain = -1;
2332 bool hogged =
false;
2333 bool clock_drift =
false;
2335 for (node = params; node; node = jack_slist_next(node)) {
2338 switch (param->character) {
2341 capture_driver_uid = param->value.str;
2342 playback_driver_uid = param->value.str;
2351 chan_in = chan_out = param->value.i;
2355 chan_in = param->value.i;
2359 chan_out = param->value.i;
2363 chan_in_list = param->value.str;
2367 chan_out_list = param->value.str;
2372 if (strcmp(param->value.str,
"none") != 0) {
2373 capture_driver_uid = param->value.str;
2379 if (strcmp(param->value.str,
"none") != 0) {
2380 playback_driver_uid = param->value.str;
2385 monitor = param->value.i;
2389 srate = param->value.ui;
2393 frames_per_interrupt = (
unsigned int)param->value.ui;
2397 systemic_input_latency = param->value.ui;
2401 systemic_output_latency = param->value.ui;
2405 Jack::DisplayDeviceNames();
2413 async_output_latency = param->value.ui;
2417 computation_grain = param->value.ui;
2427 if (!capture && !playback) {
2432 if (strcmp(chan_in_list,
"") != 0 && chan_in >= 0) {
2433 printf(
"Input channel list and in channels are both specified, input channel list will take over...\n");
2436 if (strcmp(chan_out_list,
"") != 0 && chan_out >= 0) {
2437 printf(
"Output channel list and out channels are both specified, output channel list will take over...\n");
2441 if (driver->Open(frames_per_interrupt,
2444 chan_out, chan_in_list,
2445 chan_out_list, monitor,
2447 playback_driver_uid,
2448 systemic_input_latency,
2449 systemic_output_latency,
2450 async_output_latency,
2452 hogged, clock_drift) == 0) {