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 "JackAlsaAdapter.h"
00025 #include "JackServer.h"
00026 #include "JackEngineControl.h"
00027
00028 namespace Jack
00029 {
00030
00031 JackAlsaAdapter::JackAlsaAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params ) :
00032 JackAudioAdapterInterface ( buffer_size, sample_rate ),
00033 fThread ( this ),
00034 fAudioInterface ( buffer_size, sample_rate )
00035 {
00036 const JSList* node;
00037 const jack_driver_param_t* param;
00038
00039 fCaptureChannels = 2;
00040 fPlaybackChannels = 2;
00041
00042 fAudioInterface.fPeriod = 2;
00043
00044 for ( node = params; node; node = jack_slist_next ( node ) )
00045 {
00046 param = ( const jack_driver_param_t* ) node->data;
00047
00048 switch ( param->character )
00049 {
00050 case 'i':
00051 fCaptureChannels = param->value.ui;
00052 break;
00053 case 'o':
00054 fPlaybackChannels = param->value.ui;
00055 break;
00056 case 'C':
00057 break;
00058 case 'P':
00059 break;
00060 case 'D':
00061 break;
00062 case 'n':
00063 fAudioInterface.fPeriod = param->value.ui;
00064 break;
00065 case 'd':
00066 fAudioInterface.fCardName = strdup ( param->value.str );
00067 break;
00068 case 'r':
00069 SetAdaptedSampleRate ( param->value.ui );
00070 break;
00071 case 'p':
00072 SetAdaptedBufferSize ( param->value.ui );
00073 break;
00074 }
00075 }
00076
00077 fAudioInterface.setInputs ( fCaptureChannels );
00078 fAudioInterface.setOutputs ( fPlaybackChannels );
00079 }
00080
00081 int JackAlsaAdapter::Open()
00082 {
00083
00084 if ( fAudioInterface.open() )
00085 return -1;
00086
00087
00088 if ( fThread.StartSync() < 0 )
00089 {
00090 jack_error ( "Cannot start audioadapter thread" );
00091 return -1;
00092 }
00093
00094
00095 fAudioInterface.longinfo();
00096
00097
00098 fThread.AcquireRealTime ( JackServer::fInstance->GetEngineControl()->fPriority );
00099
00100 return 0;
00101 }
00102
00103 int JackAlsaAdapter::Close()
00104 {
00105 #ifdef JACK_MONITOR
00106 fTable.Save();
00107 #endif
00108 switch ( fThread.GetStatus() )
00109 {
00110
00111
00112 case JackThread::kStarting:
00113 case JackThread::kIniting:
00114 if ( fThread.Kill() < 0 )
00115 {
00116 jack_error ( "Cannot kill thread" );
00117 return -1;
00118 }
00119 break;
00120
00121
00122 case JackThread::kRunning:
00123 if ( fThread.Stop() < 0 )
00124 {
00125 jack_error ( "Cannot stop thread" );
00126 return -1;
00127 }
00128 break;
00129
00130 default:
00131 break;
00132 }
00133 return fAudioInterface.close();
00134 }
00135
00136 bool JackAlsaAdapter::Init()
00137 {
00138
00139 for ( unsigned int i = 0; i < fAudioInterface.fPeriod; i++ )
00140 fAudioInterface.write();
00141 return true;
00142 }
00143
00144 bool JackAlsaAdapter::Execute()
00145 {
00146
00147 if ( fAudioInterface.read() < 0 )
00148 return false;
00149
00150 bool failure = false;
00151
00152
00153 jack_nframes_t time1, time2;
00154 ResampleFactor ( time1, time2 );
00155
00156
00157 for ( int i = 0; i < fCaptureChannels; i++ )
00158 {
00159 fCaptureRingBuffer[i]->SetRatio ( time1, time2 );
00160 if ( fCaptureRingBuffer[i]->WriteResample ( fAudioInterface.fInputSoftChannels[i], fAdaptedBufferSize ) < fAdaptedBufferSize )
00161 failure = true;
00162 }
00163
00164 for ( int i = 0; i < fPlaybackChannels; i++ )
00165 {
00166 fPlaybackRingBuffer[i]->SetRatio ( time2, time1 );
00167 if ( fPlaybackRingBuffer[i]->ReadResample ( fAudioInterface.fOutputSoftChannels[i], fAdaptedBufferSize ) < fAdaptedBufferSize )
00168 failure = true;
00169 }
00170
00171 #ifdef JACK_MONITOR
00172 fTable.Write ( time1, time2, double ( time1 ) / double ( time2 ), double ( time2 ) / double ( time1 ),
00173 fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace() );
00174 #endif
00175
00176
00177 if ( fAudioInterface.write() < 0 )
00178 return false;
00179
00180
00181 if ( failure )
00182 {
00183 jack_error ( "JackAlsaAdapter::Execute ringbuffer failure... reset" );
00184 ResetRingBuffers();
00185 }
00186
00187 return true;
00188 }
00189
00190 int JackAlsaAdapter::SetSampleRate ( jack_nframes_t sample_rate )
00191 {
00192 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
00193 Close();
00194 return Open();
00195 }
00196
00197 int JackAlsaAdapter::SetBufferSize ( jack_nframes_t buffer_size )
00198 {
00199 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
00200 Close();
00201 return Open();
00202 }
00203
00204 }
00205
00206 #ifdef __cplusplus
00207 extern "C"
00208 {
00209 #endif
00210
00211 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00212 {
00213 jack_driver_desc_t *desc;
00214 jack_driver_param_desc_t * params;
00215 unsigned int i;
00216
00217 desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
00218
00219 strcpy ( desc->name, "audioadapter" );
00220 strcpy ( desc->desc, "netjack audio <==> net backend adapter" );
00221
00222 desc->nparams = 9;
00223 params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
00224
00225 i = 0;
00226 strcpy ( params[i].name, "capture" );
00227 params[i].character = 'C';
00228 params[i].type = JackDriverParamString;
00229 strcpy ( params[i].value.str, "none" );
00230 strcpy ( params[i].short_desc,
00231 "Provide capture ports. Optionally set device" );
00232 strcpy ( params[i].long_desc, params[i].short_desc );
00233
00234 i++;
00235 strcpy ( params[i].name, "playback" );
00236 params[i].character = 'P';
00237 params[i].type = JackDriverParamString;
00238 strcpy ( params[i].value.str, "none" );
00239 strcpy ( params[i].short_desc,
00240 "Provide playback ports. Optionally set device" );
00241 strcpy ( params[i].long_desc, params[i].short_desc );
00242
00243 i++;
00244 strcpy ( params[i].name, "device" );
00245 params[i].character = 'd';
00246 params[i].type = JackDriverParamString;
00247 strcpy ( params[i].value.str, "hw:0" );
00248 strcpy ( params[i].short_desc, "ALSA device name" );
00249 strcpy ( params[i].long_desc, params[i].short_desc );
00250
00251 i++;
00252 strcpy ( params[i].name, "rate" );
00253 params[i].character = 'r';
00254 params[i].type = JackDriverParamUInt;
00255 params[i].value.ui = 48000U;
00256 strcpy ( params[i].short_desc, "Sample rate" );
00257 strcpy ( params[i].long_desc, params[i].short_desc );
00258
00259 i++;
00260 strcpy ( params[i].name, "periodsize" );
00261 params[i].character = 'p';
00262 params[i].type = JackDriverParamUInt;
00263 params[i].value.ui = 512U;
00264 strcpy ( params[i].short_desc, "Period size" );
00265 strcpy ( params[i].long_desc, params[i].short_desc );
00266
00267 i++;
00268 strcpy ( params[i].name, "nperiods" );
00269 params[i].character = 'n';
00270 params[i].type = JackDriverParamUInt;
00271 params[i].value.ui = 2U;
00272 strcpy ( params[i].short_desc, "Number of periods of playback latency" );
00273 strcpy ( params[i].long_desc, params[i].short_desc );
00274
00275 i++;
00276 strcpy ( params[i].name, "duplex" );
00277 params[i].character = 'D';
00278 params[i].type = JackDriverParamBool;
00279 params[i].value.i = 1;
00280 strcpy ( params[i].short_desc,
00281 "Provide both capture and playback ports" );
00282 strcpy ( params[i].long_desc, params[i].short_desc );
00283
00284 i++;
00285 strcpy ( params[i].name, "inchannels" );
00286 params[i].character = 'i';
00287 params[i].type = JackDriverParamUInt;
00288 params[i].value.i = 0;
00289 strcpy ( params[i].short_desc,
00290 "Number of capture channels (defaults to hardware max)" );
00291 strcpy ( params[i].long_desc, params[i].short_desc );
00292
00293 i++;
00294 strcpy ( params[i].name, "outchannels" );
00295 params[i].character = 'o';
00296 params[i].type = JackDriverParamUInt;
00297 params[i].value.i = 0;
00298 strcpy ( params[i].short_desc,
00299 "Number of playback channels (defaults to hardware max)" );
00300 strcpy ( params[i].long_desc, params[i].short_desc );
00301
00302 desc->params = params;
00303 return desc;
00304 }
00305
00306 #ifdef __cplusplus
00307 }
00308 #endif
00309