Fix yet another merge conflict
[jack2.git] / macosx / coreaudio / JackCoreAudioDriver.mm
blobd944803099b42cb280e3e76c1fb02a9087ad270f
1 /*
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"
32 #include <sstream>
33 #include <iostream>
34 #include <CoreServices/CoreServices.h>
35 #include <CoreFoundation/CFNumber.h>
37 namespace Jack
40 static void Print4CharCode(const char* msg, long c)
42     UInt32 __4CC_number = (c);
43     char __4CC_string[5];
44     *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number);
45     __4CC_string[4] = 0;
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)
65     switch (err) {
66         case kAudioHardwareNoError:
67             jack_log("error code : kAudioHardwareNoError");
68             break;
69         case kAudioConverterErr_FormatNotSupported:
70             jack_log("error code : kAudioConverterErr_FormatNotSupported");
71             break;
72         case kAudioConverterErr_OperationNotSupported:
73             jack_log("error code : kAudioConverterErr_OperationNotSupported");
74             break;
75         case kAudioConverterErr_PropertyNotSupported:
76             jack_log("error code : kAudioConverterErr_PropertyNotSupported");
77             break;
78         case kAudioConverterErr_InvalidInputSize:
79             jack_log("error code : kAudioConverterErr_InvalidInputSize");
80             break;
81         case kAudioConverterErr_InvalidOutputSize:
82             jack_log("error code : kAudioConverterErr_InvalidOutputSize");
83             break;
84         case kAudioConverterErr_UnspecifiedError:
85             jack_log("error code : kAudioConverterErr_UnspecifiedError");
86             break;
87         case kAudioConverterErr_BadPropertySizeError:
88             jack_log("error code : kAudioConverterErr_BadPropertySizeError");
89             break;
90         case kAudioConverterErr_RequiresPacketDescriptionsError:
91             jack_log("error code : kAudioConverterErr_RequiresPacketDescriptionsError");
92             break;
93         case kAudioConverterErr_InputSampleRateOutOfRange:
94             jack_log("error code : kAudioConverterErr_InputSampleRateOutOfRange");
95             break;
96         case kAudioConverterErr_OutputSampleRateOutOfRange:
97             jack_log("error code : kAudioConverterErr_OutputSampleRateOutOfRange");
98             break;
99         case kAudioHardwareNotRunningError:
100             jack_log("error code : kAudioHardwareNotRunningError");
101             break;
102         case kAudioHardwareUnknownPropertyError:
103             jack_log("error code : kAudioHardwareUnknownPropertyError");
104             break;
105         case kAudioHardwareIllegalOperationError:
106             jack_log("error code : kAudioHardwareIllegalOperationError");
107             break;
108         case kAudioHardwareBadDeviceError:
109             jack_log("error code : kAudioHardwareBadDeviceError");
110             break;
111         case kAudioHardwareBadStreamError:
112             jack_log("error code : kAudioHardwareBadStreamError");
113             break;
114         case kAudioDeviceUnsupportedFormatError:
115             jack_log("error code : kAudioDeviceUnsupportedFormatError");
116             break;
117         case kAudioDevicePermissionsError:
118             jack_log("error code : kAudioDevicePermissionsError");
119             break;
120         case kAudioHardwareBadObjectError:
121             jack_log("error code : kAudioHardwareBadObjectError");
122             break;
123         case kAudioHardwareUnsupportedOperationError:
124             jack_log("error code : kAudioHardwareUnsupportedOperationError");
125             break;
126         default:
127             Print4CharCode("error code : unknown ", err);
128             break;
129     }
132 static bool CheckAvailableDeviceName(const char* device_name, AudioDeviceID* device_id)
134     UInt32 size;
135     Boolean isWritable;
136     int i, deviceNum;
137     OSStatus err;
139     err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
140     if (err != noErr) {
141         return false;
142     }
144     deviceNum = size / sizeof(AudioDeviceID);
145     AudioDeviceID devices[deviceNum];
147     err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
148     if (err != noErr) {
149         return false;
150     }
152     for (i = 0; i < deviceNum; i++) {
153         char device_name_aux[256];
155         size = 256;
156         err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name_aux);
157         if (err != noErr) {
158             return false;
159         }
161         if (strncmp(device_name_aux, device_name, strlen(device_name)) == 0) {
162             *device_id = devices[i];
163             return true;
164         }
165     }
167     return false;
170 static bool CheckAvailableDevice(AudioDeviceID device_id)
172     UInt32 size;
173     Boolean isWritable;
174     int i, deviceNum;
175     OSStatus err;
177     err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
178     if (err != noErr) {
179         return false;
180     }
182     deviceNum = size / sizeof(AudioDeviceID);
183     AudioDeviceID devices[deviceNum];
185     err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
186     if (err != noErr) {
187         return false;
188     }
190     for (i = 0; i < deviceNum; i++) {
191         if (device_id == devices[i]) {
192             return true;
193         }
194     }
196     return false;
199 static OSStatus DisplayDeviceNames()
201     UInt32 size;
202     Boolean isWritable;
203     int i, deviceNum;
204     OSStatus err;
205     CFStringRef UIname;
207     err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
208     if (err != noErr) {
209         return err;
210     }
212     deviceNum = size / sizeof(AudioDeviceID);
213     AudioDeviceID devices[deviceNum];
215     err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
216     if (err != noErr) {
217         return err;
218     }
220     for (i = 0; i < deviceNum; i++) {
221         char device_name[256];
222         char internal_name[256];
224         size = sizeof(CFStringRef);
225         UIname = NULL;
226         err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
227         if (err == noErr) {
228             CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
229         } else {
230             goto error;
231         }
233         size = 256;
234         err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
235         if (err != noErr) {
236             return err;
237         }
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);
240     }
242     return noErr;
244 error:
245     if (UIname != NULL) {
246         CFRelease(UIname);
247     }
248     return err;
251 static CFStringRef GetDeviceName(AudioDeviceID id)
253     UInt32 size = sizeof(CFStringRef);
254     CFStringRef UIname;
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);
262     string token;
263     int chan;
264   
265     while (ss >> token) {
266         istringstream ins;
267         ins.str(token);
268         ins >> chan;
269         if (chan < 0 || chan >= max_chan) {
270             jack_error("Ignore incorrect channel mapping value = %d", chan);
271         } else {
272             result.push_back(chan);
273         }
274     }
277 OSStatus JackCoreAudioDriver::Render(void* inRefCon,
278                                      AudioUnitRenderActionFlags* ioActionFlags,
279                                      const AudioTimeStamp* inTimeStamp,
280                                      UInt32 inBusNumber,
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;
302         }
303     }
305     // Signal waiting start function...
306     fState = true;
308     CycleTakeBeginTime();
310     if (Process() < 0) {
311         jack_error("Process error, stopping driver");
312         NotifyFailure(JackFailure | JackBackendError, "Process error, stopping driver");    // Message length limited to JACK_MESSAGE_SIZE
313         Stop();
314         kill(JackTools::GetPID(), SIGINT);
315         return kAudioHardwareUnsupportedOperationError;
316     } else {
317         return noErr;
318     }
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;
325     } else {
326         return 0;
327     }
330 int JackCoreAudioDriver::Write()
332     int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
333     
334     if (fAC3Encoder) {
335     
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);
344             }
345         }
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);
349         
350     } else {
351        
352         // Standard write
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);
357                 // Monitor ports
358                 if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
359                     memcpy(GetMonitorBuffer(i), buffer, size);
360                 }
361             } else {
362                 memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, size);
363             }
364         }
365     }
366     return 0;
369 OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
370                                                     UInt32 inChannel,
371                                                     Boolean     isInput,
372                                                     AudioDevicePropertyID inPropertyID,
373                                                     void* inClientData)
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);
385             if (err != noErr) {
386                 jack_error("Cannot get current sample rate");
387                 printError(err);
388             } else {
389                 jack_log("JackCoreAudioDriver::SRNotificationCallback : checked sample rate = %f", tmp_sample_rate);
390             }
391             driver->fState = true;
392             break;
393         }
394     }
396     return noErr;
399 OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
400                                                      UInt32 inChannel,
401                                                      Boolean isInput,
402                                                      AudioDevicePropertyID inPropertyID,
403                                                      void* inClientData)
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);
415             if (err != noErr) {
416                 jack_error("Cannot get current buffer size");
417                 printError(err);
418             } else {
419                 jack_log("JackCoreAudioDriver::BSNotificationCallback : checked buffer size = %d", tmp_buffer_size);
420             }
421             driver->fState = true;
422             break;
423         }
424     }
426     return noErr;
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))) {
444             }
445             break;
446         }
447     }
449     return noErr;
452 OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
453                                                         UInt32 inChannel,
454                                                         Boolean isInput,
455                                                         AudioDevicePropertyID inPropertyID,
456                                                         void* inClientData)
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);
467             }
468             break;
469         }
471         case kAudioDevicePropertyDeviceIsAlive: {
472             UInt32 isalive = 0;
473             UInt32 outsize = sizeof(UInt32);
474             if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsAlive, &outsize, &isalive) == noErr) {
475                 jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsAlive = %d", isalive);
476             }
477             break;
478         }
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);
485             }
486             break;
487         }
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...
493             break;
494         }
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;
502         }
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);
508             if (err != noErr) {
509                 return kAudioHardwareUnsupportedOperationError;
510             }
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);
526                     if (err != noErr) {
527                         jack_error("Cannot set sample rate = %f", sample_rate);
528                         printError(err);
529                     } else {
530                         jack_log("JackCoreAudioDriver::DeviceNotificationCallback : set sample rate = %f", sample_rate);
531                     }
533                     // Check new sample rate again...
534                     outsize = sizeof(Float64);
535                     err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
536                     if (err != noErr) {
537                         jack_error("Cannot get current sample rate");
538                         printError(err);
539                     } else {
540                         jack_log("JackCoreAudioDriver::DeviceNotificationCallback : checked sample rate = %f", sample_rate);
541                     }
542                     return noErr;
544                 } else {
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;
549                 }
550             }
551         }
553     }
554     return noErr;
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) };
563     if (inIUD == NULL) {
564         return kAudioHardwareUnspecifiedError;
565     } else {
566         OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
567         CFRelease(inIUD);
568         jack_log("JackCoreAudioDriver::GetDeviceIDFromUID %s %ld", UID, *id);
569         return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
570     }
573 OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id)
575     OSStatus res;
576     UInt32 theSize = sizeof(UInt32);
577     AudioDeviceID inDefault;
578     AudioDeviceID outDefault;
580     if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
581         return res;
582     }
584     if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
585         return res;
586     }
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;
597     } else {
598         *id = inDefault;
599         return noErr;
600     }
603 OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id)
605     OSStatus res;
606     UInt32 theSize = sizeof(UInt32);
607     AudioDeviceID inDefault;
609     if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
610         return res;
611     }
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);
618             return noErr;
619         } else {
620             jack_error("Cannot find any input device to use...");
621             return -1;
622         }
623     }
624     jack_log("JackCoreAudioDriver::GetDefaultInputDevice : input = %ld ", inDefault);
625     *id = inDefault;
626     return noErr;
629 OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id)
631     OSStatus res;
632     UInt32 theSize = sizeof(UInt32);
633     AudioDeviceID outDefault;
635     if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
636         return res;
637     }
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);
643             return noErr;
644         } else {
645             jack_error("Cannot find any output device to use...");
646             return -1;
647         }
648     }
649     jack_log("JackCoreAudioDriver::GetDefaultOutputDevice : output = %ld", outDefault);
650     *id = outDefault;
651     return noErr;
654 OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID id, char* name)
656     UInt32 size = 256;
657     return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
660 OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
662     OSStatus err = noErr;
663     UInt32 outSize;
664     Boolean     outWritable;
666     channelCount = 0;
667     err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
668     if (err == noErr) {
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);
673         if (err == noErr) {
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);
677             }
678         }
679     }
680     return err;
683 OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies)
685     OSStatus err = noErr;
686     UInt32 outSize1, outSize2, outSize3;
687     Boolean     outWritable;
689     err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable);
690     if (err == noErr) {
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);
698         if (err != noErr) {
699             jack_error("GetStreamLatencies kAudioDevicePropertyStreams err = %d", err);
700             return err;
701         }
703         err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable);
704         if (err != noErr) {
705             jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
706             return err;
707         }
709         for (int i = 0; i < stream_count; i++) {
710             err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency);
711             if (err != noErr) {
712                 jack_error("GetStreamLatencies kAudioStreamPropertyLatency err = %d", err);
713                 return err;
714             }
715             err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList);
716             if (err != noErr) {
717                 jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
718                 return err;
719             }
720             // Push 'channel' time the stream latency
721             for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) {
722                 latencies.push_back(streamLatency);
723             }
724         }
725     }
726     return err;
729 bool JackCoreAudioDriver::IsDigitalDevice(AudioDeviceID device)
731     OSStatus err = noErr;
732     UInt32 outSize1;
733     bool is_digital = false;
734     
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);
738     if (err != noErr) {
739         jack_error("IsDigitalDevice kAudioDevicePropertyStreams err = %d", err);
740         return false;
741     }
742     
743     int stream_count = outSize1 / sizeof(AudioStreamID);
744     AudioStreamID streamIDs[stream_count];
745     
746     err = AudioObjectGetPropertyData(device, &streamsAddress, 0, NULL, &outSize1, streamIDs);
748     if (err != noErr) {
749         jack_error("IsDigitalDevice kAudioDevicePropertyStreams list err = %d", err);
750         return false;
751     }
752     
753     AudioObjectPropertyAddress physicalFormatsAddress = { kAudioStreamPropertyAvailablePhysicalFormats, kAudioObjectPropertyScopeGlobal, 0 };
754      
755     for (int i = 0; i < stream_count ; i++) {
756    
757         /* Find a stream with a cac3 stream */
758         int  format_num = 0;
759     
760         /* Retrieve all the stream formats supported by each output stream */
761         err = AudioObjectGetPropertyDataSize(streamIDs[i], &physicalFormatsAddress, 0, NULL, &outSize1);
762         
763         if (err != noErr) {
764             jack_error("IsDigitalDevice kAudioStreamPropertyAvailablePhysicalFormats err = %d", err);
765             return false;
766         }
768         format_num = outSize1 / sizeof(AudioStreamRangedDescription);
769         AudioStreamRangedDescription format_list[format_num];
770       
771         err = AudioObjectGetPropertyData(streamIDs[i], &physicalFormatsAddress, 0, NULL, &outSize1, format_list);
772          
773         if (err != noErr) {
774             jack_error("IsDigitalDevice could not get the list of streamformats err = %d", err);
775             return false;
776         }
777    
778         /* Check if one of the supported formats is a digital format */
779         for (int j = 0; j < format_num; j++) {
780         
781             PrintStreamDesc(&format_list[j].mFormat);
782             
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)
787             {
788                 is_digital = true;
789                 break;
790             }
791         }
792     }
793        
794     return is_digital;
797 JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
798         : JackAudioDriver(name, alias, engine, table),
799         fAC3Encoder(NULL),
800         fJackInputData(NULL),
801         fDriverOutputData(NULL),
802         fPluginID(0),
803         fState(false),
804         fHogged(false),
805         fIOUsage(1.f),
806         fComputationGrain(-1.f),
807         fClockDriftCompensate(false),
808         fDigitalPlayback(false)
811 JackCoreAudioDriver::~JackCoreAudioDriver()
813     delete fAC3Encoder;
816 OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
818     OSStatus osErr = noErr;
819     AudioObjectPropertyAddress pluginAOPA;
820     pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
821     pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
822     pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
823     UInt32 outDataSize;
825     if (fPluginID > 0) {
827         osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
828         if (osErr != noErr) {
829             jack_error("DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
830             printError(osErr);
831             return osErr;
832         }
834         osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
835         if (osErr != noErr) {
836             jack_error("DestroyAggregateDevice : AudioObjectGetPropertyData error");
837             printError(osErr);
838             return osErr;
839         }
841     }
843     return noErr;
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;
854     
855     jack_log("JackCoreAudioDriver::CreateAggregateDevice : input device %d", captureDeviceID);
857     if (err != noErr) {
858         jack_log("JackCoreAudioDriver::CreateAggregateDevice : input device does not have subdevices");
859         captureDeviceIDArray.push_back(captureDeviceID);
860     } else {
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]);
866         }
867     }
869     outSize = sizeof(sub_device);
870     err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
871     vector<AudioDeviceID> playbackDeviceIDArray;
872     
873     jack_log("JackCoreAudioDriver::CreateAggregateDevice : output device %d", playbackDeviceID);
875     if (err != noErr) {
876         jack_log("JackCoreAudioDriver::CreateAggregateDevice : output device does not have subdevices");
877         playbackDeviceIDArray.push_back(playbackDeviceID);
878     } else {
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]);
884         }
885     }
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;
893     UInt32 outSize;
894     Boolean outWritable;
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");
916         } else  {
917             // Check clock domain
918             osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
919             if (osErr != 0) {
920                 jack_error("CreateAggregateDeviceAux : kAudioDevicePropertyClockDomain error");
921                 printError(osErr);
922             } else {
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;
928                 }
929             }
930         }
931     }
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");
936         } else {
937             // Check clock domain
938             osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
939             if (osErr != 0) {
940                 jack_error("CreateAggregateDeviceAux : kAudioDevicePropertyClockDomain error");
941                 printError(osErr);
942             } else {
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;
948                 }
949             }
950         }
951     }
953     // If no valid clock domain was found, then assume we have to compensate...
954     if (keptclockdomain == 0) {
955         need_clock_drift_compensation = true;
956     }
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);
966     }
968     for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
969         GetDeviceNameFromID(playbackDeviceID[i], device_name);
970         jack_info("Separated output = '%s' ", device_name);
971     }
973     osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
974     if (osErr != noErr) {
975         jack_error("CreateAggregateDeviceAux : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
976         printError(osErr);
977         return osErr;
978     }
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");
992         printError(osErr);
993         return osErr;
994     }
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
1012     int value = 1;
1013     CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
1015     SInt32 system;
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....");
1023     } else {
1024         jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : private aggregate device....");
1025         CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
1026     }
1028     // Prepare sub-devices for clock drift compensation
1029     CFMutableArrayRef subDevicesArrayClock = NULL;
1031     /*
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]);
1039                 if (UID) {
1040                     CFMutableDictionaryRef subdeviceAggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1041                     CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceUIDKey), UID);
1042                     CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceDriftCompensationKey), AggregateDeviceNumberRef);
1043                     //CFRelease(UID);
1044                     CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict);
1045                 }
1046             }
1048             for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
1049                 CFStringRef UID = GetDeviceName(playbackDeviceID[i]);
1050                 if (UID) {
1051                     CFMutableDictionaryRef subdeviceAggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1052                     CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceUIDKey), UID);
1053                     CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceDriftCompensationKey), AggregateDeviceNumberRef);
1054                     //CFRelease(UID);
1055                     CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict);
1056                 }
1057             }
1059             // add sub-device clock array for the aggregate device to the dictionary
1060             CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceSubDeviceListKey), subDevicesArrayClock);
1061         } else {
1062             jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
1063         }
1064     }
1065     */
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]);
1077         if (ref == NULL) {
1078             return -1;
1079         }
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);
1083    }
1085     vector<CFStringRef> playbackDeviceUID;
1086     for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
1087         CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
1088         if (ref == NULL) {
1089             return -1;
1090         }
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);
1094     }
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;
1104     UInt32 outDataSize;
1106     osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
1107     if (osErr != noErr) {
1108         jack_error("CreateAggregateDeviceAux : AudioObjectGetPropertyDataSize error");
1109         printError(osErr);
1110         goto error;
1111     }
1113     osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
1114     if (osErr != noErr) {
1115         jack_error("CreateAggregateDeviceAux : AudioObjectGetPropertyData error");
1116         printError(osErr);
1117         goto error;
1118     }
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");
1135         printError(osErr);
1136         goto error;
1137     }
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");
1155         printError(osErr);
1156         goto error;
1157     }
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");
1173                 printError(osErr);
1174             }
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");
1185                 printError(osErr);
1186             }
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");
1194                     printError(osErr);
1195                 }
1196             }
1197         } else {
1198             jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
1199         }
1200     }
1202     // pause again to give the changes time to take effect
1203     CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1205     //----------
1206     // Clean up
1207     //----------
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);
1218     }
1220     // release the device UID
1221     for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
1222         CFRelease(captureDeviceUID[i]);
1223     }
1225     for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
1226         CFRelease(playbackDeviceUID[i]);
1227     }
1229     jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : new aggregate device %ld", *outAggregateDevice);
1230     return noErr;
1232 error:
1233     DestroyAggregateDevice();
1234     return -1;
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,
1242                                       bool ac3_encoding)
1244     capture_driver_name[0] = 0;
1245     playback_driver_name[0] = 0;
1247     // Duplex
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");
1258                     return -1;
1259                 }
1260             }
1261             
1262             if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
1263                 jack_error("Cannot get device name from device ID");
1264                 return -1;
1265             }
1266             
1267             if (fHogged) {
1268                 if (!TakeHogAux(fDeviceID, false)) {
1269                     jack_error("Cannot take hog mode");
1270                 } 
1271                 if (ac3_encoding) {
1272                     fDigitalPlayback = IsDigitalDevice(fDeviceID);
1273                 }
1274             }
1276         } else {
1278             // Creates aggregate device
1279             AudioDeviceID captureID = -1;
1280             AudioDeviceID playbackID = -1;
1281     
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");
1286                     return -1;
1287                 }
1288             }
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");
1294                     return -1;
1295                 }
1296             }
1298             if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1299                 return -1;
1300             }
1302             GetDeviceNameFromID(captureID, fCaptureUID);
1303             GetDeviceNameFromID(playbackID, fPlaybackUID);
1304             
1305             if (fHogged) {
1306                 if (!TakeHogAux(captureID, true)) {
1307                     jack_error("Cannot take hog mode for capture device");
1308                 }
1309                 if (!TakeHogAux(playbackID, false)) {
1310                     jack_error("Cannot take hog mode for playback device");
1311                 }
1312                 if (ac3_encoding) {
1313                     fDigitalPlayback = IsDigitalDevice(playbackID);
1314                 }
1315             }
1316             
1317         }
1319     // Capture only
1320     } else if (strcmp(capture_driver_uid, "") != 0) {
1321     
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");
1327                 return -1;
1328             }
1329         }
1330         
1331         if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
1332             jack_error("Cannot get device name from device ID");
1333             return -1;
1334         }
1335         
1336         if (fHogged) {
1337             if (!TakeHogAux(fDeviceID, true)) {
1338                 jack_error("Cannot take hog mode for capture device");
1339             }
1340         }
1342     // Playback only
1343     } else if (strcmp(playback_driver_uid, "") != 0) {
1344     
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");
1350                 return -1;
1351             }
1352         }
1353         
1354         if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
1355             jack_error("Cannot get device name from device ID");
1356             return -1;
1357         }
1358         
1359         if (fHogged) {
1360             if (!TakeHogAux(fDeviceID, false)) {
1361                 jack_error("Cannot take hog mode for playback device");
1362             }
1363             if (ac3_encoding) {
1364                 fDigitalPlayback = IsDigitalDevice(fDeviceID);
1365             }
1366         }
1368     // Use default driver in duplex mode
1369     } else {
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;
1377             
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");
1382                     return -1;
1383                 }
1384             }
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");
1390                     return -1;
1391                 }
1392             }
1394             if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1395                 return -1;
1396             }
1398             GetDeviceNameFromID(captureID, fCaptureUID);
1399             GetDeviceNameFromID(playbackID, fPlaybackUID);
1400             
1401             if (fHogged) {
1402                 if (!TakeHogAux(captureID, true)) {
1403                     jack_error("Cannot take hog mode for capture device");
1404                 }
1405                 if (!TakeHogAux(playbackID, false)) {
1406                     jack_error("Cannot take hog mode for playback device");
1407                 }
1408                 if (ac3_encoding) {
1409                     fDigitalPlayback = IsDigitalDevice(playbackID);
1410                 }
1411             }
1412         }
1413     }
1414      
1415     return 0;
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;
1424     
1425     jack_log("JackCoreAudioDriver::SetupChannels : fDeviceID = %d", fDeviceID);
1427     if (capturing) {
1428         err = GetTotalChannels(fDeviceID, in_maxChannels, true);
1429         if (err != noErr) {
1430             jack_error("SetupChannels : cannot get input channel number");
1431             printError(err);
1432             return -1;
1433         } else {
1434             jack_log("JackCoreAudioDriver::SetupChannels : max input channels : %d", in_maxChannels);
1435         }
1436     }
1438     if (playing) {
1439         err = GetTotalChannels(fDeviceID, out_maxChannels, false);
1440         if (err != noErr) {
1441             jack_error("Cannot get output channel number");
1442             printError(err);
1443             return -1;
1444         } else {
1445             jack_log("JackCoreAudioDriver::SetupChannels : max output channels : %d", out_maxChannels);
1446         }
1447     }
1449     if (inchannels > in_maxChannels) {
1450         jack_error("This device hasn't required input channels inchannels = %d in_maxChannels = %d", inchannels, in_maxChannels);
1451         if (strict) {
1452             return -1;
1453         }
1454     }
1456     if (outchannels > out_maxChannels) {
1457         jack_error("This device hasn't required output channels outchannels = %d out_maxChannels = %d", outchannels, out_maxChannels);
1458         if (strict) {
1459             return -1;
1460         }
1461     }
1463     if (inchannels == -1) {
1464         jack_log("JackCoreAudioDriver::SetupChannels : setup max in channels = %d", in_maxChannels);
1465         inchannels = in_maxChannels;
1466     }
1468     if (outchannels == -1) {
1469         jack_log("JackCoreAudioDriver::SetupChannels : setup max out channels = %d", out_maxChannels);
1470         outchannels = out_maxChannels;
1471     }
1473     return 0;
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);
1484     if (err != noErr) {
1485         jack_error("Cannot get buffer size %ld", buffer_size);
1486         printError(err);
1487         return -1;
1488     } else {
1489         jack_log("JackCoreAudioDriver::SetupBufferSize : current buffer size = %ld", tmp_buffer_size);
1490     }
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);
1498         if (err != noErr) {
1499             jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyBufferFrameSize");
1500             printError(err);
1501             return -1;
1502         }
1504         // Waiting for BS change notification
1505         int count = 0;
1506         fState = false;
1508         err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, outSize, &tmp_buffer_size);
1509         if (err != noErr) {
1510             jack_error("SetupBufferSize : cannot set buffer size = %ld", tmp_buffer_size);
1511             printError(err);
1512             goto error;
1513         }
1515         while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1516             usleep(100000);
1517             jack_log("JackCoreAudioDriver::SetupBufferSize : wait count = %d", count);
1518         }
1520         if (count >= WAIT_NOTIFICATION_COUNTER) {
1521             jack_error("Did not get buffer size notification...");
1522             goto error;
1523         }
1525         // Check new buffer size
1526         outSize = sizeof(UInt32);
1527         err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
1528         if (err != noErr) {
1529             jack_error("Cannot get current buffer size");
1530             printError(err);
1531         } else {
1532             jack_log("JackCoreAudioDriver::SetupBufferSize : checked buffer size = %ld", tmp_buffer_size);
1533         }
1535         // Remove BS change notification
1536         AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1537     }
1539     return 0;
1541 error:
1543     // Remove BS change notification
1544     AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1545     return -1;
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;
1556     UInt32 outSize;
1557     Float64 tmp_sample_rate;
1559     // Get sample rate
1560     outSize =  sizeof(Float64);
1561     err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
1562     if (err != noErr) {
1563         jack_error("Cannot get current sample rate");
1564         printError(err);
1565         return -1;
1566     } else {
1567         jack_log("JackCoreAudioDriver::SetupSampleRateAux : current sample rate = %f", tmp_sample_rate);
1568     }
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);
1576         if (err != noErr) {
1577             jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
1578             printError(err);
1579             return -1;
1580         }
1582         // Waiting for SR change notification
1583         int count = 0;
1584         fState = false;
1586         err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &tmp_sample_rate);
1587         if (err != noErr) {
1588             jack_error("Cannot set sample rate = %ld", sample_rate);
1589             printError(err);
1590             goto error;
1591         }
1593         while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1594             usleep(100000);
1595             jack_log("JackCoreAudioDriver::SetupSampleRateAux : wait count = %d", count);
1596         }
1598         if (count >= WAIT_NOTIFICATION_COUNTER) {
1599             jack_error("Did not get sample rate notification...");
1600             goto error;
1601         }
1603         // Check new sample rate
1604         outSize = sizeof(Float64);
1605         err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
1606         if (err != noErr) {
1607             jack_error("Cannot get current sample rate");
1608             printError(err);
1609         } else {
1610             jack_log("JackCoreAudioDriver::SetupSampleRateAux : checked sample rate = %f", tmp_sample_rate);
1611         }
1613         // Remove SR change notification
1614         AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1615     }
1617     return 0;
1619 error:
1621     // Remove SR change notification
1622     AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1623     return -1;
1626 int JackCoreAudioDriver::OpenAUHAL(bool capturing,
1627                                    bool playing,
1628                                    int inchannels,
1629                                    int outchannels,
1630                                    int in_maxChannels,
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;
1638     UInt32 enableIO;
1639     AudioStreamBasicDescription srcFormat, dstFormat;
1640     AudioDeviceID currAudioDeviceID;
1641     UInt32 size;
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...");
1648         return -1;
1649     }
1650     
1651     // AUHAL
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");
1658         printError(err1);
1659         goto error;
1660     }
1661 #else 
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");
1667         printError(err1);
1668         goto error;
1669     }
1670 #endif
1672     err1 = AudioUnitInitialize(fAUHAL);
1673     if (err1 != noErr) {
1674         jack_error("Cannot initialize AUHAL unit");
1675         printError(err1);
1676         goto error;
1677     }
1678     
1679     // Start I/O
1680     if (capturing && inchannels > 0) {
1681         enableIO = 1;
1682         jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL input on");
1683     } else {
1684         enableIO = 0;
1685         jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL input off");
1686     }
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");
1691         printError(err1);
1692         goto error;
1693     }
1695     if (playing && outchannels > 0) {
1696         enableIO = 1;
1697         jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL output on");
1698     } else {
1699         enableIO = 0;
1700         jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL output off");
1701     }
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");
1706         printError(err1);
1707         goto error;
1708     }
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");
1714         printError(err1);
1715         goto error;
1716     } else {
1717         jack_log("JackCoreAudioDriver::OpenAUHAL : AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
1718     }
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");
1724         printError(err1);
1725         goto error;
1726     }
1728     // Set buffer size
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");
1733             printError(err1);
1734             goto error;
1735         }
1736     }
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");
1742             printError(err1);
1743             goto error;
1744         }
1745     }
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++) {
1751             chanArr[i] = -1;
1752         }
1753         // Explicit mapping
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
1759                     chanArr[chan] = i;
1760                     jack_info("Input channel = %d ==> JACK input port = %d", chan, i);
1761                 } else {
1762                     jack_info("Error input channel number is incorrect : %d", chan);
1763                     goto error;
1764                 }
1765             }
1766         } else {
1767             for (int i = 0; i < inchannels; i++) {
1768                 chanArr[i] = i;
1769                 jack_info("Input channel = %d ==> JACK input port = %d", chanArr[i], i);
1770             }
1771         }
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");
1776             printError(err1);
1777             goto error;
1778         }
1779     }
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++) {
1785             chanArr[i] = -1;
1786         }
1787         // Explicit mapping
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
1793                     chanArr[chan] = i;
1794                     jack_info("JACK output port = %d ==> output channel = %d", i, chan);
1795                 } else {
1796                     jack_info("Error output channel number is incorrect : %d", chan);
1797                     goto error;
1798                 }
1799             }
1800         } else {
1801             for (int i = 0; i < outchannels; i++) {
1802                 chanArr[i] = i;
1803                 jack_info("JACK output port = %d ==> output channel = %d", i, chanArr[i]);
1804             }
1805         }
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");
1810             printError(err1);
1811             goto error;
1812         }
1813     }
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");
1822             printError(err1);
1823             goto error;
1824         }
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");
1841             printError(err1);
1842             goto error;
1843         }
1844     }
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");
1852             printError(err1);
1853             goto error;
1854         }
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");
1871             printError(err1);
1872             goto error;
1873         }
1874     }
1876     // Setup callbacks
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");
1884             printError(err1);
1885             goto error;
1886         }
1887     } else {
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");
1894             printError(err1);
1895             goto error;
1896         }
1897     }
1899     return 0;
1901 error:
1902     CloseAUHAL();
1903     return -1;
1906 int JackCoreAudioDriver::SetupBuffers(int inchannels)
1908     // Prepare buffers
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);
1914     }
1915     return 0;
1918 void JackCoreAudioDriver::DisposeBuffers()
1920     if (fJackInputData) {
1921         free(fJackInputData);
1922         fJackInputData = 0;
1923     }
1926 void JackCoreAudioDriver::CloseAUHAL()
1928     AudioOutputUnitStop(fAUHAL);
1929     AudioUnitUninitialize(fAUHAL);
1930     CloseComponent(fAUHAL);
1933 int JackCoreAudioDriver::AddListeners()
1935     OSStatus err = noErr;
1937     // Add listeners
1938     err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this);
1939     if (err != noErr) {
1940         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
1941         printError(err);
1942         return -1;
1943     }
1945     err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback, this);
1946     if (err != noErr) {
1947         jack_error("Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
1948         printError(err);
1949         return -1;
1950     }
1952     err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this);
1953     if (err != noErr) {
1954         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
1955         printError(err);
1956         return -1;
1957     }
1959     err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this);
1960     if (err != noErr) {
1961         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
1962         printError(err);
1963         return -1;
1964     }
1966     err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback, this);
1967     if (err != noErr) {
1968         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsAlive");
1969         printError(err);
1970         return -1;
1971     }
1973     err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback, this);
1974     if (err != noErr) {
1975         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceHasChanged");
1976         printError(err);
1977         return -1;
1978     }
1980     err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
1981     if (err != noErr) {
1982         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
1983         printError(err);
1984         return -1;
1985     }
1987     err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
1988     if (err != noErr) {
1989         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
1990         printError(err);
1991         return -1;
1992     }
1994     if (!fEngineControl->fSyncMode && fIOUsage != 1.f) {
1995         UInt32 outSize = sizeof(float);
1996         err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyIOCycleUsage, outSize, &fIOUsage);
1997         if (err != noErr) {
1998             jack_error("Error calling AudioDeviceSetProperty kAudioDevicePropertyIOCycleUsage");
1999             printError(err);
2000         }
2001     }
2003     return 0;
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,
2020                               bool capturing,
2021                               bool playing,
2022                               int inchannels,
2023                               int outchannels,
2024                               const char* chan_in_list,
2025                               const char* chan_out_list,
2026                               bool monitor,
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,
2033                               bool hogged,
2034                               bool clock_drift,
2035                               bool ac3_encoding,
2036                               int ac3_bitrate,
2037                               bool ac3_lfe)
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;
2048     fHogged = hogged;
2049     fClockDriftCompensate = clock_drift;
2051     SInt32 major;
2052     SInt32 minor;
2053     Gestalt(gestaltSystemVersionMajor, &major);
2054     Gestalt(gestaltSystemVersionMinor, &minor);
2056     vector<int> parsed_chan_in_list;
2057     vector<int> parsed_chan_out_list;
2058    
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");
2066             printError(osErr);
2067         }
2068     }
2069   
2070     if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate, ac3_encoding) < 0) {
2071         goto error;
2072     }
2074     // Generic JackAudioDriver Open
2075     if (JackAudioDriver::Open(buffer_size, sample_rate,
2076                             capturing, playing,
2077                             inchannels, outchannels,
2078                             monitor,
2079                             capture_driver_name,
2080                             playback_driver_name,
2081                             capture_latency,
2082                             playback_latency) != 0) {
2083         goto error;
2084     }
2086     if (SetupChannels(capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, !ac3_encoding) < 0) {
2087         goto error;
2088     }
2089     
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();
2094     }
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();
2100     }  
2102     if (SetupBufferSize(buffer_size) < 0) {
2103         goto error;
2104     }
2106     if (SetupSampleRate(sample_rate) < 0) {
2107         goto error;
2108     }
2109     
2110     if (ac3_encoding) {
2111           
2112         if (!fDigitalPlayback) {
2113             jack_error("AC3 encoding can only be used with a digital device");
2114             goto error;
2115         }
2116         
2117         JackAC3EncoderParams params;
2118         memset(&params, 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);
2124         
2125         if (!fAC3Encoder || !fAC3Encoder->Init(sample_rate)) {
2126             jack_error("Cannot allocate or init AC3 encoder");
2127             goto error;
2128         }
2129         
2130         // Setup AC3 channel number
2131         fPlaybackChannels = outchannels;
2132         if (ac3_lfe) {
2133             fPlaybackChannels++;
2134         }
2135         
2136         if (fPlaybackChannels < 2 || fPlaybackChannels > 6) {
2137             jack_error("AC3 encoder channels must be between 2 and 6");
2138             goto error;
2139         }
2140         
2141         // Force real output channel number to 2
2142         outchannels = out_maxChannels = 2;
2143         
2144     } else {
2145         fPlaybackChannels = outchannels;
2146     }
2147     
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) {
2152         goto error;
2153     }
2155     if (capturing && inchannels > 0) {
2156         if (SetupBuffers(inchannels) < 0) {
2157             goto error;
2158         }
2159     }
2161     if (AddListeners() < 0) {
2162         goto error;
2163     }
2164   
2165     return noErr;
2167 error:
2168     Close();
2169     return -1;
2172 int JackCoreAudioDriver::Close()
2174     jack_log("JackCoreAudioDriver::Close");
2176     // Generic audio driver close
2177     int res = JackAudioDriver::Close();
2179     RemoveListeners();
2180     DisposeBuffers();
2181     CloseAUHAL();
2182     DestroyAggregateDevice();
2183     return res;
2186 void JackCoreAudioDriver::UpdateLatencies()
2188     UInt32 size;
2189     OSStatus err;
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);
2196     UInt32 value1 = 0;
2197     UInt32 value2 = 0;
2198     err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);
2199     if (err != noErr) {
2200         jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
2201     }
2202     err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
2203     if (err != noErr) {
2204         jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
2205     }
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++) {
2214         if (err != noErr) {
2215             input_range.min += input_latencies[i];
2216             input_range.max += input_latencies[i];
2217         }
2218         fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
2219     }
2221     // Get Output latency
2222     size = sizeof(UInt32);
2223     value1 = 0;
2224     value2 = 0;
2225     err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1);
2226     if (err != noErr) {
2227         jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
2228     }
2229     err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
2230     if (err != noErr) {
2231         jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
2232     }
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++) {
2243         if (err != noErr) {
2244             output_range.min += output_latencies[i];
2245             output_range.max += output_latencies[i];
2246         }
2247         fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
2249         // Monitor port
2250         if (fWithMonitorPorts) {
2251             monitor_range.min = monitor_range.max = fEngineControl->fBufferSize;
2252             fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
2253         }
2254     }
2257 int JackCoreAudioDriver::Attach()
2259     OSStatus err;
2260     JackPort* port;
2261     jack_port_id_t port_index;
2262     UInt32 size;
2263     Boolean isWritable;
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);
2273         if (err != noErr) {
2274             jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
2275         }
2276         if (err == noErr && size > 0) {
2277             err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
2278             if (err != noErr) {
2279                 jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
2280             }
2281             snprintf(alias, sizeof(alias), "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
2282         } else {
2283             snprintf(alias, sizeof(alias), "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
2284         }
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);
2290             return -1;
2291         }
2293         port = fGraphManager->GetPort(port_index);
2294         port->SetAlias(alias);
2295         fCapturePortList[i] = port_index;
2296     }
2298     for (int i = 0; i < fPlaybackChannels; i++) {
2300         err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
2301         if (err != noErr) {
2302             jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
2303         }
2304         if (err == noErr && size > 0) {
2305             err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
2306             if (err != noErr) {
2307                 jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
2308             }
2309             snprintf(alias, sizeof(alias), "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
2310         } else {
2311             snprintf(alias, sizeof(alias), "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
2312         }
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);
2318             return -1;
2319         }
2321         port = fGraphManager->GetPort(port_index);
2322         port->SetAlias(alias);
2323         fPlaybackPortList[i] = port_index;
2325         // Monitor ports
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);
2331                 return -1;
2332             } else {
2333                 fMonitorPortList[i] = port_index;
2334             }
2335         }
2336     }
2337     
2338     if (fAC3Encoder) {
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);
2344         }
2345     }
2347     UpdateLatencies();
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);
2352     }
2354     return 0;
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)
2363         fState = false;
2364         int count = 0;
2366         if (AudioOutputUnitStart(fAUHAL) == noErr) {
2368             while (!fState && count++ < WAIT_COUNTER) {
2369                 usleep(100000);
2370                 jack_log("JackCoreAudioDriver::Start : wait count = %d", count);
2371             }
2373             if (count < WAIT_COUNTER) {
2374                 jack_info("CoreAudio driver is running...");
2375                 return 0;
2376             }
2378             jack_error("CoreAudio driver cannot start...");
2379         }
2380         JackAudioDriver::Stop();
2381     }
2382     return -1;
2385 int JackCoreAudioDriver::Stop()
2387     jack_log("JackCoreAudioDriver::Stop");
2388     int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
2389     if (JackAudioDriver::Stop() < 0) {
2390         res = -1;
2391     }
2392     return res;
2395 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
2397     if (SetupBufferSize(buffer_size) < 0) {
2398         return -1;
2399     }
2401     JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
2403     // CoreAudio specific
2404     UpdateLatencies();
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);
2411     }
2413     return 0;
2416 bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID, bool isInput)
2418     pid_t hog_pid;
2419     UInt32 propSize = sizeof(hog_pid);
2420     
2421     OSStatus err = AudioDeviceGetProperty(deviceID, 0, isInput, kAudioDevicePropertyHogMode, &propSize, &hog_pid);
2422     if (err) {
2423         jack_error("Cannot read hog state...");
2424         printError(err);
2425     }
2426     
2427     jack_log("JackCoreAudioDriver::TakeHogAux : deviceID = %d", deviceID);
2429     if (hog_pid != getpid()) {
2430         hog_pid = getpid();
2431         err = AudioDeviceSetProperty(deviceID, 0, 0, isInput, kAudioDevicePropertyHogMode, propSize, &hog_pid);
2432         if (err != noErr) {
2433             jack_error("Can't hog device = %d because it's being hogged by another program or cannot be hogged", deviceID);
2434             return false;
2435         }
2436     }
2438     return true;
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);
2448     if (err != noErr) {
2449         jack_log("JackCoreAudioDriver::TakeHog : device does not have subdevices");
2450         return TakeHogAux(fDeviceID, true);
2451     } else {
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)) {
2456                 return false;
2457             }
2458         }
2459         return true;
2460     }
2463 bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
2465     UInt32 deviceType, outSize = sizeof(UInt32);
2466     OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
2468     if (err != noErr) {
2469         jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
2470         return false;
2471     } else {
2472         return (deviceType == kAudioDeviceTransportTypeAggregate);
2473     }
2477 } // end of namespace
2480 #ifdef __cplusplus
2481 extern "C"
2483 #endif
2485     SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
2486     {
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);
2493         value.i = -1;
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");
2498         value.str[0] = 0;
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\")");
2502         value.str[0] = 0;
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);
2506         value.i  = 0;
2507         jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL);
2508         
2509 #ifndef __ppc__
2510         value.i  = 0;
2511         jack_driver_descriptor_add_parameter(desc, &filler, "AC3-encoding", 'a', JackDriverParamBool, &value, NULL, "AC3 multi-channels encoding", NULL);
2512         
2513         value.i  = 448;
2514         jack_driver_descriptor_add_parameter(desc, &filler, "AC3-bitrate", 'b', JackDriverParamUInt, &value, NULL, "AC3 bitrate", NULL);
2515        
2516         value.i  = 0;
2517         jack_driver_descriptor_add_parameter(desc, &filler, "AC3-LFE", 'f', JackDriverParamBool, &value, NULL, "AC3 LFE channel", NULL);
2518 #endif
2519         value.i  = true;
2520         jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
2522         value.ui  = 44100U;
2523         jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
2525         value.ui  = 256U;
2526         jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
2528         value.str[0] = 0;
2529         jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "CoreAudio device name", NULL);
2531         value.ui  = 0;
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);
2535         value.i  = false;
2536         jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available CoreAudio devices", NULL);
2538         value.i  = false;
2539         jack_driver_descriptor_add_parameter(desc, &filler, "hog", 'H', JackDriverParamBool, &value, NULL, "Take exclusive access of the audio device", NULL);
2541         value.ui  = 100;
2542         jack_driver_descriptor_add_parameter(desc, &filler, "async-latency", 'L', JackDriverParamUInt, &value, NULL, "Extra output latency in asynchronous mode (percent)", NULL);
2544         value.ui  = 100;
2545         jack_driver_descriptor_add_parameter(desc, &filler, "grain", 'G', JackDriverParamUInt, &value, NULL, "Computation grain in RT thread (percent)", NULL);
2547         value.i = false;
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");
2550         return desc;
2551     }
2553     SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
2554     {
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 = "";
2566         const JSList *node;
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) {
2583                 case 'd':
2584                     capture_driver_uid = param->value.str;
2585                     playback_driver_uid = param->value.str;
2586                     break;
2588                 case 'D':
2589                     capture = true;
2590                     playback = true;
2591                     break;
2593                 case 'c':
2594                     chan_in = chan_out = param->value.i;
2595                     break;
2597                 case 'i':
2598                     chan_in = param->value.i;
2599                     break;
2601                 case 'o':
2602                     chan_out = param->value.i;
2603                     break;
2605                 case 'n':
2606                     chan_in_list = param->value.str;
2607                     break;
2609                 case 'N':
2610                     chan_out_list = param->value.str;
2611                     break;
2613                 case 'C':
2614                     capture = true;
2615                     if (strcmp(param->value.str, "none") != 0) {
2616                         capture_driver_uid = param->value.str;
2617                     }
2618                     break;
2620                 case 'P':
2621                     playback = true;
2622                     if (strcmp(param->value.str, "none") != 0) {
2623                         playback_driver_uid = param->value.str;
2624                     }
2625                     break;
2627                 case 'm':
2628                     monitor = param->value.i;
2629                     break;
2630                     
2631             #ifndef __ppc__            
2632                 case 'a':
2633                     ac3_encoding = param->value.i;
2634                     break;
2635                      
2636                 case 'b':
2637                     ac3_bitrate = param->value.i;
2638                     break;
2639                     
2640                 case 'f':
2641                     ac3_lfe = param->value.i;
2642                     break;
2643             #endif
2645                 case 'r':
2646                     srate = param->value.ui;
2647                     break;
2649                 case 'p':
2650                     frames_per_interrupt = (unsigned int)param->value.ui;
2651                     break;
2653                 case 'I':
2654                     systemic_input_latency = param->value.ui;
2655                     break;
2657                 case 'O':
2658                     systemic_output_latency = param->value.ui;
2659                     break;
2661                 case 'l':
2662                     Jack::DisplayDeviceNames();
2663                     // Stops the server in this case
2664                     return NULL;
2666                 case 'H':
2667                     hogged = true;
2668                     break;
2670                 case 'L':
2671                     async_output_latency = param->value.ui;
2672                     break;
2674                 case 'G':
2675                     computation_grain = param->value.ui;
2676                     break;
2678                 case 's':
2679                     clock_drift = true;
2680                     break;
2681             }
2682         }
2684         /* duplex is the default */
2685         if (!capture && !playback) {
2686             capture = true;
2687             playback = true;
2688         }
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");
2692         }
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");
2696         }
2698         Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
2699         if (driver->Open(frames_per_interrupt,
2700                         srate, capture,
2701                         playback, chan_in,
2702                         chan_out, chan_in_list,
2703                         chan_out_list, monitor,
2704                         capture_driver_uid,
2705                         playback_driver_uid,
2706                         systemic_input_latency,
2707                         systemic_output_latency,
2708                         async_output_latency,
2709                         computation_grain,
2710                         hogged, clock_drift, 
2711                         ac3_encoding, ac3_bitrate, ac3_lfe) == 0) {
2712             return driver;
2713         } else {
2714             delete driver;
2715             return NULL;
2716         }
2717     }
2719 #ifdef __cplusplus
2721 #endif