00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "JackDriverLoader.h"
00021 #include "driver_interface.h"
00022 #include "JackPortAudioDriver.h"
00023 #include "JackEngineControl.h"
00024 #include "JackError.h"
00025 #include "JackTime.h"
00026 #include "JackCompilerDeps.h"
00027 #include <iostream>
00028 #include <assert.h>
00029
00030 using namespace std;
00031
00032 namespace Jack
00033 {
00034 int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer,
00035 unsigned long framesPerBuffer,
00036 const PaStreamCallbackTimeInfo* timeInfo,
00037 PaStreamCallbackFlags statusFlags,
00038 void* userData)
00039 {
00040 JackPortAudioDriver* driver = (JackPortAudioDriver*)userData;
00041 driver->fInputBuffer = (float**)inputBuffer;
00042 driver->fOutputBuffer = (float**)outputBuffer;
00043
00044 set_threaded_log_function();
00045 driver->CycleTakeBeginTime();
00046 return (driver->Process() == 0) ? paContinue : paAbort;
00047 }
00048
00049 int JackPortAudioDriver::Read()
00050 {
00051 for (int i = 0; i < fCaptureChannels; i++)
00052 memcpy(GetInputBuffer(i), fInputBuffer[i], sizeof(float) * fEngineControl->fBufferSize);
00053 return 0;
00054 }
00055
00056 int JackPortAudioDriver::Write()
00057 {
00058 for (int i = 0; i < fPlaybackChannels; i++)
00059 memcpy(fOutputBuffer[i], GetOutputBuffer(i), sizeof(float) * fEngineControl->fBufferSize);
00060 return 0;
00061 }
00062
00063 int JackPortAudioDriver::Open(jack_nframes_t buffer_size,
00064 jack_nframes_t samplerate,
00065 bool capturing,
00066 bool playing,
00067 int inchannels,
00068 int outchannels,
00069 bool monitor,
00070 const char* capture_driver_uid,
00071 const char* playback_driver_uid,
00072 jack_nframes_t capture_latency,
00073 jack_nframes_t playback_latency)
00074 {
00075 PaError err = paNoError;
00076 PaStreamParameters inputParameters;
00077 PaStreamParameters outputParameters;
00078 int in_max = 0;
00079 int out_max = 0;
00080
00081 jack_log("JackPortAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s samplerate = %ld",
00082 buffer_size, inchannels, outchannels, capture_driver_uid, playback_driver_uid, samplerate);
00083
00084
00085 if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0)
00086 return -1;
00087
00088
00089 if (capturing)
00090 {
00091 if (fPaDevices->GetInputDeviceFromName(capture_driver_uid, fInputDevice, in_max) < 0)
00092 goto error;
00093 }
00094 if (playing)
00095 {
00096 if (fPaDevices->GetOutputDeviceFromName(playback_driver_uid, fOutputDevice, out_max) < 0)
00097 goto error;
00098 }
00099
00100 jack_log("JackPortAudioDriver::Open fInputDevice = %d, fOutputDevice %d", fInputDevice, fOutputDevice);
00101
00102
00103 if (inchannels == 0)
00104 {
00105 jack_log("JackPortAudioDriver::Open setup max in channels = %ld", in_max);
00106 inchannels = in_max;
00107 }
00108 if (outchannels == 0)
00109 {
00110 jack_log("JackPortAudioDriver::Open setup max out channels = %ld", out_max);
00111 outchannels = out_max;
00112 }
00113
00114
00115 if (inchannels > in_max)
00116 {
00117 jack_error("This device has only %d available input channels.", in_max);
00118 inchannels = in_max;
00119 }
00120 if (outchannels > out_max)
00121 {
00122 jack_error("This device has only %d available output channels.", out_max);
00123 outchannels = out_max;
00124 }
00125
00126
00127 inputParameters.device = fInputDevice;
00128 inputParameters.channelCount = inchannels;
00129 inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00130 inputParameters.suggestedLatency = (fInputDevice != paNoDevice)
00131 ? fPaDevices->GetDeviceInfo(fInputDevice)->defaultLowInputLatency
00132 : 0;
00133 inputParameters.hostApiSpecificStreamInfo = NULL;
00134
00135 outputParameters.device = fOutputDevice;
00136 outputParameters.channelCount = outchannels;
00137 outputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00138 outputParameters.suggestedLatency = (fOutputDevice != paNoDevice)
00139 ? fPaDevices->GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
00140 : 0;
00141 outputParameters.hostApiSpecificStreamInfo = NULL;
00142
00143 err = Pa_OpenStream(&fStream,
00144 (fInputDevice == paNoDevice) ? 0 : &inputParameters,
00145 (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
00146 samplerate,
00147 buffer_size,
00148 paNoFlag,
00149 Render,
00150 this);
00151 if (err != paNoError)
00152 {
00153 jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
00154 goto error;
00155 }
00156
00157 #ifdef __APPLE__
00158 fEngineControl->fPeriod = fEngineControl->fPeriodUsecs * 1000;
00159 fEngineControl->fComputation = 500 * 1000;
00160 fEngineControl->fConstraint = fEngineControl->fPeriodUsecs * 1000;
00161 #endif
00162
00163
00164 fCaptureChannels = inchannels;
00165 fPlaybackChannels = outchannels;
00166
00167 assert(strlen(capture_driver_uid) < JACK_CLIENT_NAME_SIZE);
00168 assert(strlen(playback_driver_uid) < JACK_CLIENT_NAME_SIZE);
00169
00170 strcpy(fCaptureDriverName, capture_driver_uid);
00171 strcpy(fPlaybackDriverName, playback_driver_uid);
00172
00173 return 0;
00174
00175 error:
00176 JackAudioDriver::Close();
00177 jack_error("Can't open default PortAudio device : %s", Pa_GetErrorText(err));
00178 return -1;
00179 }
00180
00181 int JackPortAudioDriver::Close()
00182 {
00183 int res = JackAudioDriver::Close();
00184 jack_log("JackPortAudioDriver::Close");
00185 Pa_CloseStream(fStream);
00186 return res;
00187 }
00188
00189 int JackPortAudioDriver::Start()
00190 {
00191 jack_log("JackPortAudioDriver::Start");
00192 JackAudioDriver::Start();
00193 PaError err = Pa_StartStream(fStream);
00194 return (err == paNoError) ? 0 : -1;
00195 }
00196
00197 int JackPortAudioDriver::Stop()
00198 {
00199 jack_log("JackPortAudioDriver::Stop");
00200 PaError err = Pa_StopStream(fStream);
00201 return (err == paNoError) ? 0 : -1;
00202 }
00203
00204 int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
00205 {
00206 PaError err;
00207 PaStreamParameters inputParameters;
00208 PaStreamParameters outputParameters;
00209
00210 if ((err = Pa_CloseStream(fStream)) != paNoError)
00211 {
00212 jack_error("Pa_CloseStream error = %s", Pa_GetErrorText(err));
00213 return -1;
00214 }
00215
00216
00217 inputParameters.device = fInputDevice;
00218 inputParameters.channelCount = fCaptureChannels;
00219 inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00220 inputParameters.suggestedLatency = (fInputDevice != paNoDevice)
00221 ? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency
00222 : 0;
00223 inputParameters.hostApiSpecificStreamInfo = NULL;
00224
00225 outputParameters.device = fOutputDevice;
00226 outputParameters.channelCount = fPlaybackChannels;
00227 outputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00228 outputParameters.suggestedLatency = (fOutputDevice != paNoDevice)
00229 ? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency
00230 : 0;
00231 outputParameters.hostApiSpecificStreamInfo = NULL;
00232
00233 err = Pa_OpenStream(&fStream,
00234 (fInputDevice == paNoDevice) ? 0 : &inputParameters,
00235 (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
00236 fEngineControl->fSampleRate,
00237 buffer_size,
00238 paNoFlag,
00239 Render,
00240 this);
00241
00242 if (err != paNoError)
00243 {
00244 jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
00245 return -1;
00246 }
00247 else
00248 {
00249
00250 return JackAudioDriver::SetBufferSize(buffer_size);
00251 }
00252 }
00253
00254 }
00255
00256 #ifdef __cplusplus
00257 extern "C"
00258 {
00259 #endif
00260
00261 #include "JackCompilerDeps.h"
00262
00263 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
00264 {
00265 jack_driver_desc_t *desc;
00266 unsigned int i;
00267 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
00268
00269 strcpy(desc->name, "portaudio");
00270 strcpy(desc->desc, "PortAudio API based audio backend");
00271
00272 desc->nparams = 13;
00273 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
00274
00275 i = 0;
00276 strcpy(desc->params[i].name, "channels");
00277 desc->params[i].character = 'c';
00278 desc->params[i].type = JackDriverParamInt;
00279 desc->params[i].value.ui = 0;
00280 strcpy(desc->params[i].short_desc, "Maximum number of channels");
00281 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00282
00283 i++;
00284 strcpy(desc->params[i].name, "inchannels");
00285 desc->params[i].character = 'i';
00286 desc->params[i].type = JackDriverParamInt;
00287 desc->params[i].value.ui = 0;
00288 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
00289 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00290
00291 i++;
00292 strcpy(desc->params[i].name, "outchannels");
00293 desc->params[i].character = 'o';
00294 desc->params[i].type = JackDriverParamInt;
00295 desc->params[i].value.ui = 0;
00296 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
00297 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00298
00299 i++;
00300 strcpy(desc->params[i].name, "capture");
00301 desc->params[i].character = 'C';
00302 desc->params[i].type = JackDriverParamString;
00303 strcpy(desc->params[i].value.str, "will take default PortAudio input device");
00304 strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
00305 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00306
00307 i++;
00308 strcpy(desc->params[i].name, "playback");
00309 desc->params[i].character = 'P';
00310 desc->params[i].type = JackDriverParamString;
00311 strcpy(desc->params[i].value.str, "will take default PortAudio output device");
00312 strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
00313 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00314
00315 i++;
00316 strcpy (desc->params[i].name, "monitor");
00317 desc->params[i].character = 'm';
00318 desc->params[i].type = JackDriverParamBool;
00319 desc->params[i].value.i = 0;
00320 strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
00321 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00322
00323 i++;
00324 strcpy(desc->params[i].name, "duplex");
00325 desc->params[i].character = 'D';
00326 desc->params[i].type = JackDriverParamBool;
00327 desc->params[i].value.i = TRUE;
00328 strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
00329 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00330
00331 i++;
00332 strcpy(desc->params[i].name, "rate");
00333 desc->params[i].character = 'r';
00334 desc->params[i].type = JackDriverParamUInt;
00335 desc->params[i].value.ui = 44100U;
00336 strcpy(desc->params[i].short_desc, "Sample rate");
00337 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00338
00339 i++;
00340 strcpy(desc->params[i].name, "period");
00341 desc->params[i].character = 'p';
00342 desc->params[i].type = JackDriverParamUInt;
00343 desc->params[i].value.ui = 128U;
00344 strcpy(desc->params[i].short_desc, "Frames per period");
00345 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00346
00347 i++;
00348 strcpy(desc->params[i].name, "device");
00349 desc->params[i].character = 'd';
00350 desc->params[i].type = JackDriverParamString;
00351 strcpy(desc->params[i].value.str, "will take default PortAudio device name");
00352 strcpy(desc->params[i].short_desc, "PortAudio device name");
00353 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00354
00355 i++;
00356 strcpy(desc->params[i].name, "input-latency");
00357 desc->params[i].character = 'I';
00358 desc->params[i].type = JackDriverParamUInt;
00359 desc->params[i].value.i = 0;
00360 strcpy(desc->params[i].short_desc, "Extra input latency");
00361 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00362
00363 i++;
00364 strcpy(desc->params[i].name, "output-latency");
00365 desc->params[i].character = 'O';
00366 desc->params[i].type = JackDriverParamUInt;
00367 desc->params[i].value.i = 0;
00368 strcpy(desc->params[i].short_desc, "Extra output latency");
00369 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00370
00371 i++;
00372 strcpy(desc->params[i].name, "list-devices");
00373 desc->params[i].character = 'l';
00374 desc->params[i].type = JackDriverParamBool;
00375 desc->params[i].value.i = TRUE;
00376 strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
00377 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00378
00379 return desc;
00380 }
00381
00382 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
00383 {
00384 jack_nframes_t srate = 44100;
00385 jack_nframes_t frames_per_interrupt = 512;
00386 const char* capture_pcm_name = "";
00387 const char* playback_pcm_name = "";
00388 bool capture = false;
00389 bool playback = false;
00390 int chan_in = 0;
00391 int chan_out = 0;
00392 bool monitor = false;
00393 const JSList *node;
00394 const jack_driver_param_t *param;
00395 jack_nframes_t systemic_input_latency = 0;
00396 jack_nframes_t systemic_output_latency = 0;
00397 PortAudioDevices* pa_devices = new PortAudioDevices();
00398
00399 for (node = params; node; node = jack_slist_next(node))
00400 {
00401 param = (const jack_driver_param_t *) node->data;
00402
00403 switch (param->character)
00404 {
00405
00406 case 'd':
00407 capture_pcm_name = strdup(param->value.str);
00408 playback_pcm_name = strdup(param->value.str);
00409 break;
00410
00411 case 'D':
00412 capture = true;
00413 playback = true;
00414 break;
00415
00416 case 'c':
00417 chan_in = chan_out = (int)param->value.ui;
00418 break;
00419
00420 case 'i':
00421 chan_in = (int)param->value.ui;
00422 break;
00423
00424 case 'o':
00425 chan_out = (int)param->value.ui;
00426 break;
00427
00428 case 'C':
00429 capture = true;
00430 if (strcmp(param->value.str, "none") != 0) {
00431 capture_pcm_name = strdup(param->value.str);
00432 }
00433 break;
00434
00435 case 'P':
00436 playback = TRUE;
00437 if (strcmp(param->value.str, "none") != 0) {
00438 playback_pcm_name = strdup(param->value.str);
00439 }
00440 break;
00441
00442 case 'm':
00443 monitor = param->value.i;
00444 break;
00445
00446 case 'r':
00447 srate = param->value.ui;
00448 break;
00449
00450 case 'p':
00451 frames_per_interrupt = (unsigned int)param->value.ui;
00452 break;
00453
00454 case 'I':
00455 systemic_input_latency = param->value.ui;
00456 break;
00457
00458 case 'O':
00459 systemic_output_latency = param->value.ui;
00460 break;
00461
00462 case 'l':
00463 pa_devices->DisplayDevicesNames();
00464 break;
00465 }
00466 }
00467
00468
00469 if (!capture && !playback) {
00470 capture = true;
00471 playback = true;
00472 }
00473
00474 Jack::JackDriverClientInterface* driver = new Jack::JackPortAudioDriver("system", "portaudio", engine, table, pa_devices);
00475 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)
00476 {
00477 return driver;
00478 }
00479 else
00480 {
00481 delete driver;
00482 return NULL;
00483 }
00484 }
00485
00486 #ifdef __cplusplus
00487 }
00488 #endif