JackPortAudioDriver.cpp

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

Generated on Wed Jan 10 11:42:46 2007 for Jackdmp by  doxygen 1.4.5