55
55
jack_log(" Bytes per Frame:%ld", inDesc->mBytesPerFrame);
56
56
jack_log(" Channels per Frame:%ld", inDesc->mChannelsPerFrame);
57
57
jack_log(" Bits per Channel:%ld", inDesc->mBitsPerChannel);
58
jack_log("- - - - - - - - - - - - - - - - - - - -\n");
58
jack_log("- - - - - - - - - - - - - - - - - - - -");
61
61
static void printError(OSStatus err)
194
194
driver->fActionFags = ioActionFlags;
195
195
driver->fCurrentTime = (AudioTimeStamp *)inTimeStamp;
196
196
driver->fDriverOutputData = ioData;
198
198
// Setup threadded based log function once...
199
199
if (set_threaded_log_function()) {
201
201
jack_log("set_threaded_log_function");
202
202
JackMachThread::GetParams(pthread_self(), &driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint);
204
204
if (driver->fComputationGrain > 0) {
205
205
jack_log("JackCoreAudioDriver::Render : RT thread computation setup to %d percent of period", int(driver->fComputationGrain * 100));
206
206
driver->fEngineControl->fComputation = driver->fEngineControl->fPeriod * driver->fComputationGrain;
209
209
// Signal waiting start function...
210
210
driver->fState = true;
213
213
driver->CycleTakeBeginTime();
214
214
return driver->Process();
217
217
int JackCoreAudioDriver::Read()
219
AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData);
219
OSStatus err = AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData);
220
return (err == noErr) ? 0 : -1;
223
223
int JackCoreAudioDriver::Write()
225
225
for (int i = 0; i < fPlaybackChannels; i++) {
226
226
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
227
float* buffer = GetOutputBuffer(i);
228
int size = sizeof(float) * fEngineControl->fBufferSize;
229
memcpy((float*)fDriverOutputData->mBuffers[i].mData, buffer, size);
227
jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
228
int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
229
memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
231
231
if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
232
232
memcpy(GetMonitorBuffer(i), buffer, size);
234
memset((float*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(float) * fEngineControl->fBufferSize);
234
memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
241
240
OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
242
241
UInt32 inChannel,
291
290
case kAudioDeviceProcessorOverload: {
292
291
jack_error("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload");
293
292
jack_time_t cur_time = GetMicroSeconds();
294
driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing...
293
driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing...
298
297
case kAudioDevicePropertyStreamConfiguration: {
299
298
jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration : server will quit...");
300
299
driver->NotifyFailure(JackBackendError, "Another application has changed the device configuration."); // Message length limited to JACK_MESSAGE_SIZE
302
301
kill(JackTools::GetPID(), SIGINT);
303
302
return kAudioHardwareUnsupportedOperationError;
306
305
case kAudioDevicePropertyNominalSampleRate: {
307
306
Float64 sampleRate = 0;
308
307
UInt32 outsize = sizeof(Float64);
309
308
OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sampleRate);
310
309
if (err != noErr)
311
310
return kAudioHardwareUnsupportedOperationError;
313
312
char device_name[256];
314
313
const char* digidesign_name = "Digidesign";
315
314
driver->GetDeviceNameFromID(driver->fDeviceID, device_name);
317
316
if (sampleRate != driver->fEngineControl->fSampleRate) {
319
318
// Digidesign hardware, so "special" code : change the SR again here
320
319
if (strncmp(device_name, digidesign_name, sizeof(digidesign_name)) == 0) {
322
321
jack_log("Digidesign HW = %s", device_name);
324
323
// Set sample rate again...
325
324
sampleRate = driver->fEngineControl->fSampleRate;
326
325
err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sampleRate);
331
330
jack_log("Set sample rate = %f", sampleRate);
334
333
// Check new sample rate again...
335
334
outsize = sizeof(Float64);
336
335
err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sampleRate);
452
459
JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
453
: JackAudioDriver(name, alias, engine, table),
454
fJackInputData(NULL),
455
fDriverOutputData(NULL),
460
: JackAudioDriver(name, alias, engine, table),
461
fJackInputData(NULL),
462
fDriverOutputData(NULL),
460
467
fComputationGrain(-1.f),
472
479
pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
473
480
pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
474
481
UInt32 outDataSize;
476
483
if (fPluginID > 0) {
478
485
osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
479
486
if (osErr != noErr) {
480
487
jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
481
488
printError(osErr);
485
492
osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
486
493
if (osErr != noErr) {
487
494
jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error");
488
495
printError(osErr);
497
OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
504
OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
499
506
OSStatus err = noErr;
500
507
AudioObjectID sub_device[32];
501
508
UInt32 outSize = sizeof(sub_device);
503
510
err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
504
511
vector<AudioDeviceID> captureDeviceIDArray;
506
513
if (err != noErr) {
507
514
jack_log("Input device does not have subdevices");
508
515
captureDeviceIDArray.push_back(captureDeviceID);
513
520
captureDeviceIDArray.push_back(sub_device[i]);
517
err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
524
err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
518
525
vector<AudioDeviceID> playbackDeviceIDArray;
520
527
if (err != noErr) {
521
528
jack_log("Output device does not have subdevices");
522
529
playbackDeviceIDArray.push_back(playbackDeviceID);
527
534
playbackDeviceIDArray.push_back(sub_device[i]);
531
538
return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
534
OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
541
OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
536
543
OSStatus osErr = noErr;
538
545
Boolean outWritable;
540
547
// Prepare sub-devices for clock drift compensation
541
548
// Workaround for bug in the HAL : until 10.6.2
542
549
AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
545
552
AudioClassID inClass = kAudioSubDeviceClassID;
546
553
void* theQualifierData = &inClass;
547
554
UInt32 subDevicesNum = 0;
549
556
//---------------------------------------------------------------------------
550
557
// Setup SR of both devices otherwise creating AD may fail...
551
558
//---------------------------------------------------------------------------
553
560
UInt32 clockdomain = 0;
554
561
outSize = sizeof(UInt32);
555
562
bool need_clock_drift_compensation = false;
557
564
for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
558
565
if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
559
566
jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device");
561
568
// Check clock domain
562
osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
569
osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
563
570
if (osErr != 0) {
564
571
jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
565
572
printError(osErr);
567
keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
574
keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
568
575
jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain);
569
576
if (clockdomain != 0 && clockdomain != keptclockdomain) {
570
577
jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
577
584
for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
578
585
if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
579
586
jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device");
581
588
// Check clock domain
582
osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
589
osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
583
590
if (osErr != 0) {
584
591
jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
585
592
printError(osErr);
587
keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
594
keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
588
595
jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain);
589
596
if (clockdomain != 0 && clockdomain != keptclockdomain) {
590
597
jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
602
609
//---------------------------------------------------------------------------
603
610
// Start to create a new aggregate by getting the base audio hardware plugin
604
611
//---------------------------------------------------------------------------
606
613
char device_name[256];
607
614
for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
608
615
GetDeviceNameFromID(captureDeviceID[i], device_name);
609
616
jack_info("Separated input = '%s' ", device_name);
612
619
for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
613
620
GetDeviceNameFromID(playbackDeviceID[i], device_name);
614
621
jack_info("Separated output = '%s' ", device_name);
617
624
osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
618
625
if (osErr != noErr) {
619
626
jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
646
653
CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
647
654
CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
649
656
// add the name of the device to the dictionary
650
657
CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
652
659
// add our choice of UID for the aggregate device to the dictionary
653
660
CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
655
662
// add a "private aggregate key" to the dictionary
657
664
CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
660
667
Gestalt(gestaltSystemVersion, &system);
662
669
jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
664
671
// Starting with 10.5.4 systems, the AD can be internal... (better)
665
672
if (system < 0x00001054) {
666
673
jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
668
675
jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
669
676
CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
672
679
// Prepare sub-devices for clock drift compensation
673
680
CFMutableArrayRef subDevicesArrayClock = NULL;
676
683
if (fClockDriftCompensate) {
677
684
if (need_clock_drift_compensation) {
678
685
jack_info("Clock drift compensation activated...");
679
686
subDevicesArrayClock = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
681
688
for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
682
689
CFStringRef UID = GetDeviceName(captureDeviceID[i]);
711
718
//-------------------------------------------------
712
719
// Create a CFMutableArray for our sub-device list
713
720
//-------------------------------------------------
715
722
// we need to append the UID for each device to a CFMutableArray, so create one here
716
723
CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
718
725
vector<CFStringRef> captureDeviceUID;
719
726
for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
720
727
CFStringRef ref = GetDeviceName(captureDeviceID[i]);
724
731
// input sub-devices in this example, so append the sub-device's UID to the CFArray
725
732
CFArrayAppendValue(subDevicesArray, ref);
728
735
vector<CFStringRef> playbackDeviceUID;
729
736
for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
730
737
CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
734
741
// output sub-devices in this example, so append the sub-device's UID to the CFArray
735
742
CFArrayAppendValue(subDevicesArray, ref);
738
745
//-----------------------------------------------------------------------
739
746
// Feed the dictionary to the plugin, to create a blank aggregate device
740
747
//-----------------------------------------------------------------------
742
749
AudioObjectPropertyAddress pluginAOPA;
743
750
pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
744
751
pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
797
804
printError(osErr);
801
808
// pause again to give the changes time to take effect
802
809
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
804
811
// Prepare sub-devices for clock drift compensation
805
812
// Workaround for bug in the HAL : until 10.6.2
807
814
if (fClockDriftCompensate) {
808
815
if (need_clock_drift_compensation) {
809
816
jack_info("Clock drift compensation activated...");
811
818
// Get the property data size
812
819
osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
813
820
if (osErr != noErr) {
814
821
jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
815
822
printError(osErr);
818
825
// Calculate the number of object IDs
819
826
subDevicesNum = outSize / sizeof(AudioObjectID);
820
827
jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum);
821
828
AudioObjectID subDevices[subDevicesNum];
822
829
outSize = sizeof(subDevices);
824
831
osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
825
832
if (osErr != noErr) {
826
833
jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
827
834
printError(osErr);
830
837
// Set kAudioSubDevicePropertyDriftCompensation property...
831
838
for (UInt32 index = 0; index < subDevicesNum; ++index) {
832
839
UInt32 theDriftCompensationValue = 1;
840
847
jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
844
851
// pause again to give the changes time to take effect
845
852
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
851
858
// release the private AD key
852
859
CFRelease(AggregateDeviceNumberRef);
854
861
// release the CF objects we have created - we don't need them any more
855
862
CFRelease(aggDeviceDict);
856
863
CFRelease(subDevicesArray);
858
865
if (subDevicesArrayClock)
859
866
CFRelease(subDevicesArrayClock);
862
869
for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
863
870
CFRelease(captureDeviceUID[i]);
866
873
for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
867
874
CFRelease(playbackDeviceUID[i]);
870
877
jack_log("New aggregate device %ld", *outAggregateDevice);
874
881
DestroyAggregateDevice();
878
int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
879
const char* playback_driver_uid,
880
char* capture_driver_name,
881
char* playback_driver_name,
885
int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
886
const char* playback_driver_uid,
887
char* capture_driver_name,
888
char* playback_driver_name,
882
889
jack_nframes_t samplerate)
884
891
capture_driver_name[0] = 0;
885
892
playback_driver_name[0] = 0;
888
895
if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
889
896
jack_log("JackCoreAudioDriver::Open duplex");
891
898
// Same device for capture and playback...
892
899
if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
894
901
if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
895
902
jack_log("Will take default in/out");
896
903
if (GetDefaultDevice(&fDeviceID) != noErr) {
902
909
jack_error("Cannot get device name from device ID");
908
915
// Creates aggregate device
909
916
AudioDeviceID captureID, playbackID;
911
918
if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
912
919
jack_log("Will take default input");
913
920
if (GetDefaultInputDevice(&captureID) != noErr) {
963
970
jack_log("JackCoreAudioDriver::Open default driver");
964
971
if (GetDefaultDevice(&fDeviceID) != noErr) {
965
972
jack_error("Cannot open default device in duplex mode, so aggregate default input and default output");
967
974
// Creates aggregate device
968
975
AudioDeviceID captureID, playbackID;
970
977
if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
971
978
jack_log("Will take default input");
972
979
if (GetDefaultInputDevice(&captureID) != noErr) {
1111
1118
usleep(100000);
1112
1119
jack_log("Wait count = %d", count);
1115
1122
// Check new sample rate
1116
1123
outSize = sizeof(Float64);
1117
1124
err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
1178
1185
jack_log("Setup AUHAL input off");
1181
1188
err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
1182
1189
if (err1 != noErr) {
1183
1190
jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
1193
1200
jack_log("Setup AUHAL output off");
1196
1203
err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
1197
1204
if (err1 != noErr) {
1198
1205
jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
1199
1206
printError(err1);
1203
1210
size = sizeof(AudioDeviceID);
1204
1211
err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
1205
1212
if (err1 != noErr) {
1273
1280
// Setup stream converters
1274
1281
if (capturing && inchannels > 0) {
1276
1283
size = sizeof(AudioStreamBasicDescription);
1277
1284
err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &size);
1278
1285
if (err1 != noErr) {
1283
1290
PrintStreamDesc(&srcFormat);
1285
1292
jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
1286
1293
srcFormat.mSampleRate = samplerate;
1287
1294
srcFormat.mFormatID = kAudioFormatLinearPCM;
1288
1295
srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1289
srcFormat.mBytesPerPacket = sizeof(float);
1296
srcFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
1290
1297
srcFormat.mFramesPerPacket = 1;
1291
srcFormat.mBytesPerFrame = sizeof(float);
1298
srcFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
1292
1299
srcFormat.mChannelsPerFrame = inchannels;
1293
1300
srcFormat.mBitsPerChannel = 32;
1294
1301
PrintStreamDesc(&srcFormat);
1296
1303
err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
1297
1304
if (err1 != noErr) {
1298
1305
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
1313
1320
PrintStreamDesc(&dstFormat);
1315
1322
jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
1316
1323
dstFormat.mSampleRate = samplerate;
1317
1324
dstFormat.mFormatID = kAudioFormatLinearPCM;
1318
1325
dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1319
dstFormat.mBytesPerPacket = sizeof(float);
1326
dstFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
1320
1327
dstFormat.mFramesPerPacket = 1;
1321
dstFormat.mBytesPerFrame = sizeof(float);
1328
dstFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
1322
1329
dstFormat.mChannelsPerFrame = outchannels;
1323
1330
dstFormat.mBitsPerChannel = 32;
1324
1331
PrintStreamDesc(&dstFormat);
1326
1333
err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
1327
1334
if (err1 != noErr) {
1328
1335
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
1486
1493
fComputationGrain = float(computation_grain) / 100.f;
1487
1494
fHogged = hogged;
1488
1495
fClockDriftCompensate = clock_drift;
1492
1499
Gestalt(gestaltSystemVersionMajor, &major);
1493
1500
Gestalt(gestaltSystemVersionMinor, &minor);
1495
1502
// Starting with 10.6 systems, the HAL notification thread is created internally
1496
1503
if (major == 10 && minor >= 6) {
1497
1504
CFRunLoopRef theRunLoop = NULL;
1516
1523
if (SetupBufferSize(buffer_size) < 0)
1519
1526
if (SetupSampleRate(samplerate) < 0)
1522
1529
if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, samplerate) < 0)
1544
1551
jack_log("JackCoreAudioDriver::Close");
1546
JackAudioDriver::Close();
1554
// Generic audio driver close
1555
int res = JackAudioDriver::Close();
1547
1557
RemoveListeners();
1548
1558
DisposeBuffers();
1550
1560
DestroyAggregateDevice();
1554
1564
int JackCoreAudioDriver::Attach()
1561
1571
char channel_name[64];
1562
1572
char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
1563
1573
char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
1574
jack_latency_range_t range;
1565
1576
jack_log("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
1567
1578
for (int i = 0; i < fCaptureChannels; i++) {
1569
1580
err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
1570
1581
if (err != noErr)
1571
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error ");
1582
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
1572
1583
if (err == noErr && size > 0) {
1573
1584
err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
1574
1585
if (err != noErr)
1575
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error ");
1586
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
1576
1587
snprintf(alias, sizeof(alias) - 1, "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
1578
1589
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
1590
1601
UInt32 value2 = 0;
1591
1602
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);
1592
1603
if (err != noErr)
1593
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error ");
1604
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
1594
1605
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
1595
1606
if (err != noErr)
1596
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error ");
1607
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
1598
1609
port = fGraphManager->GetPort(port_index);
1599
1610
port->SetAlias(alias);
1600
port->SetLatency(fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency);
1611
range.min = range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
1612
port->SetLatencyRange(JackCaptureLatency, &range);
1601
1613
fCapturePortList[i] = port_index;
1606
1618
err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
1607
1619
if (err != noErr)
1608
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error ");
1620
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
1609
1621
if (err == noErr && size > 0) {
1610
1622
err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
1611
1623
if (err != noErr)
1612
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error ");
1624
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
1613
1625
snprintf(alias, sizeof(alias) - 1, "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
1615
1627
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
1627
1639
UInt32 value2 = 0;
1628
1640
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1);
1629
1641
if (err != noErr)
1630
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error ");
1642
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
1631
1643
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
1632
1644
if (err != noErr)
1633
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error ");
1645
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
1635
1647
port = fGraphManager->GetPort(port_index);
1636
1648
port->SetAlias(alias);
1637
1649
// Add more latency if "async" mode is used...
1638
port->SetLatency(fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency);
1650
range.min = range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency;
1651
port->SetLatencyRange(JackPlaybackLatency, &range);
1639
1652
fPlaybackPortList[i] = port_index;
1641
1654
// Monitor ports
1642
1655
if (fWithMonitorPorts) {
1643
jack_log("Create monitor port ");
1656
jack_log("Create monitor port");
1644
1657
snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1);
1645
1658
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
1646
1659
jack_error("Cannot register monitor port for %s", name);
1649
1662
port = fGraphManager->GetPort(port_index);
1650
port->SetAlias(alias);
1651
port->SetLatency(fEngineControl->fBufferSize);
1663
range.min = range.max = fEngineControl->fBufferSize;
1664
port->SetLatencyRange(JackCaptureLatency, &range);
1652
1665
fMonitorPortList[i] = port_index;
1665
1678
int JackCoreAudioDriver::Start()
1667
1680
jack_log("JackCoreAudioDriver::Start");
1668
JackAudioDriver::Start();
1670
OSStatus err = AudioOutputUnitStart(fAUHAL);
1674
// Waiting for Measure callback to be called (= driver has started)
1677
while (!fState && count++ < WAIT_COUNTER) {
1679
jack_log("JackCoreAudioDriver::Start wait count = %d", count);
1682
if (count < WAIT_COUNTER) {
1683
jack_info("CoreAudio driver is running...");
1686
jack_error("CoreAudio driver cannot start...");
1681
if (JackAudioDriver::Start() >= 0) {
1682
OSStatus err = AudioOutputUnitStart(fAUHAL);
1685
// Waiting for Measure callback to be called (= driver has started)
1688
while (!fState && count++ < WAIT_COUNTER) {
1690
jack_log("JackCoreAudioDriver::Start wait count = %d", count);
1693
if (count < WAIT_COUNTER) {
1694
jack_info("CoreAudio driver is running...");
1698
jack_error("CoreAudio driver cannot start...");
1700
JackAudioDriver::Stop();
1691
1705
int JackCoreAudioDriver::Stop()
1693
1707
jack_log("JackCoreAudioDriver::Stop");
1694
return (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
1708
int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
1709
if (JackAudioDriver::Stop() < 0) {
1697
1715
int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
1711
1729
// Input buffers do no change : prepare them only once
1712
1730
for (int i = 0; i < fCaptureChannels; i++) {
1713
1731
fJackInputData->mBuffers[i].mNumberChannels = 1;
1714
fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float);
1732
fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t);
1715
1733
fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
1745
1763
bool JackCoreAudioDriver::TakeHog()
1747
1765
OSStatus err = noErr;
1748
1766
AudioObjectID sub_device[32];
1749
1767
UInt32 outSize = sizeof(sub_device);
1750
1768
err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
1752
1770
if (err != noErr) {
1753
1771
jack_log("Device does not have subdevices");
1754
1772
return TakeHogAux(fDeviceID, true);
1767
1785
bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
1769
1787
UInt32 deviceType, outSize = sizeof(UInt32);
1770
1788
OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
1772
1790
if (err != noErr) {
1773
1791
jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
1898
1916
desc->params[i].value.i = FALSE;
1899
1917
strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
1900
1918
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
1903
1921
strcpy(desc->params[i].name, "hog");
1904
1922
desc->params[i].character = 'H';
1906
1924
desc->params[i].value.i = FALSE;
1907
1925
strcpy(desc->params[i].short_desc, "Take exclusive access of the audio device");
1908
1926
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
1911
1929
strcpy(desc->params[i].name, "async-latency");
1912
1930
desc->params[i].character = 'L';
1914
1932
desc->params[i].value.i = 100;
1915
1933
strcpy(desc->params[i].short_desc, "Extra output latency in asynchronous mode (percent)");
1916
1934
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
1919
1937
strcpy(desc->params[i].name, "grain");
1920
1938
desc->params[i].character = 'G';
1922
1940
desc->params[i].value.i = 100;
1923
1941
strcpy(desc->params[i].short_desc, "Computation grain in RT thread (percent)");
1924
1942
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
1927
1945
strcpy(desc->params[i].name, "clock-drift");
1928
1946
desc->params[i].character = 's';
1937
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
1955
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
1939
1957
jack_nframes_t srate = 44100;
1940
1958
jack_nframes_t frames_per_interrupt = 128;
2046
2064
Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
2047
if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid,
2065
if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid,
2048
2066
playback_driver_uid, systemic_input_latency, systemic_output_latency, async_output_latency, computation_grain, hogged, clock_drift) == 0) {