00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #if defined(HAVE_CONFIG_H)
00021 #include "config.h"
00022 #endif
00023
00024 #include "JackPortAudioAdapter.h"
00025 #include "JackError.h"
00026
00027 namespace Jack
00028 {
00029
00030 int JackPortAudioAdapter::Render ( const void* inputBuffer,
00031 void* outputBuffer,
00032 unsigned long framesPerBuffer,
00033 const PaStreamCallbackTimeInfo* timeInfo,
00034 PaStreamCallbackFlags statusFlags,
00035 void* userData)
00036 {
00037 JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(userData);
00038 float** paBuffer;
00039 bool failure = false;
00040
00041 jack_nframes_t time1, time2;
00042 adapter->ResampleFactor ( time1, time2 );
00043
00044 paBuffer = (float**)inputBuffer;
00045 for ( int i = 0; i < adapter->fCaptureChannels; i++ )
00046 {
00047 adapter->fCaptureRingBuffer[i]->SetRatio ( time1, time2 );
00048 if (adapter->fCaptureRingBuffer[i]->WriteResample ( (float*)paBuffer[i], framesPerBuffer ) < framesPerBuffer )
00049 failure = true;
00050 }
00051
00052 paBuffer = (float**)outputBuffer;
00053 for ( int i = 0; i < adapter->fPlaybackChannels; i++ )
00054 {
00055 adapter->fPlaybackRingBuffer[i]->SetRatio ( time2, time1 );
00056 if ( adapter->fPlaybackRingBuffer[i]->ReadResample ( (float*)paBuffer[i], framesPerBuffer ) < framesPerBuffer )
00057 failure = true;
00058 }
00059
00060 #ifdef JACK_MONITOR
00061 adapter->fTable.Write ( time1, time2, double(time1) / double(time2), double(time2) / double(time1),
00062 adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace() );
00063 #endif
00064
00065
00066 if ( failure )
00067 {
00068 jack_error ( "JackPortAudioAdapter::Render ringbuffer failure... reset" );
00069 adapter->ResetRingBuffers();
00070 }
00071 return paContinue;
00072 }
00073
00074 JackPortAudioAdapter::JackPortAudioAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params )
00075 : JackAudioAdapterInterface ( buffer_size, sample_rate )
00076 {
00077 jack_log ( "JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate );
00078
00079 const JSList* node;
00080 const jack_driver_param_t* param;
00081 int in_max = 0;
00082 int out_max = 0;
00083
00084 fInputDevice = Pa_GetDefaultInputDevice();
00085 fOutputDevice = Pa_GetDefaultOutputDevice();
00086
00087 for (node = params; node; node = jack_slist_next(node))
00088 {
00089 param = (const jack_driver_param_t*) node->data;
00090
00091 switch (param->character)
00092 {
00093 case 'i' :
00094 fCaptureChannels = param->value.ui;
00095 break;
00096 case 'o' :
00097 fPlaybackChannels = param->value.ui;
00098 break;
00099 case 'C' :
00100 if ( fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0 )
00101 {
00102 jack_error ( "Can't use %s, taking default input device", param->value.str );
00103 fInputDevice = Pa_GetDefaultInputDevice();
00104 }
00105 break;
00106 case 'P' :
00107 if ( fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0 )
00108 {
00109 jack_error ( "Can't use %s, taking default output device", param->value.str );
00110 fOutputDevice = Pa_GetDefaultOutputDevice();
00111 }
00112 break;
00113 case 'r' :
00114 SetAdaptedSampleRate ( param->value.ui );
00115 break;
00116 case 'p' :
00117 SetAdaptedBufferSize ( param->value.ui );
00118 break;
00119 case 'd' :
00120 if ( fPaDevices.GetInputDeviceFromName ( param->value.str, fInputDevice, in_max ) < 0 )
00121 jack_error ( "Can't use %s, taking default input device", param->value.str );
00122 if ( fPaDevices.GetOutputDeviceFromName ( param->value.str, fOutputDevice, out_max ) < 0 )
00123 jack_error ( "Can't use %s, taking default output device", param->value.str );
00124 break;
00125 case 'l' :
00126 fPaDevices.DisplayDevicesNames();
00127 break;
00128 }
00129 }
00130
00131
00132 if ( in_max == 0 )
00133 in_max = fPaDevices.GetDeviceInfo ( fInputDevice )->maxInputChannels;
00134 if ( out_max == 0 )
00135 out_max = fPaDevices.GetDeviceInfo ( fOutputDevice )->maxOutputChannels;
00136
00137
00138 if ( ( fCaptureChannels == 0 ) || ( fCaptureChannels > in_max ) )
00139 fCaptureChannels = in_max;
00140 if ( ( fPlaybackChannels == 0 ) || ( fPlaybackChannels > out_max ) )
00141 fPlaybackChannels = out_max;
00142
00143
00144 SetInputs ( fCaptureChannels );
00145 SetOutputs ( fPlaybackChannels );
00146 }
00147
00148 int JackPortAudioAdapter::Open()
00149 {
00150 PaError err;
00151 PaStreamParameters inputParameters;
00152 PaStreamParameters outputParameters;
00153
00154 if ( JackAudioAdapterInterface::Open() < 0 )
00155 return -1;
00156
00157 jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str());
00158 jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str());
00159 jack_log("JackPortAudioAdapter::Open fAdaptedBufferSize = %u fAdaptedSampleRate %u", fAdaptedBufferSize, fAdaptedSampleRate);
00160
00161 inputParameters.device = fInputDevice;
00162 inputParameters.channelCount = fCaptureChannels;
00163 inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00164 inputParameters.suggestedLatency = ( fInputDevice != paNoDevice )
00165 ? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency
00166 : 0;
00167 inputParameters.hostApiSpecificStreamInfo = NULL;
00168
00169 outputParameters.device = fOutputDevice;
00170 outputParameters.channelCount = fPlaybackChannels;
00171 outputParameters.sampleFormat = paFloat32 | paNonInterleaved;
00172 outputParameters.suggestedLatency = ( fOutputDevice != paNoDevice )
00173 ? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
00174 : 0;
00175 outputParameters.hostApiSpecificStreamInfo = NULL;
00176
00177 err = Pa_OpenStream( &fStream,
00178 ( fInputDevice == paNoDevice ) ? 0 : &inputParameters,
00179 ( fOutputDevice == paNoDevice ) ? 0 : &outputParameters,
00180 fAdaptedSampleRate,
00181 fAdaptedBufferSize,
00182 paNoFlag,
00183 Render,
00184 this );
00185
00186 if ( err != paNoError )
00187 {
00188 jack_error ( "Pa_OpenStream error = %s", Pa_GetErrorText ( err ) );
00189 return -1;
00190 }
00191
00192 err = Pa_StartStream ( fStream );
00193
00194 if ( err != paNoError )
00195 {
00196 jack_error ( "Pa_StartStream error = %s", Pa_GetErrorText ( err ) );
00197 return -1;
00198 }
00199
00200 jack_log ( "JackPortAudioAdapter::Open OK" );
00201 return 0;
00202 }
00203
00204 int JackPortAudioAdapter::Close()
00205 {
00206 #ifdef JACK_MONITOR
00207 fTable.Save();
00208 #endif
00209 jack_log ( "JackPortAudioAdapter::Close" );
00210 Pa_StopStream ( fStream );
00211 jack_log ( "JackPortAudioAdapter:: Pa_StopStream" );
00212 Pa_CloseStream ( fStream );
00213 jack_log ( "JackPortAudioAdapter:: Pa_CloseStream" );
00214 return JackAudioAdapterInterface::Close();
00215 }
00216
00217 int JackPortAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate )
00218 {
00219 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
00220 Close();
00221 return Open();
00222 }
00223
00224 int JackPortAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size )
00225 {
00226 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
00227 Close();
00228 return Open();
00229 }
00230
00231 }
00232
00233 #ifdef __cplusplus
00234 extern "C"
00235 {
00236 #endif
00237
00238 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00239 {
00240 jack_driver_desc_t *desc;
00241 unsigned int i;
00242 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
00243
00244 strcpy(desc->name, "audioadapter");
00245 strcpy(desc->desc, "netjack audio <==> net backend adapter");
00246
00247 desc->nparams = 8;
00248 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
00249
00250 i = 0;
00251 strcpy(desc->params[i].name, "inchannels");
00252 desc->params[i].character = 'i';
00253 desc->params[i].type = JackDriverParamInt;
00254 desc->params[i].value.ui = 0;
00255 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
00256 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00257
00258 i++;
00259 strcpy(desc->params[i].name, "outchannels");
00260 desc->params[i].character = 'o';
00261 desc->params[i].type = JackDriverParamInt;
00262 desc->params[i].value.ui = 0;
00263 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
00264 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00265
00266 i++;
00267 strcpy(desc->params[i].name, "capture");
00268 desc->params[i].character = 'C';
00269 desc->params[i].type = JackDriverParamString;
00270 strcpy(desc->params[i].value.str, "default input device");
00271 strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
00272 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00273
00274 i++;
00275 strcpy(desc->params[i].name, "playback");
00276 desc->params[i].character = 'P';
00277 desc->params[i].type = JackDriverParamString;
00278 strcpy(desc->params[i].value.str, "default output device");
00279 strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
00280 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00281
00282 i++;
00283 strcpy(desc->params[i].name, "rate");
00284 desc->params[i].character = 'r';
00285 desc->params[i].type = JackDriverParamUInt;
00286 desc->params[i].value.ui = 44100U;
00287 strcpy(desc->params[i].short_desc, "Sample rate");
00288 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00289
00290 i++;
00291 strcpy(desc->params[i].name, "periodsize");
00292 desc->params[i].character = 'p';
00293 desc->params[i].type = JackDriverParamUInt;
00294 desc->params[i].value.ui = 512U;
00295 strcpy(desc->params[i].short_desc, "Period size");
00296 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00297
00298 i++;
00299 strcpy(desc->params[i].name, "device");
00300 desc->params[i].character = 'd';
00301 desc->params[i].type = JackDriverParamString;
00302 desc->params[i].value.ui = 128U;
00303 strcpy(desc->params[i].value.str, "default device");
00304 strcpy(desc->params[i].short_desc, "PortAudio device name");
00305 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00306
00307 i++;
00308 strcpy(desc->params[i].name, "list-devices");
00309 desc->params[i].character = 'l';
00310 desc->params[i].type = JackDriverParamBool;
00311 desc->params[i].value.i = TRUE;
00312 strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
00313 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00314
00315 return desc;
00316 }
00317
00318 #ifdef __cplusplus
00319 }
00320 #endif