Jack2  1.9.9
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 (strcmp(device_name_aux, device_name) == 0) {
162  *device_id = devices[i];
163  return true;
164  }
165 
166  }
167 
168  return false;
169 }
170 
171 static bool CheckAvailableDevice(AudioDeviceID device_id)
172 {
173  UInt32 size;
174  Boolean isWritable;
175  int i, deviceNum;
176  OSStatus err;
177 
178  err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
179  if (err != noErr) {
180  return false;
181  }
182 
183  deviceNum = size / sizeof(AudioDeviceID);
184  AudioDeviceID devices[deviceNum];
185 
186  err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
187  if (err != noErr) {
188  return false;
189  }
190 
191  for (i = 0; i < deviceNum; i++) {
192  if (device_id == devices[i]) {
193  return true;
194  }
195  }
196 
197  return false;
198 }
199 
200 
201 static OSStatus DisplayDeviceNames()
202 {
203  UInt32 size;
204  Boolean isWritable;
205  int i, deviceNum;
206  OSStatus err;
207  CFStringRef UIname;
208 
209  err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
210  if (err != noErr) {
211  return err;
212  }
213 
214  deviceNum = size / sizeof(AudioDeviceID);
215  AudioDeviceID devices[deviceNum];
216 
217  err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
218  if (err != noErr) {
219  return err;
220  }
221 
222  for (i = 0; i < deviceNum; i++) {
223  char device_name[256];
224  char internal_name[256];
225 
226  size = sizeof(CFStringRef);
227  UIname = NULL;
228  err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
229  if (err == noErr) {
230  CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
231  } else {
232  goto error;
233  }
234 
235  size = 256;
236  err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
237  if (err != noErr) {
238  return err;
239  }
240 
241  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);
242  }
243 
244  return noErr;
245 
246 error:
247  if (UIname != NULL) {
248  CFRelease(UIname);
249  }
250  return err;
251 }
252 
253 static CFStringRef GetDeviceName(AudioDeviceID id)
254 {
255  UInt32 size = sizeof(CFStringRef);
256  CFStringRef UIname;
257  OSStatus err = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
258  return (err == noErr) ? UIname : NULL;
259 }
260 
261 static void ParseChannelList(const string& list, vector<int>& result, int max_chan)
262 {
263  stringstream ss(list);
264  string token;
265  int chan;
266 
267  while (ss >> token) {
268  istringstream ins;
269  ins.str(token);
270  ins >> chan;
271  if (chan < 0 || chan >= max_chan) {
272  jack_error("Ignore incorrect channel mapping value = %d", chan);
273  } else {
274  result.push_back(chan);
275  }
276  }
277 }
278 
279 OSStatus JackCoreAudioDriver::Render(void* inRefCon,
280  AudioUnitRenderActionFlags* ioActionFlags,
281  const AudioTimeStamp* inTimeStamp,
282  UInt32 inBusNumber,
283  UInt32 inNumberFrames,
284  AudioBufferList* ioData)
285 {
286  JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon;
287  driver->fActionFags = ioActionFlags;
288  driver->fCurrentTime = inTimeStamp;
289  driver->fDriverOutputData = ioData;
290 
291  // Setup threaded based log function et get RT thread parameters once...
292  if (set_threaded_log_function()) {
293 
294  jack_log("JackCoreAudioDriver::Render : set_threaded_log_function");
295  JackMachThread::GetParams(pthread_self(), &driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint);
296 
297  if (driver->fComputationGrain > 0) {
298  jack_log("JackCoreAudioDriver::Render : RT thread computation setup to %d percent of period", int(driver->fComputationGrain * 100));
299  driver->fEngineControl->fComputation = driver->fEngineControl->fPeriod * driver->fComputationGrain;
300  }
301  }
302 
303  // Signal waiting start function...
304  driver->fState = true;
305 
306  driver->CycleTakeBeginTime();
307 
308  if (driver->Process() < 0) {
309  jack_error("Process error, stopping driver");
310  driver->NotifyFailure(JackBackendError, "Process error, stopping driver"); // Message length limited to JACK_MESSAGE_SIZE
311  driver->Stop();
312  kill(JackTools::GetPID(), SIGINT);
313  return kAudioHardwareUnsupportedOperationError;
314  } else {
315  return noErr;
316  }
317 }
318 
319 int JackCoreAudioDriver::Read()
320 {
321  if (fCaptureChannels > 0) { // Calling AudioUnitRender with no input returns a '????' error (callback setting issue ??), so hack to avoid it here...
322  return (AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData) == noErr) ? 0 : -1;
323  } else {
324  return 0;
325  }
326 }
327 
328 int JackCoreAudioDriver::Write()
329 {
330  if (fAC3Encoder) {
331 
332  // AC3 encoding and SPDIF write
333  jack_default_audio_sample_t* AC3_inputs[MAX_AC3_CHANNELS];
334  jack_default_audio_sample_t* AC3_outputs[2];
335  for (int i = 0; i < fPlaybackChannels; i++) {
336  AC3_inputs[i] = GetOutputBuffer(i);
337  // If not connected, clear the buffer
338  if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) == 0) {
339  memset(AC3_inputs[i], 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
340  }
341  }
342  AC3_outputs[0] = (jack_default_audio_sample_t*)fDriverOutputData->mBuffers[0].mData;
343  AC3_outputs[1] = (jack_default_audio_sample_t*)fDriverOutputData->mBuffers[1].mData;
344  fAC3Encoder->Process(AC3_inputs, AC3_outputs, fEngineControl->fBufferSize);
345 
346  } else {
347 
348  // Standard write
349  for (int i = 0; i < fPlaybackChannels; i++) {
350  if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
351  jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
352  int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
353  memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
354  // Monitor ports
355  if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
356  memcpy(GetMonitorBuffer(i), buffer, size);
357  }
358  } else {
359  memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
360  }
361  }
362  }
363  return 0;
364 }
365 
366 OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
367  UInt32 inChannel,
368  Boolean isInput,
369  AudioDevicePropertyID inPropertyID,
370  void* inClientData)
371 {
372  JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
373 
374  switch (inPropertyID) {
375 
376  case kAudioDevicePropertyNominalSampleRate: {
377  jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
378  // Check new sample rate
379  Float64 tmp_sample_rate;
380  UInt32 outSize = sizeof(Float64);
381  OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
382  if (err != noErr) {
383  jack_error("Cannot get current sample rate");
384  printError(err);
385  } else {
386  jack_log("JackCoreAudioDriver::SRNotificationCallback : checked sample rate = %f", tmp_sample_rate);
387  }
388  driver->fState = true;
389  break;
390  }
391  }
392 
393  return noErr;
394 }
395 
396 OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
397  UInt32 inChannel,
398  Boolean isInput,
399  AudioDevicePropertyID inPropertyID,
400  void* inClientData)
401 {
402  JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
403 
404  switch (inPropertyID) {
405 
406  case kAudioDevicePropertyBufferFrameSize: {
407  jack_log("JackCoreAudioDriver::BSNotificationCallback kAudioDevicePropertyBufferFrameSize");
408  // Check new buffer size
409  UInt32 tmp_buffer_size;
410  UInt32 outSize = sizeof(UInt32);
411  OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
412  if (err != noErr) {
413  jack_error("Cannot get current buffer size");
414  printError(err);
415  } else {
416  jack_log("JackCoreAudioDriver::BSNotificationCallback : checked buffer size = %d", tmp_buffer_size);
417  }
418  driver->fState = true;
419  break;
420  }
421  }
422 
423  return noErr;
424 }
425 
426 // A better implementation would possibly try to recover in case of hardware device change (see HALLAB HLFilePlayerWindowControllerAudioDevicePropertyListenerProc code)
427 OSStatus JackCoreAudioDriver::AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID, void* inClientData)
428 {
429  JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
430 
431  switch (inPropertyID) {
432 
433  case kAudioHardwarePropertyDevices: {
434  jack_log("JackCoreAudioDriver::AudioHardwareNotificationCallback kAudioHardwarePropertyDevices");
435  DisplayDeviceNames();
436  AudioDeviceID captureID, playbackID;
437  if (CheckAvailableDevice(driver->fDeviceID) ||
438  (CheckAvailableDeviceName(driver->fCaptureUID, &captureID)
439  && CheckAvailableDeviceName(driver->fPlaybackUID, &playbackID))) {
440 
441  }
442  break;
443  }
444  }
445 
446  return noErr;
447 }
448 
449 OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
450  UInt32 inChannel,
451  Boolean isInput,
452  AudioDevicePropertyID inPropertyID,
453  void* inClientData)
454 {
455  JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
456 
457  switch (inPropertyID) {
458 
459  case kAudioDevicePropertyDeviceIsRunning: {
460  UInt32 isrunning = 0;
461  UInt32 outsize = sizeof(UInt32);
462  if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsRunning, &outsize, &isrunning) == noErr) {
463  jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsRunning = %d", isrunning);
464  }
465  break;
466  }
467 
468  case kAudioDevicePropertyDeviceIsAlive: {
469  UInt32 isalive = 0;
470  UInt32 outsize = sizeof(UInt32);
471  if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsAlive, &outsize, &isalive) == noErr) {
472  jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsAlive = %d", isalive);
473  }
474  break;
475  }
476 
477  case kAudioDevicePropertyDeviceHasChanged: {
478  UInt32 hachanged = 0;
479  UInt32 outsize = sizeof(UInt32);
480  if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceHasChanged, &outsize, &hachanged) == noErr) {
481  jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceHasChanged = %d", hachanged);
482  }
483  break;
484  }
485 
486  case kAudioDeviceProcessorOverload: {
487  jack_error("DeviceNotificationCallback kAudioDeviceProcessorOverload");
488  jack_time_t cur_time = GetMicroSeconds();
489  driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing...
490  break;
491  }
492 
493  case kAudioDevicePropertyStreamConfiguration: {
494  jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration : server will quit...");
495  driver->NotifyFailure(JackBackendError, "Another application has changed the device configuration"); // Message length limited to JACK_MESSAGE_SIZE
496  driver->CloseAUHAL();
497  kill(JackTools::GetPID(), SIGINT);
498  return kAudioHardwareUnsupportedOperationError;
499  }
500 
501  case kAudioDevicePropertyNominalSampleRate: {
502  Float64 sample_rate = 0;
503  UInt32 outsize = sizeof(Float64);
504  OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
505  if (err != noErr) {
506  return kAudioHardwareUnsupportedOperationError;
507  }
508 
509  char device_name[256];
510  const char* digidesign_name = "Digidesign";
511  driver->GetDeviceNameFromID(driver->fDeviceID, device_name);
512 
513  if (sample_rate != driver->fEngineControl->fSampleRate) {
514 
515  // Digidesign hardware, so "special" code : change the SR again here
516  if (strncmp(device_name, digidesign_name, 10) == 0) {
517 
518  jack_log("JackCoreAudioDriver::DeviceNotificationCallback Digidesign HW = %s", device_name);
519 
520  // Set sample rate again...
521  sample_rate = driver->fEngineControl->fSampleRate;
522  err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sample_rate);
523  if (err != noErr) {
524  jack_error("Cannot set sample rate = %f", sample_rate);
525  printError(err);
526  } else {
527  jack_log("JackCoreAudioDriver::DeviceNotificationCallback : set sample rate = %f", sample_rate);
528  }
529 
530  // Check new sample rate again...
531  outsize = sizeof(Float64);
532  err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
533  if (err != noErr) {
534  jack_error("Cannot get current sample rate");
535  printError(err);
536  } else {
537  jack_log("JackCoreAudioDriver::DeviceNotificationCallback : checked sample rate = %f", sample_rate);
538  }
539  return noErr;
540 
541  } else {
542  driver->NotifyFailure(JackBackendError, "Another application has changed the sample rate"); // Message length limited to JACK_MESSAGE_SIZE
543  driver->CloseAUHAL();
544  kill(JackTools::GetPID(), SIGINT);
545  return kAudioHardwareUnsupportedOperationError;
546  }
547  }
548  }
549 
550  }
551  return noErr;
552 }
553 
554 OSStatus JackCoreAudioDriver::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
555 {
556  UInt32 size = sizeof(AudioValueTranslation);
557  CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
558  AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
559 
560  if (inIUD == NULL) {
561  return kAudioHardwareUnspecifiedError;
562  } else {
563  OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
564  CFRelease(inIUD);
565  jack_log("JackCoreAudioDriver::GetDeviceIDFromUID %s %ld", UID, *id);
566  return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
567  }
568 }
569 
570 OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id)
571 {
572  OSStatus res;
573  UInt32 theSize = sizeof(UInt32);
574  AudioDeviceID inDefault;
575  AudioDeviceID outDefault;
576 
577  if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
578  return res;
579  }
580 
581  if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
582  return res;
583  }
584 
585  jack_log("JackCoreAudioDriver::GetDefaultDevice : input = %ld output = %ld", inDefault, outDefault);
586 
587  // Get the device only if default input and output are the same
588  if (inDefault != outDefault) {
589  jack_error("Default input and output devices are not the same !!");
590  return kAudioHardwareBadDeviceError;
591  } else if (inDefault == 0) {
592  jack_error("Default input and output devices are null !!");
593  return kAudioHardwareBadDeviceError;
594  } else {
595  *id = inDefault;
596  return noErr;
597  }
598 }
599 
600 OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id)
601 {
602  OSStatus res;
603  UInt32 theSize = sizeof(UInt32);
604  AudioDeviceID inDefault;
605 
606  if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
607  return res;
608  }
609 
610  if (inDefault == 0) {
611  jack_error("Error default input device is 0, please select a correct one !!");
612  return -1;
613  }
614  jack_log("JackCoreAudioDriver::GetDefaultInputDevice : input = %ld ", inDefault);
615  *id = inDefault;
616  return noErr;
617 }
618 
619 OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id)
620 {
621  OSStatus res;
622  UInt32 theSize = sizeof(UInt32);
623  AudioDeviceID outDefault;
624 
625  if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
626  return res;
627  }
628 
629  if (outDefault == 0) {
630  jack_error("Error default output device is 0, please select a correct one !!");
631  return -1;
632  }
633  jack_log("JackCoreAudioDriver::GetDefaultOutputDevice : output = %ld", outDefault);
634  *id = outDefault;
635  return noErr;
636 }
637 
638 OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID id, char* name)
639 {
640  UInt32 size = 256;
641  return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
642 }
643 
644 OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
645 {
646  OSStatus err = noErr;
647  UInt32 outSize;
648  Boolean outWritable;
649 
650  channelCount = 0;
651  err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
652  if (err == noErr) {
653  int stream_count = outSize / sizeof(AudioBufferList);
654  jack_log("JackCoreAudioDriver::GetTotalChannels stream_count = %d", stream_count);
655  AudioBufferList bufferList[stream_count];
656  err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
657  if (err == noErr) {
658  for (uint i = 0; i < bufferList->mNumberBuffers; i++) {
659  channelCount += bufferList->mBuffers[i].mNumberChannels;
660  jack_log("JackCoreAudioDriver::GetTotalChannels stream = %d channels = %d", i, bufferList->mBuffers[i].mNumberChannels);
661  }
662  }
663  }
664  return err;
665 }
666 
667 OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies)
668 {
669  OSStatus err = noErr;
670  UInt32 outSize1, outSize2, outSize3;
671  Boolean outWritable;
672 
673  err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable);
674  if (err == noErr) {
675  int stream_count = outSize1 / sizeof(UInt32);
676  AudioStreamID streamIDs[stream_count];
677  AudioBufferList bufferList[stream_count];
678  UInt32 streamLatency;
679  outSize2 = sizeof(UInt32);
680 
681  err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs);
682  if (err != noErr) {
683  jack_error("GetStreamLatencies kAudioDevicePropertyStreams err = %d", err);
684  return err;
685  }
686 
687  err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable);
688  if (err != noErr) {
689  jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
690  return err;
691  }
692 
693  for (int i = 0; i < stream_count; i++) {
694  err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency);
695  if (err != noErr) {
696  jack_error("GetStreamLatencies kAudioStreamPropertyLatency err = %d", err);
697  return err;
698  }
699  err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList);
700  if (err != noErr) {
701  jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
702  return err;
703  }
704  // Push 'channel' time the stream latency
705  for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) {
706  latencies.push_back(streamLatency);
707  }
708  }
709  }
710  return err;
711 }
712 
713 bool JackCoreAudioDriver::IsDigitalDevice(AudioDeviceID device)
714 {
715  OSStatus err = noErr;
716  UInt32 outSize1;
717  bool is_digital = false;
718 
719  /* Get a list of all the streams on this device */
720  AudioObjectPropertyAddress streamsAddress = { kAudioDevicePropertyStreams, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
721  err = AudioObjectGetPropertyDataSize(device, &streamsAddress, 0, NULL, &outSize1);
722  if (err != noErr) {
723  jack_error("IsDigitalDevice kAudioDevicePropertyStreams err = %d", err);
724  return false;
725  }
726 
727  int stream_count = outSize1 / sizeof(AudioStreamID);
728  AudioStreamID streamIDs[stream_count];
729 
730  err = AudioObjectGetPropertyData(device, &streamsAddress, 0, NULL, &outSize1, streamIDs);
731 
732  if (err != noErr) {
733  jack_error("IsDigitalDevice kAudioDevicePropertyStreams list err = %d", err);
734  return false;
735  }
736 
737  AudioObjectPropertyAddress physicalFormatsAddress = { kAudioStreamPropertyAvailablePhysicalFormats, kAudioObjectPropertyScopeGlobal, 0 };
738 
739  for (int i = 0; i < stream_count ; i++) {
740 
741  /* Find a stream with a cac3 stream */
742  int format_num = 0;
743 
744  /* Retrieve all the stream formats supported by each output stream */
745  err = AudioObjectGetPropertyDataSize(streamIDs[i], &physicalFormatsAddress, 0, NULL, &outSize1);
746 
747  if (err != noErr) {
748  jack_error("IsDigitalDevice kAudioStreamPropertyAvailablePhysicalFormats err = %d", err);
749  return false;
750  }
751 
752  format_num = outSize1 / sizeof(AudioStreamRangedDescription);
753  AudioStreamRangedDescription format_list[format_num];
754 
755  err = AudioObjectGetPropertyData(streamIDs[i], &physicalFormatsAddress, 0, NULL, &outSize1, format_list);
756 
757  if (err != noErr) {
758  jack_error("IsDigitalDevice could not get the list of streamformats err = %d", err);
759  return false;
760  }
761 
762  /* Check if one of the supported formats is a digital format */
763  for (int j = 0; j < format_num; j++) {
764 
765  PrintStreamDesc(&format_list[j].mFormat);
766 
767  if (format_list[j].mFormat.mFormatID == 'IAC3' ||
768  format_list[j].mFormat.mFormatID == 'iac3' ||
769  format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 ||
770  format_list[j].mFormat.mFormatID == kAudioFormatAC3)
771  {
772  is_digital = true;
773  break;
774  }
775  }
776  }
777 
778  return is_digital;
779 }
780 
781 JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
782  : JackAudioDriver(name, alias, engine, table),
783  fAC3Encoder(NULL),
784  fJackInputData(NULL),
785  fDriverOutputData(NULL),
786  fPluginID(0),
787  fState(false),
788  fHogged(false),
789  fIOUsage(1.f),
790  fComputationGrain(-1.f),
791  fClockDriftCompensate(false),
792  fDigitalPlayback(false)
793 {}
794 
795 JackCoreAudioDriver::~JackCoreAudioDriver()
796 {
797  delete fAC3Encoder;
798 }
799 
800 OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
801 {
802  OSStatus osErr = noErr;
803  AudioObjectPropertyAddress pluginAOPA;
804  pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
805  pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
806  pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
807  UInt32 outDataSize;
808 
809  if (fPluginID > 0) {
810 
811  osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
812  if (osErr != noErr) {
813  jack_error("DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
814  printError(osErr);
815  return osErr;
816  }
817 
818  osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
819  if (osErr != noErr) {
820  jack_error("DestroyAggregateDevice : AudioObjectGetPropertyData error");
821  printError(osErr);
822  return osErr;
823  }
824 
825  }
826 
827  return noErr;
828 }
829 
830 OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
831 {
832  OSStatus err = noErr;
833  AudioObjectID sub_device[32];
834  UInt32 outSize = sizeof(sub_device);
835 
836  err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
837  vector<AudioDeviceID> captureDeviceIDArray;
838 
839  if (err != noErr) {
840  jack_log("JackCoreAudioDriver::CreateAggregateDevice : input device does not have subdevices");
841  captureDeviceIDArray.push_back(captureDeviceID);
842  } else {
843  int num_devices = outSize / sizeof(AudioObjectID);
844  jack_log("JackCoreAudioDriver::CreateAggregateDevice :Input device has %d subdevices", num_devices);
845  for (int i = 0; i < num_devices; i++) {
846  captureDeviceIDArray.push_back(sub_device[i]);
847  }
848  }
849 
850  err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
851  vector<AudioDeviceID> playbackDeviceIDArray;
852 
853  if (err != noErr) {
854  jack_log("JackCoreAudioDriver::CreateAggregateDevice : output device does not have subdevices");
855  playbackDeviceIDArray.push_back(playbackDeviceID);
856  } else {
857  int num_devices = outSize / sizeof(AudioObjectID);
858  jack_log("JackCoreAudioDriver::CreateAggregateDevice : output device has %d subdevices", num_devices);
859  for (int i = 0; i < num_devices; i++) {
860  playbackDeviceIDArray.push_back(sub_device[i]);
861  }
862  }
863 
864  return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
865 }
866 
867 OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
868 {
869  OSStatus osErr = noErr;
870  UInt32 outSize;
871  Boolean outWritable;
872 
873  // Prepare sub-devices for clock drift compensation
874  // Workaround for bug in the HAL : until 10.6.2
875  AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
876  AudioObjectPropertyAddress theAddressDrift = { kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
877  UInt32 theQualifierDataSize = sizeof(AudioObjectID);
878  AudioClassID inClass = kAudioSubDeviceClassID;
879  void* theQualifierData = &inClass;
880  UInt32 subDevicesNum = 0;
881 
882  //---------------------------------------------------------------------------
883  // Setup SR of both devices otherwise creating AD may fail...
884  //---------------------------------------------------------------------------
885  UInt32 keptclockdomain = 0;
886  UInt32 clockdomain = 0;
887  outSize = sizeof(UInt32);
888  bool need_clock_drift_compensation = false;
889 
890  for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
891  if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
892  jack_error("CreateAggregateDevice : cannot set SR of input device");
893  } else {
894  // Check clock domain
895  osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
896  if (osErr != 0) {
897  jack_error("CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
898  printError(osErr);
899  } else {
900  keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
901  jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain);
902  if (clockdomain != 0 && clockdomain != keptclockdomain) {
903  jack_error("CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
904  need_clock_drift_compensation = true;
905  }
906  }
907  }
908  }
909 
910  for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
911  if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
912  jack_error("CreateAggregateDevice : cannot set SR of output device");
913  } else {
914  // Check clock domain
915  osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
916  if (osErr != 0) {
917  jack_error("CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
918  printError(osErr);
919  } else {
920  keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
921  jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain);
922  if (clockdomain != 0 && clockdomain != keptclockdomain) {
923  jack_error("CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
924  need_clock_drift_compensation = true;
925  }
926  }
927  }
928  }
929 
930  // If no valid clock domain was found, then assume we have to compensate...
931  if (keptclockdomain == 0) {
932  need_clock_drift_compensation = true;
933  }
934 
935  //---------------------------------------------------------------------------
936  // Start to create a new aggregate by getting the base audio hardware plugin
937  //---------------------------------------------------------------------------
938 
939  char device_name[256];
940  for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
941  GetDeviceNameFromID(captureDeviceID[i], device_name);
942  jack_info("Separated input = '%s' ", device_name);
943  }
944 
945  for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
946  GetDeviceNameFromID(playbackDeviceID[i], device_name);
947  jack_info("Separated output = '%s' ", device_name);
948  }
949 
950  osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
951  if (osErr != noErr) {
952  jack_error("CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
953  printError(osErr);
954  return osErr;
955  }
956 
957  AudioValueTranslation pluginAVT;
958 
959  CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
960 
961  pluginAVT.mInputData = &inBundleRef;
962  pluginAVT.mInputDataSize = sizeof(inBundleRef);
963  pluginAVT.mOutputData = &fPluginID;
964  pluginAVT.mOutputDataSize = sizeof(fPluginID);
965 
966  osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
967  if (osErr != noErr) {
968  jack_error("CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
969  printError(osErr);
970  return osErr;
971  }
972 
973  //-------------------------------------------------
974  // Create a CFDictionary for our aggregate device
975  //-------------------------------------------------
976 
977  CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
978 
979  CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
980  CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
981 
982  // add the name of the device to the dictionary
983  CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
984 
985  // add our choice of UID for the aggregate device to the dictionary
986  CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
987 
988  // add a "private aggregate key" to the dictionary
989  int value = 1;
990  CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
991 
992  SInt32 system;
993  Gestalt(gestaltSystemVersion, &system);
994 
995  jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
996 
997  // Starting with 10.5.4 systems, the AD can be internal... (better)
998  if (system < 0x00001054) {
999  jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
1000  } else {
1001  jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
1002  CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
1003  }
1004 
1005  // Prepare sub-devices for clock drift compensation
1006  CFMutableArrayRef subDevicesArrayClock = NULL;
1007 
1008  /*
1009  if (fClockDriftCompensate) {
1010  if (need_clock_drift_compensation) {
1011  jack_info("Clock drift compensation activated...");
1012  subDevicesArrayClock = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1013 
1014  for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
1015  CFStringRef UID = GetDeviceName(captureDeviceID[i]);
1016  if (UID) {
1017  CFMutableDictionaryRef subdeviceAggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1018  CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceUIDKey), UID);
1019  CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceDriftCompensationKey), AggregateDeviceNumberRef);
1020  //CFRelease(UID);
1021  CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict);
1022  }
1023  }
1024 
1025  for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
1026  CFStringRef UID = GetDeviceName(playbackDeviceID[i]);
1027  if (UID) {
1028  CFMutableDictionaryRef subdeviceAggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1029  CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceUIDKey), UID);
1030  CFDictionaryAddValue(subdeviceAggDeviceDict, CFSTR(kAudioSubDeviceDriftCompensationKey), AggregateDeviceNumberRef);
1031  //CFRelease(UID);
1032  CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict);
1033  }
1034  }
1035 
1036  // add sub-device clock array for the aggregate device to the dictionary
1037  CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceSubDeviceListKey), subDevicesArrayClock);
1038  } else {
1039  jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
1040  }
1041  }
1042  */
1043 
1044  //-------------------------------------------------
1045  // Create a CFMutableArray for our sub-device list
1046  //-------------------------------------------------
1047 
1048  // we need to append the UID for each device to a CFMutableArray, so create one here
1049  CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1050 
1051  vector<CFStringRef> captureDeviceUID;
1052  for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
1053  CFStringRef ref = GetDeviceName(captureDeviceID[i]);
1054  if (ref == NULL) {
1055  return -1;
1056  }
1057  captureDeviceUID.push_back(ref);
1058  // input sub-devices in this example, so append the sub-device's UID to the CFArray
1059  CFArrayAppendValue(subDevicesArray, ref);
1060  }
1061 
1062  vector<CFStringRef> playbackDeviceUID;
1063  for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
1064  CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
1065  if (ref == NULL) {
1066  return -1;
1067  }
1068  playbackDeviceUID.push_back(ref);
1069  // output sub-devices in this example, so append the sub-device's UID to the CFArray
1070  CFArrayAppendValue(subDevicesArray, ref);
1071  }
1072 
1073  //-----------------------------------------------------------------------
1074  // Feed the dictionary to the plugin, to create a blank aggregate device
1075  //-----------------------------------------------------------------------
1076 
1077  AudioObjectPropertyAddress pluginAOPA;
1078  pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
1079  pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1080  pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1081  UInt32 outDataSize;
1082 
1083  osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
1084  if (osErr != noErr) {
1085  jack_error("CreateAggregateDevice : AudioObjectGetPropertyDataSize error");
1086  printError(osErr);
1087  goto error;
1088  }
1089 
1090  osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
1091  if (osErr != noErr) {
1092  jack_error("CreateAggregateDevice : AudioObjectGetPropertyData error");
1093  printError(osErr);
1094  goto error;
1095  }
1096 
1097  // pause for a bit to make sure that everything completed correctly
1098  // this is to work around a bug in the HAL where a new aggregate device seems to disappear briefly after it is created
1099  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1100 
1101  //-------------------------
1102  // Set the sub-device list
1103  //-------------------------
1104 
1105  pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList;
1106  pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1107  pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1108  outDataSize = sizeof(CFMutableArrayRef);
1109  osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
1110  if (osErr != noErr) {
1111  jack_error("CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error");
1112  printError(osErr);
1113  goto error;
1114  }
1115 
1116  // pause again to give the changes time to take effect
1117  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1118 
1119  //-----------------------
1120  // Set the master device
1121  //-----------------------
1122 
1123  // set the master device manually (this is the device which will act as the master clock for the aggregate device)
1124  // pass in the UID of the device you want to use
1125  pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
1126  pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
1127  pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
1128  outDataSize = sizeof(CFStringRef);
1129  osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]); // First apture is master...
1130  if (osErr != noErr) {
1131  jack_error("CreateAggregateDevice : AudioObjectSetPropertyData for master device error");
1132  printError(osErr);
1133  goto error;
1134  }
1135 
1136  // pause again to give the changes time to take effect
1137  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1138 
1139  // Prepare sub-devices for clock drift compensation
1140  // Workaround for bug in the HAL : until 10.6.2
1141 
1142  if (fClockDriftCompensate) {
1143  if (need_clock_drift_compensation) {
1144  jack_info("Clock drift compensation activated...");
1145 
1146  // Get the property data size
1147  osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
1148  if (osErr != noErr) {
1149  jack_error("CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
1150  printError(osErr);
1151  }
1152 
1153  // Calculate the number of object IDs
1154  subDevicesNum = outSize / sizeof(AudioObjectID);
1155  jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum);
1156  AudioObjectID subDevices[subDevicesNum];
1157  outSize = sizeof(subDevices);
1158 
1159  osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
1160  if (osErr != noErr) {
1161  jack_error("CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
1162  printError(osErr);
1163  }
1164 
1165  // Set kAudioSubDevicePropertyDriftCompensation property...
1166  for (UInt32 index = 0; index < subDevicesNum; ++index) {
1167  UInt32 theDriftCompensationValue = 1;
1168  osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL, sizeof(UInt32), &theDriftCompensationValue);
1169  if (osErr != noErr) {
1170  jack_error("CreateAggregateDevice kAudioSubDevicePropertyDriftCompensation error");
1171  printError(osErr);
1172  }
1173  }
1174  } else {
1175  jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
1176  }
1177  }
1178 
1179  // pause again to give the changes time to take effect
1180  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
1181 
1182  //----------
1183  // Clean up
1184  //----------
1185 
1186  // release the private AD key
1187  CFRelease(AggregateDeviceNumberRef);
1188 
1189  // release the CF objects we have created - we don't need them any more
1190  CFRelease(aggDeviceDict);
1191  CFRelease(subDevicesArray);
1192 
1193  if (subDevicesArrayClock) {
1194  CFRelease(subDevicesArrayClock);
1195  }
1196 
1197  // release the device UID
1198  for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
1199  CFRelease(captureDeviceUID[i]);
1200  }
1201 
1202  for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
1203  CFRelease(playbackDeviceUID[i]);
1204  }
1205 
1206  jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : new aggregate device %ld", *outAggregateDevice);
1207  return noErr;
1208 
1209 error:
1210  DestroyAggregateDevice();
1211  return -1;
1212 }
1213 
1214 int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
1215  const char* playback_driver_uid,
1216  char* capture_driver_name,
1217  char* playback_driver_name,
1218  jack_nframes_t samplerate,
1219  bool ac3_encoding)
1220 {
1221  capture_driver_name[0] = 0;
1222  playback_driver_name[0] = 0;
1223 
1224  // Duplex
1225  if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
1226  jack_log("JackCoreAudioDriver::SetupDevices : duplex");
1227 
1228  // Same device for capture and playback...
1229  if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
1230 
1231  if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
1232  jack_log("JackCoreAudioDriver::SetupDevices : will take default in/out");
1233  if (GetDefaultDevice(&fDeviceID) != noErr) {
1234  jack_error("Cannot open default device");
1235  return -1;
1236  }
1237  }
1238  if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
1239  jack_error("Cannot get device name from device ID");
1240  return -1;
1241  }
1242 
1243  if (fHogged) {
1244  if (!TakeHogAux(fDeviceID, false)) {
1245  jack_error("Cannot take hog mode");
1246  }
1247  if (ac3_encoding) {
1248  fDigitalPlayback = IsDigitalDevice(fDeviceID);
1249  }
1250  }
1251 
1252  } else {
1253 
1254  // Creates aggregate device
1255  AudioDeviceID captureID = -1;
1256  AudioDeviceID playbackID = -1;
1257 
1258  if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
1259  jack_log("JackCoreAudioDriver::SetupDevices : will take default input");
1260  if (GetDefaultInputDevice(&captureID) != noErr) {
1261  jack_error("Cannot open default input device");
1262  return -1;
1263  }
1264  }
1265 
1266  if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
1267  jack_log("JackCoreAudioDriver::SetupDevices : will take default output");
1268  if (GetDefaultOutputDevice(&playbackID) != noErr) {
1269  jack_error("Cannot open default output device");
1270  return -1;
1271  }
1272  }
1273 
1274  if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1275  return -1;
1276  }
1277 
1278  GetDeviceNameFromID(captureID, fCaptureUID);
1279  GetDeviceNameFromID(playbackID, fPlaybackUID);
1280 
1281  if (fHogged) {
1282  if (!TakeHogAux(captureID, true)) {
1283  jack_error("Cannot take hog mode for capture device");
1284  }
1285  if (!TakeHogAux(playbackID, false)) {
1286  jack_error("Cannot take hog mode for playback device");
1287  }
1288  if (ac3_encoding) {
1289  fDigitalPlayback = IsDigitalDevice(playbackID);
1290  }
1291  }
1292 
1293  }
1294 
1295  // Capture only
1296  } else if (strcmp(capture_driver_uid, "") != 0) {
1297  jack_log("JackCoreAudioDriver::SetupDevices : capture only");
1298  if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
1299  jack_log("JackCoreAudioDriver::SetupDevices : will take default input");
1300  if (GetDefaultInputDevice(&fDeviceID) != noErr) {
1301  jack_error("Cannot open default input device");
1302  return -1;
1303  }
1304  }
1305  if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
1306  jack_error("Cannot get device name from device ID");
1307  return -1;
1308  }
1309 
1310  if (fHogged) {
1311  if (!TakeHogAux(fDeviceID, true)) {
1312  jack_error("Cannot take hog mode for capture device");
1313  }
1314  }
1315 
1316  // Playback only
1317  } else if (strcmp(playback_driver_uid, "") != 0) {
1318  jack_log("JackCoreAudioDriver::SetupDevices : playback only");
1319  if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
1320  jack_log("JackCoreAudioDriver::SetupDevices : will take default output");
1321  if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
1322  jack_error("Cannot open default output device");
1323  return -1;
1324  }
1325  }
1326  if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
1327  jack_error("Cannot get device name from device ID");
1328  return -1;
1329  }
1330 
1331  if (fHogged) {
1332  if (!TakeHogAux(fDeviceID, false)) {
1333  jack_error("Cannot take hog mode for playback device");
1334  }
1335  if (ac3_encoding) {
1336  fDigitalPlayback = IsDigitalDevice(fDeviceID);
1337  }
1338  }
1339 
1340  // Use default driver in duplex mode
1341  } else {
1342  jack_log("JackCoreAudioDriver::SetupDevices : default driver");
1343  if (GetDefaultDevice(&fDeviceID) != noErr) {
1344  jack_error("Cannot open default device in duplex mode, so aggregate default input and default output");
1345 
1346  // Creates aggregate device
1347  AudioDeviceID captureID = -1;
1348  AudioDeviceID playbackID = -1;
1349 
1350  if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
1351  jack_log("JackCoreAudioDriver::SetupDevices : will take default input");
1352  if (GetDefaultInputDevice(&captureID) != noErr) {
1353  jack_error("Cannot open default input device");
1354  return -1;
1355  }
1356  }
1357 
1358  if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
1359  jack_log("JackCoreAudioDriver::SetupDevices : will take default output");
1360  if (GetDefaultOutputDevice(&playbackID) != noErr) {
1361  jack_error("Cannot open default output device");
1362  return -1;
1363  }
1364  }
1365 
1366  if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
1367  return -1;
1368  }
1369 
1370  GetDeviceNameFromID(captureID, fCaptureUID);
1371  GetDeviceNameFromID(playbackID, fPlaybackUID);
1372 
1373  if (fHogged) {
1374  if (!TakeHogAux(captureID, true)) {
1375  jack_error("Cannot take hog mode for capture device");
1376  }
1377  if (!TakeHogAux(playbackID, false)) {
1378  jack_error("Cannot take hog mode for playback device");
1379  }
1380  if (ac3_encoding) {
1381  fDigitalPlayback = IsDigitalDevice(playbackID);
1382  }
1383  }
1384  }
1385  }
1386 
1387  return 0;
1388 }
1389 
1390 /*
1391 Return the max possible input channels in in_maxChannels and output channels in out_maxChannels.
1392 */
1393 int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchannels, int& outchannels, int& in_maxChannels, int& out_maxChannels, bool strict)
1394 {
1395  OSStatus err = noErr;
1396 
1397  if (capturing) {
1398  err = GetTotalChannels(fDeviceID, in_maxChannels, true);
1399  if (err != noErr) {
1400  jack_error("SetupChannels : cannot get input channel number");
1401  printError(err);
1402  return -1;
1403  } else {
1404  jack_log("JackCoreAudioDriver::SetupChannels : max input channels : %d", in_maxChannels);
1405  }
1406  }
1407 
1408  if (playing) {
1409  err = GetTotalChannels(fDeviceID, out_maxChannels, false);
1410  if (err != noErr) {
1411  jack_error("Cannot get output channel number");
1412  printError(err);
1413  return -1;
1414  } else {
1415  jack_log("JackCoreAudioDriver::SetupChannels : max output channels : %d", out_maxChannels);
1416  }
1417  }
1418 
1419  if (inchannels > in_maxChannels) {
1420  jack_error("This device hasn't required input channels inchannels = %d in_maxChannels = %d", inchannels, in_maxChannels);
1421  if (strict) {
1422  return -1;
1423  }
1424  }
1425 
1426  if (outchannels > out_maxChannels) {
1427  jack_error("This device hasn't required output channels outchannels = %d out_maxChannels = %d", outchannels, out_maxChannels);
1428  if (strict) {
1429  return -1;
1430  }
1431  }
1432 
1433  if (inchannels == -1) {
1434  jack_log("JackCoreAudioDriver::SetupChannels : setup max in channels = %d", in_maxChannels);
1435  inchannels = in_maxChannels;
1436  }
1437 
1438  if (outchannels == -1) {
1439  jack_log("JackCoreAudioDriver::SetupChannels : setup max out channels = %d", out_maxChannels);
1440  outchannels = out_maxChannels;
1441  }
1442 
1443  return 0;
1444 }
1445 
1446 int JackCoreAudioDriver::SetupBufferSize(jack_nframes_t buffer_size)
1447 {
1448  // Setting buffer size
1449  OSStatus err = noErr;
1450  UInt32 tmp_buffer_size = buffer_size;
1451  UInt32 outSize = sizeof(UInt32);
1452 
1453  err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
1454  if (err != noErr) {
1455  jack_error("Cannot get buffer size %ld", buffer_size);
1456  printError(err);
1457  return -1;
1458  } else {
1459  jack_log("JackCoreAudioDriver::SetupBufferSize : current buffer size = %ld", tmp_buffer_size);
1460  }
1461 
1462  // If needed, set new buffer size
1463  if (buffer_size != tmp_buffer_size) {
1464  tmp_buffer_size = buffer_size;
1465 
1466  // To get BS change notification
1467  err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback, this);
1468  if (err != noErr) {
1469  jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyBufferFrameSize");
1470  printError(err);
1471  return -1;
1472  }
1473 
1474  // Waiting for BS change notification
1475  int count = 0;
1476  fState = false;
1477 
1478  err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, outSize, &tmp_buffer_size);
1479  if (err != noErr) {
1480  jack_error("SetupBufferSize : cannot set buffer size = %ld", tmp_buffer_size);
1481  printError(err);
1482  goto error;
1483  }
1484 
1485  while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1486  usleep(100000);
1487  jack_log("JackCoreAudioDriver::SetupBufferSize : wait count = %d", count);
1488  }
1489 
1490  if (count >= WAIT_NOTIFICATION_COUNTER) {
1491  jack_error("Did not get buffer size notification...");
1492  goto error;
1493  }
1494 
1495  // Check new buffer size
1496  outSize = sizeof(UInt32);
1497  err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
1498  if (err != noErr) {
1499  jack_error("Cannot get current buffer size");
1500  printError(err);
1501  } else {
1502  jack_log("JackCoreAudioDriver::SetupBufferSize : checked buffer size = %ld", tmp_buffer_size);
1503  }
1504 
1505  // Remove BS change notification
1506  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1507  }
1508 
1509  return 0;
1510 
1511 error:
1512 
1513  // Remove BS change notification
1514  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
1515  return -1;
1516 }
1517 
1518 int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t sample_rate)
1519 {
1520  return SetupSampleRateAux(fDeviceID, sample_rate);
1521 }
1522 
1523 int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t sample_rate)
1524 {
1525  OSStatus err = noErr;
1526  UInt32 outSize;
1527  Float64 tmp_sample_rate;
1528 
1529  // Get sample rate
1530  outSize = sizeof(Float64);
1531  err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
1532  if (err != noErr) {
1533  jack_error("Cannot get current sample rate");
1534  printError(err);
1535  return -1;
1536  } else {
1537  jack_log("JackCoreAudioDriver::SetupSampleRateAux : current sample rate = %f", tmp_sample_rate);
1538  }
1539 
1540  // If needed, set new sample rate
1541  if (sample_rate != (jack_nframes_t)tmp_sample_rate) {
1542  tmp_sample_rate = (Float64)sample_rate;
1543 
1544  // To get SR change notification
1545  err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
1546  if (err != noErr) {
1547  jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
1548  printError(err);
1549  return -1;
1550  }
1551 
1552  // Waiting for SR change notification
1553  int count = 0;
1554  fState = false;
1555 
1556  err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &tmp_sample_rate);
1557  if (err != noErr) {
1558  jack_error("Cannot set sample rate = %ld", sample_rate);
1559  printError(err);
1560  goto error;
1561  }
1562 
1563  while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
1564  usleep(100000);
1565  jack_log("JackCoreAudioDriver::SetupSampleRateAux : wait count = %d", count);
1566  }
1567 
1568  if (count >= WAIT_NOTIFICATION_COUNTER) {
1569  jack_error("Did not get sample rate notification...");
1570  goto error;
1571  }
1572 
1573  // Check new sample rate
1574  outSize = sizeof(Float64);
1575  err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
1576  if (err != noErr) {
1577  jack_error("Cannot get current sample rate");
1578  printError(err);
1579  } else {
1580  jack_log("JackCoreAudioDriver::SetupSampleRateAux : checked sample rate = %f", tmp_sample_rate);
1581  }
1582 
1583  // Remove SR change notification
1584  AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1585  }
1586 
1587  return 0;
1588 
1589 error:
1590 
1591  // Remove SR change notification
1592  AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
1593  return -1;
1594 }
1595 
1596 int JackCoreAudioDriver::OpenAUHAL(bool capturing,
1597  bool playing,
1598  int inchannels,
1599  int outchannels,
1600  int in_maxChannels,
1601  int out_maxChannels,
1602  const vector<int>& chan_in_list,
1603  const vector<int>& chan_out_list,
1604  jack_nframes_t buffer_size,
1605  jack_nframes_t sample_rate)
1606 {
1607  ComponentResult err1;
1608  UInt32 enableIO;
1609  AudioStreamBasicDescription srcFormat, dstFormat;
1610  AudioDeviceID currAudioDeviceID;
1611  UInt32 size;
1612 
1613  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",
1614  capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, chan_in_list.size(), chan_out_list.size());
1615 
1616  if (inchannels == 0 && outchannels == 0) {
1617  jack_error("No input and output channels...");
1618  return -1;
1619  }
1620 
1621  // AUHAL
1622 #ifdef MAC_OS_X_VERSION_10_5
1623  ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
1624  Component HALOutput = FindNextComponent(NULL, &cd);
1625  err1 = OpenAComponent(HALOutput, &fAUHAL);
1626  if (err1 != noErr) {
1627  jack_error("Error calling OpenAComponent");
1628  printError(err1);
1629  goto error;
1630  }
1631 #else
1632  AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
1633  AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd);
1634  err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL);
1635  if (err1 != noErr) {
1636  jack_error("Error calling AudioComponentInstanceNew");
1637  printError(err1);
1638  goto error;
1639  }
1640 #endif
1641 
1642  err1 = AudioUnitInitialize(fAUHAL);
1643  if (err1 != noErr) {
1644  jack_error("Cannot initialize AUHAL unit");
1645  printError(err1);
1646  goto error;
1647  }
1648 
1649  // Start I/O
1650  if (capturing && inchannels > 0) {
1651  enableIO = 1;
1652  jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL input on");
1653  } else {
1654  enableIO = 0;
1655  jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL input off");
1656  }
1657 
1658  err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
1659  if (err1 != noErr) {
1660  jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
1661  printError(err1);
1662  goto error;
1663  }
1664 
1665  if (playing && outchannels > 0) {
1666  enableIO = 1;
1667  jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL output on");
1668  } else {
1669  enableIO = 0;
1670  jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL output off");
1671  }
1672 
1673  err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
1674  if (err1 != noErr) {
1675  jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
1676  printError(err1);
1677  goto error;
1678  }
1679 
1680  size = sizeof(AudioDeviceID);
1681  err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
1682  if (err1 != noErr) {
1683  jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
1684  printError(err1);
1685  goto error;
1686  } else {
1687  jack_log("JackCoreAudioDriver::OpenAUHAL : AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
1688  }
1689 
1690  // Setup up choosen device, in both input and output cases
1691  err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
1692  if (err1 != noErr) {
1693  jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
1694  printError(err1);
1695  goto error;
1696  }
1697 
1698  // Set buffer size
1699  if (capturing && inchannels > 0) {
1700  err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
1701  if (err1 != noErr) {
1702  jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
1703  printError(err1);
1704  goto error;
1705  }
1706  }
1707 
1708  if (playing && outchannels > 0) {
1709  err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size, sizeof(UInt32));
1710  if (err1 != noErr) {
1711  jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
1712  printError(err1);
1713  goto error;
1714  }
1715  }
1716 
1717  // Setup input channel map
1718  if (capturing && inchannels > 0 && inchannels <= in_maxChannels) {
1719  SInt32 chanArr[in_maxChannels];
1720  for (int i = 0; i < in_maxChannels; i++) {
1721  chanArr[i] = -1;
1722  }
1723  // Explicit mapping
1724  if (chan_in_list.size() > 0) {
1725  for (uint i = 0; i < chan_in_list.size(); i++) {
1726  int chan = chan_in_list[i];
1727  if (chan < out_maxChannels) {
1728  // The wanted JACK input index for the 'chan' channel value
1729  chanArr[chan] = i;
1730  jack_info("Input channel = %d ==> JACK input port = %d", chan, i);
1731  } else {
1732  jack_info("Error input channel number is incorrect : %d", chan);
1733  goto error;
1734  }
1735  }
1736  } else {
1737  for (int i = 0; i < inchannels; i++) {
1738  chanArr[i] = i;
1739  jack_info("Input channel = %d ==> JACK input port = %d", chanArr[i], i);
1740  }
1741  }
1742 
1743  AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_maxChannels);
1744  if (err1 != noErr) {
1745  jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for input");
1746  printError(err1);
1747  goto error;
1748  }
1749  }
1750 
1751  // Setup output channel map
1752  if (playing && outchannels > 0 && outchannels <= out_maxChannels) {
1753  SInt32 chanArr[out_maxChannels];
1754  for (int i = 0; i < out_maxChannels; i++) {
1755  chanArr[i] = -1;
1756  }
1757  // Explicit mapping
1758  if (chan_out_list.size() > 0) {
1759  for (uint i = 0; i < chan_out_list.size(); i++) {
1760  int chan = chan_out_list[i];
1761  if (chan < out_maxChannels) {
1762  // The wanted JACK output index for the 'chan' channel value
1763  chanArr[chan] = i;
1764  jack_info("JACK output port = %d ==> output channel = %d", i, chan);
1765  } else {
1766  jack_info("Error output channel number is incorrect : %d", chan);
1767  goto error;
1768  }
1769  }
1770  } else {
1771  for (int i = 0; i < outchannels; i++) {
1772  chanArr[i] = i;
1773  jack_info("JACK output port = %d ==> output channel = %d", i, chanArr[i]);
1774  }
1775  }
1776 
1777  err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_maxChannels);
1778  if (err1 != noErr) {
1779  jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for output");
1780  printError(err1);
1781  goto error;
1782  }
1783  }
1784 
1785  // Setup stream converters
1786  if (capturing && inchannels > 0) {
1787 
1788  size = sizeof(AudioStreamBasicDescription);
1789  err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &size);
1790  if (err1 != noErr) {
1791  jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
1792  printError(err1);
1793  goto error;
1794  }
1795  PrintStreamDesc(&srcFormat);
1796 
1797  jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL input stream converter SR = %ld", sample_rate);
1798  srcFormat.mSampleRate = sample_rate;
1799  srcFormat.mFormatID = kAudioFormatLinearPCM;
1800  srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1801  srcFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
1802  srcFormat.mFramesPerPacket = 1;
1803  srcFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
1804  srcFormat.mChannelsPerFrame = inchannels;
1805  srcFormat.mBitsPerChannel = 32;
1806  PrintStreamDesc(&srcFormat);
1807 
1808  err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
1809  if (err1 != noErr) {
1810  jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
1811  printError(err1);
1812  goto error;
1813  }
1814  }
1815 
1816  if (playing && outchannels > 0) {
1817 
1818  size = sizeof(AudioStreamBasicDescription);
1819  err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &size);
1820  if (err1 != noErr) {
1821  jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
1822  printError(err1);
1823  goto error;
1824  }
1825  PrintStreamDesc(&dstFormat);
1826 
1827  jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL output stream converter SR = %ld", sample_rate);
1828  dstFormat.mSampleRate = sample_rate;
1829  dstFormat.mFormatID = kAudioFormatLinearPCM;
1830  dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1831  dstFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
1832  dstFormat.mFramesPerPacket = 1;
1833  dstFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
1834  dstFormat.mChannelsPerFrame = outchannels;
1835  dstFormat.mBitsPerChannel = 32;
1836  PrintStreamDesc(&dstFormat);
1837 
1838  err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
1839  if (err1 != noErr) {
1840  jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
1841  printError(err1);
1842  goto error;
1843  }
1844  }
1845 
1846  // Setup callbacks
1847  if (inchannels > 0 && outchannels == 0) {
1848  AURenderCallbackStruct output;
1849  output.inputProc = Render;
1850  output.inputProcRefCon = this;
1851  err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
1852  if (err1 != noErr) {
1853  jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
1854  printError(err1);
1855  goto error;
1856  }
1857  } else {
1858  AURenderCallbackStruct output;
1859  output.inputProc = Render;
1860  output.inputProcRefCon = this;
1861  err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
1862  if (err1 != noErr) {
1863  jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
1864  printError(err1);
1865  goto error;
1866  }
1867  }
1868 
1869  return 0;
1870 
1871 error:
1872  CloseAUHAL();
1873  return -1;
1874 }
1875 
1876 int JackCoreAudioDriver::SetupBuffers(int inchannels)
1877 {
1878  // Prepare buffers
1879  fJackInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
1880  fJackInputData->mNumberBuffers = inchannels;
1881  for (int i = 0; i < inchannels; i++) {
1882  fJackInputData->mBuffers[i].mNumberChannels = 1;
1883  fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t);
1884  }
1885  return 0;
1886 }
1887 
1888 void JackCoreAudioDriver::DisposeBuffers()
1889 {
1890  if (fJackInputData) {
1891  free(fJackInputData);
1892  fJackInputData = 0;
1893  }
1894 }
1895 
1896 void JackCoreAudioDriver::CloseAUHAL()
1897 {
1898  AudioOutputUnitStop(fAUHAL);
1899  AudioUnitUninitialize(fAUHAL);
1900  CloseComponent(fAUHAL);
1901 }
1902 
1903 int JackCoreAudioDriver::AddListeners()
1904 {
1905  OSStatus err = noErr;
1906 
1907  // Add listeners
1908  err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this);
1909  if (err != noErr) {
1910  jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
1911  printError(err);
1912  return -1;
1913  }
1914 
1915  err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback, this);
1916  if (err != noErr) {
1917  jack_error("Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
1918  printError(err);
1919  return -1;
1920  }
1921 
1922  err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this);
1923  if (err != noErr) {
1924  jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
1925  printError(err);
1926  return -1;
1927  }
1928 
1929  err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this);
1930  if (err != noErr) {
1931  jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
1932  printError(err);
1933  return -1;
1934  }
1935 
1936  err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback, this);
1937  if (err != noErr) {
1938  jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsAlive");
1939  printError(err);
1940  return -1;
1941  }
1942 
1943  err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback, this);
1944  if (err != noErr) {
1945  jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceHasChanged");
1946  printError(err);
1947  return -1;
1948  }
1949 
1950  err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
1951  if (err != noErr) {
1952  jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
1953  printError(err);
1954  return -1;
1955  }
1956 
1957  err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
1958  if (err != noErr) {
1959  jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
1960  printError(err);
1961  return -1;
1962  }
1963 
1964  if (!fEngineControl->fSyncMode && fIOUsage != 1.f) {
1965  UInt32 outSize = sizeof(float);
1966  err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyIOCycleUsage, outSize, &fIOUsage);
1967  if (err != noErr) {
1968  jack_error("Error calling AudioDeviceSetProperty kAudioDevicePropertyIOCycleUsage");
1969  printError(err);
1970  }
1971  }
1972 
1973  return 0;
1974 }
1975 
1976 void JackCoreAudioDriver::RemoveListeners()
1977 {
1978  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
1979  AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback);
1980  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
1981  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
1982  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback);
1983  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback);
1984  AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
1985  AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
1986 }
1987 
1988 int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
1989  jack_nframes_t sample_rate,
1990  bool capturing,
1991  bool playing,
1992  int inchannels,
1993  int outchannels,
1994  const char* chan_in_list,
1995  const char* chan_out_list,
1996  bool monitor,
1997  const char* capture_driver_uid,
1998  const char* playback_driver_uid,
1999  jack_nframes_t capture_latency,
2000  jack_nframes_t playback_latency,
2001  int async_output_latency,
2002  int computation_grain,
2003  bool hogged,
2004  bool clock_drift,
2005  bool ac3_encoding,
2006  int ac3_bitrate,
2007  bool ac3_lfe)
2008 {
2009  int in_maxChannels = 0;
2010  int out_maxChannels = 0;
2011  char capture_driver_name[256];
2012  char playback_driver_name[256];
2013 
2014  fCaptureLatency = capture_latency;
2015  fPlaybackLatency = playback_latency;
2016  fIOUsage = float(async_output_latency) / 100.f;
2017  fComputationGrain = float(computation_grain) / 100.f;
2018  fHogged = hogged;
2019  fClockDriftCompensate = clock_drift;
2020 
2021  SInt32 major;
2022  SInt32 minor;
2023  Gestalt(gestaltSystemVersionMajor, &major);
2024  Gestalt(gestaltSystemVersionMinor, &minor);
2025 
2026  vector<int> parsed_chan_in_list;
2027  vector<int> parsed_chan_out_list;
2028 
2029  // Starting with 10.6 systems, the HAL notification thread is created internally
2030  if (major == 10 && minor >= 6) {
2031  CFRunLoopRef theRunLoop = NULL;
2032  AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
2033  OSStatus osErr = AudioObjectSetPropertyData (kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
2034  if (osErr != noErr) {
2035  jack_error("Open kAudioHardwarePropertyRunLoop error");
2036  printError(osErr);
2037  }
2038  }
2039 
2040  if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate, ac3_encoding) < 0) {
2041  goto error;
2042  }
2043 
2044  // Generic JackAudioDriver Open
2045  if (JackAudioDriver::Open(buffer_size, sample_rate,
2046  capturing, playing,
2047  inchannels, outchannels,
2048  monitor,
2049  capture_driver_name,
2050  playback_driver_name,
2051  capture_latency,
2052  playback_latency) != 0) {
2053  goto error;
2054  }
2055 
2056  if (SetupChannels(capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, !ac3_encoding) < 0) {
2057  goto error;
2058  }
2059 
2060  ParseChannelList(chan_in_list, parsed_chan_in_list, in_maxChannels);
2061  if (parsed_chan_in_list.size() > 0) {
2062  jack_info("Explicit input channel list size = %d", parsed_chan_in_list.size());
2063  inchannels = parsed_chan_in_list.size();
2064  }
2065 
2066  ParseChannelList(chan_out_list, parsed_chan_out_list, out_maxChannels);
2067  if (parsed_chan_out_list.size() > 0) {
2068  jack_info("Explicit output channel list size = %d", parsed_chan_out_list.size());
2069  outchannels = parsed_chan_out_list.size();
2070  }
2071 
2072  if (SetupBufferSize(buffer_size) < 0) {
2073  goto error;
2074  }
2075 
2076  if (SetupSampleRate(sample_rate) < 0) {
2077  goto error;
2078  }
2079 
2080  if (ac3_encoding) {
2081 
2082  if (!fDigitalPlayback) {
2083  jack_error("AC3 encoding can only be used with a digital device");
2084  goto error;
2085  }
2086 
2087  JackAC3EncoderParams params;
2088  memset(&params, 0, sizeof(JackAC3EncoderParams));
2089  params.bitrate = ac3_bitrate;
2090  params.channels = outchannels;
2091  params.sample_rate = sample_rate;
2092  params.lfe = ac3_lfe;
2093  fAC3Encoder = new JackAC3Encoder(params);
2094 
2095  if (!fAC3Encoder || !fAC3Encoder->Init(sample_rate)) {
2096  jack_error("Cannot allocate or init AC3 encoder");
2097  goto error;
2098  }
2099 
2100  // Setup AC3 channel number
2101  fPlaybackChannels = outchannels;
2102  if (ac3_lfe) {
2103  fPlaybackChannels++;
2104  }
2105 
2106  if (fPlaybackChannels < 2 || fPlaybackChannels > 6) {
2107  jack_error("AC3 encoder channels must be between 2 and 6");
2108  goto error;
2109  }
2110 
2111  // Force real output channel number to 2
2112  outchannels = out_maxChannels = 2;
2113 
2114  } else {
2115  fPlaybackChannels = outchannels;
2116  }
2117 
2118  // Core driver may have changed the in/out values
2119  fCaptureChannels = inchannels;
2120 
2121  if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) {
2122  goto error;
2123  }
2124 
2125  if (capturing && inchannels > 0) {
2126  if (SetupBuffers(inchannels) < 0) {
2127  goto error;
2128  }
2129  }
2130 
2131  if (AddListeners() < 0) {
2132  goto error;
2133  }
2134 
2135  return noErr;
2136 
2137 error:
2138  Close();
2139  return -1;
2140 }
2141 
2142 int JackCoreAudioDriver::Close()
2143 {
2144  jack_log("JackCoreAudioDriver::Close");
2145 
2146  // Generic audio driver close
2147  int res = JackAudioDriver::Close();
2148 
2149  RemoveListeners();
2150  DisposeBuffers();
2151  CloseAUHAL();
2152  DestroyAggregateDevice();
2153  return res;
2154 }
2155 
2156 void JackCoreAudioDriver::UpdateLatencies()
2157 {
2158  UInt32 size;
2159  OSStatus err;
2160  jack_latency_range_t input_range;
2161  jack_latency_range_t output_range;
2162  jack_latency_range_t monitor_range;
2163 
2164  // Get Input latency
2165  size = sizeof(UInt32);
2166  UInt32 value1 = 0;
2167  UInt32 value2 = 0;
2168  err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);
2169  if (err != noErr) {
2170  jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
2171  }
2172  err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
2173  if (err != noErr) {
2174  jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
2175  }
2176 
2177  input_range.min = input_range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
2178 
2179  // Get input stream latencies
2180  vector<int> input_latencies;
2181  err = GetStreamLatencies(fDeviceID, true, input_latencies);
2182 
2183  for (int i = 0; i < fCaptureChannels; i++) {
2184  if (err != noErr) {
2185  input_range.min += input_latencies[i];
2186  input_range.max += input_latencies[i];
2187  }
2188  fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
2189  }
2190 
2191  // Get Output latency
2192  size = sizeof(UInt32);
2193  value1 = 0;
2194  value2 = 0;
2195  err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1);
2196  if (err != noErr) {
2197  jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
2198  }
2199  err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
2200  if (err != noErr) {
2201  jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
2202  }
2203 
2204  // Get output stream latencies
2205  vector<int> output_latencies;
2206  err = GetStreamLatencies(fDeviceID, false, output_latencies);
2207 
2208  // Add more latency if "async" mode is used...
2209  output_range.min = output_range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode)
2210  ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency;
2211 
2212  for (int i = 0; i < fPlaybackChannels; i++) {
2213  if (err != noErr) {
2214  output_range.min += output_latencies[i];
2215  output_range.max += output_latencies[i];
2216  }
2217  fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
2218 
2219  // Monitor port
2220  if (fWithMonitorPorts) {
2221  monitor_range.min = monitor_range.max = fEngineControl->fBufferSize;
2222  fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
2223  }
2224  }
2225 }
2226 
2227 int JackCoreAudioDriver::Attach()
2228 {
2229  OSStatus err;
2230  JackPort* port;
2231  jack_port_id_t port_index;
2232  UInt32 size;
2233  Boolean isWritable;
2234  char channel_name[64];
2235  char name[REAL_JACK_PORT_NAME_SIZE];
2236  char alias[REAL_JACK_PORT_NAME_SIZE];
2237 
2238  jack_log("JackCoreAudioDriver::Attach : fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
2239 
2240  for (int i = 0; i < fCaptureChannels; i++) {
2241 
2242  err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
2243  if (err != noErr) {
2244  jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
2245  }
2246  if (err == noErr && size > 0) {
2247  err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
2248  if (err != noErr) {
2249  jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
2250  }
2251  snprintf(alias, sizeof(alias), "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
2252  } else {
2253  snprintf(alias, sizeof(alias), "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
2254  }
2255 
2256  snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, i + 1);
2257 
2258  if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
2259  jack_error("Cannot register port for %s", name);
2260  return -1;
2261  }
2262 
2263  port = fGraphManager->GetPort(port_index);
2264  port->SetAlias(alias);
2265  fCapturePortList[i] = port_index;
2266  }
2267 
2268  for (int i = 0; i < fPlaybackChannels; i++) {
2269 
2270  err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
2271  if (err != noErr) {
2272  jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
2273  }
2274  if (err == noErr && size > 0) {
2275  err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
2276  if (err != noErr) {
2277  jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
2278  }
2279  snprintf(alias, sizeof(alias), "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
2280  } else {
2281  snprintf(alias, sizeof(alias), "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
2282  }
2283 
2284  snprintf(name, sizeof(name), "%s:playback_%d", fClientControl.fName, i + 1);
2285 
2286  if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
2287  jack_error("Cannot register port for %s", name);
2288  return -1;
2289  }
2290 
2291  port = fGraphManager->GetPort(port_index);
2292  port->SetAlias(alias);
2293  fPlaybackPortList[i] = port_index;
2294 
2295  // Monitor ports
2296  if (fWithMonitorPorts) {
2297  jack_log("JackCoreAudioDriver::Attach : create monitor port");
2298  snprintf(name, sizeof(name), "%s:monitor_%u", fClientControl.fName, i + 1);
2299  if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
2300  jack_error("Cannot register monitor port for %s", name);
2301  return -1;
2302  } else {
2303  fMonitorPortList[i] = port_index;
2304  }
2305  }
2306  }
2307 
2308  if (fAC3Encoder) {
2309  // Setup specific AC3 channels names
2310  for (int i = 0; i < fPlaybackChannels; i++) {
2311  fAC3Encoder->GetChannelName("coreaudio", "", alias, i);
2312  port = fGraphManager->GetPort(fPlaybackPortList[i]);
2313  port->SetAlias(alias);
2314  }
2315  }
2316 
2317  UpdateLatencies();
2318 
2319  // Input buffers do no change : prepare them only once
2320  for (int i = 0; i < fCaptureChannels; i++) {
2321  fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
2322  }
2323 
2324  return 0;
2325 }
2326 
2327 int JackCoreAudioDriver::Start()
2328 {
2329  jack_log("JackCoreAudioDriver::Start");
2330  if (JackAudioDriver::Start() == 0) {
2331 
2332  // Waiting for Render callback to be called (= driver has started)
2333  fState = false;
2334  int count = 0;
2335 
2336  OSStatus err = AudioOutputUnitStart(fAUHAL);
2337  if (err == noErr) {
2338 
2339  while (!fState && count++ < WAIT_COUNTER) {
2340  usleep(100000);
2341  jack_log("JackCoreAudioDriver::Start : wait count = %d", count);
2342  }
2343 
2344  if (count < WAIT_COUNTER) {
2345  jack_info("CoreAudio driver is running...");
2346  return 0;
2347  }
2348 
2349  jack_error("CoreAudio driver cannot start...");
2350  }
2351  JackAudioDriver::Stop();
2352  }
2353  return -1;
2354 }
2355 
2356 int JackCoreAudioDriver::Stop()
2357 {
2358  jack_log("JackCoreAudioDriver::Stop");
2359  int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
2360  if (JackAudioDriver::Stop() < 0) {
2361  res = -1;
2362  }
2363  return res;
2364 }
2365 
2366 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
2367 {
2368  if (SetupBufferSize(buffer_size) < 0) {
2369  return -1;
2370  }
2371 
2372  JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
2373 
2374  // CoreAudio specific
2375  UpdateLatencies();
2376 
2377  // Input buffers do no change : prepare them only once
2378  for (int i = 0; i < fCaptureChannels; i++) {
2379  fJackInputData->mBuffers[i].mNumberChannels = 1;
2380  fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t);
2381  fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
2382  }
2383 
2384  return 0;
2385 }
2386 
2387 bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID, bool isInput)
2388 {
2389  pid_t hog_pid;
2390  OSStatus err;
2391 
2392  UInt32 propSize = sizeof(hog_pid);
2393  err = AudioDeviceGetProperty(deviceID, 0, isInput, kAudioDevicePropertyHogMode, &propSize, &hog_pid);
2394  if (err) {
2395  jack_error("Cannot read hog state...");
2396  printError(err);
2397  }
2398 
2399  jack_log("JackCoreAudioDriver::TakeHogAux : deviceID = %d", deviceID);
2400 
2401  if (hog_pid != getpid()) {
2402  hog_pid = getpid();
2403  err = AudioDeviceSetProperty(deviceID, 0, 0, isInput, kAudioDevicePropertyHogMode, propSize, &hog_pid);
2404  if (err != noErr) {
2405  jack_error("Can't hog device = %d because it's being hogged by another program or cannot be hogged", deviceID);
2406  return false;
2407  }
2408  }
2409 
2410  return true;
2411 }
2412 
2413 bool JackCoreAudioDriver::TakeHog()
2414 {
2415  OSStatus err = noErr;
2416  AudioObjectID sub_device[32];
2417  UInt32 outSize = sizeof(sub_device);
2418  err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
2419 
2420  if (err != noErr) {
2421  jack_log("JackCoreAudioDriver::TakeHog : device does not have subdevices");
2422  return TakeHogAux(fDeviceID, true);
2423  } else {
2424  int num_devices = outSize / sizeof(AudioObjectID);
2425  jack_log("JackCoreAudioDriver::TakeHog : device does has %d subdevices", num_devices);
2426  for (int i = 0; i < num_devices; i++) {
2427  if (!TakeHogAux(sub_device[i], true)) {
2428  return false;
2429  }
2430  }
2431  return true;
2432  }
2433 }
2434 
2435 bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
2436 {
2437  UInt32 deviceType, outSize = sizeof(UInt32);
2438  OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
2439 
2440  if (err != noErr) {
2441  jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
2442  return false;
2443  } else {
2444  return (deviceType == kAudioDeviceTransportTypeAggregate);
2445  }
2446 }
2447 
2448 
2449 } // end of namespace
2450 
2451 
2452 #ifdef __cplusplus
2453 extern "C"
2454 {
2455 #endif
2456 
2457  SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
2458  {
2459  jack_driver_desc_t * desc;
2462 
2463  desc = jack_driver_descriptor_construct("coreaudio", JackDriverMaster, "Apple CoreAudio API based audio backend", &filler);
2464 
2465  value.i = -1;
2466  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");
2467  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");
2468  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");
2469 
2470  value.str[0] = 0;
2471  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\")");
2472  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\")");
2473 
2474  value.str[0] = 0;
2475  jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL);
2476  jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output CoreAudio device name", NULL);
2477 
2478  value.i = 0;
2479  jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL);
2480 
2481 #ifndef __ppc__
2482  value.i = 0;
2483  jack_driver_descriptor_add_parameter(desc, &filler, "AC3-encoding", 'a', JackDriverParamBool, &value, NULL, "AC3 multi-channels encoding", NULL);
2484 
2485  value.i = 448;
2486  jack_driver_descriptor_add_parameter(desc, &filler, "AC3-bitrate", 'b', JackDriverParamUInt, &value, NULL, "AC3 bitrate", NULL);
2487 
2488  value.i = 0;
2489  jack_driver_descriptor_add_parameter(desc, &filler, "AC3-LFE", 'f', JackDriverParamBool, &value, NULL, "AC3 LFE channel", NULL);
2490 #endif
2491  value.i = TRUE;
2492  jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
2493 
2494  value.ui = 44100U;
2495  jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
2496 
2497  value.ui = 256U;
2498  jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
2499 
2500  value.str[0] = 0;
2501  jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "CoreAudio device name", NULL);
2502 
2503  value.ui = 0;
2504  jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
2505  jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
2506 
2507  value.i = FALSE;
2508  jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available CoreAudio devices", NULL);
2509 
2510  value.i = FALSE;
2511  jack_driver_descriptor_add_parameter(desc, &filler, "hog", 'H', JackDriverParamBool, &value, NULL, "Take exclusive access of the audio device", NULL);
2512 
2513  value.ui = 100;
2514  jack_driver_descriptor_add_parameter(desc, &filler, "async-latency", 'L', JackDriverParamUInt, &value, NULL, "Extra output latency in asynchronous mode (percent)", NULL);
2515 
2516  value.ui = 100;
2517  jack_driver_descriptor_add_parameter(desc, &filler, "grain", 'G', JackDriverParamUInt, &value, NULL, "Computation grain in RT thread (percent)", NULL);
2518 
2519  value.i = FALSE;
2520  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");
2521 
2522  return desc;
2523  }
2524 
2525  SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
2526  {
2527  jack_nframes_t srate = 44100;
2528  jack_nframes_t frames_per_interrupt = 256;
2529  bool capture = false;
2530  bool playback = false;
2531  int chan_in = -1; // Default: if not explicitely set, then max possible will be used...
2532  int chan_out = -1; // Default: if not explicitely set, then max possible will be used...
2533  const char* chan_in_list = "";
2534  const char* chan_out_list = "";
2535  bool monitor = false;
2536  const char* capture_driver_uid = "";
2537  const char* playback_driver_uid = "";
2538  const JSList *node;
2539  const jack_driver_param_t *param;
2540  jack_nframes_t systemic_input_latency = 0;
2541  jack_nframes_t systemic_output_latency = 0;
2542  int async_output_latency = 100;
2543  int computation_grain = -1;
2544  bool hogged = false;
2545  bool clock_drift = false;
2546  bool ac3_encoding = false;
2547  int ac3_bitrate = 448;
2548  bool ac3_lfe = false;
2549 
2550  for (node = params; node; node = jack_slist_next(node)) {
2551  param = (const jack_driver_param_t *) node->data;
2552 
2553  switch (param->character) {
2554 
2555  case 'd':
2556  capture_driver_uid = param->value.str;
2557  playback_driver_uid = param->value.str;
2558  break;
2559 
2560  case 'D':
2561  capture = true;
2562  playback = true;
2563  break;
2564 
2565  case 'c':
2566  chan_in = chan_out = param->value.i;
2567  break;
2568 
2569  case 'i':
2570  chan_in = param->value.i;
2571  break;
2572 
2573  case 'o':
2574  chan_out = param->value.i;
2575  break;
2576 
2577  case 'n':
2578  chan_in_list = param->value.str;
2579  break;
2580 
2581  case 'N':
2582  chan_out_list = param->value.str;
2583  break;
2584 
2585  case 'C':
2586  capture = true;
2587  if (strcmp(param->value.str, "none") != 0) {
2588  capture_driver_uid = param->value.str;
2589  }
2590  break;
2591 
2592  case 'P':
2593  playback = true;
2594  if (strcmp(param->value.str, "none") != 0) {
2595  playback_driver_uid = param->value.str;
2596  }
2597  break;
2598 
2599  case 'm':
2600  monitor = param->value.i;
2601  break;
2602 
2603  #ifndef __ppc__
2604  case 'a':
2605  ac3_encoding = param->value.i;
2606  break;
2607 
2608  case 'b':
2609  ac3_bitrate = param->value.i;
2610  break;
2611 
2612  case 'f':
2613  ac3_lfe = param->value.i;
2614  break;
2615  #endif
2616 
2617  case 'r':
2618  srate = param->value.ui;
2619  break;
2620 
2621  case 'p':
2622  frames_per_interrupt = (unsigned int)param->value.ui;
2623  break;
2624 
2625  case 'I':
2626  systemic_input_latency = param->value.ui;
2627  break;
2628 
2629  case 'O':
2630  systemic_output_latency = param->value.ui;
2631  break;
2632 
2633  case 'l':
2634  Jack::DisplayDeviceNames();
2635  // Stops the server in this case
2636  return NULL;
2637 
2638  case 'H':
2639  hogged = true;
2640  break;
2641 
2642  case 'L':
2643  async_output_latency = param->value.ui;
2644  break;
2645 
2646  case 'G':
2647  computation_grain = param->value.ui;
2648  break;
2649 
2650  case 's':
2651  clock_drift = true;
2652  break;
2653  }
2654  }
2655 
2656  /* duplex is the default */
2657  if (!capture && !playback) {
2658  capture = true;
2659  playback = true;
2660  }
2661 
2662  if (strcmp(chan_in_list, "") != 0 && chan_in >= 0) {
2663  printf("Input channel list and in channels are both specified, input channel list will take over...\n");
2664  }
2665 
2666  if (strcmp(chan_out_list, "") != 0 && chan_out >= 0) {
2667  printf("Output channel list and out channels are both specified, output channel list will take over...\n");
2668  }
2669 
2670  Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
2671  if (driver->Open(frames_per_interrupt,
2672  srate, capture,
2673  playback, chan_in,
2674  chan_out, chan_in_list,
2675  chan_out_list, monitor,
2676  capture_driver_uid,
2677  playback_driver_uid,
2678  systemic_input_latency,
2679  systemic_output_latency,
2680  async_output_latency,
2681  computation_grain,
2682  hogged, clock_drift,
2683  ac3_encoding, ac3_bitrate, ac3_lfe) == 0) {
2684  return driver;
2685  } else {
2686  delete driver;
2687  return NULL;
2688  }
2689  }
2690 
2691 #ifdef __cplusplus
2692 }
2693 #endif
2694 
2695 
Inter process synchronization using using Mach semaphore.
Locked Engine, access to methods is serialized using a mutex.
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:91
jack_nframes_t min
Definition: types.h:268
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:99
jack_nframes_t max
Definition: types.h:272
The base interface for drivers clients.
Definition: JackDriver.h:122
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:107