2 Copyright (C) 2004-2008 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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;
293 // Setup threaded based log function et get RT thread parameters once...
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;
305 // Signal waiting start function...
308 CycleTakeBeginTime();
311 jack_error("Process error, stopping driver");
312 NotifyFailure(JackFailure | JackBackendError, "Process error, stopping driver"); // Message length limited to JACK_MESSAGE_SIZE
314 kill(JackTools::GetPID(), SIGINT);
315 return kAudioHardwareUnsupportedOperationError;
321 int JackCoreAudioDriver::Read()
323 if (fCaptureChannels > 0) { // Calling AudioUnitRender with no input returns a '????' error (callback setting issue ??), so hack to avoid it here...
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;
336 // AC3 encoding and SPDIF write
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);
341 // If not connected, clear the buffer
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");
381 // Check new sample rate
382 Float64 tmp_sample_rate;
383 UInt32 outSize = sizeof(Float64);
384 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
386 jack_error("Cannot get current 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");
411 // Check new buffer size
412 UInt32 tmp_buffer_size;
413 UInt32 outSize = sizeof(UInt32);
414 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
416 jack_error("Cannot get current buffer size");
419 jack_log("JackCoreAudioDriver::BSNotificationCallback : checked buffer size = %d", tmp_buffer_size);
421 driver->fState = true;
429 // A better implementation would possibly try to recover in case of hardware device change (see HALLAB HLFilePlayerWindowControllerAudioDevicePropertyListenerProc code)
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)); // Better this value than nothing...
496 case kAudioDevicePropertyStreamConfiguration: {
497 jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration : server will quit...");
498 driver->NotifyFailure(JackFailure | JackBackendError, "Another application has changed the device configuration"); // Message length limited to JACK_MESSAGE_SIZE
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) {
518 // Digidesign hardware, so "special" code : change the SR again here
519 if (strncmp(device_name, digidesign_name, 10) == 0) {
521 jack_log("JackCoreAudioDriver::DeviceNotificationCallback Digidesign HW = %s", device_name);
523 // Set sample rate again...
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);
533 // Check new sample rate again...
534 outsize = sizeof(Float64);
535 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
537 jack_error("Cannot get current 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"); // Message length limited to JACK_MESSAGE_SIZE
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);
590 // Get the device only if default input and output are the same
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);
720 // Push 'channel' time the stream latency
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;
735 /* Get a list of all the streams on this device */
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++) {
757 /* Find a stream with a cac3 stream */
760 /* Retrieve all the stream formats supported by each output stream */
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);
778 /* Check if one of the supported formats is a digital format */
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;
896 // Prepare sub-devices for clock drift compensation
897 // Workaround for bug in the HAL : until 10.6.2
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;
905 //---------------------------------------------------------------------------
906 // Setup SR of both devices otherwise creating AD may fail...
907 //---------------------------------------------------------------------------
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");
917 // Check clock domain
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");
937 // Check clock domain
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;
953 // If no valid clock domain was found, then assume we have to compensate...
954 if (keptclockdomain == 0) {
955 need_clock_drift_compensation = true;
958 //---------------------------------------------------------------------------
959 // Start to create a new aggregate by getting the base audio hardware plugin
960 //---------------------------------------------------------------------------
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");
996 //-------------------------------------------------
997 // Create a CFDictionary for our aggregate device
998 //-------------------------------------------------
1000 CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1002 CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
1003 CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
1005 // add the name of the device to the dictionary
1006 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
1008 // add our choice of UID for the aggregate device to the dictionary
1009 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
1011 // add a "private aggregate key" to the dictionary
1013 CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
1016 Gestalt(gestaltSystemVersion, &system);
1018 jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : system version = %x limit = %x", system, 0x00001054);
1020 // Starting with 10.5.4 systems, the AD can be internal... (better)
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);
1028 // Prepare sub-devices for clock drift compensation
1029 CFMutableArrayRef subDevicesArrayClock = NULL;
1032 if (fClockDriftCompensate) {
1033 if (need_clock_drift_compensation) {
1034 jack_info("Clock drift compensation activated...");
1035 subDevicesArrayClock = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1037 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
1038 CFStringRef UID = GetDeviceName(captureDeviceID[i]);
1040 CFMutableDictionaryRef subdeviceAggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1041 CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceUIDKey), UID);
1042 CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceDriftCompensationKey), AggregateDeviceNumberRef);
1044 CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict);
1048 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
1049 CFStringRef UID = GetDeviceName(playbackDeviceID[i]);
1051 CFMutableDictionaryRef subdeviceAggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1052 CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceUIDKey), UID);
1053 CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceDriftCompensationKey), AggregateDeviceNumberRef);
1055 CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict);
1059 // add sub-device clock array for the aggregate device to the dictionary
1060 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceSubDeviceListKey), subDevicesArrayClock);
1062 jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
1067 //-------------------------------------------------
1068 // Create a CFMutableArray for our sub-device list
1069 //-------------------------------------------------
1071 // we need to append the UID for each device to a CFMutableArray, so create one here
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);
1081 // input sub-devices in this example, so append the sub-device's UID to the CFArray
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);
1092 // output sub-devices in this example, so append the sub-device's UID to the CFArray
1093 CFArrayAppendValue(subDevicesArray, ref);
1096 //-----------------------------------------------------------------------
1097 // Feed the dictionary to the plugin, to create a blank aggregate device
1098 //-----------------------------------------------------------------------
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");
1120 // pause for a bit to make sure that everything completed correctly
1121 // this is to work around a bug in the HAL where a new aggregate device seems to disappear briefly after it is created
1122 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1124 //-------------------------
1125 // Set the sub-device list
1126 //-------------------------
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");
1139 // pause again to give the changes time to take effect
1140 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1142 //-----------------------
1143 // Set the master device
1144 //-----------------------
1146 // set the master device manually (this is the device which will act as the master clock for the aggregate device)
1147 // pass in the UID of the device you want to use
1148 pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
1149 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1150 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1151 outDataSize = sizeof(CFStringRef);
1152 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &playbackDeviceUID[0]); // First playback is master...
1153 if (osErr != noErr) {
1154 jack_error("CreateAggregateDeviceAux : AudioObjectSetPropertyData for master device error");
1159 // pause again to give the changes time to take effect
1160 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1162 // Prepare sub-devices for clock drift compensation
1163 // Workaround for bug in the HAL : until 10.6.2
1165 if (fClockDriftCompensate) {
1166 if (need_clock_drift_compensation) {
1167 jack_info("Clock drift compensation activated...");
1169 // Get the property data size
1170 osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
1171 if (osErr != noErr) {
1172 jack_error("CreateAggregateDeviceAux kAudioObjectPropertyOwnedObjects error");
1176 // Calculate the number of object IDs
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");
1188 // Set kAudioSubDevicePropertyDriftCompensation property...
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)");
1202 // pause again to give the changes time to take effect
1203 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1209 // release the private AD key
1210 CFRelease(AggregateDeviceNumberRef);
1212 // release the CF objects we have created - we don't need them any more
1213 CFRelease(aggDeviceDict);
1214 CFRelease(subDevicesArray);
1216 if (subDevicesArrayClock) {
1217 CFRelease(subDevicesArrayClock);
1220 // release the device UID
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");
1251 // Same device for capture and playback...
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) {
1257 jack_error("Cannot open default device");
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)) {
1269 jack_error("Cannot take hog mode");
1272 fDigitalPlayback = IsDigitalDevice(fDeviceID);
1278 // Creates aggregate device
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);
1368 // Use default driver in duplex mode
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");
1374 // Creates aggregate device
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);
1419 Return the max possible input channels in in_maxChannels and output channels in out_maxChannels.
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)
1478 // Setting 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);
1492 // If needed, set new buffer size
1493 if (buffer_size != tmp_buffer_size) {
1494 tmp_buffer_size = buffer_size;
1496 // To get BS change notification
1497 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback, this);
1499 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyBufferFrameSize");
1504 // Waiting for BS change notification
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...");
1525 // Check new buffer size
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);
1535 // Remove BS change notification
1536 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1543 // Remove BS change notification
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);
1570 // If needed, set new sample rate
1571 if (sample_rate != (jack_nframes_t)tmp_sample_rate) {
1572 tmp_sample_rate = (Float64)sample_rate;
1574 // To get SR change notification
1575 err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
1577 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
1582 // Waiting for SR change notification
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...");
1603 // Check new sample rate
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);
1613 // Remove SR change notification
1614 AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1621 // Remove SR change notification
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) {
1657 jack_error("Error calling OpenAComponent");
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) {
1674 jack_error("Cannot initialize AUHAL unit");
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);
1720 // Setup up choosen device, in both input and output cases
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");
1747 // Setup input channel map
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) {
1758 // The wanted JACK input index for the 'chan' channel value
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");
1781 // Setup output channel map
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) {
1792 // The wanted JACK output index for the 'chan' channel value
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");
1815 // Setup stream converters
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;
2059 // Starting with 10.6 systems, the HAL notification thread is created internally
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) {
2074 // Generic JackAudioDriver Open
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");
2130 // Setup AC3 channel number
2131 fPlaybackChannels = outchannels;
2133 fPlaybackChannels++;
2136 if (fPlaybackChannels < 2 || fPlaybackChannels > 6) {
2137 jack_error("AC3 encoder channels must be between 2 and 6");
2141 // Force real output channel number to 2
2142 outchannels = out_maxChannels = 2;
2145 fPlaybackChannels = outchannels;
2148 // Core driver may have changed the in/out values
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");
2176 // Generic audio driver close
2177 int res = JackAudioDriver::Close();
2182 DestroyAggregateDevice();
2186 void JackCoreAudioDriver::UpdateLatencies()
2190 jack_latency_range_t input_range;
2191 jack_latency_range_t output_range;
2192 jack_latency_range_t monitor_range;
2194 // Get Input latency
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;
2209 // Get input stream latencies
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);
2221 // Get Output latency
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");
2234 // Get output stream latencies
2235 vector<int> output_latencies;
2236 err = GetStreamLatencies(fDeviceID, false, output_latencies);
2238 // Add more latency if "async" mode is used...
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+1];
2266 char alias[REAL_JACK_PORT_NAME_SIZE+1];
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;
2339 // Setup specific AC3 channels names
2340 for (int i = 0; i < fPlaybackChannels; i++) {
2341 fAC3Encoder->GetChannelName("coreaudio", "", alias, i);
2342 port = fGraphManager->GetPort(fPlaybackPortList[i]);
2343 port->SetAlias(alias);
2349 // Input buffers do no change : prepare them only once
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) {
2362 // Waiting for Render callback to be called (= driver has started)
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); // Generic change, never fails
2403 // CoreAudio specific
2406 // Input buffers do no change : prepare them only once
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);
2423 jack_error("Cannot read hog state...");
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);
2477 } // end of namespace
2485 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
2487 jack_driver_desc_t * desc;
2488 jack_driver_desc_filler_t filler;
2489 jack_driver_param_value_t value;
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");
2553 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
2555 jack_nframes_t srate = 44100;
2556 jack_nframes_t frames_per_interrupt = 256;
2557 bool capture = false;
2558 bool playback = false;
2559 int chan_in = -1; // Default: if not explicitely set, then max possible will be used...
2560 int chan_out = -1; // Default: if not explicitely set, then max possible will be used...
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 = "";
2567 const jack_driver_param_t *param;
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)) {
2579 param = (const jack_driver_param_t *) node->data;
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();
2663 // Stops the server in this case
2671 async_output_latency = param->value.ui;
2675 computation_grain = param->value.ui;
2684 /* duplex is the default */
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");
2698 Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
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) {