Jack2  1.9.10
JackCoreAudioDriver.cpp
1 /*
2 Copyright (C) 2004-2008 Grame
3 
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.
8 
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.
13 
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.
17 
18 */
19 
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"
31 
32 #include <sstream>
33 #include <iostream>
34 #include <CoreServices/CoreServices.h>
35 #include <CoreFoundation/CFNumber.h>
36 
37 namespace Jack
38 {
39 
40 static void Print4CharCode(const char* msg, long c)
41 {
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);
47 }
48 
49 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
50 {
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("- - - - - - - - - - - - - - - - - - - -");
61 }
62 
63 static void printError(OSStatus err)
64 {
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  }
130 }
131 
132 static bool CheckAvailableDeviceName(const char* device_name, AudioDeviceID* device_id)
133 {
134  UInt32 size;
135  Boolean isWritable;
136  int i, deviceNum;
137  OSStatus err;
138 
139  err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
140  if (err != noErr) {
141  return false;
142  }
143 
144  deviceNum = size / sizeof(AudioDeviceID);
145  AudioDeviceID devices[deviceNum];
146 
147  err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
148  if (err != noErr) {
149  return false;
150  }
151 
152  for (i = 0; i < deviceNum; i++) {
153  char device_name_aux[256];
154 
155  size = 256;
156  err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name_aux);
157  if (err != noErr) {
158  return false;
159  }
160 
161  if (strncmp(device_name_aux, device_name, strlen(device_name)) == 0) {
162  *device_id = devices[i];
163  return true;
164  }
165  }
166 
167  return false;
168 }
169 
170 static bool CheckAvailableDevice(AudioDeviceID device_id)
171 {
172  UInt32 size;
173  Boolean isWritable;
174  int i, deviceNum;
175  OSStatus err;
176 
177  err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
178  if (err != noErr) {
179  return false;
180  }
181 
182  deviceNum = size / sizeof(AudioDeviceID);
183  AudioDeviceID devices[deviceNum];
184 
185  err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
186  if (err != noErr) {
187  return false;
188  }
189 
190  for (i = 0; i < deviceNum; i++) {
191  if (device_id == devices[i]) {
192  return true;
193  }
194  }
195 
196  return false;
197 }
198 
199 static OSStatus DisplayDeviceNames()
200 {
201  UInt32 size;
202  Boolean isWritable;
203  int i, deviceNum;
204  OSStatus err;
205  CFStringRef UIname;
206 
207  err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
208  if (err != noErr) {
209  return err;
210  }
211 
212  deviceNum = size / sizeof(AudioDeviceID);
213  AudioDeviceID devices[deviceNum];
214 
215  err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
216  if (err != noErr) {
217  return err;
218  }
219 
220  for (i = 0; i < deviceNum; i++) {
221  char device_name[256];
222  char internal_name[256];
223 
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  }
232 
233  size = 256;
234  err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
235  if (err != noErr) {
236  return err;
237  }
238 
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  }
241 
242  return noErr;
243 
244 error:
245  if (UIname != NULL) {
246  CFRelease(UIname);
247  }
248  return err;
249 }
250 
251 static CFStringRef GetDeviceName(AudioDeviceID id)
252 {
253  UInt32 size = sizeof(CFStringRef);
254  CFStringRef UIname;
255  OSStatus err = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
256  return (err == noErr) ? UIname : NULL;
257 }
258 
259 static void ParseChannelList(const string& list, vector<int>& result, int max_chan)
260 {
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  }
275 }
276 
277 OSStatus JackCoreAudioDriver::Render(void* inRefCon,
278  AudioUnitRenderActionFlags* ioActionFlags,
279  const AudioTimeStamp* inTimeStamp,
280  UInt32 inBusNumber,
281  UInt32 inNumberFrames,
282  AudioBufferList* ioData)
283 {
284  return static_cast<JackCoreAudioDriver*>(inRefCon)->Render(ioActionFlags, inTimeStamp, ioData);
285 }
286 
287 OSStatus JackCoreAudioDriver::Render(AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, AudioBufferList* ioData)
288 {
289  fActionFags = ioActionFlags;
290  fCurrentTime = inTimeStamp;
291  fDriverOutputData = ioData;
292 
293  // Setup threaded based log function et get RT thread parameters once...
294  if (set_threaded_log_function()) {
295 
296  jack_log("JackCoreAudioDriver::Render : set_threaded_log_function");
297  JackMachThread::GetParams(pthread_self(), &fEngineControl->fPeriod, &fEngineControl->fComputation, &fEngineControl->fConstraint);
298 
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  }
304 
305  // Signal waiting start function...
306  fState = true;
307 
308  CycleTakeBeginTime();
309 
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  }
319 }
320 
321 int JackCoreAudioDriver::Read()
322 {
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  }
328 }
329 
330 int JackCoreAudioDriver::Write()
331 {
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;
367 }
368 
369 OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
370  UInt32 inChannel,
371  Boolean isInput,
372  AudioDevicePropertyID inPropertyID,
373  void* inClientData)
374 {
375  JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
376 
377  switch (inPropertyID) {
378 
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  }
395 
396  return noErr;
397 }
398 
399 OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
400  UInt32 inChannel,
401  Boolean isInput,
402  AudioDevicePropertyID inPropertyID,
403  void* inClientData)
404 {
405  JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
406 
407  switch (inPropertyID) {
408 
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  }
425 
426  return noErr;
427 }
428 
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)
431 {
432  JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
433 
434  switch (inPropertyID) {
435 
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))) {
443 
444  }
445  break;
446  }
447  }
448 
449  return noErr;
450 }
451 
452 OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
453  UInt32 inChannel,
454  Boolean isInput,
455  AudioDevicePropertyID inPropertyID,
456  void* inClientData)
457 {
458  JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
459 
460  switch (inPropertyID) {
461 
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  }
470 
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  }
479 
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  }
488 
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  }
495 
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  }
503 
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  }
511 
512  char device_name[256];
513  const char* digidesign_name = "Digidesign";
514  driver->GetDeviceNameFromID(driver->fDeviceID, device_name);
515 
516  if (sample_rate != driver->fEngineControl->fSampleRate) {
517 
518  // Digidesign hardware, so "special" code : change the SR again here
519  if (strncmp(device_name, digidesign_name, 10) == 0) {
520 
521  jack_log("JackCoreAudioDriver::DeviceNotificationCallback Digidesign HW = %s", device_name);
522 
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  }
532 
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;
543 
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  }
552 
553  }
554  return noErr;
555 }
556 
557 OSStatus JackCoreAudioDriver::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
558 {
559  UInt32 size = sizeof(AudioValueTranslation);
560  CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
561  AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
562 
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  }
571 }
572 
573 OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id)
574 {
575  OSStatus res;
576  UInt32 theSize = sizeof(UInt32);
577  AudioDeviceID inDefault;
578  AudioDeviceID outDefault;
579 
580  if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
581  return res;
582  }
583 
584  if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
585  return res;
586  }
587 
588  jack_log("JackCoreAudioDriver::GetDefaultDevice : input = %ld output = %ld", inDefault, outDefault);
589 
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  }
601 }
602 
603 OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id)
604 {
605  OSStatus res;
606  UInt32 theSize = sizeof(UInt32);
607  AudioDeviceID inDefault;
608 
609  if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
610  return res;
611  }
612 
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;
627 }
628 
629 OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id)
630 {
631  OSStatus res;
632  UInt32 theSize = sizeof(UInt32);
633  AudioDeviceID outDefault;
634 
635  if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
636  return res;
637  }
638 
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;
652 }
653 
654 OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID id, char* name)
655 {
656  UInt32 size = 256;
657  return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
658 }
659 
660 OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
661 {
662  OSStatus err = noErr;
663  UInt32 outSize;
664  Boolean outWritable;
665 
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;
681 }
682 
683 OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies)
684 {
685  OSStatus err = noErr;
686  UInt32 outSize1, outSize2, outSize3;
687  Boolean outWritable;
688 
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);
696 
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  }
702 
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  }
708 
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;
727 }
728 
729 bool JackCoreAudioDriver::IsDigitalDevice(AudioDeviceID device)
730 {
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);
747 
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  }
767 
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;
795 }
796 
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)
809 {}
810 
811 JackCoreAudioDriver::~JackCoreAudioDriver()
812 {
813  delete fAC3Encoder;
814 }
815 
816 OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
817 {
818  OSStatus osErr = noErr;
819  AudioObjectPropertyAddress pluginAOPA;
820  pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
821  pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
822  pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
823  UInt32 outDataSize;
824 
825  if (fPluginID > 0) {
826 
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  }
833 
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  }
840 
841  }
842 
843  return noErr;
844 }
845 
846 OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
847 {
848  OSStatus err = noErr;
849  AudioObjectID sub_device[32];
850  UInt32 outSize = sizeof(sub_device);
851 
852  err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
853  vector<AudioDeviceID> captureDeviceIDArray;
854 
855  jack_log("JackCoreAudioDriver::CreateAggregateDevice : input device %d", captureDeviceID);
856 
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  }
868 
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);
874 
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  }
886 
887  return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
888 }
889 
890 OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
891 {
892  OSStatus osErr = noErr;
893  UInt32 outSize;
894  Boolean outWritable;
895 
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;
904 
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;
912 
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  }
932 
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  }
952 
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  }
957 
958  //---------------------------------------------------------------------------
959  // Start to create a new aggregate by getting the base audio hardware plugin
960  //---------------------------------------------------------------------------
961 
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  }
967 
968  for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
969  GetDeviceNameFromID(playbackDeviceID[i], device_name);
970  jack_info("Separated output = '%s' ", device_name);
971  }
972 
973  osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
974  if (osErr != noErr) {
975  jack_error("CreateAggregateDeviceAux : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
976  printError(osErr);
977  return osErr;
978  }
979 
980  AudioValueTranslation pluginAVT;
981 
982  CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
983 
984  pluginAVT.mInputData = &inBundleRef;
985  pluginAVT.mInputDataSize = sizeof(inBundleRef);
986  pluginAVT.mOutputData = &fPluginID;
987  pluginAVT.mOutputDataSize = sizeof(fPluginID);
988 
989  osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
990  if (osErr != noErr) {
991  jack_error("CreateAggregateDeviceAux : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
992  printError(osErr);
993  return osErr;
994  }
995 
996  //-------------------------------------------------
997  // Create a CFDictionary for our aggregate device
998  //-------------------------------------------------
999 
1000  CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1001 
1002  CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
1003  CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
1004 
1005  // add the name of the device to the dictionary
1006  CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
1007 
1008  // add our choice of UID for the aggregate device to the dictionary
1009  CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
1010 
1011  // add a "private aggregate key" to the dictionary
1012  int value = 1;
1013  CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
1014 
1015  SInt32 system;
1016  Gestalt(gestaltSystemVersion, &system);
1017 
1018  jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : system version = %x limit = %x", system, 0x00001054);
1019 
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  }
1027 
1028  // Prepare sub-devices for clock drift compensation
1029  CFMutableArrayRef subDevicesArrayClock = NULL;
1030 
1031  /*
1032  if (fClockDriftCompensate) {
1033  if (need_clock_drift_compensation) {
1034  jack_info("Clock drift compensation activated...");
1035  subDevicesArrayClock = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1036 
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  }
1047 
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  }
1058 
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  */
1066 
1067  //-------------------------------------------------
1068  // Create a CFMutableArray for our sub-device list
1069  //-------------------------------------------------
1070 
1071  // we need to append the UID for each device to a CFMutableArray, so create one here
1072  CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1073 
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  }
1084 
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  }
1095 
1096  //-----------------------------------------------------------------------
1097  // Feed the dictionary to the plugin, to create a blank aggregate device
1098  //-----------------------------------------------------------------------
1099 
1100  AudioObjectPropertyAddress pluginAOPA;
1101  pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
1102  pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1103  pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1104  UInt32 outDataSize;
1105 
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  }
1112 
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  }
1119 
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);
1123 
1124  //-------------------------
1125  // Set the sub-device list
1126  //-------------------------
1127 
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  }
1138 
1139  // pause again to give the changes time to take effect
1140  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1141 
1142  //-----------------------
1143  // Set the master device
1144  //-----------------------
1145 
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, &captureDeviceUID[0]); // First capture is master...
1153  if (osErr != noErr) {
1154  jack_error("CreateAggregateDeviceAux : AudioObjectSetPropertyData for master device error");
1155  printError(osErr);
1156  goto error;
1157  }
1158 
1159  // pause again to give the changes time to take effect
1160  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1161 
1162  // Prepare sub-devices for clock drift compensation
1163  // Workaround for bug in the HAL : until 10.6.2
1164 
1165  if (fClockDriftCompensate) {
1166  if (need_clock_drift_compensation) {
1167  jack_info("Clock drift compensation activated...");
1168 
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  }
1175 
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);
1181 
1182  osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
1183  if (osErr != noErr) {
1184  jack_error("CreateAggregateDeviceAux kAudioObjectPropertyOwnedObjects error");
1185  printError(osErr);
1186  }
1187 
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  }
1201 
1202  // pause again to give the changes time to take effect
1203  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1204 
1205  //----------
1206  // Clean up
1207  //----------
1208 
1209  // release the private AD key
1210  CFRelease(AggregateDeviceNumberRef);
1211 
1212  // release the CF objects we have created - we don't need them any more
1213  CFRelease(aggDeviceDict);
1214  CFRelease(subDevicesArray);
1215 
1216  if (subDevicesArrayClock) {
1217  CFRelease(subDevicesArrayClock);
1218  }
1219 
1220  // release the device UID
1221  for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
1222  CFRelease(captureDeviceUID[i]);
1223  }
1224 
1225  for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
1226  CFRelease(playbackDeviceUID[i]);
1227  }
1228 
1229  jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : new aggregate device %ld", *outAggregateDevice);
1230  return noErr;
1231 
1232 error:
1233  DestroyAggregateDevice();
1234  return -1;
1235 }
1236 
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)
1243 {
1244  capture_driver_name[0] = 0;
1245  playback_driver_name[0] = 0;
1246 
1247  // Duplex
1248  if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
1249  jack_log("JackCoreAudioDriver::SetupDevices : duplex");
1250 
1251  // Same device for capture and playback...
1252  if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
1253 
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  }
1275 
1276  } else {
1277 
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  }
1289 
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  }
1297 
1298  if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1299  return -1;
1300  }
1301 
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  }
1318 
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  }
1341 
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  }
1367 
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");
1373 
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  }
1385 
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  }
1393 
1394  if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1395  return -1;
1396  }
1397 
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;
1416 }
1417 
1418 /*
1419 Return the max possible input channels in in_maxChannels and output channels in out_maxChannels.
1420 */
1421 int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchannels, int& outchannels, int& in_maxChannels, int& out_maxChannels, bool strict)
1422 {
1423  OSStatus err = noErr;
1424 
1425  jack_log("JackCoreAudioDriver::SetupChannels : fDeviceID = %d", fDeviceID);
1426 
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  }
1437 
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  }
1448 
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  }
1455 
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  }
1462 
1463  if (inchannels == -1) {
1464  jack_log("JackCoreAudioDriver::SetupChannels : setup max in channels = %d", in_maxChannels);
1465  inchannels = in_maxChannels;
1466  }
1467 
1468  if (outchannels == -1) {
1469  jack_log("JackCoreAudioDriver::SetupChannels : setup max out channels = %d", out_maxChannels);
1470  outchannels = out_maxChannels;
1471  }
1472 
1473  return 0;
1474 }
1475 
1476 int JackCoreAudioDriver::SetupBufferSize(jack_nframes_t buffer_size)
1477 {
1478  // Setting buffer size
1479  OSStatus err = noErr;
1480  UInt32 tmp_buffer_size = buffer_size;
1481  UInt32 outSize = sizeof(UInt32);
1482 
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  }
1491 
1492  // If needed, set new buffer size
1493  if (buffer_size != tmp_buffer_size) {
1494  tmp_buffer_size = buffer_size;
1495 
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  }
1503 
1504  // Waiting for BS change notification
1505  int count = 0;
1506  fState = false;
1507 
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  }
1514 
1515  while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1516  usleep(100000);
1517  jack_log("JackCoreAudioDriver::SetupBufferSize : wait count = %d", count);
1518  }
1519 
1520  if (count >= WAIT_NOTIFICATION_COUNTER) {
1521  jack_error("Did not get buffer size notification...");
1522  goto error;
1523  }
1524 
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  }
1534 
1535  // Remove BS change notification
1536  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1537  }
1538 
1539  return 0;
1540 
1541 error:
1542 
1543  // Remove BS change notification
1544  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1545  return -1;
1546 }
1547 
1548 int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t sample_rate)
1549 {
1550  return SetupSampleRateAux(fDeviceID, sample_rate);
1551 }
1552 
1553 int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t sample_rate)
1554 {
1555  OSStatus err = noErr;
1556  UInt32 outSize;
1557  Float64 tmp_sample_rate;
1558 
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  }
1569 
1570  // If needed, set new sample rate
1571  if (sample_rate != (jack_nframes_t)tmp_sample_rate) {
1572  tmp_sample_rate = (Float64)sample_rate;
1573 
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  }
1581 
1582  // Waiting for SR change notification
1583  int count = 0;
1584  fState = false;
1585 
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  }
1592 
1593  while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1594  usleep(100000);
1595  jack_log("JackCoreAudioDriver::SetupSampleRateAux : wait count = %d", count);
1596  }
1597 
1598  if (count >= WAIT_NOTIFICATION_COUNTER) {
1599  jack_error("Did not get sample rate notification...");
1600  goto error;
1601  }
1602 
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  }
1612 
1613  // Remove SR change notification
1614  AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1615  }
1616 
1617  return 0;
1618 
1619 error:
1620 
1621  // Remove SR change notification
1622  AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1623  return -1;
1624 }
1625 
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)
1636 {
1637  ComponentResult err1;
1638  UInt32 enableIO;
1639  AudioStreamBasicDescription srcFormat, dstFormat;
1640  AudioDeviceID currAudioDeviceID;
1641  UInt32 size;
1642 
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());
1645 
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
1671 
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  }
1687 
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  }
1694 
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  }
1702 
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  }
1709 
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  }
1719 
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  }
1727 
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  }
1737 
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  }
1746 
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  }
1772 
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  }
1780 
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  }
1806 
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  }
1814 
1815  // Setup stream converters
1816  if (capturing && inchannels > 0) {
1817 
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);
1826 
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);
1837 
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  }
1845 
1846  if (playing && outchannels > 0) {
1847 
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);
1856 
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);
1867 
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  }
1875 
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  }
1898 
1899  return 0;
1900 
1901 error:
1902  CloseAUHAL();
1903  return -1;
1904 }
1905 
1906 int JackCoreAudioDriver::SetupBuffers(int inchannels)
1907 {
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;
1916 }
1917 
1918 void JackCoreAudioDriver::DisposeBuffers()
1919 {
1920  if (fJackInputData) {
1921  free(fJackInputData);
1922  fJackInputData = 0;
1923  }
1924 }
1925 
1926 void JackCoreAudioDriver::CloseAUHAL()
1927 {
1928  AudioOutputUnitStop(fAUHAL);
1929  AudioUnitUninitialize(fAUHAL);
1930  CloseComponent(fAUHAL);
1931 }
1932 
1933 int JackCoreAudioDriver::AddListeners()
1934 {
1935  OSStatus err = noErr;
1936 
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  }
1944 
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  }
1951 
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  }
1958 
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  }
1965 
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  }
1972 
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  }
1979 
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  }
1986 
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  }
1993 
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  }
2002 
2003  return 0;
2004 }
2005 
2006 void JackCoreAudioDriver::RemoveListeners()
2007 {
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);
2016 }
2017 
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)
2038 {
2039  int in_maxChannels = 0;
2040  int out_maxChannels = 0;
2041  char capture_driver_name[256];
2042  char playback_driver_name[256];
2043 
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;
2050 
2051  SInt32 major;
2052  SInt32 minor;
2053  Gestalt(gestaltSystemVersionMajor, &major);
2054  Gestalt(gestaltSystemVersionMinor, &minor);
2055 
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  }
2073 
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  }
2085 
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  }
2095 
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  }
2101 
2102  if (SetupBufferSize(buffer_size) < 0) {
2103  goto error;
2104  }
2105 
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;
2150 
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  }
2154 
2155  if (capturing && inchannels > 0) {
2156  if (SetupBuffers(inchannels) < 0) {
2157  goto error;
2158  }
2159  }
2160 
2161  if (AddListeners() < 0) {
2162  goto error;
2163  }
2164 
2165  return noErr;
2166 
2167 error:
2168  Close();
2169  return -1;
2170 }
2171 
2172 int JackCoreAudioDriver::Close()
2173 {
2174  jack_log("JackCoreAudioDriver::Close");
2175 
2176  // Generic audio driver close
2177  int res = JackAudioDriver::Close();
2178 
2179  RemoveListeners();
2180  DisposeBuffers();
2181  CloseAUHAL();
2182  DestroyAggregateDevice();
2183  return res;
2184 }
2185 
2186 void JackCoreAudioDriver::UpdateLatencies()
2187 {
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;
2193 
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  }
2206 
2207  input_range.min = input_range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
2208 
2209  // Get input stream latencies
2210  vector<int> input_latencies;
2211  err = GetStreamLatencies(fDeviceID, true, input_latencies);
2212 
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  }
2220 
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  }
2233 
2234  // Get output stream latencies
2235  vector<int> output_latencies;
2236  err = GetStreamLatencies(fDeviceID, false, output_latencies);
2237 
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;
2241 
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);
2248 
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  }
2255 }
2256 
2257 int JackCoreAudioDriver::Attach()
2258 {
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];
2266  char alias[REAL_JACK_PORT_NAME_SIZE];
2267 
2268  jack_log("JackCoreAudioDriver::Attach : fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
2269 
2270  for (int i = 0; i < fCaptureChannels; i++) {
2271 
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  }
2285 
2286  snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, i + 1);
2287 
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  }
2292 
2293  port = fGraphManager->GetPort(port_index);
2294  port->SetAlias(alias);
2295  fCapturePortList[i] = port_index;
2296  }
2297 
2298  for (int i = 0; i < fPlaybackChannels; i++) {
2299 
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  }
2313 
2314  snprintf(name, sizeof(name), "%s:playback_%d", fClientControl.fName, i + 1);
2315 
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  }
2320 
2321  port = fGraphManager->GetPort(port_index);
2322  port->SetAlias(alias);
2323  fPlaybackPortList[i] = port_index;
2324 
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  }
2346 
2347  UpdateLatencies();
2348 
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  }
2353 
2354  return 0;
2355 }
2356 
2357 int JackCoreAudioDriver::Start()
2358 {
2359  jack_log("JackCoreAudioDriver::Start");
2360  if (JackAudioDriver::Start() == 0) {
2361 
2362  // Waiting for Render callback to be called (= driver has started)
2363  fState = false;
2364  int count = 0;
2365 
2366  if (AudioOutputUnitStart(fAUHAL) == noErr) {
2367 
2368  while (!fState && count++ < WAIT_COUNTER) {
2369  usleep(100000);
2370  jack_log("JackCoreAudioDriver::Start : wait count = %d", count);
2371  }
2372 
2373  if (count < WAIT_COUNTER) {
2374  jack_info("CoreAudio driver is running...");
2375  return 0;
2376  }
2377 
2378  jack_error("CoreAudio driver cannot start...");
2379  }
2380  JackAudioDriver::Stop();
2381  }
2382  return -1;
2383 }
2384 
2385 int JackCoreAudioDriver::Stop()
2386 {
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;
2393 }
2394 
2395 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
2396 {
2397  if (SetupBufferSize(buffer_size) < 0) {
2398  return -1;
2399  }
2400 
2401  JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
2402 
2403  // CoreAudio specific
2404  UpdateLatencies();
2405 
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  }
2412 
2413  return 0;
2414 }
2415 
2416 bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID, bool isInput)
2417 {
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);
2428 
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  }
2437 
2438  return true;
2439 }
2440 
2441 bool JackCoreAudioDriver::TakeHog()
2442 {
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);
2447 
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  }
2461 }
2462 
2463 bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
2464 {
2465  UInt32 deviceType, outSize = sizeof(UInt32);
2466  OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
2467 
2468  if (err != noErr) {
2469  jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
2470  return false;
2471  } else {
2472  return (deviceType == kAudioDeviceTransportTypeAggregate);
2473  }
2474 }
2475 
2476 
2477 } // end of namespace
2478 
2479 
2480 #ifdef __cplusplus
2481 extern "C"
2482 {
2483 #endif
2484 
2485  SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
2486  {
2487  jack_driver_desc_t * desc;
2490 
2491  desc = jack_driver_descriptor_construct("coreaudio", JackDriverMaster, "Apple CoreAudio API based audio backend", &filler);
2492 
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");
2497 
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\")");
2501 
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);
2505 
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);
2521 
2522  value.ui = 44100U;
2523  jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
2524 
2525  value.ui = 256U;
2526  jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
2527 
2528  value.str[0] = 0;
2529  jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "CoreAudio device name", NULL);
2530 
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);
2534 
2535  value.i = false;
2536  jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available CoreAudio devices", NULL);
2537 
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);
2540 
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);
2543 
2544  value.ui = 100;
2545  jack_driver_descriptor_add_parameter(desc, &filler, "grain", 'G', JackDriverParamUInt, &value, NULL, "Computation grain in RT thread (percent)", NULL);
2546 
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");
2549 
2550  return desc;
2551  }
2552 
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;
2577 
2578  for (node = params; node; node = jack_slist_next(node)) {
2579  param = (const jack_driver_param_t *) node->data;
2580 
2581  switch (param->character) {
2582 
2583  case 'd':
2584  capture_driver_uid = param->value.str;
2585  playback_driver_uid = param->value.str;
2586  break;
2587 
2588  case 'D':
2589  capture = true;
2590  playback = true;
2591  break;
2592 
2593  case 'c':
2594  chan_in = chan_out = param->value.i;
2595  break;
2596 
2597  case 'i':
2598  chan_in = param->value.i;
2599  break;
2600 
2601  case 'o':
2602  chan_out = param->value.i;
2603  break;
2604 
2605  case 'n':
2606  chan_in_list = param->value.str;
2607  break;
2608 
2609  case 'N':
2610  chan_out_list = param->value.str;
2611  break;
2612 
2613  case 'C':
2614  capture = true;
2615  if (strcmp(param->value.str, "none") != 0) {
2616  capture_driver_uid = param->value.str;
2617  }
2618  break;
2619 
2620  case 'P':
2621  playback = true;
2622  if (strcmp(param->value.str, "none") != 0) {
2623  playback_driver_uid = param->value.str;
2624  }
2625  break;
2626 
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
2644 
2645  case 'r':
2646  srate = param->value.ui;
2647  break;
2648 
2649  case 'p':
2650  frames_per_interrupt = (unsigned int)param->value.ui;
2651  break;
2652 
2653  case 'I':
2654  systemic_input_latency = param->value.ui;
2655  break;
2656 
2657  case 'O':
2658  systemic_output_latency = param->value.ui;
2659  break;
2660 
2661  case 'l':
2662  Jack::DisplayDeviceNames();
2663  // Stops the server in this case
2664  return NULL;
2665 
2666  case 'H':
2667  hogged = true;
2668  break;
2669 
2670  case 'L':
2671  async_output_latency = param->value.ui;
2672  break;
2673 
2674  case 'G':
2675  computation_grain = param->value.ui;
2676  break;
2677 
2678  case 's':
2679  clock_drift = true;
2680  break;
2681  }
2682  }
2683 
2684  /* duplex is the default */
2685  if (!capture && !playback) {
2686  capture = true;
2687  playback = true;
2688  }
2689 
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  }
2693 
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  }
2697 
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  }
2718 
2719 #ifdef __cplusplus
2720 }
2721 #endif
2722 
2723