JackCoreAudioDriver.cpp

00001 /*
00002 Copyright (C) 2004-2008 Grame
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 
00018 */
00019 
00020 #include "JackCoreAudioDriver.h"
00021 #include "JackEngineControl.h"
00022 #include "JackMachThread.h"
00023 #include "JackGraphManager.h"
00024 #include "JackError.h"
00025 #include "JackClientControl.h"
00026 #include "JackDriverLoader.h"
00027 #include "JackGlobals.h"
00028 #include "driver_interface.h"
00029 #include <iostream>
00030 
00031 namespace Jack
00032 {
00033 
00034 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
00035 {
00036     JackLog("- - - - - - - - - - - - - - - - - - - -\n");
00037     JackLog("  Sample Rate:%f\n", inDesc->mSampleRate);
00038     JackLog("  Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID);
00039     JackLog("  Format Flags:%lX\n", inDesc->mFormatFlags);
00040     JackLog("  Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
00041     JackLog("  Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
00042     JackLog("  Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
00043     JackLog("  Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
00044     JackLog("  Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
00045     JackLog("- - - - - - - - - - - - - - - - - - - -\n");
00046 }
00047 
00048 static void printError(OSStatus err)
00049 {
00050     switch (err) {
00051         case kAudioHardwareNoError:
00052             JackLog("error code : kAudioHardwareNoError\n");
00053             break;
00054         case kAudioConverterErr_FormatNotSupported:
00055             JackLog("error code : kAudioConverterErr_FormatNotSupported\n");
00056             break;
00057         case kAudioConverterErr_OperationNotSupported:
00058             JackLog("error code : kAudioConverterErr_OperationNotSupported\n");
00059             break;
00060         case kAudioConverterErr_PropertyNotSupported:
00061             JackLog("error code : kAudioConverterErr_PropertyNotSupported\n");
00062             break;
00063         case kAudioConverterErr_InvalidInputSize:
00064             JackLog("error code : kAudioConverterErr_InvalidInputSize\n");
00065             break;
00066         case kAudioConverterErr_InvalidOutputSize:
00067             JackLog("error code : kAudioConverterErr_InvalidOutputSize\n");
00068             break;
00069         case kAudioConverterErr_UnspecifiedError:
00070             JackLog("error code : kAudioConverterErr_UnspecifiedError\n");
00071             break;
00072         case kAudioConverterErr_BadPropertySizeError:
00073             JackLog("error code : kAudioConverterErr_BadPropertySizeError\n");
00074             break;
00075         case kAudioConverterErr_RequiresPacketDescriptionsError:
00076             JackLog("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n");
00077             break;
00078         case kAudioConverterErr_InputSampleRateOutOfRange:
00079             JackLog("error code : kAudioConverterErr_InputSampleRateOutOfRange\n");
00080             break;
00081         case kAudioConverterErr_OutputSampleRateOutOfRange:
00082             JackLog("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n");
00083             break;
00084         case kAudioHardwareNotRunningError:
00085             JackLog("error code : kAudioHardwareNotRunningError\n");
00086             break;
00087         case kAudioHardwareUnknownPropertyError:
00088             JackLog("error code : kAudioHardwareUnknownPropertyError\n");
00089             break;
00090         case kAudioHardwareIllegalOperationError:
00091             JackLog("error code : kAudioHardwareIllegalOperationError\n");
00092             break;
00093         case kAudioHardwareBadDeviceError:
00094             JackLog("error code : kAudioHardwareBadDeviceError\n");
00095             break;
00096         case kAudioHardwareBadStreamError:
00097             JackLog("error code : kAudioHardwareBadStreamError\n");
00098             break;
00099         case kAudioDeviceUnsupportedFormatError:
00100             JackLog("error code : kAudioDeviceUnsupportedFormatError\n");
00101             break;
00102         case kAudioDevicePermissionsError:
00103             JackLog("error code : kAudioDevicePermissionsError\n");
00104             break;
00105                 case kAudioHardwareBadObjectError:
00106             JackLog("error code : kAudioHardwareBadObjectError\n");
00107             break;
00108                         case kAudioHardwareUnsupportedOperationError:
00109             JackLog("error code : kAudioHardwareUnsupportedOperationError\n");
00110             break;
00111         default:
00112             JackLog("error code : unknown\n");
00113             break;
00114     }
00115 }
00116 
00117 static OSStatus DisplayDeviceNames()
00118 {
00119     UInt32 size;
00120     Boolean isWritable;
00121     int i, deviceNum;
00122     OSStatus err;
00123     CFStringRef UIname;
00124 
00125     err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00126     if (err != noErr)
00127         return err;
00128 
00129     deviceNum = size / sizeof(AudioDeviceID);
00130     AudioDeviceID devices[deviceNum];
00131 
00132     err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00133     if (err != noErr)
00134         return err;
00135 
00136     for (i = 0; i < deviceNum; i++) {
00137         char device_name[256];
00138         char internal_name[256];
00139 
00140         size = sizeof(CFStringRef);
00141         UIname = NULL;
00142         err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
00143         if (err == noErr) {
00144             CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
00145         } else {
00146             goto error;
00147         }
00148 
00149         size = 256;
00150         err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
00151         if (err != noErr)
00152             return err;
00153 
00154         printf("Device name = \'%s\', internal_name = \'%s\' (to be used as -C, -P, or -d parameter)\n", device_name, internal_name);
00155     }
00156 
00157     return noErr;
00158 
00159 error:
00160     if (UIname != NULL)
00161         CFRelease(UIname);
00162     return err;
00163 }
00164 
00165 OSStatus JackCoreAudioDriver::Render(void *inRefCon,
00166                                      AudioUnitRenderActionFlags *ioActionFlags,
00167                                      const AudioTimeStamp *inTimeStamp,
00168                                      UInt32 inBusNumber,
00169                                      UInt32 inNumberFrames,
00170                                      AudioBufferList *ioData)
00171 {
00172         JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon;
00173     driver->fLastWaitUst = GetMicroSeconds(); // Take callback date here
00174         driver->fActionFags = ioActionFlags;
00175         driver->fCurrentTime = (AudioTimeStamp *)inTimeStamp;
00176         driver->fDriverOutputData = ioData;
00177     return driver->Process();
00178 }
00179 
00180 int JackCoreAudioDriver::Read()
00181 {
00182         AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData);
00183     return 0;
00184 }
00185 
00186 int JackCoreAudioDriver::Write()
00187 {
00188     for (int i = 0; i < fPlaybackChannels; i++) {
00189         if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
00190             float* buffer = GetOutputBuffer(i);
00191             int size = sizeof(float) * fEngineControl->fBufferSize;
00192             memcpy((float*)fDriverOutputData->mBuffers[i].mData, buffer, size);
00193             // Monitor ports
00194             if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
00195                 memcpy(GetMonitorBuffer(i), buffer, size);
00196         } else {
00197             memset((float*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(float) * fEngineControl->fBufferSize);
00198         }
00199     }
00200     return 0;
00201 }
00202 
00203 // Will run only once
00204 OSStatus JackCoreAudioDriver::MeasureCallback(AudioDeviceID inDevice,
00205         const AudioTimeStamp* inNow,
00206         const AudioBufferList* inInputData,
00207         const AudioTimeStamp* inInputTime,
00208         AudioBufferList* outOutputData,
00209         const AudioTimeStamp* inOutputTime,
00210         void* inClientData)
00211 {
00212     JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00213     AudioDeviceStop(driver->fDeviceID, MeasureCallback);
00214     AudioDeviceRemoveIOProc(driver->fDeviceID, MeasureCallback);
00215     JackLog("JackCoreAudioDriver::MeasureCallback called\n");
00216     JackMachThread::GetParams(&driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint);
00217     return noErr;
00218 }
00219 
00220 OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
00221         UInt32 inChannel,
00222         Boolean isInput,
00223         AudioDevicePropertyID inPropertyID,
00224         void* inClientData)
00225 {
00226         JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00227         
00228         switch (inPropertyID) {
00229 
00230                 case kAudioDevicePropertyNominalSampleRate: {
00231                         JackLog("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate \n");
00232                         driver->fState = true;
00233                         break;
00234                 }
00235         }
00236         
00237         return noErr;
00238 }
00239 
00240 // A better implementation would try to recover in case of hardware device change (see HALLAB HLFilePlayerWindowControllerAudioDevicePropertyListenerProc code)
00241 
00242 OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
00243         UInt32 inChannel,
00244         Boolean isInput,
00245         AudioDevicePropertyID inPropertyID,
00246         void* inClientData)
00247 {
00248     JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00249         
00250         switch (inPropertyID) {
00251         
00252                 case kAudioDeviceProcessorOverload:
00253                         JackLog("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload\n");
00254                 #ifdef DEBUG
00255                         //driver->fLogFile->Capture(AudioGetCurrentHostTime() - AudioConvertNanosToHostTime(LOG_SAMPLE_DURATION * 1000000), AudioGetCurrentHostTime(), true, "Captured Latency Log for I/O Cycle Overload\n");
00256                 #endif
00257                         driver->NotifyXRun(GetMicroSeconds());
00258                         break;
00259                         
00260                 case kAudioDevicePropertyStreamConfiguration:
00261                 case kAudioDevicePropertyNominalSampleRate: {
00262                 
00263                         UInt32 outSize = sizeof(Float64);
00264                         Float64 sampleRate;
00265                         int in_nChannels = 0;
00266                         int out_nChannels = 0;
00267                         char capture_driver_name[256];
00268                         char playback_driver_name[256];
00269                         
00270                         // Stop and restart
00271                         driver->Stop();
00272                         driver->RemoveListeners();
00273                         driver->CloseAUHAL();
00274                         
00275                         OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
00276                         if (err != noErr) {
00277                                 jack_error("Cannot get current sample rate");
00278                                 printError(err);
00279                         }
00280                         JackLog("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyNominalSampleRate %ld\n", long(sampleRate));
00281                         
00282                         if (driver->SetupDevices(driver->fCaptureUID, driver->fPlaybackUID, capture_driver_name, playback_driver_name) < 0)
00283                                 return -1;
00284                 
00285                         if (driver->SetupChannels(driver->fCapturing, driver->fPlaying, driver->fInChannels, driver->fOutChannels, in_nChannels, out_nChannels, false) < 0)
00286                                 return -1;
00287                                  
00288                         if (driver->SetupBufferSizeAndSampleRate(driver->fEngineControl->fBufferSize, sampleRate)  < 0)
00289                                 return -1;      
00290 
00291                         if (driver->OpenAUHAL(driver->fCapturing, 
00292                                                                         driver->fPlaying, 
00293                                                                         driver->fInChannels, 
00294                                                                         driver->fOutChannels, 
00295                                                                         in_nChannels, 
00296                                                                         out_nChannels, 
00297                                                                         driver->fEngineControl->fBufferSize, 
00298                                                                         sampleRate,
00299                                                                         false) < 0)
00300                                 goto error;
00301 
00302                         if (driver->AddListeners() < 0)
00303                                 goto error;
00304               
00305                     driver->Start();
00306                         
00307                         // Send notification to be used in JackPilot or JackRouter plugin 
00308                         jack_error("Device restart...");
00309                         CFStringRef ref = CFStringCreateWithCString(NULL, driver->fEngineControl->fServerName, kCFStringEncodingMacRoman);
00310                         CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(),
00311                                                                                                                         CFSTR("com.grame.jackserver.restart"),
00312                                                                                                                         ref,
00313                                                                                                                         NULL,
00314                                                                                                                         kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions);
00315                         CFRelease(ref);
00316                         return noErr;
00317                 error:
00318                         driver->CloseAUHAL();
00319                         break;
00320                 }
00321         }
00322     return noErr;
00323 }
00324 
00325 OSStatus JackCoreAudioDriver::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
00326 {
00327     UInt32 size = sizeof(AudioValueTranslation);
00328     CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
00329     AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
00330 
00331     if (inIUD == NULL) {
00332         return kAudioHardwareUnspecifiedError;
00333     } else {
00334         OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
00335         CFRelease(inIUD);
00336         JackLog("get_device_id_from_uid %s %ld \n", UID, *id);
00337         return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
00338     }
00339 }
00340 
00341 OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id)
00342 {
00343     OSStatus res;
00344     UInt32 theSize = sizeof(UInt32);
00345     AudioDeviceID inDefault;
00346     AudioDeviceID outDefault;
00347 
00348     if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
00349         return res;
00350 
00351     if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
00352         return res;
00353 
00354     JackLog("GetDefaultDevice: input = %ld output = %ld\n", inDefault, outDefault);
00355 
00356     // Get the device only if default input and ouput are the same
00357     if (inDefault == outDefault) {
00358         *id = inDefault;
00359         return noErr;
00360     } else {
00361         jack_error("Default input and output devices are not the same !!");
00362         return kAudioHardwareBadDeviceError;
00363     }
00364 }
00365 
00366 OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id)
00367 {
00368     OSStatus res;
00369     UInt32 theSize = sizeof(UInt32);
00370     AudioDeviceID inDefault;
00371 
00372     if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
00373         return res;
00374 
00375     JackLog("GetDefaultInputDevice: input = %ld \n", inDefault);
00376     *id = inDefault;
00377     return noErr;
00378 }
00379 
00380 OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id)
00381 {
00382     OSStatus res;
00383     UInt32 theSize = sizeof(UInt32);
00384     AudioDeviceID outDefault;
00385 
00386     if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
00387         return res;
00388 
00389     JackLog("GetDefaultOutputDevice: output = %ld\n", outDefault);
00390     *id = outDefault;
00391     return noErr;
00392 }
00393 
00394 OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID id, char* name)
00395 {
00396     UInt32 size = 256;
00397     return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
00398 }
00399 
00400 OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int* channelCount, bool isInput)
00401 {
00402     OSStatus err = noErr;
00403     UInt32      outSize;
00404     Boolean     outWritable;
00405     AudioBufferList* bufferList = 0;
00406         
00407     *channelCount = 0;
00408     err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
00409     if (err == noErr) {
00410         bufferList = (AudioBufferList*)malloc(outSize);
00411         err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
00412         if (err == noErr) {
00413             for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
00414                 *channelCount += bufferList->mBuffers[i].mNumberChannels;
00415         }
00416                 
00417                 if (bufferList)
00418                         free(bufferList);
00419     }
00420 
00421     return err;
00422 }
00423 
00424 JackCoreAudioDriver::JackCoreAudioDriver(const char* name, JackEngine* engine, JackSynchro** table)
00425         : JackAudioDriver(name, engine, table), fJackInputData(NULL), fDriverOutputData(NULL), fState(false)
00426 {
00427 #ifdef DEBUG
00428     //fLogFile = new CALatencyLog("jackmp_latency", ".txt");
00429 #endif
00430 }
00431 
00432 JackCoreAudioDriver::~JackCoreAudioDriver()
00433 {
00434 #ifdef DEBUG
00435     //delete fLogFile;
00436 #endif
00437 }
00438 
00439 int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char* playback_driver_uid, char* capture_driver_name, char* playback_driver_name)
00440 {
00441         capture_driver_name[0] = 0;
00442     playback_driver_name[0] = 0;
00443         
00444         // Duplex
00445     if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
00446         JackLog("JackCoreAudioDriver::Open duplex \n");
00447         if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00448             if (GetDefaultDevice(&fDeviceID) != noErr) {
00449                 jack_error("Cannot open default device");
00450                 return -1;
00451             }
00452         }
00453         if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00454             jack_error("Cannot get device name from device ID");
00455             return -1;
00456         }
00457 
00458         // Capture only
00459     } else if (strcmp(capture_driver_uid, "") != 0) {
00460         JackLog("JackCoreAudioDriver::Open capture only \n");
00461         if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
00462             if (GetDefaultInputDevice(&fDeviceID) != noErr) {
00463                 jack_error("Cannot open default device");
00464                 return -1;
00465             }
00466         }
00467         if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
00468             jack_error("Cannot get device name from device ID");
00469             return -1;
00470         }
00471 
00472         // Playback only
00473     } else if (strcmp(playback_driver_uid, "") != 0) {
00474         JackLog("JackCoreAudioDriver::Open playback only \n");
00475         if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00476             if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
00477                 jack_error("Cannot open default device");
00478                 return -1;
00479             }
00480         }
00481         if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00482             jack_error("Cannot get device name from device ID");
00483             return -1;
00484         }
00485 
00486         // Use default driver in duplex mode
00487     } else {
00488         JackLog("JackCoreAudioDriver::Open default driver \n");
00489         if (GetDefaultDevice(&fDeviceID) != noErr) {
00490             jack_error("Cannot open default device");
00491             return -1;
00492         }
00493         if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00494             jack_error("Cannot get device name from device ID");
00495             return -1;
00496         }
00497     }
00498         
00499         return 0;
00500 }
00501 
00502 int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchannels, int& outchannels, int& in_nChannels, int& out_nChannels, bool strict)
00503 {
00504         OSStatus err = noErr;
00505         
00506         if (capturing) {
00507         err = GetTotalChannels(fDeviceID, &in_nChannels, true);
00508         if (err != noErr) {
00509             jack_error("Cannot get input channel number");
00510             printError(err);
00511             return -1;
00512         }
00513     }
00514 
00515     if (playing) {
00516         err = GetTotalChannels(fDeviceID, &out_nChannels, false);
00517         if (err != noErr) {
00518             jack_error("Cannot get output channel number");
00519             printError(err);
00520             return -1;
00521         }
00522     }
00523 
00524     if (inchannels > in_nChannels) {
00525         jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels);
00526                 if (strict)
00527                         return -1;
00528         }
00529 
00530     if (outchannels > out_nChannels) {
00531         jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels);
00532         if (strict)
00533                         return -1;
00534     }
00535 
00536     if (inchannels == 0) {
00537         JackLog("Setup max in channels = %ld\n", in_nChannels);
00538         inchannels = in_nChannels;
00539     }
00540 
00541     if (outchannels == 0) {
00542         JackLog("Setup max out channels = %ld\n", out_nChannels);
00543         outchannels = out_nChannels;
00544     }
00545         
00546         return 0;
00547 }
00548 
00549 int JackCoreAudioDriver::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate)
00550 {
00551         OSStatus err = noErr;
00552     UInt32 outSize;
00553         Float64 sampleRate;
00554         
00555         // Setting buffer size
00556     outSize = sizeof(UInt32);
00557         err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes);
00558     if (err != noErr) {
00559         jack_error("Cannot set buffer size %ld", nframes);
00560         printError(err);
00561         return -1;
00562     }
00563 
00564     // Get sample rate
00565         outSize =  sizeof(Float64);
00566         err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
00567         if (err != noErr) {
00568                 jack_error("Cannot get current sample rate");
00569                 printError(err);
00570                 return -1;
00571         }
00572 
00573         // If needed, set new sample rate
00574         if (samplerate != (jack_nframes_t)sampleRate) {
00575                 sampleRate = (Float64)samplerate;
00576                 
00577                 // To get SR change notification
00578                 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
00579                 if (err != noErr) {
00580                         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
00581                         printError(err);
00582                         return -1;
00583                 }
00584                 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
00585                 if (err != noErr) {
00586                         jack_error("Cannot set sample rate = %ld", samplerate);
00587                         printError(err);
00588                         return -1;
00589                 }
00590                 
00591                 // Waiting for SR change notification
00592                 int count = 0;
00593                 while (!fState && count++ < 100) {
00594                         usleep(100000);
00595                         JackLog("Wait count = %ld\n", count);
00596                 }
00597                 
00598                 // Remove SR change notification
00599                 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
00600         }
00601         
00602         return 0;
00603 }
00604 
00605 int JackCoreAudioDriver::OpenAUHAL(bool capturing, 
00606                                                                 bool playing, 
00607                                                                 int inchannels, 
00608                                                                 int outchannels, 
00609                                                                 int in_nChannels, 
00610                                                                 int out_nChannels, 
00611                                                                 jack_nframes_t nframes,
00612                                                                 jack_nframes_t samplerate,
00613                                                                 bool strict)
00614 {
00615         ComponentResult err1;
00616     UInt32 enableIO;
00617     AudioStreamBasicDescription srcFormat, dstFormat;
00618         
00619         JackLog("OpenAUHAL capturing = %ld playing = %ld playing = %ld outchannels = %ld in_nChannels = %ld out_nChannels = %ld \n", capturing, playing, inchannels, inchannels, in_nChannels, out_nChannels);
00620         
00621          // AUHAL
00622     ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
00623     Component HALOutput = FindNextComponent(NULL, &cd);
00624 
00625     err1 = OpenAComponent(HALOutput, &fAUHAL);
00626     if (err1 != noErr) {
00627         jack_error("Error calling OpenAComponent");
00628         printError(err1);
00629         return -1;
00630     }
00631 
00632     err1 = AudioUnitInitialize(fAUHAL);
00633     if (err1 != noErr) {
00634         jack_error("Cannot initialize AUHAL unit");
00635         printError(err1);
00636         return -1;
00637     }
00638 
00639     // Start I/O
00640     enableIO = 1;
00641     if (capturing && inchannels > 0) {
00642         JackLog("Setup AUHAL input\n");
00643         err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
00644         if (err1 != noErr) {
00645             jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
00646             printError(err1);
00647             if (strict)
00648                                 return -1;
00649         }
00650     }
00651 
00652     if (playing && outchannels > 0) {
00653         JackLog("Setup AUHAL output\n");
00654         err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
00655         if (err1 != noErr) {
00656             jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
00657             printError(err1);
00658             if (strict)
00659                                 return -1;
00660         }
00661     }
00662 
00663     // Setup up choosen device, in both input and output cases
00664     err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
00665     if (err1 != noErr) {
00666         jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
00667         printError(err1);
00668         if (strict)
00669                         return -1;
00670     }
00671 
00672     // Set buffer size
00673     if (capturing && inchannels > 0) {
00674         err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&nframes, sizeof(UInt32));
00675         if (err1 != noErr) {
00676             jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00677             printError(err1);
00678             if (strict)
00679                                 return -1;
00680         }
00681     }
00682 
00683     if (playing && outchannels > 0) {
00684         err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&nframes, sizeof(UInt32));
00685         if (err1 != noErr) {
00686             jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00687             printError(err1);
00688                         if (strict)
00689                                 return -1;
00690         }
00691     }
00692 
00693     // Setup channel map
00694     if (capturing && inchannels > 0 && inchannels < in_nChannels) {
00695         SInt32 chanArr[in_nChannels];
00696         for (int i = 0; i < in_nChannels; i++) {
00697             chanArr[i] = -1;
00698         }
00699         for (int i = 0; i < inchannels; i++) {
00700             chanArr[i] = i;
00701         }
00702         AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
00703         if (err1 != noErr) {
00704             jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
00705             printError(err1);
00706         }
00707     }
00708 
00709     if (playing && outchannels > 0 && outchannels < out_nChannels) {
00710         SInt32 chanArr[out_nChannels];
00711         for (int i = 0; i < out_nChannels; i++) {
00712             chanArr[i] = -1;
00713         }
00714         for (int i = 0; i < outchannels; i++) {
00715             chanArr[i] = i;
00716         }
00717         err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
00718         if (err1 != noErr) {
00719             jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
00720             printError(err1);
00721         }
00722     }
00723 
00724     // Setup stream converters
00725         JackLog("Setup AUHAL input stream converter SR = %ld\n", samplerate);
00726         srcFormat.mSampleRate = samplerate;
00727         srcFormat.mFormatID = kAudioFormatLinearPCM;
00728         srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00729         srcFormat.mBytesPerPacket = sizeof(float);
00730         srcFormat.mFramesPerPacket = 1;
00731         srcFormat.mBytesPerFrame = sizeof(float);
00732         srcFormat.mChannelsPerFrame = outchannels;
00733         srcFormat.mBitsPerChannel = 32;
00734         
00735         err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
00736         if (err1 != noErr) {
00737                 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
00738                 printError(err1);
00739         }
00740 
00741         JackLog("Setup AUHAL output stream converter SR = %ld\n", samplerate);
00742         dstFormat.mSampleRate = samplerate;
00743         dstFormat.mFormatID = kAudioFormatLinearPCM;
00744         dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00745         dstFormat.mBytesPerPacket = sizeof(float);
00746         dstFormat.mFramesPerPacket = 1;
00747         dstFormat.mBytesPerFrame = sizeof(float);
00748         dstFormat.mChannelsPerFrame = inchannels;
00749         dstFormat.mBitsPerChannel = 32;
00750 
00751         err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
00752         if (err1 != noErr) {
00753                 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
00754                 printError(err1);
00755         }
00756         
00757     // Setup callbacks
00758     if (inchannels > 0 && outchannels == 0) {
00759         AURenderCallbackStruct output;
00760         output.inputProc = Render;
00761         output.inputProcRefCon = this;
00762         err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
00763         if (err1 != noErr) {
00764             jack_error("Error calling  AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
00765             printError(err1);
00766             return -1;
00767         }
00768     } else {
00769         AURenderCallbackStruct output;
00770         output.inputProc = Render;
00771         output.inputProcRefCon = this;
00772         err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
00773         if (err1 != noErr) {
00774             jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
00775             printError(err1);
00776             return -1;
00777         }
00778     }
00779 
00780         return 0;
00781 }
00782 
00783 int JackCoreAudioDriver::SetupBuffers(int inchannels, int outchannels)
00784 {
00785         // Prepare buffers
00786         fJackInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
00787         if (fJackInputData == 0) {
00788                 jack_error("Cannot allocate memory for input buffers");
00789                 return -1;
00790         }
00791         fJackInputData->mNumberBuffers = inchannels;
00792         for (int i = 0; i < fCaptureChannels; i++) {
00793                 fJackInputData->mBuffers[i].mNumberChannels = 1;
00794                 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float);
00795         }
00796         return 0;
00797 }
00798 
00799 void JackCoreAudioDriver::DisposeBuffers()
00800 {
00801         if (fJackInputData) {
00802                 free(fJackInputData);
00803                 fJackInputData = 0;
00804         }
00805 }
00806 
00807 void JackCoreAudioDriver::CloseAUHAL()
00808 {
00809     AudioUnitUninitialize(fAUHAL);
00810     CloseComponent(fAUHAL);
00811 }
00812 
00813 int JackCoreAudioDriver::AddListeners()
00814 {
00815         OSStatus err = noErr;
00816          
00817         // Add listeners
00818     err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this);
00819     if (err != noErr) {
00820         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
00821         printError(err);
00822         return -1;
00823     }
00824 
00825     err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
00826     if (err != noErr) {
00827         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
00828         printError(err);
00829         return -1;
00830     }
00831         
00832         err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this);
00833     if (err != noErr) {
00834         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
00835         printError(err);
00836         return -1;
00837     }
00838         
00839         err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this);
00840     if (err != noErr) {
00841         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
00842         printError(err);
00843         return -1;
00844     }
00845         
00846         err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
00847     if (err != noErr) {
00848         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
00849         printError(err);
00850         return -1;
00851     }
00852 
00853         err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
00854     if (err != noErr) {
00855         jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
00856         printError(err);
00857         return -1;
00858     }
00859 
00860         return 0;
00861 }
00862 
00863 void JackCoreAudioDriver::RemoveListeners()
00864 {
00865         AudioDeviceRemoveIOProc(fDeviceID, MeasureCallback);
00866     AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
00867         AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback);
00868         AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
00869         AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
00870         AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
00871         AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
00872 }
00873 
00874 int JackCoreAudioDriver::Open(jack_nframes_t nframes,
00875                               jack_nframes_t samplerate,
00876                               bool capturing,
00877                               bool playing,
00878                               int inchannels,
00879                               int outchannels,
00880                               bool monitor,
00881                               const char* capture_driver_uid,
00882                               const char* playback_driver_uid,
00883                               jack_nframes_t capture_latency,
00884                               jack_nframes_t playback_latency)
00885 {
00886         int in_nChannels = 0;
00887     int out_nChannels = 0;
00888     char capture_driver_name[256];
00889     char playback_driver_name[256];
00890         
00891         // Keep initial state
00892         fCapturing = capturing;
00893         fPlaying = playing;
00894         fInChannels = inchannels;
00895         fOutChannels = outchannels;
00896         fMonitor = monitor;
00897         strcpy(fCaptureUID, capture_driver_uid);
00898         strcpy(fPlaybackUID, playback_driver_uid);
00899         fCaptureLatency = capture_latency;
00900         fPlaybackLatency = playback_latency;
00901         
00902         if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name) < 0)
00903                 return -1;
00904                 
00905     // Generic JackAudioDriver Open
00906     if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) 
00907                 return -1;
00908         
00909         if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0)
00910                 return -1;
00911                                  
00912         if (SetupBufferSizeAndSampleRate(nframes, samplerate)  < 0)
00913                 return -1;      
00914 
00915         if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, nframes, samplerate, true) < 0)
00916                 goto error;
00917                 
00918         if (capturing && inchannels > 0)
00919                 if (SetupBuffers(inchannels, outchannels) < 0)
00920                         goto error;
00921 
00922         if (AddListeners() < 0)
00923                 goto error;
00924         
00925     // Core driver may have changed the in/out values
00926     fCaptureChannels = inchannels;
00927     fPlaybackChannels = outchannels;
00928     return noErr;
00929 
00930 error:
00931         Close();
00932     return -1;
00933 }
00934 
00935 int JackCoreAudioDriver::Close()
00936 {
00937         JackLog("JackCoreAudioDriver::Close\n");
00938         Stop();
00939     JackAudioDriver::Close();
00940     RemoveListeners();
00941         DisposeBuffers();
00942         CloseAUHAL();
00943     return 0;
00944 }
00945 
00946 int JackCoreAudioDriver::Attach()
00947 {
00948     OSStatus err;
00949     JackPort* port;
00950     jack_port_id_t port_index;
00951     UInt32 size;
00952     Boolean isWritable;
00953     char channel_name[64];
00954     char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
00955         char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
00956     unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
00957 
00958     JackLog("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld\n", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
00959 
00960     for (int i = 0; i < fCaptureChannels; i++) {
00961 
00962         err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
00963         if (err != noErr)
00964             JackLog("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error \n");
00965         if (err == noErr && size > 0) {
00966             err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
00967             if (err != noErr)
00968                 JackLog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n");
00969             snprintf(alias, sizeof(alias) - 1, "%s:%s:out_%s%u", fClientControl->fName, fCaptureDriverName, channel_name, i + 1);
00970         } else {
00971             snprintf(alias, sizeof(alias) - 1, "%s:%s:out%u", fClientControl->fName, fCaptureDriverName, i + 1);
00972         }
00973                 
00974                 snprintf(name, sizeof(name) - 1, "system:capture_%d", i + 1);
00975         
00976         if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) {
00977             jack_error("Cannot register port for %s", name);
00978             return -1;
00979         }
00980                 
00981                 size = sizeof(UInt32);
00982                 UInt32 value1 = 0;
00983                 UInt32 value2 = 0;
00984                 err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);  
00985                 if (err != noErr) 
00986                         JackLog("AudioDeviceGetProperty kAudioDevicePropertyLatency error \n");
00987                 err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);     
00988                 if (err != noErr) 
00989                         JackLog("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error \n");
00990         
00991         port = fGraphManager->GetPort(port_index);
00992                 port->SetAlias(alias);
00993         port->SetLatency(fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency);
00994         fCapturePortList[i] = port_index;
00995     }
00996 
00997     port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
00998 
00999     for (int i = 0; i < fPlaybackChannels; i++) {
01000 
01001         err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
01002         if (err != noErr)
01003             JackLog("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error \n");
01004         if (err == noErr && size > 0) {
01005             err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
01006             if (err != noErr)
01007                 JackLog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n");
01008             snprintf(alias, sizeof(alias) - 1, "%s:%s:in_%s%u", fClientControl->fName, fPlaybackDriverName, channel_name, i + 1);
01009         } else {
01010             snprintf(alias, sizeof(alias) - 1, "%s:%s:in%u", fClientControl->fName, fPlaybackDriverName, i + 1);
01011         }
01012                 
01013                 snprintf(name, sizeof(name) - 1, "system:playback_%d", i + 1);
01014 
01015         if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) {
01016             jack_error("Cannot register port for %s", name);
01017             return -1;
01018         }
01019                 
01020                 size = sizeof(UInt32);
01021                 UInt32 value1 = 0;
01022                 UInt32 value2 = 0;
01023                 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1); 
01024                 if (err != noErr) 
01025                         JackLog("AudioDeviceGetProperty kAudioDevicePropertyLatency error \n");
01026                 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);    
01027                 if (err != noErr) 
01028                         JackLog("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error \n");
01029 
01030             port = fGraphManager->GetPort(port_index);
01031                 port->SetAlias(alias);
01032         port->SetLatency(fEngineControl->fBufferSize + value1 + value2 + fPlaybackLatency);
01033         fPlaybackPortList[i] = port_index;
01034 
01035         // Monitor ports
01036         if (fWithMonitorPorts) {
01037             JackLog("Create monitor port \n");
01038             snprintf(name, sizeof(name) - 1, "%s:%s:monitor_%u", fClientControl->fName, fPlaybackDriverName, i + 1);
01039             if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, fEngineControl->fBufferSize)) == NO_PORT) {
01040                 jack_error("Cannot register monitor port for %s", name);
01041                 return -1;
01042             } else {
01043                 port = fGraphManager->GetPort(port_index);
01044                 port->SetLatency(fEngineControl->fBufferSize);
01045                 fMonitorPortList[i] = port_index;
01046             }
01047         }
01048     }
01049 
01050     // Input buffers do no change : prepare them only once
01051     for (int i = 0; i < fCaptureChannels; i++) {
01052         fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
01053     }
01054 
01055     return 0;
01056 }
01057 
01058 int JackCoreAudioDriver::Start()
01059 {
01060     JackLog("JackCoreAudioDriver::Start\n");
01061     JackAudioDriver::Start();
01062 
01063     OSStatus err = AudioDeviceAddIOProc(fDeviceID, MeasureCallback, this);
01064     if (err != noErr)
01065         return -1;
01066 
01067     err = AudioOutputUnitStart(fAUHAL);
01068     if (err != noErr)
01069         return -1;
01070 
01071     if ((err = AudioDeviceStart(fDeviceID, MeasureCallback)) != noErr) {
01072         jack_error("Cannot start MeasureCallback");
01073         printError(err);
01074         return -1;
01075     }
01076         
01077         return 0;
01078 }
01079 
01080 int JackCoreAudioDriver::Stop()
01081 {
01082         JackLog("JackCoreAudioDriver::Stop\n");
01083     AudioDeviceStop(fDeviceID, MeasureCallback);
01084     AudioDeviceRemoveIOProc(fDeviceID, MeasureCallback);
01085     return (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
01086 }
01087 
01088 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
01089 {
01090     OSStatus err;
01091     UInt32 outSize = sizeof(UInt32);
01092 
01093     err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size);
01094     if (err != noErr) {
01095         jack_error("Cannot set buffer size %ld", buffer_size);
01096         printError(err);
01097         return -1;
01098     }
01099         
01100         JackAudioDriver::SetBufferSize(buffer_size); // never fails
01101 
01102     // Input buffers do no change : prepare them only once
01103     for (int i = 0; i < fCaptureChannels; i++) {
01104         fJackInputData->mBuffers[i].mNumberChannels = 1;
01105         fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float);
01106         fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
01107     }
01108 
01109     return 0;
01110 }
01111 
01112 } // end of namespace
01113 
01114 
01115 #ifdef __cplusplus
01116 extern "C"
01117 {
01118 #endif
01119 
01120     jack_driver_desc_t* driver_get_descriptor() {
01121         jack_driver_desc_t *desc;
01122         unsigned int i;
01123         desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
01124 
01125         strcpy(desc->name, "coreaudio");
01126         desc->nparams = 13;
01127         desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
01128 
01129         i = 0;
01130         strcpy(desc->params[i].name, "channels");
01131         desc->params[i].character = 'c';
01132         desc->params[i].type = JackDriverParamInt;
01133         desc->params[i].value.ui = 0;
01134         strcpy(desc->params[i].short_desc, "Maximum number of channels");
01135         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01136 
01137         i++;
01138         strcpy(desc->params[i].name, "inchannels");
01139         desc->params[i].character = 'i';
01140         desc->params[i].type = JackDriverParamInt;
01141         desc->params[i].value.ui = 0;
01142         strcpy(desc->params[i].short_desc, "Maximum number of input channels");
01143         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01144 
01145         i++;
01146         strcpy(desc->params[i].name, "outchannels");
01147         desc->params[i].character = 'o';
01148         desc->params[i].type = JackDriverParamInt;
01149         desc->params[i].value.ui = 0;
01150         strcpy(desc->params[i].short_desc, "Maximum number of output channels");
01151         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01152 
01153         i++;
01154         strcpy(desc->params[i].name, "capture");
01155         desc->params[i].character = 'C';
01156         desc->params[i].type = JackDriverParamString;
01157         strcpy(desc->params[i].value.str, "will take default CoreAudio input device");
01158         strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set CoreAudio device name");
01159         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01160 
01161         i++;
01162         strcpy(desc->params[i].name, "playback");
01163         desc->params[i].character = 'P';
01164         desc->params[i].type = JackDriverParamString;
01165         strcpy(desc->params[i].value.str, "will take default CoreAudio output device");
01166         strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set CoreAudio device name");
01167         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01168 
01169         i++;
01170         strcpy (desc->params[i].name, "monitor");
01171         desc->params[i].character = 'm';
01172         desc->params[i].type = JackDriverParamBool;
01173         desc->params[i].value.i = 0;
01174         strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
01175         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01176 
01177         i++;
01178         strcpy(desc->params[i].name, "duplex");
01179         desc->params[i].character = 'D';
01180         desc->params[i].type = JackDriverParamBool;
01181         desc->params[i].value.i = TRUE;
01182         strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
01183         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01184 
01185         i++;
01186         strcpy(desc->params[i].name, "rate");
01187         desc->params[i].character = 'r';
01188         desc->params[i].type = JackDriverParamUInt;
01189         desc->params[i].value.ui = 44100U;
01190         strcpy(desc->params[i].short_desc, "Sample rate");
01191         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01192 
01193         i++;
01194         strcpy(desc->params[i].name, "period");
01195         desc->params[i].character = 'p';
01196         desc->params[i].type = JackDriverParamUInt;
01197         desc->params[i].value.ui = 128U;
01198         strcpy(desc->params[i].short_desc, "Frames per period");
01199         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01200 
01201         i++;
01202         strcpy(desc->params[i].name, "device");
01203         desc->params[i].character = 'd';
01204         desc->params[i].type = JackDriverParamString;
01205         desc->params[i].value.ui = 128U;
01206         strcpy(desc->params[i].value.str, "will take default CoreAudio device name");
01207         strcpy(desc->params[i].short_desc, "CoreAudio device name");
01208         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01209 
01210         i++;
01211         strcpy(desc->params[i].name, "input-latency");
01212         desc->params[i].character = 'I';
01213         desc->params[i].type = JackDriverParamUInt;
01214         desc->params[i].value.i = 0;
01215         strcpy(desc->params[i].short_desc, "Extra input latency");
01216         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01217 
01218         i++;
01219         strcpy(desc->params[i].name, "output-latency");
01220         desc->params[i].character = 'O';
01221         desc->params[i].type = JackDriverParamUInt;
01222         desc->params[i].value.i = 0;
01223         strcpy(desc->params[i].short_desc, "Extra output latency");
01224         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01225 
01226         i++;
01227         strcpy(desc->params[i].name, "list-devices");
01228         desc->params[i].character = 'l';
01229         desc->params[i].type = JackDriverParamBool;
01230         desc->params[i].value.i = TRUE;
01231         strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
01232         strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01233 
01234         return desc;
01235     }
01236 
01237     Jack::JackDriverClientInterface* driver_initialize(Jack::JackEngine* engine, Jack::JackSynchro** table, const JSList* params) {
01238         jack_nframes_t srate = 44100;
01239         jack_nframes_t frames_per_interrupt = 128;
01240         int capture = FALSE;
01241         int playback = FALSE;
01242         int chan_in = 0;
01243         int chan_out = 0;
01244         bool monitor = false;
01245         char* capture_pcm_name = "";
01246         char* playback_pcm_name = "";
01247         const JSList *node;
01248         const jack_driver_param_t *param;
01249         jack_nframes_t systemic_input_latency = 0;
01250         jack_nframes_t systemic_output_latency = 0;
01251 
01252         for (node = params; node; node = jack_slist_next(node)) {
01253             param = (const jack_driver_param_t *) node->data;
01254 
01255             switch (param->character) {
01256 
01257                 case 'd':
01258                     capture_pcm_name = strdup(param->value.str);
01259                     playback_pcm_name = strdup(param->value.str);
01260                     break;
01261 
01262                 case 'D':
01263                     capture = TRUE;
01264                     playback = TRUE;
01265                     break;
01266 
01267                 case 'c':
01268                     chan_in = chan_out = (int) param->value.ui;
01269                     break;
01270 
01271                 case 'i':
01272                     chan_in = (int) param->value.ui;
01273                     break;
01274 
01275                 case 'o':
01276                     chan_out = (int) param->value.ui;
01277                     break;
01278 
01279                 case 'C':
01280                     capture = TRUE;
01281                     if (strcmp(param->value.str, "none") != 0) {
01282                         capture_pcm_name = strdup(param->value.str);
01283                     }
01284                     break;
01285 
01286                 case 'P':
01287                     playback = TRUE;
01288                     if (strcmp(param->value.str, "none") != 0) {
01289                         playback_pcm_name = strdup(param->value.str);
01290                     }
01291                     break;
01292 
01293                 case 'm':
01294                     monitor = param->value.i;
01295                     break;
01296 
01297                 case 'r':
01298                     srate = param->value.ui;
01299                     break;
01300 
01301                 case 'p':
01302                     frames_per_interrupt = (unsigned int) param->value.ui;
01303                     break;
01304 
01305                 case 'I':
01306                     systemic_input_latency = param->value.ui;
01307                     break;
01308 
01309                 case 'O':
01310                     systemic_output_latency = param->value.ui;
01311                     break;
01312 
01313                 case 'l':
01314                     Jack::DisplayDeviceNames();
01315                     break;
01316             }
01317         }
01318 
01319         /* duplex is the default */
01320         if (!capture && !playback) {
01321             capture = TRUE;
01322             playback = TRUE;
01323         }
01324 
01325         Jack::JackDriverClientInterface* driver = new Jack::JackCoreAudioDriver("coreaudio", engine, table);
01326         if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency) == 0) {
01327             return driver;
01328         } else {
01329             delete driver;
01330             return NULL;
01331         }
01332     }
01333 
01334 #ifdef __cplusplus
01335 }
01336 #endif
01337 
01338 

Generated on Thu Feb 14 11:16:01 2008 for Jackdmp by  doxygen 1.5.1