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 = (jack_default_audio_sample_t**)inputBuffer;
00042 driver->fOutputBuffer = (jack_default_audio_sample_t**)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(jack_default_audio_sample_t) * 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(jack_default_audio_sample_t) * 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
00184 int res = JackAudioDriver::Close();
00185
00186 jack_log("JackPortAudioDriver::Close");
00187 Pa_CloseStream(fStream);
00188 return res;
00189 }
00190
00191 int JackPortAudioDriver::Start()
00192 {
00193 jack_log("JackPortAudioDriver::Start");
00194 if (JackAudioDriver::Start() >= 0) {
00195 PaError err = Pa_StartStream(fStream);
00196 if (err == paNoError) {
00197 return 0;
00198 }
00199 JackAudioDriver::Stop();
00200 }
00201 return -1;
00202 }
00203
00204 int JackPortAudioDriver::Stop()
00205 {
00206 jack_log("JackPortAudioDriver::Stop");
00207 PaError err = Pa_StopStream(fStream);
00208 int res = (err == paNoError) ? 0 : -1;
00209 if (JackAudioDriver::Stop() < 0) {
00210 res = -1;
00211 }
00212 return res;
00213 }
00214
00215 int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
00216 {
00217 PaError err;
00218 PaStreamParameters inputParameters;
00219 PaStreamParameters outputParameters;
00220
00221 if ((err = Pa_CloseStream(fStream)) != paNoError)
00222 {
00223 jack_error("Pa_CloseStream error = %s", Pa_GetErrorText(err));
00224 return -1;
00225 }
00226
00227
00228 inputParameters.device = fInputDevice;
00229 inputParameters.channelCount = fCaptureChannels;
00230 inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00231 inputParameters.suggestedLatency = (fInputDevice != paNoDevice)
00232 ? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency
00233 : 0;
00234 inputParameters.hostApiSpecificStreamInfo = NULL;
00235
00236 outputParameters.device = fOutputDevice;
00237 outputParameters.channelCount = fPlaybackChannels;
00238 outputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00239 outputParameters.suggestedLatency = (fOutputDevice != paNoDevice)
00240 ? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency
00241 : 0;
00242 outputParameters.hostApiSpecificStreamInfo = NULL;
00243
00244 err = Pa_OpenStream(&fStream,
00245 (fInputDevice == paNoDevice) ? 0 : &inputParameters,
00246 (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
00247 fEngineControl->fSampleRate,
00248 buffer_size,
00249 paNoFlag,
00250 Render,
00251 this);
00252
00253 if (err != paNoError)
00254 {
00255 jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
00256 return -1;
00257 }
00258 else
00259 {
00260
00261 return JackAudioDriver::SetBufferSize(buffer_size);
00262 }
00263 }
00264
00265 }
00266
00267 #ifdef __cplusplus
00268 extern "C"
00269 {
00270 #endif
00271
00272 #include "JackCompilerDeps.h"
00273
00274 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
00275 {
00276 jack_driver_desc_t *desc;
00277 unsigned int i;
00278 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
00279
00280 strcpy(desc->name, "portaudio");
00281 strcpy(desc->desc, "PortAudio API based audio backend");
00282
00283 desc->nparams = 13;
00284 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
00285
00286 i = 0;
00287 strcpy(desc->params[i].name, "channels");
00288 desc->params[i].character = 'c';
00289 desc->params[i].type = JackDriverParamInt;
00290 desc->params[i].value.ui = 0;
00291 strcpy(desc->params[i].short_desc, "Maximum number of channels");
00292 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00293
00294 i++;
00295 strcpy(desc->params[i].name, "inchannels");
00296 desc->params[i].character = 'i';
00297 desc->params[i].type = JackDriverParamInt;
00298 desc->params[i].value.ui = 0;
00299 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
00300 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00301
00302 i++;
00303 strcpy(desc->params[i].name, "outchannels");
00304 desc->params[i].character = 'o';
00305 desc->params[i].type = JackDriverParamInt;
00306 desc->params[i].value.ui = 0;
00307 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
00308 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00309
00310 i++;
00311 strcpy(desc->params[i].name, "capture");
00312 desc->params[i].character = 'C';
00313 desc->params[i].type = JackDriverParamString;
00314 strcpy(desc->params[i].value.str, "will take default PortAudio input device");
00315 strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
00316 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00317
00318 i++;
00319 strcpy(desc->params[i].name, "playback");
00320 desc->params[i].character = 'P';
00321 desc->params[i].type = JackDriverParamString;
00322 strcpy(desc->params[i].value.str, "will take default PortAudio output device");
00323 strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
00324 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00325
00326 i++;
00327 strcpy (desc->params[i].name, "monitor");
00328 desc->params[i].character = 'm';
00329 desc->params[i].type = JackDriverParamBool;
00330 desc->params[i].value.i = 0;
00331 strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
00332 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00333
00334 i++;
00335 strcpy(desc->params[i].name, "duplex");
00336 desc->params[i].character = 'D';
00337 desc->params[i].type = JackDriverParamBool;
00338 desc->params[i].value.i = TRUE;
00339 strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
00340 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00341
00342 i++;
00343 strcpy(desc->params[i].name, "rate");
00344 desc->params[i].character = 'r';
00345 desc->params[i].type = JackDriverParamUInt;
00346 desc->params[i].value.ui = 44100U;
00347 strcpy(desc->params[i].short_desc, "Sample rate");
00348 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00349
00350 i++;
00351 strcpy(desc->params[i].name, "period");
00352 desc->params[i].character = 'p';
00353 desc->params[i].type = JackDriverParamUInt;
00354 desc->params[i].value.ui = 128U;
00355 strcpy(desc->params[i].short_desc, "Frames per period");
00356 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00357
00358 i++;
00359 strcpy(desc->params[i].name, "device");
00360 desc->params[i].character = 'd';
00361 desc->params[i].type = JackDriverParamString;
00362 strcpy(desc->params[i].value.str, "will take default PortAudio device name");
00363 strcpy(desc->params[i].short_desc, "PortAudio device name");
00364 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00365
00366 i++;
00367 strcpy(desc->params[i].name, "input-latency");
00368 desc->params[i].character = 'I';
00369 desc->params[i].type = JackDriverParamUInt;
00370 desc->params[i].value.i = 0;
00371 strcpy(desc->params[i].short_desc, "Extra input latency");
00372 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00373
00374 i++;
00375 strcpy(desc->params[i].name, "output-latency");
00376 desc->params[i].character = 'O';
00377 desc->params[i].type = JackDriverParamUInt;
00378 desc->params[i].value.i = 0;
00379 strcpy(desc->params[i].short_desc, "Extra output latency");
00380 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00381
00382 i++;
00383 strcpy(desc->params[i].name, "list-devices");
00384 desc->params[i].character = 'l';
00385 desc->params[i].type = JackDriverParamBool;
00386 desc->params[i].value.i = TRUE;
00387 strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
00388 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00389
00390 return desc;
00391 }
00392
00393 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
00394 {
00395 jack_nframes_t srate = 44100;
00396 jack_nframes_t frames_per_interrupt = 512;
00397 const char* capture_pcm_name = "";
00398 const char* playback_pcm_name = "";
00399 bool capture = false;
00400 bool playback = false;
00401 int chan_in = 0;
00402 int chan_out = 0;
00403 bool monitor = false;
00404 const JSList *node;
00405 const jack_driver_param_t *param;
00406 jack_nframes_t systemic_input_latency = 0;
00407 jack_nframes_t systemic_output_latency = 0;
00408 PortAudioDevices* pa_devices = new PortAudioDevices();
00409
00410 for (node = params; node; node = jack_slist_next(node))
00411 {
00412 param = (const jack_driver_param_t *) node->data;
00413
00414 switch (param->character)
00415 {
00416
00417 case 'd':
00418 capture_pcm_name = param->value.str;
00419 playback_pcm_name = param->value.str;
00420 break;
00421
00422 case 'D':
00423 capture = true;
00424 playback = true;
00425 break;
00426
00427 case 'c':
00428 chan_in = chan_out = (int)param->value.ui;
00429 break;
00430
00431 case 'i':
00432 chan_in = (int)param->value.ui;
00433 break;
00434
00435 case 'o':
00436 chan_out = (int)param->value.ui;
00437 break;
00438
00439 case 'C':
00440 capture = true;
00441 if (strcmp(param->value.str, "none") != 0) {
00442 capture_pcm_name = param->value.str;
00443 }
00444 break;
00445
00446 case 'P':
00447 playback = TRUE;
00448 if (strcmp(param->value.str, "none") != 0) {
00449 playback_pcm_name = param->value.str;
00450 }
00451 break;
00452
00453 case 'm':
00454 monitor = param->value.i;
00455 break;
00456
00457 case 'r':
00458 srate = param->value.ui;
00459 break;
00460
00461 case 'p':
00462 frames_per_interrupt = (unsigned int)param->value.ui;
00463 break;
00464
00465 case 'I':
00466 systemic_input_latency = param->value.ui;
00467 break;
00468
00469 case 'O':
00470 systemic_output_latency = param->value.ui;
00471 break;
00472
00473 case 'l':
00474 pa_devices->DisplayDevicesNames();
00475 break;
00476 }
00477 }
00478
00479
00480 if (!capture && !playback) {
00481 capture = true;
00482 playback = true;
00483 }
00484
00485 Jack::JackDriverClientInterface* driver = new Jack::JackPortAudioDriver("system", "portaudio", engine, table, pa_devices);
00486 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)
00487 {
00488 return driver;
00489 }
00490 else
00491 {
00492 delete driver;
00493 return NULL;
00494 }
00495 }
00496
00497 #ifdef __cplusplus
00498 }
00499 #endif