Jack2 1.9.6
|
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 "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 // Setup threadded based log function 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 // Generic JackAudioDriver Open 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 //get devices 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 //default channels number required 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 //too many channels required, take max available 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 //in/out streams parametering 00127 inputParameters.device = fInputDevice; 00128 inputParameters.channelCount = inchannels; 00129 inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output 00130 inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO 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; // 32 bit floating point output 00138 outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO 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, // Clipping is on... 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 // Core driver may have changed the in/out values 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 //change parametering 00217 inputParameters.device = fInputDevice; 00218 inputParameters.channelCount = fCaptureChannels; 00219 inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output 00220 inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO 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; // 32 bit floating point output 00228 outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO 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, // Clipping is on... 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 // Only done when success 00250 return JackAudioDriver::SetBufferSize(buffer_size); // never fails 00251 } 00252 } 00253 00254 } // end of namespace 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"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 00270 strcpy(desc->desc, "PortAudio API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 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 = param->value.str; 00408 playback_pcm_name = 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 = 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 = 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 // duplex is the default 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