00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef WIN32
00021 #pragma warning (disable : 4786)
00022 #endif
00023
00024 #include "pa_asio.h"
00025 #include "JackDriverLoader.h"
00026 #include "driver_interface.h"
00027 #include "JackPortAudioDriver.h"
00028 #include "JackEngineControl.h"
00029 #include "JackError.h"
00030 #include "JackTime.h"
00031 #include <iostream>
00032 #include <assert.h>
00033
00034 namespace Jack
00035 {
00036
00037 void JackPortAudioDriver::PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters)
00038 {
00039 static double standardSampleRates[] = {
00040 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
00041 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1
00042 };
00043 int i, printCount;
00044 PaError err;
00045
00046 printCount = 0;
00047 for (i = 0; standardSampleRates[i] > 0; i++) {
00048 err = Pa_IsFormatSupported(inputParameters, outputParameters, standardSampleRates[i]);
00049 if (err == paFormatIsSupported) {
00050 if (printCount == 0) {
00051 printf("\t%8.2f", standardSampleRates[i]);
00052 printCount = 1;
00053 } else if (printCount == 4) {
00054 printf(",\n\t%8.2f", standardSampleRates[i]);
00055 printCount = 1;
00056 } else {
00057 printf(", %8.2f", standardSampleRates[i]);
00058 ++printCount;
00059 }
00060 }
00061 }
00062 if (!printCount)
00063 printf("None\n");
00064 else
00065 printf("\n");
00066 }
00067
00068 bool JackPortAudioDriver::GetInputDeviceFromName(const char* name, PaDeviceIndex* device, int* in_max)
00069 {
00070 const PaDeviceInfo* deviceInfo;
00071 PaDeviceIndex numDevices = Pa_GetDeviceCount();
00072
00073 for (int i = 0; i < numDevices; i++) {
00074 deviceInfo = Pa_GetDeviceInfo(i);
00075 if (strcmp(name, deviceInfo->name) == 0) {
00076 *device = i;
00077 *in_max = deviceInfo->maxInputChannels;
00078 return true;
00079 }
00080 }
00081
00082 return false;
00083 }
00084
00085 bool JackPortAudioDriver::GetOutputDeviceFromName(const char* name, PaDeviceIndex* device, int* out_max)
00086 {
00087 const PaDeviceInfo* deviceInfo;
00088 PaDeviceIndex numDevices = Pa_GetDeviceCount();
00089
00090 for (int i = 0; i < numDevices; i++) {
00091 deviceInfo = Pa_GetDeviceInfo(i);
00092 if (strcmp(name, deviceInfo->name) == 0) {
00093 *device = i;
00094 *out_max = deviceInfo->maxOutputChannels;
00095 return true;
00096 }
00097 }
00098
00099 return false;
00100 }
00101
00102 static void DisplayDeviceNames()
00103 {
00104 PaError err;
00105 const PaDeviceInfo* deviceInfo;
00106 PaStreamParameters inputParameters, outputParameters;
00107 int defaultDisplayed;
00108
00109 err = Pa_Initialize();
00110 if (err != paNoError)
00111 return ;
00112
00113 PaDeviceIndex numDevices = Pa_GetDeviceCount();
00114 printf("Number of devices = %d\n", numDevices);
00115
00116 for (int i = 0; i < numDevices; i++) {
00117 deviceInfo = Pa_GetDeviceInfo(i);
00118 printf( "--------------------------------------- device #%d\n", i );
00119
00120
00121 defaultDisplayed = 0;
00122 if (i == Pa_GetDefaultInputDevice()) {
00123 printf("[ Default Input");
00124 defaultDisplayed = 1;
00125 } else if (i == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultInputDevice) {
00126 const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
00127 printf("[ Default %s Input", hostInfo->name);
00128 defaultDisplayed = 1;
00129 }
00130
00131 if (i == Pa_GetDefaultOutputDevice()) {
00132 printf((defaultDisplayed ? "," : "["));
00133 printf(" Default Output");
00134 defaultDisplayed = 1;
00135 } else if (i == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultOutputDevice) {
00136 const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
00137 printf((defaultDisplayed ? "," : "["));
00138 printf(" Default %s Output", hostInfo->name);
00139 defaultDisplayed = 1;
00140 }
00141
00142 if (defaultDisplayed)
00143 printf(" ]\n");
00144
00145
00146 printf("Name = %s\n", deviceInfo->name);
00147 printf("Host API = %s\n", Pa_GetHostApiInfo(deviceInfo->hostApi)->name);
00148 printf("Max inputs = %d", deviceInfo->maxInputChannels);
00149 printf(", Max outputs = %d\n", deviceInfo->maxOutputChannels);
00150
00151
00152
00153
00154
00155
00156
00157 #ifdef WIN32
00158 #ifndef PA_NO_ASIO
00159
00160 if (Pa_GetHostApiInfo(deviceInfo->hostApi)->type == paASIO) {
00161 long minLatency, maxLatency, preferredLatency, granularity;
00162
00163 err = PaAsio_GetAvailableLatencyValues(i, &minLatency, &maxLatency, &preferredLatency, &granularity);
00164
00165 printf("ASIO minimum buffer size = %ld\n", minLatency);
00166 printf("ASIO maximum buffer size = %ld\n", maxLatency);
00167 printf("ASIO preferred buffer size = %ld\n", preferredLatency);
00168
00169 if (granularity == -1)
00170 printf("ASIO buffer granularity = power of 2\n");
00171 else
00172 printf("ASIO buffer granularity = %ld\n", granularity);
00173 }
00174 #endif
00175 #endif
00176
00177 printf("Default sample rate = %8.2f\n", deviceInfo->defaultSampleRate);
00178
00179
00180 inputParameters.device = i;
00181 inputParameters.channelCount = deviceInfo->maxInputChannels;
00182 inputParameters.sampleFormat = paInt16;
00183 inputParameters.suggestedLatency = 0;
00184 inputParameters.hostApiSpecificStreamInfo = NULL;
00185
00186 outputParameters.device = i;
00187 outputParameters.channelCount = deviceInfo->maxOutputChannels;
00188 outputParameters.sampleFormat = paInt16;
00189 outputParameters.suggestedLatency = 0;
00190 outputParameters.hostApiSpecificStreamInfo = NULL;
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 }
00210
00211 Pa_Terminate();
00212 }
00213
00214 int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer,
00215 unsigned long framesPerBuffer,
00216 const PaStreamCallbackTimeInfo* timeInfo,
00217 PaStreamCallbackFlags statusFlags,
00218 void* userData)
00219 {
00220 JackPortAudioDriver* driver = (JackPortAudioDriver*)userData;
00221 driver->fLastWaitUst = GetMicroSeconds();
00222 driver->fInputBuffer = (float**)inputBuffer;
00223 driver->fOutputBuffer = (float**)outputBuffer;
00224 return (driver->Process() == 0) ? paContinue : paAbort;
00225 }
00226
00227 int JackPortAudioDriver::Read()
00228 {
00229 for (int i = 0; i < fCaptureChannels; i++) {
00230 memcpy(GetInputBuffer(i), fInputBuffer[i], sizeof(float) * fEngineControl->fBufferSize);
00231 }
00232 return 0;
00233 }
00234
00235 int JackPortAudioDriver::Write()
00236 {
00237 for (int i = 0; i < fPlaybackChannels; i++) {
00238 memcpy(fOutputBuffer[i], GetOutputBuffer(i), sizeof(float) * fEngineControl->fBufferSize);
00239 }
00240 return 0;
00241 }
00242
00243 int JackPortAudioDriver::Open(jack_nframes_t nframes,
00244 jack_nframes_t samplerate,
00245 bool capturing,
00246 bool playing,
00247 int inchannels,
00248 int outchannels,
00249 bool monitor,
00250 const char* capture_driver_uid,
00251 const char* playback_driver_uid,
00252 jack_nframes_t capture_latency,
00253 jack_nframes_t playback_latency)
00254 {
00255 PaError err;
00256 PaStreamParameters inputParameters;
00257 PaStreamParameters outputParameters;
00258 const PaDeviceInfo* deviceInfo;
00259 int in_max = 0;
00260 int out_max = 0;
00261
00262 JackLog("JackPortAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s samplerate = %ld\n",
00263 nframes, inchannels, outchannels, capture_driver_uid, playback_driver_uid, samplerate);
00264
00265
00266 if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) {
00267 return -1;
00268 }
00269
00270 err = Pa_Initialize();
00271 if (err != paNoError) {
00272 jack_error("JackPortAudioDriver::Pa_Initialize error = %s\n", Pa_GetErrorText(err));
00273 goto error;
00274 }
00275
00276 JackLog("JackPortAudioDriver::Pa_GetDefaultInputDevice %ld\n", Pa_GetDefaultInputDevice());
00277 JackLog("JackPortAudioDriver::Pa_GetDefaultOutputDevice %ld\n", Pa_GetDefaultOutputDevice());
00278
00279 if (capturing) {
00280 if (!GetInputDeviceFromName(capture_driver_uid, &fInputDevice, &in_max)) {
00281 JackLog("JackPortAudioDriver::GetInputDeviceFromName cannot open %s\n", capture_driver_uid);
00282 fInputDevice = Pa_GetDefaultInputDevice();
00283 if (fInputDevice == paNoDevice)
00284 goto error;
00285 deviceInfo = Pa_GetDeviceInfo(fInputDevice);
00286 in_max = deviceInfo->maxInputChannels;
00287 capture_driver_uid = strdup(deviceInfo->name);
00288 }
00289 }
00290
00291 if (inchannels > in_max) {
00292 jack_error("This device hasn't required input channels inchannels = %ld in_max = %ld", inchannels, in_max);
00293 goto error;
00294 }
00295
00296 if (playing) {
00297 if (!GetOutputDeviceFromName(playback_driver_uid, &fOutputDevice, &out_max)) {
00298 JackLog("JackPortAudioDriver::GetOutputDeviceFromName cannot open %s\n", playback_driver_uid);
00299 fOutputDevice = Pa_GetDefaultOutputDevice();
00300 if (fOutputDevice == paNoDevice)
00301 goto error;
00302 deviceInfo = Pa_GetDeviceInfo(fOutputDevice);
00303 out_max = deviceInfo->maxOutputChannels;
00304 playback_driver_uid = strdup(deviceInfo->name);
00305 }
00306 }
00307
00308 if (outchannels > out_max) {
00309 jack_error("This device hasn't required output channels outchannels = %ld out_max = %ld", outchannels, out_max);
00310 goto error;
00311 }
00312
00313 if (inchannels == 0) {
00314 JackLog("JackPortAudioDriver::Open setup max in channels = %ld\n", in_max);
00315 inchannels = in_max;
00316 }
00317
00318 if (outchannels == 0) {
00319 JackLog("JackPortAudioDriver::Open setup max out channels = %ld\n", out_max);
00320 outchannels = out_max;
00321 }
00322
00323 inputParameters.device = fInputDevice;
00324 inputParameters.channelCount = inchannels;
00325 inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00326 inputParameters.suggestedLatency = (fInputDevice != paNoDevice)
00327 ? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency
00328 : 0;
00329 inputParameters.hostApiSpecificStreamInfo = NULL;
00330
00331 outputParameters.device = fOutputDevice;
00332 outputParameters.channelCount = outchannels;
00333 outputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00334 outputParameters.suggestedLatency = (fOutputDevice != paNoDevice)
00335 ? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency
00336 : 0;
00337 outputParameters.hostApiSpecificStreamInfo = NULL;
00338
00339 err = Pa_OpenStream(&fStream,
00340 (fInputDevice == paNoDevice) ? 0 : &inputParameters,
00341 (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
00342 samplerate,
00343 nframes,
00344 paNoFlag,
00345 Render,
00346 this);
00347 if (err != paNoError) {
00348 jack_error("Pa_OpenStream error = %s\n", Pa_GetErrorText(err));
00349 goto error;
00350 }
00351
00352 #ifdef __APPLE__
00353 fEngineControl->fPeriod = fEngineControl->fPeriodUsecs * 1000;
00354 fEngineControl->fComputation = 500 * 1000;
00355 fEngineControl->fConstraint = fEngineControl->fPeriodUsecs * 1000;
00356 #endif
00357
00358
00359 fCaptureChannels = inchannels;
00360 fPlaybackChannels = outchannels;
00361
00362 assert(strlen(capture_driver_uid) < JACK_CLIENT_NAME_SIZE);
00363 assert(strlen(playback_driver_uid) < JACK_CLIENT_NAME_SIZE);
00364
00365 strcpy(fCaptureDriverName, capture_driver_uid);
00366 strcpy(fPlaybackDriverName, playback_driver_uid);
00367
00368 return 0;
00369
00370 error:
00371 Pa_Terminate();
00372 return -1;
00373 }
00374
00375 int JackPortAudioDriver::Close()
00376 {
00377 JackAudioDriver::Close();
00378 JackLog("JackPortAudioDriver::Close\n");
00379 Pa_CloseStream(fStream);
00380 Pa_Terminate();
00381 return 0;
00382 }
00383
00384 int JackPortAudioDriver::Start()
00385 {
00386 JackLog("JackPortAudioDriver::Start\n");
00387 JackAudioDriver::Start();
00388 PaError err = Pa_StartStream(fStream);
00389 return (err == paNoError) ? 0 : -1;
00390 }
00391
00392 int JackPortAudioDriver::Stop()
00393 {
00394 JackLog("JackPortAudioDriver::Stop\n");
00395 PaError err = Pa_StopStream(fStream);
00396 return (err == paNoError) ? 0 : -1;
00397 }
00398
00399 int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
00400 {
00401 PaError err;
00402 PaStreamParameters inputParameters;
00403 PaStreamParameters outputParameters;
00404
00405 if ((err = Pa_CloseStream(fStream)) != paNoError) {
00406 jack_error("Pa_CloseStream error = %s\n", Pa_GetErrorText(err));
00407 return -1;
00408 }
00409
00410 inputParameters.device = fInputDevice;
00411 inputParameters.channelCount = fCaptureChannels;
00412 inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00413 inputParameters.suggestedLatency = (fInputDevice != paNoDevice)
00414 ? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency
00415 : 0;
00416 inputParameters.hostApiSpecificStreamInfo = NULL;
00417
00418 outputParameters.device = fOutputDevice;
00419 outputParameters.channelCount = fPlaybackChannels;
00420 outputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00421 outputParameters.suggestedLatency = (fOutputDevice != paNoDevice)
00422 ? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency
00423 : 0;
00424 outputParameters.hostApiSpecificStreamInfo = NULL;
00425
00426 err = Pa_OpenStream(&fStream,
00427 (fInputDevice == paNoDevice) ? 0 : &inputParameters,
00428 (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
00429 fEngineControl->fSampleRate,
00430 buffer_size,
00431 paNoFlag,
00432 Render,
00433 this);
00434
00435 if (err != paNoError) {
00436 jack_error("Pa_OpenStream error = %s\n", Pa_GetErrorText(err));
00437 return -1;
00438 } else {
00439
00440 return JackAudioDriver::SetBufferSize(buffer_size);
00441 }
00442 }
00443
00444 }
00445
00446 #ifdef __cplusplus
00447 extern "C"
00448 {
00449 #endif
00450
00451 #include "JackExports.h"
00452
00453 EXPORT jack_driver_desc_t* driver_get_descriptor() {
00454 jack_driver_desc_t *desc;
00455 unsigned int i;
00456 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
00457
00458 strcpy(desc->name, "portaudio");
00459
00460 desc->nparams = 13;
00461 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
00462
00463 i = 0;
00464 strcpy(desc->params[i].name, "channels");
00465 desc->params[i].character = 'c';
00466 desc->params[i].type = JackDriverParamInt;
00467 desc->params[i].value.ui = 0;
00468 strcpy(desc->params[i].short_desc, "Maximum number of channels");
00469 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00470
00471 i++;
00472 strcpy(desc->params[i].name, "inchannels");
00473 desc->params[i].character = 'i';
00474 desc->params[i].type = JackDriverParamInt;
00475 desc->params[i].value.ui = 0;
00476 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
00477 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00478
00479 i++;
00480 strcpy(desc->params[i].name, "outchannels");
00481 desc->params[i].character = 'o';
00482 desc->params[i].type = JackDriverParamInt;
00483 desc->params[i].value.ui = 0;
00484 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
00485 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00486
00487 i++;
00488 strcpy(desc->params[i].name, "capture");
00489 desc->params[i].character = 'C';
00490 desc->params[i].type = JackDriverParamString;
00491 strcpy(desc->params[i].value.str, "will take default PortAudio input device");
00492 strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
00493 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00494
00495 i++;
00496 strcpy(desc->params[i].name, "playback");
00497 desc->params[i].character = 'P';
00498 desc->params[i].type = JackDriverParamString;
00499 strcpy(desc->params[i].value.str, "will take default PortAudio output device");
00500 strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
00501 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00502
00503 i++;
00504 strcpy (desc->params[i].name, "monitor");
00505 desc->params[i].character = 'm';
00506 desc->params[i].type = JackDriverParamBool;
00507 desc->params[i].value.i = 0;
00508 strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
00509 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00510
00511 i++;
00512 strcpy(desc->params[i].name, "duplex");
00513 desc->params[i].character = 'D';
00514 desc->params[i].type = JackDriverParamBool;
00515 desc->params[i].value.i = TRUE;
00516 strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
00517 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00518
00519 i++;
00520 strcpy(desc->params[i].name, "rate");
00521 desc->params[i].character = 'r';
00522 desc->params[i].type = JackDriverParamUInt;
00523 desc->params[i].value.ui = 44100U;
00524 strcpy(desc->params[i].short_desc, "Sample rate");
00525 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00526
00527 i++;
00528 strcpy(desc->params[i].name, "period");
00529 desc->params[i].character = 'p';
00530 desc->params[i].type = JackDriverParamUInt;
00531 desc->params[i].value.ui = 128U;
00532 strcpy(desc->params[i].short_desc, "Frames per period");
00533 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00534
00535 i++;
00536 strcpy(desc->params[i].name, "device");
00537 desc->params[i].character = 'd';
00538 desc->params[i].type = JackDriverParamString;
00539 desc->params[i].value.ui = 128U;
00540 strcpy(desc->params[i].value.str, "will take default PortAudio device name");
00541 strcpy(desc->params[i].short_desc, "PortAudio device name");
00542 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00543
00544 i++;
00545 strcpy(desc->params[i].name, "input-latency");
00546 desc->params[i].character = 'I';
00547 desc->params[i].type = JackDriverParamUInt;
00548 desc->params[i].value.i = 0;
00549 strcpy(desc->params[i].short_desc, "Extra input latency");
00550 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00551
00552 i++;
00553 strcpy(desc->params[i].name, "output-latency");
00554 desc->params[i].character = 'O';
00555 desc->params[i].type = JackDriverParamUInt;
00556 desc->params[i].value.i = 0;
00557 strcpy(desc->params[i].short_desc, "Extra output latency");
00558 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00559
00560 i++;
00561 strcpy(desc->params[i].name, "list-devices");
00562 desc->params[i].character = 'l';
00563 desc->params[i].type = JackDriverParamBool;
00564 desc->params[i].value.i = TRUE;
00565 strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
00566 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00567
00568 return desc;
00569 }
00570
00571 EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackEngine* engine, Jack::JackSynchro** table, const JSList* params) {
00572 jack_nframes_t srate = 44100;
00573 jack_nframes_t frames_per_interrupt = 512;
00574 int capture = FALSE;
00575 int playback = FALSE;
00576 int chan_in = 0;
00577 int chan_out = 0;
00578 bool monitor = false;
00579 char* capture_pcm_name = "winmme";
00580 char* playback_pcm_name = "winmme";
00581 const JSList *node;
00582 const jack_driver_param_t *param;
00583 jack_nframes_t systemic_input_latency = 0;
00584 jack_nframes_t systemic_output_latency = 0;
00585
00586 for (node = params; node; node = jack_slist_next(node)) {
00587 param = (const jack_driver_param_t *) node->data;
00588
00589 switch (param->character) {
00590
00591 case 'd':
00592 capture_pcm_name = strdup(param->value.str);
00593 playback_pcm_name = strdup(param->value.str);
00594 break;
00595
00596 case 'D':
00597 capture = TRUE;
00598 playback = TRUE;
00599 break;
00600
00601 case 'c':
00602 chan_in = chan_out = (int) param->value.ui;
00603 break;
00604
00605 case 'i':
00606 chan_in = (int) param->value.ui;
00607 break;
00608
00609 case 'o':
00610 chan_out = (int) param->value.ui;
00611 break;
00612
00613 case 'C':
00614 capture = TRUE;
00615 if (strcmp(param->value.str, "none") != 0) {
00616 capture_pcm_name = strdup(param->value.str);
00617 }
00618 break;
00619
00620 case 'P':
00621 playback = TRUE;
00622 if (strcmp(param->value.str, "none") != 0) {
00623 playback_pcm_name = strdup(param->value.str);
00624 }
00625 break;
00626
00627 case 'm':
00628 monitor = param->value.i;
00629 break;
00630
00631 case 'r':
00632 srate = param->value.ui;
00633 break;
00634
00635 case 'p':
00636 frames_per_interrupt = (unsigned int) param->value.ui;
00637 break;
00638
00639 case 'I':
00640 systemic_input_latency = param->value.ui;
00641 break;
00642
00643 case 'O':
00644 systemic_output_latency = param->value.ui;
00645 break;
00646
00647 case 'l':
00648 Jack::DisplayDeviceNames();
00649 break;
00650 }
00651 }
00652
00653
00654 if (!capture && !playback) {
00655 capture = TRUE;
00656 playback = TRUE;
00657 }
00658
00659 Jack::JackDriverClientInterface* driver = new Jack::JackPortAudioDriver("portaudio", engine, table);
00660 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) {
00661 return driver;
00662 } else {
00663 delete driver;
00664 return NULL;
00665 }
00666 }
00667
00668 #ifdef __cplusplus
00669 }
00670 #endif