1 /*
2 Copyright (C) 2008 Remon Sijrier
3 Copyright (C) Grame, 2003.
4 Copyright (C) Johnny Petrantoni, 2003.
5
6 This file is part of Traverso
7
8 Traverso is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21
22 Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France
23 grame@rd.grame.fr
24
25 Johnny Petrantoni, johnny@lato-b.com - Italy, Rome.
26
27 Jan 30, 2004: Johnny Petrantoni: first code of the coreaudio driver, based on portaudio driver by Stephane Letz.
28 Feb 02, 2004: Johnny Petrantoni: fixed null cycle, removed double copy of buffers in AudioRender, the driver works fine (tested with Built-in Audio and Hammerfall RME), but no cpu load is displayed.
29 Feb 03, 2004: Johnny Petrantoni: some little fix.
30 Feb 03, 2004: Stephane Letz: some fix in AudioRender.cpp code.
31 Feb 03, 2004: Johnny Petrantoni: removed the default device stuff (useless, in jackosx, because JackPilot manages this behavior), the device must be specified. and all parameter must be correct.
32 Feb 04, 2004: Johnny Petrantoni: now the driver supports interfaces with multiple interleaved streams (such as the MOTU 828).
33 Nov 05, 2004: S.Letz: correct management of -I option for use with JackPilot.
34 Nov 15, 2004: S.Letz: Set a default value for deviceID.
35 Nov 30, 2004: S.Letz: In coreaudio_driver_write : clear to avoid playing dirty buffers when the client does not produce output anymore.
36 Dec 05, 2004: S.Letz: XRun detection
37 Dec 09, 2004: S.Letz: Dynamic buffer size change
38 Dec 23, 2004: S.Letz: Correct bug in dynamic buffer size change : update period_usecs
39 Jan 20, 2005: S.Letz: Almost complete rewrite using AUHAL.
40 May 20, 2005: S.Letz: Add "systemic" latencies management.
41 Jun 06, 2005: S.Letz: Remove the "-I" parameter, change the semantic of "-n" parameter : -n (driver name) now correctly uses the PropertyDeviceUID
42 (persistent accross reboot...) as the identifier for the used coreaudio driver.
43 Jun 14, 2005: S.Letz: Since the "-I" parameter is not used anymore, rename the "systemic" latencies management parametes "-I" and "-O" like for the ALSA driver.
44 Aug 16, 2005: S.Letz: Remove get_device_id_from_num, use get_default_device instead. If the -n option is not used or the device name cannot
45 be found, the default device is used. Note: the default device can be used only if both default input and default output are the same.
46 Dec 19, 2005: S.Letz: Add -d option (display_device_names).
47 Apri 7, 2006: S.Letz: Synchronization with the jackdmp coreaudio driver version: improve half-duplex management.
48 May 17, 2006: S.Letz: Minor fix in driver_initialize.
49 May 18, 2006: S.Letz: Document sample rate default value.
50 May 31, 2006: S.Letz: Apply Rui patch for more consistent driver parameter naming.
51 Dec 04, 2007: S.Letz: Fix a bug in sample rate management (occuring in particular with "aggregate" devices).
52 Dec 05, 2007: S.Letz: Correct sample_rate management in Open. Better handling in sample_rate change listener.
53 Nov 11, 2008: Remon Sijrier: Ported to C++ for Traverso
54
55 */
56
57 /* CoreAudio driver based on jack-audio-connection-kit-0.xxx.x coreaudio_driver.c */
58
59
60 #include "CoreAudioDriver.h"
61 #include "AudioChannel.h"
62 #include "AudioDevice.h"
63
64 #include <Utils.h>
65
66 #include <stdio.h>
67 #include <string.h>
68
69 #include "Debugger.h"
70
71 //#define PRINTDEBUG 1
72
73
CoreAudioDriver(AudioDevice * dev,int rate,nframes_t bufferSize)74 CoreAudioDriver::CoreAudioDriver(AudioDevice * dev, int rate, nframes_t bufferSize)
75 : Driver(dev, rate, bufferSize)
76 {
77 PENTERCONS;
78 }
79
~CoreAudioDriver()80 CoreAudioDriver::~ CoreAudioDriver()
81 {
82 PENTERDES;
83 }
84
85
86
JCALog(char * fmt,...)87 void JCALog(char *fmt, ...)
88 {
89 #ifdef PRINTDEBUG
90 va_list ap;
91 va_start(ap, fmt);
92 fprintf(stderr, "JCA: ");
93 vfprintf(stderr, fmt, ap);
94 va_end(ap);
95 #endif
96 }
97
printError(OSStatus err)98 void printError(OSStatus err)
99 {
100 #ifdef DEBUG
101 switch (err) {
102 case kAudioHardwareNoError:
103 JCALog("error code : kAudioHardwareNoError\n");
104 break;
105 case kAudioHardwareNotRunningError:
106 JCALog("error code : kAudioHardwareNotRunningError\n");
107 break;
108 case kAudioHardwareUnspecifiedError:
109 JCALog("error code : kAudioHardwareUnspecifiedError\n");
110 break;
111 case kAudioHardwareUnknownPropertyError:
112 JCALog("error code : kAudioHardwareUnknownPropertyError\n");
113 break;
114 case kAudioHardwareBadPropertySizeError:
115 JCALog("error code : kAudioHardwareBadPropertySizeError\n");
116 break;
117 case kAudioHardwareIllegalOperationError:
118 JCALog("error code : kAudioHardwareIllegalOperationError\n");
119 break;
120 case kAudioHardwareBadDeviceError:
121 JCALog("error code : kAudioHardwareBadDeviceError\n");
122 break;
123 case kAudioHardwareBadStreamError:
124 JCALog("error code : kAudioHardwareBadStreamError\n");
125 break;
126 case kAudioDeviceUnsupportedFormatError:
127 JCALog("error code : kAudioDeviceUnsupportedFormatError\n");
128 break;
129 case kAudioDevicePermissionsError:
130 JCALog("error code : kAudioDevicePermissionsError\n");
131 break;
132 default:
133 JCALog("error code : unknown %ld\n", err);
134 break;
135 }
136 #endif
137 }
138
get_device_name_from_id(AudioDeviceID id,char name[256])139 OSStatus get_device_name_from_id(AudioDeviceID id, char name[256])
140 {
141 UInt32 size = sizeof(char) * 256;
142 OSStatus res = AudioDeviceGetProperty(id, 0, false,
143 kAudioDevicePropertyDeviceName,
144 &size,
145 &name[0]);
146 return res;
147 }
148
get_device_id_from_uid(char * UID,AudioDeviceID * id)149 OSStatus get_device_id_from_uid(char* UID, AudioDeviceID* id)
150 {
151 UInt32 size = sizeof(AudioValueTranslation);
152 CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
153 AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
154 if (inIUD == NULL) {
155 return kAudioHardwareUnspecifiedError;
156 } else {
157 OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
158 CFRelease(inIUD);
159 JCALog("get_device_id_from_uid %s %ld \n", UID, *id);
160 return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
161 }
162 }
163
get_default_device(AudioDeviceID * id)164 OSStatus get_default_device(AudioDeviceID * id)
165 {
166 OSStatus res;
167 UInt32 theSize = sizeof(UInt32);
168 AudioDeviceID inDefault;
169 AudioDeviceID outDefault;
170
171 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
172 &theSize, &inDefault)) != noErr)
173 return res;
174
175 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
176 &theSize, &outDefault)) != noErr)
177 return res;
178
179 JCALog("get_default_device: input %ld output %ld\n", inDefault, outDefault);
180
181 // Get the device only if default input and ouput are the same
182 if (inDefault == outDefault) {
183 *id = inDefault;
184 return noErr;
185 } else {
186 PERROR("CoreAudioDriver:: Default input and output devices are not the same !!");
187 return kAudioHardwareBadDeviceError;
188 }
189 }
190
get_default_input_device(AudioDeviceID * id)191 OSStatus get_default_input_device(AudioDeviceID* id)
192 {
193 OSStatus res;
194 UInt32 theSize = sizeof(UInt32);
195 AudioDeviceID inDefault;
196
197 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
198 &theSize, &inDefault)) != noErr)
199 return res;
200
201 JCALog("get_default_input_device: input = %ld \n", inDefault);
202 *id = inDefault;
203 return noErr;
204 }
205
get_default_output_device(AudioDeviceID * id)206 OSStatus get_default_output_device(AudioDeviceID* id)
207 {
208 OSStatus res;
209 UInt32 theSize = sizeof(UInt32);
210 AudioDeviceID outDefault;
211
212 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
213 &theSize, &outDefault)) != noErr)
214 return res;
215
216 JCALog("get_default_output_device: output = %ld\n", outDefault);
217 *id = outDefault;
218 return noErr;
219 }
220
get_total_channels(AudioDeviceID device,int * channelCount,bool isInput)221 OSStatus get_total_channels(AudioDeviceID device, int* channelCount, bool isInput)
222 {
223 OSStatus err = noErr;
224 UInt32 outSize;
225 Boolean outWritable;
226 AudioBufferList* bufferList = 0;
227 AudioStreamID* streamList = 0;
228 int i, numStream;
229
230 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize, &outWritable);
231 if (err == noErr) {
232 streamList = (AudioStreamID*)malloc(outSize);
233 numStream = outSize/sizeof(AudioStreamID);
234 JCALog("get_total_channels device stream number = %ld numStream = %ld\n", device, numStream);
235 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize, streamList);
236 if (err == noErr) {
237 AudioStreamBasicDescription streamDesc;
238 outSize = sizeof(AudioStreamBasicDescription);
239 for (i = 0; i < numStream; i++) {
240 err = AudioStreamGetProperty(streamList[i], 0, kAudioDevicePropertyStreamFormat, &outSize, &streamDesc);
241 JCALog("get_total_channels streamDesc mFormatFlags = %ld mChannelsPerFrame = %ld\n", streamDesc.mFormatFlags, streamDesc.mChannelsPerFrame);
242 }
243 }
244 }
245
246 *channelCount = 0;
247 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
248 if (err == noErr) {
249 bufferList = (AudioBufferList*)malloc(outSize);
250 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
251 if (err == noErr) {
252 for (i = 0; i < bufferList->mNumberBuffers; i++)
253 *channelCount += bufferList->mBuffers[i].mNumberChannels;
254 }
255 }
256
257 if (streamList)
258 free(streamList);
259 if (bufferList)
260 free(bufferList);
261
262 return err;
263 }
264
display_device_names()265 OSStatus display_device_names()
266 {
267 UInt32 size;
268 Boolean isWritable;
269 int i, deviceNum;
270 OSStatus err;
271 CFStringRef UIname;
272
273 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
274 if (err != noErr)
275 return err;
276
277 deviceNum = size/sizeof(AudioDeviceID);
278 AudioDeviceID devices[deviceNum];
279
280 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
281 if (err != noErr)
282 return err;
283
284 for (i = 0; i < deviceNum; i++) {
285 char device_name[256];
286 char internal_name[256];
287
288 size = sizeof(CFStringRef);
289 UIname = NULL;
290 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
291 if (err == noErr) {
292 CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
293 } else {
294 goto error;
295 }
296
297 size = 256;
298 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
299 if (err != noErr)
300 return err;
301 printf("ICI\n");
302 printf("Device name = \'%s\', internal_name = \'%s\' (to be used as -d parameter)\n", device_name, internal_name);
303 }
304
305 return noErr;
306
307 error:
308 if (UIname != NULL)
309 CFRelease(UIname);
310 return err;
311 }
312
render(AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32 inBusNumber,UInt32 inNumberFrames,AudioBufferList * ioData)313 OSStatus CoreAudioDriver::render(AudioUnitRenderActionFlags *ioActionFlags,
314 const AudioTimeStamp *inTimeStamp,
315 UInt32 inBusNumber,
316 UInt32 inNumberFrames,
317 AudioBufferList *ioData)
318 {
319 int res, i;
320
321 AudioUnitRender(au_hal, ioActionFlags, inTimeStamp, 1, inNumberFrames, input_list);
322
323 if (xrun_detected > 0) { /* XRun was detected */
324 trav_time_t current_time = get_microseconds ();
325 device->delay(current_time - (last_wait_ust + period_usecs));
326 last_wait_ust = current_time;
327 xrun_detected = 0;
328 return 0;
329 } else {
330 last_wait_ust = get_microseconds();
331 device->transport_cycle_start(get_microseconds());
332 res = device->run_cycle(inNumberFrames, 0);
333 }
334
335 if (null_cycle_occured) {
336 null_cycle_occured = 0;
337 for (i = 0; i < playback_nchannels; i++) {
338 memset((float*)ioData->mBuffers[i].mData, 0, sizeof(float) * inNumberFrames);
339 }
340 } else {
341 // TODO find out if ioData->mBuffers[i] correspond with the playbackChannels indices
342 audio_sample_t* buf;
343 for (int i=0; i<playbackChannels.size(); ++i) {
344 AudioChannel* channel = playbackChannels.at(i);
345 if (!channel->has_data()) {
346 continue;
347 }
348 buf = channel->get_data();
349
350 memcpy((float*)ioData->mBuffers[i].mData, buf, sizeof(float) * inNumberFrames);
351
352 // Not sure if this is needed? I think so though
353 channel->silence_buffer(inNumberFrames);
354 }
355 }
356
357 return res;
358 }
359
render_input(AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32 inBusNumber,UInt32 inNumberFrames,AudioBufferList * ioData)360 OSStatus CoreAudioDriver::render_input( AudioUnitRenderActionFlags *ioActionFlags,
361 const AudioTimeStamp *inTimeStamp,
362 UInt32 inBusNumber,
363 UInt32 inNumberFrames,
364 AudioBufferList *ioData)
365 {
366 AudioUnitRender(au_hal, ioActionFlags, inTimeStamp, 1, inNumberFrames, input_list);
367 if (xrun_detected > 0) { /* XRun was detected */
368 trav_time_t current_time = get_microseconds();
369 device->delay(current_time - (last_wait_ust + period_usecs));
370 last_wait_ust = current_time;
371 xrun_detected = 0;
372 return 0;
373 } else {
374 last_wait_ust = get_microseconds();
375 device->transport_cycle_start(get_microseconds());
376 return device->run_cycle(inNumberFrames, 0);
377 }
378 }
379
380
sr_notification(AudioDeviceID inDevice,UInt32 inChannel,Boolean isInput,AudioDevicePropertyID inPropertyID)381 OSStatus CoreAudioDriver::sr_notification(AudioDeviceID inDevice,
382 UInt32 inChannel,
383 Boolean isInput,
384 AudioDevicePropertyID inPropertyID)
385 {
386
387 switch (inPropertyID) {
388
389 case kAudioDevicePropertyNominalSampleRate: {
390 JCALog("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate \n");
391 state = 1;
392 break;
393 }
394 }
395
396 return noErr;
397 }
398
notification(AudioDeviceID inDevice,UInt32 inChannel,Boolean isInput,AudioDevicePropertyID inPropertyID)399 OSStatus CoreAudioDriver::notification(AudioDeviceID inDevice,
400 UInt32 inChannel,
401 Boolean isInput,
402 AudioDevicePropertyID inPropertyID)
403 {
404 switch (inPropertyID) {
405
406 case kAudioDeviceProcessorOverload:
407 xrun_detected = 1;
408 break;
409
410 case kAudioDevicePropertyNominalSampleRate: {
411 UInt32 outSize = sizeof(Float64);
412 Float64 sampleRate;
413 AudioStreamBasicDescription srcFormat, dstFormat;
414
415 // FIXME kAudioDeviceSectionGlobal not declared compile error ?
416 OSStatus err;
417 /* OSStatus err = AudioDeviceGetProperty(device_id, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
418 if (err != noErr) {
419 PERROR("Cannot get current sample rate");
420 return kAudioHardwareUnsupportedOperationError;
421 }*/
422 JCALog("JackCoreAudioDriver::NotificationCallback kAudioDevicePropertyNominalSampleRate %ld\n", (long)sampleRate);
423 outSize = sizeof(AudioStreamBasicDescription);
424
425 // Update SR for input
426 err = AudioUnitGetProperty(au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, &outSize);
427 if (err != noErr) {
428 PERROR("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
429 }
430 srcFormat.mSampleRate = sampleRate;
431 err = AudioUnitSetProperty(au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, outSize);
432 if (err != noErr) {
433 PERROR("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
434 }
435
436 // Update SR for output
437 err = AudioUnitGetProperty(au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, &outSize);
438 if (err != noErr) {
439 PERROR("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
440 }
441 dstFormat.mSampleRate = sampleRate;
442 err = AudioUnitSetProperty(au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, outSize);
443 if (err != noErr) {
444 PERROR("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
445 }
446 break;
447 }
448 }
449 return noErr;
450 }
451
452
453
attach()454 int CoreAudioDriver::attach()
455 {
456 int port_flags;
457 channel_t chn;
458 AudioChannel* chan;
459 char buf[32];
460 char channel_name[64];
461 OSStatus err;
462 UInt32 size;
463 UInt32 value1,value2;
464 Boolean isWritable;
465
466 device->set_buffer_size (frames_per_cycle);
467 device->set_sample_rate (frame_rate);
468
469 port_flags = PortIsOutput|PortIsPhysical|PortIsTerminal;
470
471 for (chn = 0; chn < capture_nchannels; chn++) {
472 err = AudioDeviceGetPropertyInfo(device_id, chn + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
473 if (err == noErr && size > 0) {
474 err = AudioDeviceGetProperty(device_id, chn + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
475 if (err != noErr)
476 JCALog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n");
477 snprintf(buf, sizeof(buf) - 1, "%s:out_%s%lu", capture_driver_name, channel_name, chn + 1);
478 } else {
479 snprintf(buf, sizeof(buf) - 1, "%s:out%lu", capture_driver_name, chn + 1);
480 }
481
482 chan = device->register_capture_channel(buf, "32 bit float audio", port_flags, frames_per_cycle, chn);
483 chan->set_latency( frames_per_cycle + capture_frame_latency );
484 captureChannels.append(chan);
485
486 size = sizeof(UInt32);
487 value1 = value2 = 0;
488 err = AudioDeviceGetProperty(device_id, 0, true, kAudioDevicePropertyLatency, &size, &value1);
489 if (err != noErr)
490 JCALog("AudioDeviceGetProperty kAudioDevicePropertyLatency error \n");
491 err = AudioDeviceGetProperty(device_id, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
492 if (err != noErr)
493 JCALog("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error \n");
494
495 }
496
497 port_flags = PortIsInput|PortIsPhysical|PortIsTerminal;
498
499 for (chn = 0; chn < playback_nchannels; chn++) {
500 err = AudioDeviceGetPropertyInfo(device_id, chn + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
501 if (err == noErr && size > 0) {
502 err = AudioDeviceGetProperty(device_id, chn + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
503 if (err != noErr)
504 JCALog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n");
505 snprintf(buf, sizeof(buf) - 1, "%s:in_%s%lu", playback_driver_name, channel_name, chn + 1);
506 } else {
507 snprintf(buf, sizeof(buf) - 1, "%s:in%lu", playback_driver_name, chn + 1);
508 }
509
510 chan = device->register_playback_channel(buf, "32 bit float audio", port_flags, frames_per_cycle, chn);
511 chan->set_latency( frames_per_cycle + capture_frame_latency );
512 playbackChannels.append(chan);
513
514 size = sizeof(UInt32);
515 value1 = value2 = 0;
516 err = AudioDeviceGetProperty(device_id, 0, false, kAudioDevicePropertyLatency, &size, &value1);
517 if (err != noErr)
518 JCALog("AudioDeviceGetProperty kAudioDevicePropertyLatency error \n");
519 err = AudioDeviceGetProperty(device_id, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
520 if (err != noErr)
521 JCALog("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error \n");
522 }
523
524
525 // Input buffers do no change : prepare them only once
526 for (chn = 0; chn < capture_nchannels; chn++) {
527 input_list->mBuffers[chn].mData = (audio_sample_t*)(captureChannels.at(chn)->get_buffer(frames_per_cycle));
528 }
529
530 return 1;
531 }
532
533
setup(bool capture,bool playback,const QString & cardDevice)534 int CoreAudioDriver::setup(bool capture, bool playback, const QString & cardDevice)
535 {
536 return -1;
537 }
538
539
540
_render(void * inRefCon,AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32 inBusNumber,UInt32 inNumberFrames,AudioBufferList * ioData)541 static OSStatus _render(void * inRefCon, AudioUnitRenderActionFlags * ioActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData)
542 {
543 CoreAudioDriver* driver = (CoreAudioDriver*)inRefCon;
544 return driver->render(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
545 }
546
_render_input(void * inRefCon,AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32 inBusNumber,UInt32 inNumberFrames,AudioBufferList * ioData)547 static OSStatus _render_input(void * inRefCon, AudioUnitRenderActionFlags * ioActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData)
548 {
549 CoreAudioDriver* driver = (CoreAudioDriver*)inRefCon;
550 return driver->render_input(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
551 }
552
_sr_notification(AudioDeviceID inDevice,UInt32 inChannel,Boolean isInput,AudioDevicePropertyID inPropertyID,void * inClientData)553 static OSStatus _sr_notification(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void * inClientData)
554 {
555 CoreAudioDriver* driver = (CoreAudioDriver*)inClientData;
556 return driver->sr_notification(inDevice, inChannel, isInput, inPropertyID);
557 }
558
_notification(AudioDeviceID inDevice,UInt32 inChannel,Boolean isInput,AudioDevicePropertyID inPropertyID,void * inClientData)559 static OSStatus _notification(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void * inClientData)
560 {
561 CoreAudioDriver* driver = (CoreAudioDriver*)inClientData;
562 return driver->notification(inDevice, inChannel, isInput, inPropertyID);
563 }
564
565