Jack2 1.9.6
|
00001 /* 00002 Copyright (C) 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 #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 adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, framesPerBuffer); 00039 return paContinue; 00040 } 00041 00042 JackPortAudioAdapter::JackPortAudioAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params ) 00043 : JackAudioAdapterInterface ( buffer_size, sample_rate ) 00044 { 00045 jack_log ( "JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate ); 00046 00047 const JSList* node; 00048 const jack_driver_param_t* param; 00049 int in_max = 0; 00050 int out_max = 0; 00051 00052 fInputDevice = Pa_GetDefaultInputDevice(); 00053 fOutputDevice = Pa_GetDefaultOutputDevice(); 00054 00055 for (node = params; node; node = jack_slist_next(node)) 00056 { 00057 param = (const jack_driver_param_t*) node->data; 00058 00059 switch (param->character) 00060 { 00061 case 'i' : 00062 fCaptureChannels = param->value.ui; 00063 break; 00064 case 'o' : 00065 fPlaybackChannels = param->value.ui; 00066 break; 00067 case 'C' : 00068 if ( fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0 ) 00069 { 00070 jack_error ( "Can't use %s, taking default input device", param->value.str ); 00071 fInputDevice = Pa_GetDefaultInputDevice(); 00072 } 00073 break; 00074 case 'P' : 00075 if ( fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0 ) 00076 { 00077 jack_error ( "Can't use %s, taking default output device", param->value.str ); 00078 fOutputDevice = Pa_GetDefaultOutputDevice(); 00079 } 00080 break; 00081 case 'r' : 00082 SetAdaptedSampleRate ( param->value.ui ); 00083 break; 00084 case 'p' : 00085 SetAdaptedBufferSize ( param->value.ui ); 00086 break; 00087 case 'd' : 00088 if ( fPaDevices.GetInputDeviceFromName ( param->value.str, fInputDevice, in_max ) < 0 ) 00089 jack_error ( "Can't use %s, taking default input device", param->value.str ); 00090 if ( fPaDevices.GetOutputDeviceFromName ( param->value.str, fOutputDevice, out_max ) < 0 ) 00091 jack_error ( "Can't use %s, taking default output device", param->value.str ); 00092 break; 00093 case 'l' : 00094 fPaDevices.DisplayDevicesNames(); 00095 break; 00096 case 'q': 00097 fQuality = param->value.ui; 00098 break; 00099 case 'g': 00100 fRingbufferCurSize = param->value.ui; 00101 fAdaptative = false; 00102 break; 00103 } 00104 } 00105 00106 //max channels 00107 if ( in_max == 0 ) 00108 in_max = fPaDevices.GetDeviceInfo ( fInputDevice )->maxInputChannels; 00109 if ( out_max == 0 ) 00110 out_max = fPaDevices.GetDeviceInfo ( fOutputDevice )->maxOutputChannels; 00111 00112 //effective channels 00113 if ( ( fCaptureChannels == 0 ) || ( fCaptureChannels > in_max ) ) 00114 fCaptureChannels = in_max; 00115 if ( ( fPlaybackChannels == 0 ) || ( fPlaybackChannels > out_max ) ) 00116 fPlaybackChannels = out_max; 00117 00118 //set adapter interface channels 00119 SetInputs ( fCaptureChannels ); 00120 SetOutputs ( fPlaybackChannels ); 00121 } 00122 00123 int JackPortAudioAdapter::Open() 00124 { 00125 PaError err; 00126 PaStreamParameters inputParameters; 00127 PaStreamParameters outputParameters; 00128 00129 if ( JackAudioAdapterInterface::Open() < 0 ) 00130 return -1; 00131 00132 jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str()); 00133 jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str()); 00134 jack_log("JackPortAudioAdapter::Open fAdaptedBufferSize = %u fAdaptedSampleRate %u", fAdaptedBufferSize, fAdaptedSampleRate); 00135 00136 inputParameters.device = fInputDevice; 00137 inputParameters.channelCount = fCaptureChannels; 00138 inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output 00139 inputParameters.suggestedLatency = ( fInputDevice != paNoDevice ) // TODO: check how to setup this on ASIO 00140 ? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency 00141 : 0; 00142 inputParameters.hostApiSpecificStreamInfo = NULL; 00143 00144 outputParameters.device = fOutputDevice; 00145 outputParameters.channelCount = fPlaybackChannels; 00146 outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output 00147 outputParameters.suggestedLatency = ( fOutputDevice != paNoDevice ) // TODO: check how to setup this on ASIO 00148 ? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency 00149 : 0; 00150 outputParameters.hostApiSpecificStreamInfo = NULL; 00151 00152 err = Pa_OpenStream( &fStream, 00153 ( fInputDevice == paNoDevice ) ? 0 : &inputParameters, 00154 ( fOutputDevice == paNoDevice ) ? 0 : &outputParameters, 00155 fAdaptedSampleRate, 00156 fAdaptedBufferSize, 00157 paNoFlag, // Clipping is on... 00158 Render, 00159 this ); 00160 00161 if ( err != paNoError ) 00162 { 00163 jack_error ( "Pa_OpenStream error = %s", Pa_GetErrorText ( err ) ); 00164 return -1; 00165 } 00166 00167 err = Pa_StartStream ( fStream ); 00168 00169 if ( err != paNoError ) 00170 { 00171 jack_error ( "Pa_StartStream error = %s", Pa_GetErrorText ( err ) ); 00172 return -1; 00173 } 00174 00175 jack_log ( "JackPortAudioAdapter::Open OK" ); 00176 return 0; 00177 } 00178 00179 int JackPortAudioAdapter::Close() 00180 { 00181 #ifdef JACK_MONITOR 00182 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); 00183 #endif 00184 jack_log ( "JackPortAudioAdapter::Close" ); 00185 Pa_StopStream ( fStream ); 00186 jack_log ( "JackPortAudioAdapter:: Pa_StopStream" ); 00187 Pa_CloseStream ( fStream ); 00188 jack_log ( "JackPortAudioAdapter:: Pa_CloseStream" ); 00189 return JackAudioAdapterInterface::Close(); 00190 } 00191 00192 int JackPortAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) 00193 { 00194 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate ); 00195 Close(); 00196 return Open(); 00197 } 00198 00199 int JackPortAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) 00200 { 00201 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size ); 00202 Close(); 00203 return Open(); 00204 } 00205 00206 } // namespace 00207 00208 #ifdef __cplusplus 00209 extern "C" 00210 { 00211 #endif 00212 00213 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() 00214 { 00215 jack_driver_desc_t *desc; 00216 unsigned int i; 00217 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); 00218 00219 strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 00220 strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 00221 00222 desc->nparams = 10; 00223 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); 00224 00225 i = 0; 00226 strcpy(desc->params[i].name, "inchannels"); 00227 desc->params[i].character = 'i'; 00228 desc->params[i].type = JackDriverParamInt; 00229 desc->params[i].value.ui = 0; 00230 strcpy(desc->params[i].short_desc, "Maximum number of input channels"); 00231 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00232 00233 i++; 00234 strcpy(desc->params[i].name, "outchannels"); 00235 desc->params[i].character = 'o'; 00236 desc->params[i].type = JackDriverParamInt; 00237 desc->params[i].value.ui = 0; 00238 strcpy(desc->params[i].short_desc, "Maximum number of output channels"); 00239 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00240 00241 i++; 00242 strcpy(desc->params[i].name, "capture"); 00243 desc->params[i].character = 'C'; 00244 desc->params[i].type = JackDriverParamString; 00245 strcpy(desc->params[i].value.str, "default input device"); 00246 strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name"); 00247 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00248 00249 i++; 00250 strcpy(desc->params[i].name, "playback"); 00251 desc->params[i].character = 'P'; 00252 desc->params[i].type = JackDriverParamString; 00253 strcpy(desc->params[i].value.str, "default output device"); 00254 strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name"); 00255 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00256 00257 i++; 00258 strcpy(desc->params[i].name, "rate"); 00259 desc->params[i].character = 'r'; 00260 desc->params[i].type = JackDriverParamUInt; 00261 desc->params[i].value.ui = 44100U; 00262 strcpy(desc->params[i].short_desc, "Sample rate"); 00263 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00264 00265 i++; 00266 strcpy(desc->params[i].name, "periodsize"); 00267 desc->params[i].character = 'p'; 00268 desc->params[i].type = JackDriverParamUInt; 00269 desc->params[i].value.ui = 512U; 00270 strcpy(desc->params[i].short_desc, "Period size"); 00271 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00272 00273 i++; 00274 strcpy(desc->params[i].name, "device"); 00275 desc->params[i].character = 'd'; 00276 desc->params[i].type = JackDriverParamString; 00277 desc->params[i].value.ui = 128U; 00278 strcpy(desc->params[i].value.str, "default device"); 00279 strcpy(desc->params[i].short_desc, "PortAudio device name"); 00280 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00281 00282 i++; 00283 strcpy(desc->params[i].name, "list-devices"); 00284 desc->params[i].character = 'l'; 00285 desc->params[i].type = JackDriverParamBool; 00286 desc->params[i].value.i = true; 00287 strcpy(desc->params[i].short_desc, "Display available PortAudio devices"); 00288 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00289 00290 i++; 00291 strcpy(desc->params[i].name, "quality"); 00292 desc->params[i].character = 'q'; 00293 desc->params[i].type = JackDriverParamInt; 00294 desc->params[i].value.ui = 0; 00295 strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); 00296 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00297 00298 i++; 00299 strcpy(desc->params[i].name, "ring-buffer"); 00300 desc->params[i].character = 'g'; 00301 desc->params[i].type = JackDriverParamInt; 00302 desc->params[i].value.ui = 32768; 00303 strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); 00304 strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); 00305 00306 return desc; 00307 } 00308 00309 #ifdef __cplusplus 00310 } 00311 #endif