Jack2 1.9.6

JackPortAudioAdapter.cpp

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