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 "JackLockedEngine.h" 30 #include "JackAC3Encoder.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 (strncmp(device_name_aux, device_name, strlen(device_name)) == 0) {
162 *device_id = devices[i];
170 static bool CheckAvailableDevice(AudioDeviceID device_id)
177 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
182 deviceNum = size /
sizeof(AudioDeviceID);
183 AudioDeviceID devices[deviceNum];
185 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
190 for (i = 0; i < deviceNum; i++) {
191 if (device_id == devices[i]) {
199 static OSStatus DisplayDeviceNames()
207 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
212 deviceNum = size /
sizeof(AudioDeviceID);
213 AudioDeviceID devices[deviceNum];
215 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
220 for (i = 0; i < deviceNum; i++) {
221 char device_name[256];
222 char internal_name[256];
224 size =
sizeof(CFStringRef);
226 err = AudioDeviceGetProperty(devices[i], 0,
false, kAudioDevicePropertyDeviceUID, &size, &UIname);
228 CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
234 err = AudioDeviceGetProperty(devices[i], 0,
false, kAudioDevicePropertyDeviceName, &size, device_name);
239 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);
245 if (UIname != NULL) {
251 static CFStringRef GetDeviceName(AudioDeviceID
id)
253 UInt32 size =
sizeof(CFStringRef);
255 OSStatus err = AudioDeviceGetProperty(
id, 0,
false, kAudioDevicePropertyDeviceUID, &size, &UIname);
256 return (err == noErr) ? UIname : NULL;
259 static void ParseChannelList(
const string& list, vector<int>& result,
int max_chan)
261 stringstream ss(list);
265 while (ss >> token) {
269 if (chan < 0 || chan >= max_chan) {
270 jack_error(
"Ignore incorrect channel mapping value = %d", chan);
272 result.push_back(chan);
277 OSStatus JackCoreAudioDriver::Render(
void* inRefCon,
278 AudioUnitRenderActionFlags* ioActionFlags,
279 const AudioTimeStamp* inTimeStamp,
281 UInt32 inNumberFrames,
282 AudioBufferList* ioData)
284 return static_cast<JackCoreAudioDriver*
>(inRefCon)->Render(ioActionFlags, inTimeStamp, ioData);
287 OSStatus JackCoreAudioDriver::Render(AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, AudioBufferList* ioData)
289 fActionFags = ioActionFlags;
290 fCurrentTime = inTimeStamp;
291 fDriverOutputData = ioData;
294 if (set_threaded_log_function()) {
296 jack_log(
"JackCoreAudioDriver::Render : set_threaded_log_function");
297 JackMachThread::GetParams(pthread_self(), &fEngineControl->fPeriod, &fEngineControl->fComputation, &fEngineControl->fConstraint);
299 if (fComputationGrain > 0) {
300 jack_log(
"JackCoreAudioDriver::Render : RT thread computation setup to %d percent of period",
int(fComputationGrain * 100));
301 fEngineControl->fComputation = fEngineControl->fPeriod * fComputationGrain;
308 CycleTakeBeginTime();
312 NotifyFailure(JackFailure | JackBackendError,
"Process error, stopping driver");
314 kill(JackTools::GetPID(), SIGINT);
315 return kAudioHardwareUnsupportedOperationError;
321 int JackCoreAudioDriver::Read()
323 if (fCaptureChannels > 0) {
324 return (AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData) == noErr) ? 0 : -1;
330 int JackCoreAudioDriver::Write()
332 int size =
sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
337 jack_default_audio_sample_t* AC3_inputs[MAX_AC3_CHANNELS];
338 jack_default_audio_sample_t* AC3_outputs[2];
339 for (
int i = 0; i < fPlaybackChannels; i++) {
340 AC3_inputs[i] = GetOutputBuffer(i);
342 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) == 0) {
343 memset(AC3_inputs[i], 0, size);
346 AC3_outputs[0] = (jack_default_audio_sample_t*)fDriverOutputData->mBuffers[0].mData;
347 AC3_outputs[1] = (jack_default_audio_sample_t*)fDriverOutputData->mBuffers[1].mData;
348 fAC3Encoder->Process(AC3_inputs, AC3_outputs, fEngineControl->fBufferSize);
353 for (
int i = 0; i < fPlaybackChannels; i++) {
354 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
355 jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
356 memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
358 if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
359 memcpy(GetMonitorBuffer(i), buffer, size);
362 memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, size);
369 OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
372 AudioDevicePropertyID inPropertyID,
375 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
377 switch (inPropertyID) {
379 case kAudioDevicePropertyNominalSampleRate: {
380 jack_log(
"JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
382 Float64 tmp_sample_rate;
383 UInt32 outSize =
sizeof(Float64);
384 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
389 jack_log(
"JackCoreAudioDriver::SRNotificationCallback : checked sample rate = %f", tmp_sample_rate);
391 driver->fState =
true;
399 OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
402 AudioDevicePropertyID inPropertyID,
405 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
407 switch (inPropertyID) {
409 case kAudioDevicePropertyBufferFrameSize: {
410 jack_log(
"JackCoreAudioDriver::BSNotificationCallback kAudioDevicePropertyBufferFrameSize");
412 UInt32 tmp_buffer_size;
413 UInt32 outSize =
sizeof(UInt32);
414 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
419 jack_log(
"JackCoreAudioDriver::BSNotificationCallback : checked buffer size = %d", tmp_buffer_size);
421 driver->fState =
true;
430 OSStatus JackCoreAudioDriver::AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID,
void* inClientData)
432 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
434 switch (inPropertyID) {
436 case kAudioHardwarePropertyDevices: {
437 jack_log(
"JackCoreAudioDriver::AudioHardwareNotificationCallback kAudioHardwarePropertyDevices");
438 DisplayDeviceNames();
439 AudioDeviceID captureID, playbackID;
440 if (CheckAvailableDevice(driver->fDeviceID) ||
441 (CheckAvailableDeviceName(driver->fCaptureUID, &captureID)
442 && CheckAvailableDeviceName(driver->fPlaybackUID, &playbackID))) {
452 OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
455 AudioDevicePropertyID inPropertyID,
458 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
460 switch (inPropertyID) {
462 case kAudioDevicePropertyDeviceIsRunning: {
463 UInt32 isrunning = 0;
464 UInt32 outsize =
sizeof(UInt32);
465 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsRunning, &outsize, &isrunning) == noErr) {
466 jack_log(
"JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsRunning = %d", isrunning);
471 case kAudioDevicePropertyDeviceIsAlive: {
473 UInt32 outsize =
sizeof(UInt32);
474 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsAlive, &outsize, &isalive) == noErr) {
475 jack_log(
"JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsAlive = %d", isalive);
480 case kAudioDevicePropertyDeviceHasChanged: {
481 UInt32 hachanged = 0;
482 UInt32 outsize =
sizeof(UInt32);
483 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceHasChanged, &outsize, &hachanged) == noErr) {
484 jack_log(
"JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceHasChanged = %d", hachanged);
489 case kAudioDeviceProcessorOverload: {
490 jack_error(
"DeviceNotificationCallback kAudioDeviceProcessorOverload");
491 jack_time_t cur_time = GetMicroSeconds();
492 driver->NotifyXRun(cur_time,
float(cur_time - driver->fBeginDateUst));
496 case kAudioDevicePropertyStreamConfiguration: {
497 jack_error(
"Cannot handle kAudioDevicePropertyStreamConfiguration : server will quit...");
498 driver->NotifyFailure(JackFailure | JackBackendError,
"Another application has changed the device configuration");
499 driver->CloseAUHAL();
500 kill(JackTools::GetPID(), SIGINT);
501 return kAudioHardwareUnsupportedOperationError;
504 case kAudioDevicePropertyNominalSampleRate: {
505 Float64 sample_rate = 0;
506 UInt32 outsize =
sizeof(Float64);
507 OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
509 return kAudioHardwareUnsupportedOperationError;
512 char device_name[256];
513 const char* digidesign_name =
"Digidesign";
514 driver->GetDeviceNameFromID(driver->fDeviceID, device_name);
516 if (sample_rate != driver->fEngineControl->fSampleRate) {
519 if (strncmp(device_name, digidesign_name, 10) == 0) {
521 jack_log(
"JackCoreAudioDriver::DeviceNotificationCallback Digidesign HW = %s", device_name);
524 sample_rate = driver->fEngineControl->fSampleRate;
525 err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sample_rate);
527 jack_error(
"Cannot set sample rate = %f", sample_rate);
530 jack_log(
"JackCoreAudioDriver::DeviceNotificationCallback : set sample rate = %f", sample_rate);
534 outsize =
sizeof(Float64);
535 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
540 jack_log(
"JackCoreAudioDriver::DeviceNotificationCallback : checked sample rate = %f", sample_rate);
545 driver->NotifyFailure(JackFailure | JackBackendError,
"Another application has changed the sample rate");
546 driver->CloseAUHAL();
547 kill(JackTools::GetPID(), SIGINT);
548 return kAudioHardwareUnsupportedOperationError;
557 OSStatus JackCoreAudioDriver::GetDeviceIDFromUID(
const char* UID, AudioDeviceID*
id)
559 UInt32 size =
sizeof(AudioValueTranslation);
560 CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
561 AudioValueTranslation value = { &inIUD,
sizeof(CFStringRef),
id,
sizeof(AudioDeviceID) };
564 return kAudioHardwareUnspecifiedError;
566 OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
568 jack_log(
"JackCoreAudioDriver::GetDeviceIDFromUID %s %ld", UID, *
id);
569 return (*
id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
573 OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID*
id)
576 UInt32 theSize =
sizeof(UInt32);
577 AudioDeviceID inDefault;
578 AudioDeviceID outDefault;
580 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
584 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
588 jack_log(
"JackCoreAudioDriver::GetDefaultDevice : input = %ld output = %ld", inDefault, outDefault);
591 if (inDefault != outDefault) {
592 jack_error(
"Default input and output devices are not the same !!");
593 return kAudioHardwareBadDeviceError;
594 }
else if (inDefault == 0) {
595 jack_error(
"Default input and output devices are null !!");
596 return kAudioHardwareBadDeviceError;
603 OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID*
id)
606 UInt32 theSize =
sizeof(UInt32);
607 AudioDeviceID inDefault;
609 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
613 if (inDefault == 0) {
614 jack_error(
"Error default input device is 0, will take 'Built-in'...");
615 if (CheckAvailableDeviceName(
"Built-in Microphone",
id)
616 || CheckAvailableDeviceName(
"Built-in Line",
id)) {
617 jack_log(
"JackCoreAudioDriver::GetDefaultInputDevice : output = %ld", *
id);
620 jack_error(
"Cannot find any input device to use...");
624 jack_log(
"JackCoreAudioDriver::GetDefaultInputDevice : input = %ld ", inDefault);
629 OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID*
id)
632 UInt32 theSize =
sizeof(UInt32);
633 AudioDeviceID outDefault;
635 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
639 if (outDefault == 0) {
640 jack_error(
"Error default ouput device is 0, will take 'Built-in'...");
641 if (CheckAvailableDeviceName(
"Built-in Output",
id)) {
642 jack_log(
"JackCoreAudioDriver::GetDefaultOutputDevice : output = %ld", *
id);
645 jack_error(
"Cannot find any output device to use...");
649 jack_log(
"JackCoreAudioDriver::GetDefaultOutputDevice : output = %ld", outDefault);
654 OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID
id,
char* name)
657 return AudioDeviceGetProperty(
id, 0,
false, kAudioDevicePropertyDeviceName, &size, name);
660 OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device,
int& channelCount,
bool isInput)
662 OSStatus err = noErr;
667 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
669 int stream_count = outSize /
sizeof(AudioBufferList);
670 jack_log(
"JackCoreAudioDriver::GetTotalChannels stream_count = %d", stream_count);
671 AudioBufferList bufferList[stream_count];
672 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
674 for (uint i = 0; i < bufferList->mNumberBuffers; i++) {
675 channelCount += bufferList->mBuffers[i].mNumberChannels;
676 jack_log(
"JackCoreAudioDriver::GetTotalChannels stream = %d channels = %d", i, bufferList->mBuffers[i].mNumberChannels);
683 OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device,
bool isInput, vector<int>& latencies)
685 OSStatus err = noErr;
686 UInt32 outSize1, outSize2, outSize3;
689 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable);
691 int stream_count = outSize1 /
sizeof(UInt32);
692 AudioStreamID streamIDs[stream_count];
693 AudioBufferList bufferList[stream_count];
694 UInt32 streamLatency;
695 outSize2 =
sizeof(UInt32);
697 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs);
699 jack_error(
"GetStreamLatencies kAudioDevicePropertyStreams err = %d", err);
703 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable);
705 jack_error(
"GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
709 for (
int i = 0; i < stream_count; i++) {
710 err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency);
712 jack_error(
"GetStreamLatencies kAudioStreamPropertyLatency err = %d", err);
715 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList);
717 jack_error(
"GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
721 for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) {
722 latencies.push_back(streamLatency);
729 bool JackCoreAudioDriver::IsDigitalDevice(AudioDeviceID device)
731 OSStatus err = noErr;
733 bool is_digital =
false;
736 AudioObjectPropertyAddress streamsAddress = { kAudioDevicePropertyStreams, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
737 err = AudioObjectGetPropertyDataSize(device, &streamsAddress, 0, NULL, &outSize1);
739 jack_error(
"IsDigitalDevice kAudioDevicePropertyStreams err = %d", err);
743 int stream_count = outSize1 /
sizeof(AudioStreamID);
744 AudioStreamID streamIDs[stream_count];
746 err = AudioObjectGetPropertyData(device, &streamsAddress, 0, NULL, &outSize1, streamIDs);
749 jack_error(
"IsDigitalDevice kAudioDevicePropertyStreams list err = %d", err);
753 AudioObjectPropertyAddress physicalFormatsAddress = { kAudioStreamPropertyAvailablePhysicalFormats, kAudioObjectPropertyScopeGlobal, 0 };
755 for (
int i = 0; i < stream_count ; i++) {
761 err = AudioObjectGetPropertyDataSize(streamIDs[i], &physicalFormatsAddress, 0, NULL, &outSize1);
764 jack_error(
"IsDigitalDevice kAudioStreamPropertyAvailablePhysicalFormats err = %d", err);
768 format_num = outSize1 /
sizeof(AudioStreamRangedDescription);
769 AudioStreamRangedDescription format_list[format_num];
771 err = AudioObjectGetPropertyData(streamIDs[i], &physicalFormatsAddress, 0, NULL, &outSize1, format_list);
774 jack_error(
"IsDigitalDevice could not get the list of streamformats err = %d", err);
779 for (
int j = 0; j < format_num; j++) {
781 PrintStreamDesc(&format_list[j].mFormat);
783 if (format_list[j].mFormat.mFormatID ==
'IAC3' ||
784 format_list[j].mFormat.mFormatID ==
'iac3' ||
785 format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 ||
786 format_list[j].mFormat.mFormatID == kAudioFormatAC3)
797 JackCoreAudioDriver::JackCoreAudioDriver(
const char* name,
const char* alias, JackLockedEngine* engine, JackSynchro* table)
798 : JackAudioDriver(name, alias, engine, table),
800 fJackInputData(NULL),
801 fDriverOutputData(NULL),
806 fComputationGrain(-1.f),
807 fClockDriftCompensate(false),
808 fDigitalPlayback(false)
811 JackCoreAudioDriver::~JackCoreAudioDriver()
816 OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
818 OSStatus osErr = noErr;
819 AudioObjectPropertyAddress pluginAOPA;
820 pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
821 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
822 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
827 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
828 if (osErr != noErr) {
829 jack_error(
"DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
834 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
835 if (osErr != noErr) {
836 jack_error(
"DestroyAggregateDevice : AudioObjectGetPropertyData error");
846 OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
848 OSStatus err = noErr;
849 AudioObjectID sub_device[32];
850 UInt32 outSize =
sizeof(sub_device);
852 err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
853 vector<AudioDeviceID> captureDeviceIDArray;
855 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : input device %d", captureDeviceID);
858 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : input device does not have subdevices");
859 captureDeviceIDArray.push_back(captureDeviceID);
861 int num_devices = outSize /
sizeof(AudioObjectID);
862 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : input device has %d subdevices", num_devices);
863 for (
int i = 0; i < num_devices; i++) {
864 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : input sub_device %d", sub_device[i]);
865 captureDeviceIDArray.push_back(sub_device[i]);
869 outSize =
sizeof(sub_device);
870 err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
871 vector<AudioDeviceID> playbackDeviceIDArray;
873 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : output device %d", playbackDeviceID);
876 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : output device does not have subdevices");
877 playbackDeviceIDArray.push_back(playbackDeviceID);
879 int num_devices = outSize /
sizeof(AudioObjectID);
880 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : output device has %d subdevices", num_devices);
881 for (
int i = 0; i < num_devices; i++) {
882 jack_log(
"JackCoreAudioDriver::CreateAggregateDevice : output sub_device %d", sub_device[i]);
883 playbackDeviceIDArray.push_back(sub_device[i]);
887 return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
890 OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
892 OSStatus osErr = noErr;
898 AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
899 AudioObjectPropertyAddress theAddressDrift = { kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
900 UInt32 theQualifierDataSize =
sizeof(AudioObjectID);
901 AudioClassID inClass = kAudioSubDeviceClassID;
902 void* theQualifierData = &inClass;
903 UInt32 subDevicesNum = 0;
908 UInt32 keptclockdomain = 0;
909 UInt32 clockdomain = 0;
910 outSize =
sizeof(UInt32);
911 bool need_clock_drift_compensation =
false;
913 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
914 if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
915 jack_error(
"CreateAggregateDeviceAux : cannot set SR of input device");
918 osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
920 jack_error(
"CreateAggregateDeviceAux : kAudioDevicePropertyClockDomain error");
923 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
924 jack_log(
"JackCoreAudioDriver::CreateAggregateDeviceAux : input clockdomain = %d", clockdomain);
925 if (clockdomain != 0 && clockdomain != keptclockdomain) {
926 jack_error(
"CreateAggregateDeviceAux : devices do not share the same clock!! clock drift compensation would be needed...");
927 need_clock_drift_compensation =
true;
933 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
934 if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
935 jack_error(
"CreateAggregateDeviceAux : cannot set SR of output device");
938 osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
940 jack_error(
"CreateAggregateDeviceAux : kAudioDevicePropertyClockDomain error");
943 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
944 jack_log(
"JackCoreAudioDriver::CreateAggregateDeviceAux : output clockdomain = %d", clockdomain);
945 if (clockdomain != 0 && clockdomain != keptclockdomain) {
946 jack_error(
"CreateAggregateDeviceAux : devices do not share the same clock!! clock drift compensation would be needed...");
947 need_clock_drift_compensation =
true;
954 if (keptclockdomain == 0) {
955 need_clock_drift_compensation =
true;
962 char device_name[256];
963 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
964 GetDeviceNameFromID(captureDeviceID[i], device_name);
965 jack_info(
"Separated input = '%s' ", device_name);
968 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
969 GetDeviceNameFromID(playbackDeviceID[i], device_name);
970 jack_info(
"Separated output = '%s' ", device_name);
973 osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
974 if (osErr != noErr) {
975 jack_error(
"CreateAggregateDeviceAux : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
980 AudioValueTranslation pluginAVT;
982 CFStringRef inBundleRef = CFSTR(
"com.apple.audio.CoreAudio");
984 pluginAVT.mInputData = &inBundleRef;
985 pluginAVT.mInputDataSize =
sizeof(inBundleRef);
986 pluginAVT.mOutputData = &fPluginID;
987 pluginAVT.mOutputDataSize =
sizeof(fPluginID);
989 osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
990 if (osErr != noErr) {
991 jack_error(
"CreateAggregateDeviceAux : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
1000 CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1002 CFStringRef AggregateDeviceNameRef = CFSTR(
"JackDuplex");
1003 CFStringRef AggregateDeviceUIDRef = CFSTR(
"com.grame.JackDuplex");
1006 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
1009 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
1013 CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
1016 Gestalt(gestaltSystemVersion, &system);
1018 jack_log(
"JackCoreAudioDriver::CreateAggregateDeviceAux : system version = %x limit = %x", system, 0x00001054);
1021 if (system < 0x00001054) {
1022 jack_log(
"JackCoreAudioDriver::CreateAggregateDeviceAux : public aggregate device....");
1024 jack_log(
"JackCoreAudioDriver::CreateAggregateDeviceAux : private aggregate device....");
1025 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
1029 CFMutableArrayRef subDevicesArrayClock = NULL;
1072 CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1074 vector<CFStringRef> captureDeviceUID;
1075 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
1076 CFStringRef ref = GetDeviceName(captureDeviceID[i]);
1080 captureDeviceUID.push_back(ref);
1082 CFArrayAppendValue(subDevicesArray, ref);
1085 vector<CFStringRef> playbackDeviceUID;
1086 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
1087 CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
1091 playbackDeviceUID.push_back(ref);
1093 CFArrayAppendValue(subDevicesArray, ref);
1100 AudioObjectPropertyAddress pluginAOPA;
1101 pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
1102 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1103 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1106 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
1107 if (osErr != noErr) {
1108 jack_error(
"CreateAggregateDeviceAux : AudioObjectGetPropertyDataSize error");
1113 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA,
sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
1114 if (osErr != noErr) {
1115 jack_error(
"CreateAggregateDeviceAux : AudioObjectGetPropertyData error");
1122 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1,
false);
1128 pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList;
1129 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1130 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1131 outDataSize =
sizeof(CFMutableArrayRef);
1132 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
1133 if (osErr != noErr) {
1134 jack_error(
"CreateAggregateDeviceAux : AudioObjectSetPropertyData for sub-device list error");
1140 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1,
false);
1148 pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
1149 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1150 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1151 outDataSize =
sizeof(CFStringRef);
1152 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]);
1153 if (osErr != noErr) {
1154 jack_error(
"CreateAggregateDeviceAux : AudioObjectSetPropertyData for master device error");
1160 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1,
false);
1165 if (fClockDriftCompensate) {
1166 if (need_clock_drift_compensation) {
1167 jack_info(
"Clock drift compensation activated...");
1170 osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
1171 if (osErr != noErr) {
1172 jack_error(
"CreateAggregateDeviceAux kAudioObjectPropertyOwnedObjects error");
1177 subDevicesNum = outSize /
sizeof(AudioObjectID);
1178 jack_info(
"JackCoreAudioDriver::CreateAggregateDeviceAux clock drift compensation, number of sub-devices = %d", subDevicesNum);
1179 AudioObjectID subDevices[subDevicesNum];
1180 outSize =
sizeof(subDevices);
1182 osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
1183 if (osErr != noErr) {
1184 jack_error(
"CreateAggregateDeviceAux kAudioObjectPropertyOwnedObjects error");
1189 for (UInt32 index = 0; index < subDevicesNum; ++index) {
1190 UInt32 theDriftCompensationValue = 1;
1191 osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL,
sizeof(UInt32), &theDriftCompensationValue);
1192 if (osErr != noErr) {
1193 jack_error(
"CreateAggregateDeviceAux kAudioSubDevicePropertyDriftCompensation error");
1198 jack_info(
"Clock drift compensation was asked but is not needed (devices use the same clock domain)");
1203 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1,
false);
1210 CFRelease(AggregateDeviceNumberRef);
1213 CFRelease(aggDeviceDict);
1214 CFRelease(subDevicesArray);
1216 if (subDevicesArrayClock) {
1217 CFRelease(subDevicesArrayClock);
1221 for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
1222 CFRelease(captureDeviceUID[i]);
1225 for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
1226 CFRelease(playbackDeviceUID[i]);
1229 jack_log(
"JackCoreAudioDriver::CreateAggregateDeviceAux : new aggregate device %ld", *outAggregateDevice);
1233 DestroyAggregateDevice();
1237 int JackCoreAudioDriver::SetupDevices(
const char* capture_driver_uid,
1238 const char* playback_driver_uid,
1239 char* capture_driver_name,
1240 char* playback_driver_name,
1241 jack_nframes_t samplerate,
1244 capture_driver_name[0] = 0;
1245 playback_driver_name[0] = 0;
1248 if (strcmp(capture_driver_uid,
"") != 0 && strcmp(playback_driver_uid,
"") != 0) {
1249 jack_log(
"JackCoreAudioDriver::SetupDevices : duplex");
1252 if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
1254 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
1255 jack_log(
"JackCoreAudioDriver::SetupDevices : will take default in/out");
1256 if (GetDefaultDevice(&fDeviceID) != noErr) {
1262 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
1263 jack_error(
"Cannot get device name from device ID");
1268 if (!TakeHogAux(fDeviceID,
false)) {
1272 fDigitalPlayback = IsDigitalDevice(fDeviceID);
1279 AudioDeviceID captureID = -1;
1280 AudioDeviceID playbackID = -1;
1282 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
1283 jack_log(
"JackCoreAudioDriver::SetupDevices : will take default input");
1284 if (GetDefaultInputDevice(&captureID) != noErr) {
1285 jack_error(
"Cannot open default input device");
1290 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
1291 jack_log(
"JackCoreAudioDriver::SetupDevices : will take default output");
1292 if (GetDefaultOutputDevice(&playbackID) != noErr) {
1293 jack_error(
"Cannot open default output device");
1298 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1302 GetDeviceNameFromID(captureID, fCaptureUID);
1303 GetDeviceNameFromID(playbackID, fPlaybackUID);
1306 if (!TakeHogAux(captureID,
true)) {
1307 jack_error(
"Cannot take hog mode for capture device");
1309 if (!TakeHogAux(playbackID,
false)) {
1310 jack_error(
"Cannot take hog mode for playback device");
1313 fDigitalPlayback = IsDigitalDevice(playbackID);
1320 }
else if (strcmp(capture_driver_uid,
"") != 0) {
1322 jack_log(
"JackCoreAudioDriver::SetupDevices : capture only");
1323 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
1324 jack_log(
"JackCoreAudioDriver::SetupDevices : will take default input");
1325 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
1326 jack_error(
"Cannot open default input device");
1331 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
1332 jack_error(
"Cannot get device name from device ID");
1337 if (!TakeHogAux(fDeviceID,
true)) {
1338 jack_error(
"Cannot take hog mode for capture device");
1343 }
else if (strcmp(playback_driver_uid,
"") != 0) {
1345 jack_log(
"JackCoreAudioDriver::SetupDevices : playback only");
1346 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
1347 jack_log(
"JackCoreAudioDriver::SetupDevices : will take default output");
1348 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
1349 jack_error(
"Cannot open default output device");
1354 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
1355 jack_error(
"Cannot get device name from device ID");
1360 if (!TakeHogAux(fDeviceID,
false)) {
1361 jack_error(
"Cannot take hog mode for playback device");
1364 fDigitalPlayback = IsDigitalDevice(fDeviceID);
1370 jack_log(
"JackCoreAudioDriver::SetupDevices : default driver");
1371 if (GetDefaultDevice(&fDeviceID) != noErr) {
1372 jack_error(
"Cannot open default device in duplex mode, so aggregate default input and default output");
1375 AudioDeviceID captureID = -1;
1376 AudioDeviceID playbackID = -1;
1378 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
1379 jack_log(
"JackCoreAudioDriver::SetupDevices : will take default input");
1380 if (GetDefaultInputDevice(&captureID) != noErr) {
1381 jack_error(
"Cannot open default input device");
1386 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
1387 jack_log(
"JackCoreAudioDriver::SetupDevices : will take default output");
1388 if (GetDefaultOutputDevice(&playbackID) != noErr) {
1389 jack_error(
"Cannot open default output device");
1394 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1398 GetDeviceNameFromID(captureID, fCaptureUID);
1399 GetDeviceNameFromID(playbackID, fPlaybackUID);
1402 if (!TakeHogAux(captureID,
true)) {
1403 jack_error(
"Cannot take hog mode for capture device");
1405 if (!TakeHogAux(playbackID,
false)) {
1406 jack_error(
"Cannot take hog mode for playback device");
1409 fDigitalPlayback = IsDigitalDevice(playbackID);
1421 int JackCoreAudioDriver::SetupChannels(
bool capturing,
bool playing,
int& inchannels,
int& outchannels,
int& in_maxChannels,
int& out_maxChannels,
bool strict)
1423 OSStatus err = noErr;
1425 jack_log(
"JackCoreAudioDriver::SetupChannels : fDeviceID = %d", fDeviceID);
1428 err = GetTotalChannels(fDeviceID, in_maxChannels,
true);
1430 jack_error(
"SetupChannels : cannot get input channel number");
1434 jack_log(
"JackCoreAudioDriver::SetupChannels : max input channels : %d", in_maxChannels);
1439 err = GetTotalChannels(fDeviceID, out_maxChannels,
false);
1441 jack_error(
"Cannot get output channel number");
1445 jack_log(
"JackCoreAudioDriver::SetupChannels : max output channels : %d", out_maxChannels);
1449 if (inchannels > in_maxChannels) {
1450 jack_error(
"This device hasn't required input channels inchannels = %d in_maxChannels = %d", inchannels, in_maxChannels);
1456 if (outchannels > out_maxChannels) {
1457 jack_error(
"This device hasn't required output channels outchannels = %d out_maxChannels = %d", outchannels, out_maxChannels);
1463 if (inchannels == -1) {
1464 jack_log(
"JackCoreAudioDriver::SetupChannels : setup max in channels = %d", in_maxChannels);
1465 inchannels = in_maxChannels;
1468 if (outchannels == -1) {
1469 jack_log(
"JackCoreAudioDriver::SetupChannels : setup max out channels = %d", out_maxChannels);
1470 outchannels = out_maxChannels;
1476 int JackCoreAudioDriver::SetupBufferSize(jack_nframes_t buffer_size)
1479 OSStatus err = noErr;
1480 UInt32 tmp_buffer_size = buffer_size;
1481 UInt32 outSize =
sizeof(UInt32);
1483 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
1485 jack_error(
"Cannot get buffer size %ld", buffer_size);
1489 jack_log(
"JackCoreAudioDriver::SetupBufferSize : current buffer size = %ld", tmp_buffer_size);
1493 if (buffer_size != tmp_buffer_size) {
1494 tmp_buffer_size = buffer_size;
1497 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback,
this);
1499 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyBufferFrameSize");
1508 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, outSize, &tmp_buffer_size);
1510 jack_error(
"SetupBufferSize : cannot set buffer size = %ld", tmp_buffer_size);
1515 while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1517 jack_log(
"JackCoreAudioDriver::SetupBufferSize : wait count = %d", count);
1520 if (count >= WAIT_NOTIFICATION_COUNTER) {
1521 jack_error(
"Did not get buffer size notification...");
1526 outSize =
sizeof(UInt32);
1527 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
1529 jack_error(
"Cannot get current buffer size");
1532 jack_log(
"JackCoreAudioDriver::SetupBufferSize : checked buffer size = %ld", tmp_buffer_size);
1536 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1544 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1548 int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t sample_rate)
1550 return SetupSampleRateAux(fDeviceID, sample_rate);
1553 int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t sample_rate)
1555 OSStatus err = noErr;
1557 Float64 tmp_sample_rate;
1560 outSize =
sizeof(Float64);
1561 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
1563 jack_error(
"Cannot get current sample rate");
1567 jack_log(
"JackCoreAudioDriver::SetupSampleRateAux : current sample rate = %f", tmp_sample_rate);
1571 if (sample_rate != (jack_nframes_t)tmp_sample_rate) {
1572 tmp_sample_rate = (Float64)sample_rate;
1575 err = AudioDeviceAddPropertyListener(inDevice, 0,
true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback,
this);
1577 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
1586 err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &tmp_sample_rate);
1588 jack_error(
"Cannot set sample rate = %ld", sample_rate);
1593 while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1595 jack_log(
"JackCoreAudioDriver::SetupSampleRateAux : wait count = %d", count);
1598 if (count >= WAIT_NOTIFICATION_COUNTER) {
1599 jack_error(
"Did not get sample rate notification...");
1604 outSize =
sizeof(Float64);
1605 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
1607 jack_error(
"Cannot get current sample rate");
1610 jack_log(
"JackCoreAudioDriver::SetupSampleRateAux : checked sample rate = %f", tmp_sample_rate);
1614 AudioDeviceRemovePropertyListener(inDevice, 0,
true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1622 AudioDeviceRemovePropertyListener(inDevice, 0,
true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1626 int JackCoreAudioDriver::OpenAUHAL(
bool capturing,
1631 int out_maxChannels,
1632 const vector<int>& chan_in_list,
1633 const vector<int>& chan_out_list,
1634 jack_nframes_t buffer_size,
1635 jack_nframes_t sample_rate)
1637 ComponentResult err1;
1639 AudioStreamBasicDescription srcFormat, dstFormat;
1640 AudioDeviceID currAudioDeviceID;
1643 jack_log(
"JackCoreAudioDriver::OpenAUHAL : capturing = %d playing = %d inchannels = %d outchannels = %d in_maxChannels = %d out_maxChannels = %d chan_in_list = %d chan_out_list = %d",
1644 capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, chan_in_list.size(), chan_out_list.size());
1646 if (inchannels == 0 && outchannels == 0) {
1647 jack_error(
"No input and output channels...");
1652 #ifdef MAC_OS_X_VERSION_10_5 1653 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
1654 Component HALOutput = FindNextComponent(NULL, &cd);
1655 err1 = OpenAComponent(HALOutput, &fAUHAL);
1656 if (err1 != noErr) {
1662 AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
1663 AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd);
1664 err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL);
1665 if (err1 != noErr) {
1666 jack_error(
"Error calling AudioComponentInstanceNew");
1672 err1 = AudioUnitInitialize(fAUHAL);
1673 if (err1 != noErr) {
1680 if (capturing && inchannels > 0) {
1682 jack_log(
"JackCoreAudioDriver::OpenAUHAL : setup AUHAL input on");
1685 jack_log(
"JackCoreAudioDriver::OpenAUHAL : setup AUHAL input off");
1688 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO,
sizeof(enableIO));
1689 if (err1 != noErr) {
1690 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
1695 if (playing && outchannels > 0) {
1697 jack_log(
"JackCoreAudioDriver::OpenAUHAL : setup AUHAL output on");
1700 jack_log(
"JackCoreAudioDriver::OpenAUHAL : setup AUHAL output off");
1703 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO,
sizeof(enableIO));
1704 if (err1 != noErr) {
1705 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output");
1710 size =
sizeof(AudioDeviceID);
1711 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
1712 if (err1 != noErr) {
1713 jack_error(
"Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
1717 jack_log(
"JackCoreAudioDriver::OpenAUHAL : AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
1721 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID,
sizeof(AudioDeviceID));
1722 if (err1 != noErr) {
1723 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
1729 if (capturing && inchannels > 0) {
1730 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size,
sizeof(UInt32));
1731 if (err1 != noErr) {
1732 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
1738 if (playing && outchannels > 0) {
1739 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size,
sizeof(UInt32));
1740 if (err1 != noErr) {
1741 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
1748 if (capturing && inchannels > 0 && inchannels <= in_maxChannels) {
1749 SInt32 chanArr[in_maxChannels];
1750 for (
int i = 0; i < in_maxChannels; i++) {
1754 if (chan_in_list.size() > 0) {
1755 for (uint i = 0; i < chan_in_list.size(); i++) {
1756 int chan = chan_in_list[i];
1757 if (chan < in_maxChannels) {
1760 jack_info(
"Input channel = %d ==> JACK input port = %d", chan, i);
1762 jack_info(
"Error input channel number is incorrect : %d", chan);
1767 for (
int i = 0; i < inchannels; i++) {
1769 jack_info(
"Input channel = %d ==> JACK input port = %d", chanArr[i], i);
1773 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr,
sizeof(SInt32) * in_maxChannels);
1774 if (err1 != noErr) {
1775 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for input");
1782 if (playing && outchannels > 0 && outchannels <= out_maxChannels) {
1783 SInt32 chanArr[out_maxChannels];
1784 for (
int i = 0; i < out_maxChannels; i++) {
1788 if (chan_out_list.size() > 0) {
1789 for (uint i = 0; i < chan_out_list.size(); i++) {
1790 int chan = chan_out_list[i];
1791 if (chan < out_maxChannels) {
1794 jack_info(
"JACK output port = %d ==> output channel = %d", i, chan);
1796 jack_info(
"Error output channel number is incorrect : %d", chan);
1801 for (
int i = 0; i < outchannels; i++) {
1803 jack_info(
"JACK output port = %d ==> output channel = %d", i, chanArr[i]);
1807 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr,
sizeof(SInt32) * out_maxChannels);
1808 if (err1 != noErr) {
1809 jack_error(
"Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for output");
1816 if (capturing && inchannels > 0) {
1818 size =
sizeof(AudioStreamBasicDescription);
1819 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &size);
1820 if (err1 != noErr) {
1821 jack_error(
"Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
1825 PrintStreamDesc(&srcFormat);
1827 jack_log(
"JackCoreAudioDriver::OpenAUHAL : setup AUHAL input stream converter SR = %ld", sample_rate);
1828 srcFormat.mSampleRate = sample_rate;
1829 srcFormat.mFormatID = kAudioFormatLinearPCM;
1830 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1831 srcFormat.mBytesPerPacket =
sizeof(jack_default_audio_sample_t);
1832 srcFormat.mFramesPerPacket = 1;
1833 srcFormat.mBytesPerFrame =
sizeof(jack_default_audio_sample_t);
1834 srcFormat.mChannelsPerFrame = inchannels;
1835 srcFormat.mBitsPerChannel = 32;
1836 PrintStreamDesc(&srcFormat);
1838 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat,
sizeof(AudioStreamBasicDescription));
1839 if (err1 != noErr) {
1840 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
1846 if (playing && outchannels > 0) {
1848 size =
sizeof(AudioStreamBasicDescription);
1849 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &size);
1850 if (err1 != noErr) {
1851 jack_error(
"Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
1855 PrintStreamDesc(&dstFormat);
1857 jack_log(
"JackCoreAudioDriver::OpenAUHAL : setup AUHAL output stream converter SR = %ld", sample_rate);
1858 dstFormat.mSampleRate = sample_rate;
1859 dstFormat.mFormatID = kAudioFormatLinearPCM;
1860 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1861 dstFormat.mBytesPerPacket =
sizeof(jack_default_audio_sample_t);
1862 dstFormat.mFramesPerPacket = 1;
1863 dstFormat.mBytesPerFrame =
sizeof(jack_default_audio_sample_t);
1864 dstFormat.mChannelsPerFrame = outchannels;
1865 dstFormat.mBitsPerChannel = 32;
1866 PrintStreamDesc(&dstFormat);
1868 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat,
sizeof(AudioStreamBasicDescription));
1869 if (err1 != noErr) {
1870 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
1877 if (inchannels > 0 && outchannels == 0) {
1878 AURenderCallbackStruct output;
1879 output.inputProc = Render;
1880 output.inputProcRefCon =
this;
1881 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output,
sizeof(output));
1882 if (err1 != noErr) {
1883 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
1888 AURenderCallbackStruct output;
1889 output.inputProc = Render;
1890 output.inputProcRefCon =
this;
1891 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output,
sizeof(output));
1892 if (err1 != noErr) {
1893 jack_error(
"Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
1906 int JackCoreAudioDriver::SetupBuffers(
int inchannels)
1909 fJackInputData = (AudioBufferList*)malloc(
sizeof(UInt32) + inchannels *
sizeof(AudioBuffer));
1910 fJackInputData->mNumberBuffers = inchannels;
1911 for (
int i = 0; i < inchannels; i++) {
1912 fJackInputData->mBuffers[i].mNumberChannels = 1;
1913 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize *
sizeof(jack_default_audio_sample_t);
1918 void JackCoreAudioDriver::DisposeBuffers()
1920 if (fJackInputData) {
1921 free(fJackInputData);
1926 void JackCoreAudioDriver::CloseAUHAL()
1928 AudioOutputUnitStop(fAUHAL);
1929 AudioUnitUninitialize(fAUHAL);
1930 CloseComponent(fAUHAL);
1933 int JackCoreAudioDriver::AddListeners()
1935 OSStatus err = noErr;
1938 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDeviceProcessorOverload, DeviceNotificationCallback,
this);
1940 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
1945 err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback,
this);
1947 jack_error(
"Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
1952 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback,
this);
1954 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
1959 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback,
this);
1961 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
1966 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback,
this);
1968 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsAlive");
1973 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback,
this);
1975 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceHasChanged");
1980 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback,
this);
1982 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
1987 err = AudioDeviceAddPropertyListener(fDeviceID, 0,
false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback,
this);
1989 jack_error(
"Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
1994 if (!fEngineControl->fSyncMode && fIOUsage != 1.f) {
1995 UInt32 outSize =
sizeof(float);
1996 err = AudioDeviceSetProperty(fDeviceID, NULL, 0,
false, kAudioDevicePropertyIOCycleUsage, outSize, &fIOUsage);
1998 jack_error(
"Error calling AudioDeviceSetProperty kAudioDevicePropertyIOCycleUsage");
2006 void JackCoreAudioDriver::RemoveListeners()
2008 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
2009 AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback);
2010 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
2011 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
2012 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback);
2013 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback);
2014 AudioDeviceRemovePropertyListener(fDeviceID, 0,
true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
2015 AudioDeviceRemovePropertyListener(fDeviceID, 0,
false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
2018 int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
2019 jack_nframes_t sample_rate,
2024 const char* chan_in_list,
2025 const char* chan_out_list,
2027 const char* capture_driver_uid,
2028 const char* playback_driver_uid,
2029 jack_nframes_t capture_latency,
2030 jack_nframes_t playback_latency,
2031 int async_output_latency,
2032 int computation_grain,
2039 int in_maxChannels = 0;
2040 int out_maxChannels = 0;
2041 char capture_driver_name[256];
2042 char playback_driver_name[256];
2044 fCaptureLatency = capture_latency;
2045 fPlaybackLatency = playback_latency;
2046 fIOUsage = float(async_output_latency) / 100.f;
2047 fComputationGrain = float(computation_grain) / 100.f;
2049 fClockDriftCompensate = clock_drift;
2053 Gestalt(gestaltSystemVersionMajor, &major);
2054 Gestalt(gestaltSystemVersionMinor, &minor);
2056 vector<int> parsed_chan_in_list;
2057 vector<int> parsed_chan_out_list;
2060 if (major == 10 && minor >= 6) {
2061 CFRunLoopRef theRunLoop = NULL;
2062 AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
2063 OSStatus osErr = AudioObjectSetPropertyData (kAudioObjectSystemObject, &theAddress, 0, NULL,
sizeof(CFRunLoopRef), &theRunLoop);
2064 if (osErr != noErr) {
2065 jack_error(
"Open kAudioHardwarePropertyRunLoop error");
2070 if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate, ac3_encoding) < 0) {
2075 if (JackAudioDriver::Open(buffer_size, sample_rate,
2077 inchannels, outchannels,
2079 capture_driver_name,
2080 playback_driver_name,
2082 playback_latency) != 0) {
2086 if (SetupChannels(capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, !ac3_encoding) < 0) {
2090 ParseChannelList(chan_in_list, parsed_chan_in_list, in_maxChannels);
2091 if (parsed_chan_in_list.size() > 0) {
2092 jack_info(
"Explicit input channel list size = %d", parsed_chan_in_list.size());
2093 inchannels = parsed_chan_in_list.size();
2096 ParseChannelList(chan_out_list, parsed_chan_out_list, out_maxChannels);
2097 if (parsed_chan_out_list.size() > 0) {
2098 jack_info(
"Explicit output channel list size = %d", parsed_chan_out_list.size());
2099 outchannels = parsed_chan_out_list.size();
2102 if (SetupBufferSize(buffer_size) < 0) {
2106 if (SetupSampleRate(sample_rate) < 0) {
2112 if (!fDigitalPlayback) {
2113 jack_error(
"AC3 encoding can only be used with a digital device");
2117 JackAC3EncoderParams params;
2118 memset(¶ms, 0,
sizeof(JackAC3EncoderParams));
2119 params.bitrate = ac3_bitrate;
2120 params.channels = outchannels;
2121 params.sample_rate = sample_rate;
2122 params.lfe = ac3_lfe;
2123 fAC3Encoder =
new JackAC3Encoder(params);
2125 if (!fAC3Encoder || !fAC3Encoder->Init(sample_rate)) {
2126 jack_error(
"Cannot allocate or init AC3 encoder");
2131 fPlaybackChannels = outchannels;
2133 fPlaybackChannels++;
2136 if (fPlaybackChannels < 2 || fPlaybackChannels > 6) {
2137 jack_error(
"AC3 encoder channels must be between 2 and 6");
2142 outchannels = out_maxChannels = 2;
2145 fPlaybackChannels = outchannels;
2149 fCaptureChannels = inchannels;
2151 if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) {
2155 if (capturing && inchannels > 0) {
2156 if (SetupBuffers(inchannels) < 0) {
2161 if (AddListeners() < 0) {
2172 int JackCoreAudioDriver::Close()
2174 jack_log(
"JackCoreAudioDriver::Close");
2177 int res = JackAudioDriver::Close();
2182 DestroyAggregateDevice();
2186 void JackCoreAudioDriver::UpdateLatencies()
2195 size =
sizeof(UInt32);
2198 err = AudioDeviceGetProperty(fDeviceID, 0,
true, kAudioDevicePropertyLatency, &size, &value1);
2200 jack_error(
"AudioDeviceGetProperty kAudioDevicePropertyLatency error");
2202 err = AudioDeviceGetProperty(fDeviceID, 0,
true, kAudioDevicePropertySafetyOffset, &size, &value2);
2204 jack_error(
"AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
2207 input_range.
min = input_range.
max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
2210 vector<int> input_latencies;
2211 err = GetStreamLatencies(fDeviceID,
true, input_latencies);
2213 for (
int i = 0; i < fCaptureChannels; i++) {
2215 input_range.
min += input_latencies[i];
2216 input_range.
max += input_latencies[i];
2218 fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
2222 size =
sizeof(UInt32);
2225 err = AudioDeviceGetProperty(fDeviceID, 0,
false, kAudioDevicePropertyLatency, &size, &value1);
2227 jack_error(
"AudioDeviceGetProperty kAudioDevicePropertyLatency error");
2229 err = AudioDeviceGetProperty(fDeviceID, 0,
false, kAudioDevicePropertySafetyOffset, &size, &value2);
2231 jack_error(
"AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
2235 vector<int> output_latencies;
2236 err = GetStreamLatencies(fDeviceID,
false, output_latencies);
2239 output_range.
min = output_range.
max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode)
2240 ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency;
2242 for (
int i = 0; i < fPlaybackChannels; i++) {
2244 output_range.
min += output_latencies[i];
2245 output_range.
max += output_latencies[i];
2247 fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
2250 if (fWithMonitorPorts) {
2251 monitor_range.
min = monitor_range.
max = fEngineControl->fBufferSize;
2252 fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
2257 int JackCoreAudioDriver::Attach()
2261 jack_port_id_t port_index;
2264 char channel_name[64];
2265 char name[REAL_JACK_PORT_NAME_SIZE];
2266 char alias[REAL_JACK_PORT_NAME_SIZE];
2268 jack_log(
"JackCoreAudioDriver::Attach : fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
2270 for (
int i = 0; i < fCaptureChannels; i++) {
2272 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1,
true, kAudioDevicePropertyChannelName, &size, &isWritable);
2274 jack_log(
"JackCoreAudioDriver::Attach : AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
2276 if (err == noErr && size > 0) {
2277 err = AudioDeviceGetProperty(fDeviceID, i + 1,
true, kAudioDevicePropertyChannelName, &size, channel_name);
2279 jack_log(
"JackCoreAudioDriver::Attach : AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
2281 snprintf(alias,
sizeof(alias),
"%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
2283 snprintf(alias,
sizeof(alias),
"%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
2286 snprintf(name,
sizeof(name),
"%s:capture_%d", fClientControl.fName, i + 1);
2288 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
2289 jack_error(
"Cannot register port for %s", name);
2293 port = fGraphManager->GetPort(port_index);
2294 port->SetAlias(alias);
2295 fCapturePortList[i] = port_index;
2298 for (
int i = 0; i < fPlaybackChannels; i++) {
2300 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1,
false, kAudioDevicePropertyChannelName, &size, &isWritable);
2302 jack_log(
"JackCoreAudioDriver::Attach : AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
2304 if (err == noErr && size > 0) {
2305 err = AudioDeviceGetProperty(fDeviceID, i + 1,
false, kAudioDevicePropertyChannelName, &size, channel_name);
2307 jack_log(
"JackCoreAudioDriver::Attach : AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
2309 snprintf(alias,
sizeof(alias),
"%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
2311 snprintf(alias,
sizeof(alias),
"%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
2314 snprintf(name,
sizeof(name),
"%s:playback_%d", fClientControl.fName, i + 1);
2316 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
2317 jack_error(
"Cannot register port for %s", name);
2321 port = fGraphManager->GetPort(port_index);
2322 port->SetAlias(alias);
2323 fPlaybackPortList[i] = port_index;
2326 if (fWithMonitorPorts) {
2327 jack_log(
"JackCoreAudioDriver::Attach : create monitor port");
2328 snprintf(name,
sizeof(name),
"%s:monitor_%u", fClientControl.fName, i + 1);
2329 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
2330 jack_error(
"Cannot register monitor port for %s", name);
2333 fMonitorPortList[i] = port_index;
2340 for (
int i = 0; i < fPlaybackChannels; i++) {
2341 fAC3Encoder->GetChannelName(
"coreaudio",
"", alias, i);
2342 port = fGraphManager->GetPort(fPlaybackPortList[i]);
2343 port->SetAlias(alias);
2350 for (
int i = 0; i < fCaptureChannels; i++) {
2351 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
2357 int JackCoreAudioDriver::Start()
2359 jack_log(
"JackCoreAudioDriver::Start");
2360 if (JackAudioDriver::Start() == 0) {
2366 if (AudioOutputUnitStart(fAUHAL) == noErr) {
2368 while (!fState && count++ < WAIT_COUNTER) {
2370 jack_log(
"JackCoreAudioDriver::Start : wait count = %d", count);
2373 if (count < WAIT_COUNTER) {
2374 jack_info(
"CoreAudio driver is running...");
2378 jack_error(
"CoreAudio driver cannot start...");
2380 JackAudioDriver::Stop();
2385 int JackCoreAudioDriver::Stop()
2387 jack_log(
"JackCoreAudioDriver::Stop");
2388 int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
2389 if (JackAudioDriver::Stop() < 0) {
2395 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
2397 if (SetupBufferSize(buffer_size) < 0) {
2401 JackAudioDriver::SetBufferSize(buffer_size);
2407 for (
int i = 0; i < fCaptureChannels; i++) {
2408 fJackInputData->mBuffers[i].mNumberChannels = 1;
2409 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize *
sizeof(jack_default_audio_sample_t);
2410 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
2416 bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID,
bool isInput)
2419 UInt32 propSize =
sizeof(hog_pid);
2421 OSStatus err = AudioDeviceGetProperty(deviceID, 0, isInput, kAudioDevicePropertyHogMode, &propSize, &hog_pid);
2427 jack_log(
"JackCoreAudioDriver::TakeHogAux : deviceID = %d", deviceID);
2429 if (hog_pid != getpid()) {
2431 err = AudioDeviceSetProperty(deviceID, 0, 0, isInput, kAudioDevicePropertyHogMode, propSize, &hog_pid);
2433 jack_error(
"Can't hog device = %d because it's being hogged by another program or cannot be hogged", deviceID);
2441 bool JackCoreAudioDriver::TakeHog()
2443 OSStatus err = noErr;
2444 AudioObjectID sub_device[32];
2445 UInt32 outSize =
sizeof(sub_device);
2446 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
2449 jack_log(
"JackCoreAudioDriver::TakeHog : device does not have subdevices");
2450 return TakeHogAux(fDeviceID,
true);
2452 int num_devices = outSize /
sizeof(AudioObjectID);
2453 jack_log(
"JackCoreAudioDriver::TakeHog : device does has %d subdevices", num_devices);
2454 for (
int i = 0; i < num_devices; i++) {
2455 if (!TakeHogAux(sub_device[i],
true)) {
2463 bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
2465 UInt32 deviceType, outSize =
sizeof(UInt32);
2466 OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
2469 jack_log(
"JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
2472 return (deviceType == kAudioDeviceTransportTypeAggregate);
2491 desc = jack_driver_descriptor_construct(
"coreaudio", JackDriverMaster,
"Apple CoreAudio API based audio backend", &filler);
2494 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");
2495 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");
2496 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");
2499 jack_driver_descriptor_add_parameter(desc, &filler,
"input-list",
'n', JackDriverParamString, &value, NULL,
"Input channel list for channel mapping",
"List of input channel number to be opened (syntax like : \"0 3 2\")");
2500 jack_driver_descriptor_add_parameter(desc, &filler,
"output-list",
'N', JackDriverParamString, &value, NULL,
"Output channel list for channel mapping",
"List of output channel number to be opened (syntax like : \"0 3 2\")");
2503 jack_driver_descriptor_add_parameter(desc, &filler,
"capture",
'C', JackDriverParamString, &value, NULL,
"Input CoreAudio device name", NULL);
2504 jack_driver_descriptor_add_parameter(desc, &filler,
"playback",
'P', JackDriverParamString, &value, NULL,
"Output CoreAudio device name", NULL);
2507 jack_driver_descriptor_add_parameter(desc, &filler,
"monitor",
'm', JackDriverParamBool, &value, NULL,
"Provide monitor ports for the output", NULL);
2511 jack_driver_descriptor_add_parameter(desc, &filler,
"AC3-encoding",
'a', JackDriverParamBool, &value, NULL,
"AC3 multi-channels encoding", NULL);
2514 jack_driver_descriptor_add_parameter(desc, &filler,
"AC3-bitrate",
'b', JackDriverParamUInt, &value, NULL,
"AC3 bitrate", NULL);
2517 jack_driver_descriptor_add_parameter(desc, &filler,
"AC3-LFE",
'f', JackDriverParamBool, &value, NULL,
"AC3 LFE channel", NULL);
2520 jack_driver_descriptor_add_parameter(desc, &filler,
"duplex",
'D', JackDriverParamBool, &value, NULL,
"Provide both capture and playback ports", NULL);
2523 jack_driver_descriptor_add_parameter(desc, &filler,
"rate",
'r', JackDriverParamUInt, &value, NULL,
"Sample rate", NULL);
2526 jack_driver_descriptor_add_parameter(desc, &filler,
"period",
'p', JackDriverParamUInt, &value, NULL,
"Frames per period", NULL);
2529 jack_driver_descriptor_add_parameter(desc, &filler,
"device",
'd', JackDriverParamString, &value, NULL,
"CoreAudio device name", NULL);
2532 jack_driver_descriptor_add_parameter(desc, &filler,
"input-latency",
'I', JackDriverParamUInt, &value, NULL,
"Extra input latency (frames)", NULL);
2533 jack_driver_descriptor_add_parameter(desc, &filler,
"output-latency",
'O', JackDriverParamUInt, &value, NULL,
"Extra output latency (frames)", NULL);
2536 jack_driver_descriptor_add_parameter(desc, &filler,
"list-devices",
'l', JackDriverParamBool, &value, NULL,
"Display available CoreAudio devices", NULL);
2539 jack_driver_descriptor_add_parameter(desc, &filler,
"hog",
'H', JackDriverParamBool, &value, NULL,
"Take exclusive access of the audio device", NULL);
2542 jack_driver_descriptor_add_parameter(desc, &filler,
"async-latency",
'L', JackDriverParamUInt, &value, NULL,
"Extra output latency in asynchronous mode (percent)", NULL);
2545 jack_driver_descriptor_add_parameter(desc, &filler,
"grain",
'G', JackDriverParamUInt, &value, NULL,
"Computation grain in RT thread (percent)", NULL);
2548 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");
2555 jack_nframes_t srate = 44100;
2556 jack_nframes_t frames_per_interrupt = 256;
2557 bool capture =
false;
2558 bool playback =
false;
2561 const char* chan_in_list =
"";
2562 const char* chan_out_list =
"";
2563 bool monitor =
false;
2564 const char* capture_driver_uid =
"";
2565 const char* playback_driver_uid =
"";
2568 jack_nframes_t systemic_input_latency = 0;
2569 jack_nframes_t systemic_output_latency = 0;
2570 int async_output_latency = 100;
2571 int computation_grain = -1;
2572 bool hogged =
false;
2573 bool clock_drift =
false;
2574 bool ac3_encoding =
false;
2575 int ac3_bitrate = 448;
2576 bool ac3_lfe =
false;
2578 for (node = params; node; node = jack_slist_next(node)) {
2581 switch (param->character) {
2584 capture_driver_uid = param->value.str;
2585 playback_driver_uid = param->value.str;
2594 chan_in = chan_out = param->value.i;
2598 chan_in = param->value.i;
2602 chan_out = param->value.i;
2606 chan_in_list = param->value.str;
2610 chan_out_list = param->value.str;
2615 if (strcmp(param->value.str,
"none") != 0) {
2616 capture_driver_uid = param->value.str;
2622 if (strcmp(param->value.str,
"none") != 0) {
2623 playback_driver_uid = param->value.str;
2628 monitor = param->value.i;
2633 ac3_encoding = param->value.i;
2637 ac3_bitrate = param->value.i;
2641 ac3_lfe = param->value.i;
2646 srate = param->value.ui;
2650 frames_per_interrupt = (
unsigned int)param->value.ui;
2654 systemic_input_latency = param->value.ui;
2658 systemic_output_latency = param->value.ui;
2662 Jack::DisplayDeviceNames();
2671 async_output_latency = param->value.ui;
2675 computation_grain = param->value.ui;
2685 if (!capture && !playback) {
2690 if (strcmp(chan_in_list,
"") != 0 && chan_in >= 0) {
2691 printf(
"Input channel list and in channels are both specified, input channel list will take over...\n");
2694 if (strcmp(chan_out_list,
"") != 0 && chan_out >= 0) {
2695 printf(
"Output channel list and out channels are both specified, output channel list will take over...\n");
2699 if (driver->Open(frames_per_interrupt,
2702 chan_out, chan_in_list,
2703 chan_out_list, monitor,
2705 playback_driver_uid,
2706 systemic_input_latency,
2707 systemic_output_latency,
2708 async_output_latency,
2710 hogged, clock_drift,
2711 ac3_encoding, ac3_bitrate, ac3_lfe) == 0) {
Inter process synchronization using using Mach semaphore.
Locked Engine, access to methods is serialized using a mutex.
SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_info(const char *fmt,...)
The base interface for drivers clients.
SERVER_EXPORT void jack_log(const char *fmt,...)