~ubuntu-branches/debian/sid/jackd2/sid

« back to all changes in this revision

Viewing changes to macosx/coreaudio/JackCoreAudioDriver.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adrian Knoth
  • Date: 2011-03-31 13:54:50 UTC
  • mfrom: (1.1.3 upstream) (2.1.4 experimental)
  • Revision ID: james.westby@ubuntu.com-20110331135450-zafc1di024kzeu31
Tags: 1.9.7~dfsg-1
* New upstream version 1.9.7 (ALSA resume, new latency API)
* Build with --mixed on i386 to be compatible with amd64.
* Don't patch jack_connect for fast consecutive calls anymore, it's now
  using the same code as in jackd1 and waits for the port connection to
  appear.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
{
40
40
    UInt32 __4CC_number = (c);
41
41
    char __4CC_string[5];
42
 
    *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number);            
 
42
    *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number);
43
43
    __4CC_string[4] = 0;
44
44
    jack_log("%s'%s'", (msg), __4CC_string);
45
45
}
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("- - - - - - - - - - - - - - - - - - - -");
59
59
}
60
60
 
61
61
static void printError(OSStatus err)
194
194
    driver->fActionFags = ioActionFlags;
195
195
    driver->fCurrentTime = (AudioTimeStamp *)inTimeStamp;
196
196
    driver->fDriverOutputData = ioData;
197
 
    
 
197
 
198
198
    // Setup threadded based log function once...
199
199
    if (set_threaded_log_function()) {
200
 
        
 
200
 
201
201
        jack_log("set_threaded_log_function");
202
202
        JackMachThread::GetParams(pthread_self(), &driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint);
203
 
        
 
203
 
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;
207
207
        }
208
 
        
 
208
 
209
209
        // Signal waiting start function...
210
210
        driver->fState = true;
211
211
    }
212
 
    
 
212
 
213
213
    driver->CycleTakeBeginTime();
214
214
    return driver->Process();
215
215
}
216
216
 
217
217
int JackCoreAudioDriver::Read()
218
218
{
219
 
    AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData);
220
 
    return 0;
 
219
    OSStatus err = AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData);
 
220
    return (err == noErr) ? 0 : -1;
221
221
}
222
222
 
223
223
int JackCoreAudioDriver::Write()
224
224
{
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);
230
230
            // Monitor ports
231
231
            if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
232
232
                memcpy(GetMonitorBuffer(i), buffer, size);
233
233
        } else {
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);
235
235
        }
236
236
    }
237
237
    return 0;
238
238
}
239
239
 
240
 
 
241
240
OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
242
241
                                                    UInt32 inChannel,
243
242
                                                    Boolean     isInput,
276
275
                                                        void* inClientData)
277
276
{
278
277
    JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
279
 
         
 
278
 
280
279
    switch (inPropertyID) {
281
 
            
 
280
 
282
281
        case kAudioDevicePropertyDeviceIsRunning: {
283
282
            UInt32 isrunning = 0;
284
283
            UInt32 outsize = sizeof(UInt32);
287
286
            }
288
287
            break;
289
288
        }
290
 
        
 
289
 
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...
295
294
            break;
296
295
        }
297
 
        
 
296
 
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;
304
303
        }
305
 
        
 
304
 
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;
312
 
            
 
311
 
313
312
            char device_name[256];
314
313
            const char* digidesign_name = "Digidesign";
315
314
            driver->GetDeviceNameFromID(driver->fDeviceID, device_name);
316
 
        
 
315
 
317
316
            if (sampleRate != driver->fEngineControl->fSampleRate) {
318
 
               
 
317
 
319
318
               // Digidesign hardware, so "special" code : change the SR again here
320
319
               if (strncmp(device_name, digidesign_name, sizeof(digidesign_name)) == 0) {
321
 
                   
 
320
 
322
321
                    jack_log("Digidesign HW = %s", device_name);
323
 
                
 
322
 
324
323
                    // Set sample rate again...
325
324
                    sampleRate = driver->fEngineControl->fSampleRate;
326
325
                    err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sampleRate);
330
329
                    } else {
331
330
                        jack_log("Set sample rate = %f", sampleRate);
332
331
                    }
333
 
                    
 
332
 
334
333
                    // Check new sample rate again...
335
334
                    outsize = sizeof(Float64);
336
335
                    err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sampleRate);
341
340
                        jack_log("Checked sample rate = %f", sampleRate);
342
341
                    }
343
342
                    return noErr;
344
 
                    
 
343
 
345
344
                } else {
346
345
                    driver->NotifyFailure(JackBackendError, "Another application has changed the sample rate.");    // Message length limited to JACK_MESSAGE_SIZE
347
346
                    driver->CloseAUHAL();
350
349
                }
351
350
            }
352
351
        }
353
 
            
 
352
 
354
353
    }
355
354
    return noErr;
356
355
}
405
404
    if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
406
405
        return res;
407
406
 
 
407
    if (inDefault == 0) {
 
408
        jack_error("Error : input device is 0, please select a correct one !!");
 
409
        return -1;
 
410
    }
408
411
    jack_log("GetDefaultInputDevice: input = %ld ", inDefault);
409
412
    *id = inDefault;
410
413
    return noErr;
419
422
    if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
420
423
        return res;
421
424
 
 
425
    if (outDefault == 0) {
 
426
        jack_error("Error : output device is 0, please select a correct one !!");
 
427
        return -1;
 
428
    }
422
429
    jack_log("GetDefaultOutputDevice: output = %ld", outDefault);
423
430
    *id = outDefault;
424
431
    return noErr;
435
442
    OSStatus err = noErr;
436
443
    UInt32      outSize;
437
444
    Boolean     outWritable;
438
 
 
 
445
 
439
446
    channelCount = 0;
440
447
    err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
441
448
    if (err == noErr) {
450
457
}
451
458
 
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), 
456
 
        fPluginID(0), 
457
 
        fState(false), 
 
460
        : JackAudioDriver(name, alias, engine, table),
 
461
        fJackInputData(NULL),
 
462
        fDriverOutputData(NULL),
 
463
        fPluginID(0),
 
464
        fState(false),
458
465
        fHogged(false),
459
466
        fIOUsage(1.f),
460
467
        fComputationGrain(-1.f),
464
471
JackCoreAudioDriver::~JackCoreAudioDriver()
465
472
{}
466
473
 
467
 
OSStatus JackCoreAudioDriver::DestroyAggregateDevice() 
 
474
OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
468
475
{
469
476
    OSStatus osErr = noErr;
470
477
    AudioObjectPropertyAddress pluginAOPA;
472
479
    pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
473
480
    pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
474
481
    UInt32 outDataSize;
475
 
     
 
482
 
476
483
    if (fPluginID > 0)   {
477
 
      
 
484
 
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);
482
489
            return osErr;
483
490
        }
484
 
            
 
491
 
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);
489
496
            return osErr;
490
497
        }
491
 
        
 
498
 
492
499
    }
493
 
    
 
500
 
494
501
    return noErr;
495
502
}
496
 
    
497
 
OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) 
 
503
 
 
504
OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
498
505
{
499
506
    OSStatus err = noErr;
500
507
    AudioObjectID sub_device[32];
501
508
    UInt32 outSize = sizeof(sub_device);
502
 
    
 
509
 
503
510
    err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
504
511
    vector<AudioDeviceID> captureDeviceIDArray;
505
 
    
 
512
 
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]);
514
521
        }
515
522
    }
516
 
    
517
 
    err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);    
 
523
 
 
524
    err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
518
525
    vector<AudioDeviceID> playbackDeviceIDArray;
519
 
    
 
526
 
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]);
528
535
        }
529
536
    }
530
 
    
 
537
 
531
538
    return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
532
539
}
533
540
 
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)
535
542
{
536
543
    OSStatus osErr = noErr;
537
544
    UInt32 outSize;
538
545
    Boolean outWritable;
539
 
    
 
546
 
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;
548
 
     
 
555
 
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;
556
 
    
 
563
 
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");
560
567
        } else  {
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);
566
573
            } else {
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...");
573
580
            }
574
581
        }
575
582
    }
576
 
    
 
583
 
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");
580
587
        } else {
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);
586
593
            } else {
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...");
593
600
            }
594
601
        }
595
602
    }
596
 
    
 
603
 
597
604
    // If no valid clock domain was found, then assume we have to compensate...
598
605
    if (keptclockdomain == 0) {
599
606
        need_clock_drift_compensation = true;
602
609
    //---------------------------------------------------------------------------
603
610
    // Start to create a new aggregate by getting the base audio hardware plugin
604
611
    //---------------------------------------------------------------------------
605
 
    
 
612
 
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);
610
617
    }
611
 
    
 
618
 
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);
615
622
    }
616
 
   
 
623
 
617
624
    osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
618
625
    if (osErr != noErr) {
619
626
        jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
624
631
    AudioValueTranslation pluginAVT;
625
632
 
626
633
    CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
627
 
   
 
634
 
628
635
    pluginAVT.mInputData = &inBundleRef;
629
636
    pluginAVT.mInputDataSize = sizeof(inBundleRef);
630
637
    pluginAVT.mOutputData = &fPluginID;
645
652
 
646
653
    CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
647
654
    CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
648
 
    
 
655
 
649
656
    // add the name of the device to the dictionary
650
657
    CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
651
658
 
652
659
    // add our choice of UID for the aggregate device to the dictionary
653
660
    CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
654
 
    
 
661
 
655
662
    // add a "private aggregate key" to the dictionary
656
663
    int value = 1;
657
664
    CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
658
 
    
 
665
 
659
666
    SInt32 system;
660
667
    Gestalt(gestaltSystemVersion, &system);
661
 
     
 
668
 
662
669
    jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
663
 
    
 
670
 
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);
670
677
    }
671
 
    
 
678
 
672
679
    // Prepare sub-devices for clock drift compensation
673
680
    CFMutableArrayRef subDevicesArrayClock = NULL;
674
 
    
 
681
 
675
682
    /*
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);
680
 
            
 
687
 
681
688
            for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
682
689
                CFStringRef UID = GetDeviceName(captureDeviceID[i]);
683
690
                if (UID) {
688
695
                    CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict);
689
696
                }
690
697
            }
691
 
            
 
698
 
692
699
            for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
693
700
                CFStringRef UID = GetDeviceName(playbackDeviceID[i]);
694
701
                if (UID) {
699
706
                    CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict);
700
707
                }
701
708
            }
702
 
            
 
709
 
703
710
            // add sub-device clock array for the aggregate device to the dictionary
704
711
            CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceSubDeviceListKey), subDevicesArrayClock);
705
712
        } else {
707
714
        }
708
715
    }
709
716
    */
710
 
    
 
717
 
711
718
    //-------------------------------------------------
712
719
    // Create a CFMutableArray for our sub-device list
713
720
    //-------------------------------------------------
714
 
    
 
721
 
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);
717
 
    
 
724
 
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);
726
733
   }
727
 
    
 
734
 
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);
736
743
    }
737
 
  
 
744
 
738
745
    //-----------------------------------------------------------------------
739
746
    // Feed the dictionary to the plugin, to create a blank aggregate device
740
747
    //-----------------------------------------------------------------------
741
 
 
 
748
 
742
749
    AudioObjectPropertyAddress pluginAOPA;
743
750
    pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
744
751
    pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
751
758
        printError(osErr);
752
759
        goto error;
753
760
    }
754
 
    
 
761
 
755
762
    osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
756
763
    if (osErr != noErr) {
757
764
        jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error");
777
784
        printError(osErr);
778
785
        goto error;
779
786
    }
780
 
    
 
787
 
781
788
    // pause again to give the changes time to take effect
782
789
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
783
 
    
 
790
 
784
791
    //-----------------------
785
792
    // Set the master device
786
793
    //-----------------------
797
804
        printError(osErr);
798
805
        goto error;
799
806
    }
800
 
    
 
807
 
801
808
    // pause again to give the changes time to take effect
802
809
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
803
 
  
 
810
 
804
811
    // Prepare sub-devices for clock drift compensation
805
812
    // Workaround for bug in the HAL : until 10.6.2
806
 
    
 
813
 
807
814
    if (fClockDriftCompensate) {
808
815
        if (need_clock_drift_compensation) {
809
816
            jack_info("Clock drift compensation activated...");
810
 
       
 
817
 
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);
816
823
            }
817
 
            
 
824
 
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);
823
 
            
 
830
 
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);
828
835
            }
829
 
            
 
836
 
830
837
            // Set kAudioSubDevicePropertyDriftCompensation property...
831
838
            for (UInt32 index = 0; index < subDevicesNum; ++index) {
832
839
                UInt32 theDriftCompensationValue = 1;
839
846
        } else {
840
847
            jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
841
848
        }
842
 
    }    
843
 
    
 
849
    }
 
850
 
844
851
    // pause again to give the changes time to take effect
845
852
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
846
 
       
 
853
 
847
854
    //----------
848
855
    // Clean up
849
856
    //----------
850
 
    
 
857
 
851
858
    // release the private AD key
852
859
    CFRelease(AggregateDeviceNumberRef);
853
860
 
854
861
    // release the CF objects we have created - we don't need them any more
855
862
    CFRelease(aggDeviceDict);
856
863
    CFRelease(subDevicesArray);
857
 
    
 
864
 
858
865
    if (subDevicesArrayClock)
859
866
        CFRelease(subDevicesArrayClock);
860
867
 
862
869
    for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
863
870
        CFRelease(captureDeviceUID[i]);
864
871
    }
865
 
    
 
872
 
866
873
    for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
867
874
        CFRelease(playbackDeviceUID[i]);
868
875
    }
869
 
    
 
876
 
870
877
    jack_log("New aggregate device %ld", *outAggregateDevice);
871
878
    return noErr;
872
 
    
 
879
 
873
880
error:
874
881
    DestroyAggregateDevice();
875
882
    return -1;
876
883
}
877
884
 
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)
883
890
{
884
891
    capture_driver_name[0] = 0;
885
892
    playback_driver_name[0] = 0;
886
 
   
 
893
 
887
894
    // Duplex
888
895
    if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
889
896
        jack_log("JackCoreAudioDriver::Open duplex");
890
 
          
 
897
 
891
898
        // Same device for capture and playback...
892
899
        if (strcmp(capture_driver_uid, playback_driver_uid) == 0)  {
893
 
            
 
900
 
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");
903
910
                return -1;
904
911
            }
905
 
            
 
912
 
906
913
        } else {
907
 
        
 
914
 
908
915
            // Creates aggregate device
909
916
            AudioDeviceID captureID, playbackID;
910
 
            
 
917
 
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");
966
 
            
 
973
 
967
974
            // Creates aggregate device
968
975
            AudioDeviceID captureID, playbackID;
969
 
            
 
976
 
970
977
            if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
971
978
                jack_log("Will take default input");
972
979
                if (GetDefaultInputDevice(&captureID) != noErr) {
974
981
                    return -1;
975
982
                }
976
983
            }
977
 
            
 
984
 
978
985
            if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
979
986
                jack_log("Will take default output");
980
987
                if (GetDefaultOutputDevice(&playbackID) != noErr) {
982
989
                    return -1;
983
990
                }
984
991
            }
985
 
            
 
992
 
986
993
            if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
987
994
                return -1;
988
995
        }
989
996
    }
990
 
    
 
997
 
991
998
    if (fHogged) {
992
999
        if (TakeHog()) {
993
1000
            jack_info("Device = %ld has been hogged", fDeviceID);
1111
1118
            usleep(100000);
1112
1119
            jack_log("Wait count = %d", count);
1113
1120
        }
1114
 
        
 
1121
 
1115
1122
        // Check new sample rate
1116
1123
        outSize =  sizeof(Float64);
1117
1124
        err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
1150
1157
        jack_error("No input and output channels...");
1151
1158
        return -1;
1152
1159
    }
1153
 
         
 
1160
 
1154
1161
    // AUHAL
1155
1162
    ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
1156
1163
    Component HALOutput = FindNextComponent(NULL, &cd);
1177
1184
        enableIO = 0;
1178
1185
        jack_log("Setup AUHAL input off");
1179
1186
    }
1180
 
    
 
1187
 
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");
1192
1199
        enableIO = 0;
1193
1200
        jack_log("Setup AUHAL output off");
1194
1201
    }
1195
 
    
 
1202
 
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);
1200
1207
        goto error;
1201
1208
    }
1202
 
    
 
1209
 
1203
1210
    size = sizeof(AudioDeviceID);
1204
1211
    err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
1205
1212
    if (err1 != noErr) {
1217
1224
        printError(err1);
1218
1225
        goto error;
1219
1226
    }
1220
 
  
 
1227
 
1221
1228
    // Set buffer size
1222
1229
    if (capturing && inchannels > 0) {
1223
1230
        err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
1272
1279
 
1273
1280
    // Setup stream converters
1274
1281
    if (capturing && inchannels > 0) {
1275
 
    
 
1282
 
1276
1283
        size = sizeof(AudioStreamBasicDescription);
1277
1284
        err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &size);
1278
1285
        if (err1 != noErr) {
1281
1288
            goto error;
1282
1289
        }
1283
1290
        PrintStreamDesc(&srcFormat);
1284
 
              
 
1291
 
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);
1295
 
      
 
1302
 
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");
1302
1309
    }
1303
1310
 
1304
1311
    if (playing && outchannels > 0) {
1305
 
    
 
1312
 
1306
1313
        size = sizeof(AudioStreamBasicDescription);
1307
1314
        err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &size);
1308
1315
        if (err1 != noErr) {
1311
1318
            goto error;
1312
1319
        }
1313
1320
        PrintStreamDesc(&dstFormat);
1314
 
         
 
1321
 
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);
1325
 
       
 
1332
 
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");
1355
1362
    }
1356
1363
 
1357
1364
    return 0;
1358
 
    
 
1365
 
1359
1366
error:
1360
1367
    CloseAUHAL();
1361
1368
    return -1;
1368
1375
    fJackInputData->mNumberBuffers = inchannels;
1369
1376
    for (int i = 0; i < inchannels; i++) {
1370
1377
        fJackInputData->mBuffers[i].mNumberChannels = 1;
1371
 
        fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float);
 
1378
        fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t);
1372
1379
    }
1373
1380
    return 0;
1374
1381
}
1486
1493
    fComputationGrain = float(computation_grain) / 100.f;
1487
1494
    fHogged = hogged;
1488
1495
    fClockDriftCompensate = clock_drift;
1489
 
    
 
1496
 
1490
1497
    SInt32 major;
1491
1498
    SInt32 minor;
1492
1499
    Gestalt(gestaltSystemVersionMajor, &major);
1493
1500
    Gestalt(gestaltSystemVersionMinor, &minor);
1494
 
    
 
1501
 
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;
1515
1522
 
1516
1523
    if (SetupBufferSize(buffer_size) < 0)
1517
1524
        goto error;
1518
 
        
 
1525
 
1519
1526
    if (SetupSampleRate(samplerate) < 0)
1520
1527
        goto error;
1521
 
 
 
1528
 
1522
1529
    if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, samplerate) < 0)
1523
1530
        goto error;
1524
1531
 
1528
1535
 
1529
1536
    if (AddListeners() < 0)
1530
1537
        goto error;
1531
 
  
 
1538
 
1532
1539
    // Core driver may have changed the in/out values
1533
1540
    fCaptureChannels = inchannels;
1534
1541
    fPlaybackChannels = outchannels;
1543
1550
{
1544
1551
    jack_log("JackCoreAudioDriver::Close");
1545
1552
    Stop();
1546
 
    JackAudioDriver::Close();
 
1553
 
 
1554
    // Generic audio driver close
 
1555
    int res = JackAudioDriver::Close();
 
1556
 
1547
1557
    RemoveListeners();
1548
1558
    DisposeBuffers();
1549
1559
    CloseAUHAL();
1550
1560
    DestroyAggregateDevice();
1551
 
    return 0;
 
1561
    return res;
1552
1562
}
1553
1563
 
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];
1564
 
 
 
1574
    jack_latency_range_t range;
 
1575
 
1565
1576
    jack_log("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
1566
1577
 
1567
1578
    for (int i = 0; i < fCaptureChannels; i++) {
1568
1579
 
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);
1577
1588
        } else {
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");
1597
1608
 
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;
1602
1614
    }
1603
1615
 
1605
1617
 
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);
1614
1626
        } else {
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");
1634
1646
 
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;
1640
1653
 
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);
1647
1660
                return -1;
1648
1661
            } else {
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;
1653
1666
            }
1654
1667
        }
1665
1678
int JackCoreAudioDriver::Start()
1666
1679
{
1667
1680
    jack_log("JackCoreAudioDriver::Start");
1668
 
    JackAudioDriver::Start();
1669
 
 
1670
 
    OSStatus err = AudioOutputUnitStart(fAUHAL);
1671
 
    if (err != noErr)
1672
 
        return -1;
1673
 
    
1674
 
    // Waiting for Measure callback to be called (= driver has started)
1675
 
    fState = false;
1676
 
    int count = 0;
1677
 
    while (!fState && count++ < WAIT_COUNTER) {
1678
 
        usleep(100000);
1679
 
        jack_log("JackCoreAudioDriver::Start wait count = %d", count);
1680
 
    }
1681
 
    
1682
 
    if (count < WAIT_COUNTER) {
1683
 
        jack_info("CoreAudio driver is running...");
1684
 
        return 0;
1685
 
    } else {
1686
 
        jack_error("CoreAudio driver cannot start...");
1687
 
        return -1;
1688
 
    }
 
1681
    if (JackAudioDriver::Start() >= 0) {
 
1682
        OSStatus err = AudioOutputUnitStart(fAUHAL);
 
1683
        if (err == noErr) {
 
1684
 
 
1685
            // Waiting for Measure callback to be called (= driver has started)
 
1686
            fState = false;
 
1687
            int count = 0;
 
1688
            while (!fState && count++ < WAIT_COUNTER) {
 
1689
                usleep(100000);
 
1690
                jack_log("JackCoreAudioDriver::Start wait count = %d", count);
 
1691
            }
 
1692
 
 
1693
            if (count < WAIT_COUNTER) {
 
1694
                jack_info("CoreAudio driver is running...");
 
1695
                return 0;
 
1696
            }
 
1697
 
 
1698
            jack_error("CoreAudio driver cannot start...");
 
1699
        }
 
1700
        JackAudioDriver::Stop();
 
1701
    }
 
1702
    return -1;
1689
1703
}
1690
1704
 
1691
1705
int JackCoreAudioDriver::Stop()
1692
1706
{
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) {
 
1710
        res = -1;
 
1711
    }
 
1712
    return res;
1695
1713
}
1696
1714
 
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);
1716
1734
    }
1717
1735
 
1738
1756
            return false;
1739
1757
        }
1740
1758
    }
1741
 
    
 
1759
 
1742
1760
    return true;
1743
1761
}
1744
 
    
 
1762
 
1745
1763
bool JackCoreAudioDriver::TakeHog()
1746
1764
{
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);
1751
 
    
 
1769
 
1752
1770
    if (err != noErr) {
1753
1771
        jack_log("Device does not have subdevices");
1754
1772
        return TakeHogAux(fDeviceID, true);
1763
1781
        return true;
1764
1782
    }
1765
1783
}
1766
 
    
 
1784
 
1767
1785
bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
1768
1786
{
1769
1787
    UInt32 deviceType, outSize = sizeof(UInt32);
1770
1788
    OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
1771
 
    
 
1789
 
1772
1790
    if (err != noErr) {
1773
1791
        jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
1774
1792
        return false;
1786
1804
{
1787
1805
#endif
1788
1806
 
1789
 
    SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() 
 
1807
    SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
1790
1808
    {
1791
1809
        jack_driver_desc_t *desc;
1792
1810
        unsigned int i;
1794
1812
 
1795
1813
        strcpy(desc->name, "coreaudio");                                    // size MUST be less then JACK_DRIVER_NAME_MAX + 1
1796
1814
        strcpy(desc->desc, "Apple CoreAudio API based audio backend");      // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
1797
 
        
 
1815
 
1798
1816
        desc->nparams = 17;
1799
1817
        desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
1800
1818
 
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);
1901
 
        
 
1919
 
1902
1920
        i++;
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);
1909
 
        
 
1927
 
1910
1928
        i++;
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);
1917
 
        
 
1935
 
1918
1936
        i++;
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);
1925
 
        
 
1943
 
1926
1944
        i++;
1927
1945
        strcpy(desc->params[i].name, "clock-drift");
1928
1946
        desc->params[i].character = 's';
1934
1952
        return desc;
1935
1953
    }
1936
1954
 
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)
1938
1956
    {
1939
1957
        jack_nframes_t srate = 44100;
1940
1958
        jack_nframes_t frames_per_interrupt = 128;
1953
1971
        int computation_grain = -1;
1954
1972
        bool hogged = false;
1955
1973
        bool clock_drift = false;
1956
 
    
 
1974
 
1957
1975
        for (node = params; node; node = jack_slist_next(node)) {
1958
1976
            param = (const jack_driver_param_t *) node->data;
1959
 
       
 
1977
 
1960
1978
            switch (param->character) {
1961
1979
 
1962
1980
                case 'd':
2018
2036
                case 'l':
2019
2037
                    Jack::DisplayDeviceNames();
2020
2038
                    break;
2021
 
                    
 
2039
 
2022
2040
                case 'H':
2023
2041
                    hogged = true;
2024
2042
                    break;
2025
 
                    
 
2043
 
2026
2044
                case 'L':
2027
2045
                    async_output_latency = param->value.ui;
2028
2046
                    break;
2029
 
                    
 
2047
 
2030
2048
                case 'G':
2031
2049
                    computation_grain = param->value.ui;
2032
2050
                    break;
2033
 
                    
 
2051
 
2034
2052
                case 's':
2035
2053
                    clock_drift = true;
2036
2054
                    break;
2044
2062
        }
2045
2063
 
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) {
2049
2067
            return driver;
2050
2068
        } else {