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 "JackAlsaAdapter.h" 00025 #include "JackServerGlobals.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 fAudioInterface.fFrequency = param->value.ui; 00070 SetAdaptedSampleRate ( param->value.ui ); 00071 break; 00072 case 'p': 00073 fAudioInterface.fBuffering = param->value.ui; 00074 SetAdaptedBufferSize ( param->value.ui ); 00075 break; 00076 case 'q': 00077 fQuality = param->value.ui; 00078 break; 00079 case 'g': 00080 fRingbufferCurSize = param->value.ui; 00081 fAdaptative = false; 00082 break; 00083 } 00084 } 00085 00086 fAudioInterface.setInputs ( fCaptureChannels ); 00087 fAudioInterface.setOutputs ( fPlaybackChannels ); 00088 } 00089 00090 int JackAlsaAdapter::Open() 00091 { 00092 //open audio interface 00093 if ( fAudioInterface.open() ) 00094 return -1; 00095 00096 //start adapter thread 00097 if ( fThread.StartSync() < 0 ) 00098 { 00099 jack_error ( "Cannot start audioadapter thread" ); 00100 return -1; 00101 } 00102 00103 //display card info 00104 fAudioInterface.longinfo(); 00105 00106 //turn the thread realtime 00107 fThread.AcquireRealTime ( JackServerGlobals::fInstance->GetEngineControl()->fClientPriority ); 00108 return 0; 00109 } 00110 00111 int JackAlsaAdapter::Close() 00112 { 00113 #ifdef JACK_MONITOR 00114 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); 00115 #endif 00116 switch ( fThread.GetStatus() ) 00117 { 00118 00119 // Kill the thread in Init phase 00120 case JackThread::kStarting: 00121 case JackThread::kIniting: 00122 if ( fThread.Kill() < 0 ) 00123 { 00124 jack_error ( "Cannot kill thread" ); 00125 return -1; 00126 } 00127 break; 00128 00129 // Stop when the thread cycle is finished 00130 case JackThread::kRunning: 00131 if ( fThread.Stop() < 0 ) 00132 { 00133 jack_error ( "Cannot stop thread" ); 00134 return -1; 00135 } 00136 break; 00137 00138 default: 00139 break; 00140 } 00141 return fAudioInterface.close(); 00142 } 00143 00144 bool JackAlsaAdapter::Init() 00145 { 00146 //fill the hardware buffers 00147 for ( unsigned int i = 0; i < fAudioInterface.fPeriod; i++ ) 00148 fAudioInterface.write(); 00149 return true; 00150 } 00151 00152 bool JackAlsaAdapter::Execute() 00153 { 00154 //read data from audio interface 00155 if (fAudioInterface.read() < 0) 00156 return false; 00157 00158 PushAndPull(fAudioInterface.fInputSoftChannels, fAudioInterface.fOutputSoftChannels, fAdaptedBufferSize); 00159 00160 //write data to audio interface 00161 if (fAudioInterface.write() < 0) 00162 return false; 00163 00164 return true; 00165 } 00166 00167 int JackAlsaAdapter::SetSampleRate ( jack_nframes_t sample_rate ) 00168 { 00169 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate ); 00170 Close(); 00171 return Open(); 00172 } 00173 00174 int JackAlsaAdapter::SetBufferSize ( jack_nframes_t buffer_size ) 00175 { 00176 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size ); 00177 Close(); 00178 return Open(); 00179 } 00180 00181 } // namespace 00182 00183 #ifdef __cplusplus 00184 extern "C" 00185 { 00186 #endif 00187 00188 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() 00189 { 00190 jack_driver_desc_t *desc; 00191 unsigned int i; 00192 desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) ); 00193 00194 strcpy ( desc->name, "audioadapter" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 00195 strcpy ( desc->desc, "netjack audio <==> net backend adapter" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 00196 00197 desc->nparams = 11; 00198 desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); 00199 00200 i = 0; 00201 strcpy ( desc->params[i].name, "capture" ); 00202 desc->params[i].character = 'C'; 00203 desc->params[i].type = JackDriverParamString; 00204 strcpy ( desc->params[i].value.str, "none" ); 00205 strcpy ( desc->params[i].short_desc, 00206 "Provide capture ports. Optionally set device" ); 00207 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00208 00209 i++; 00210 strcpy ( desc->params[i].name, "playback" ); 00211 desc->params[i].character = 'P'; 00212 desc->params[i].type = JackDriverParamString; 00213 strcpy ( desc->params[i].value.str, "none" ); 00214 strcpy ( desc->params[i].short_desc, 00215 "Provide playback ports. Optionally set device" ); 00216 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00217 00218 i++; 00219 strcpy ( desc->params[i].name, "device" ); 00220 desc->params[i].character = 'd'; 00221 desc->params[i].type = JackDriverParamString; 00222 strcpy ( desc->params[i].value.str, "hw:0" ); 00223 strcpy ( desc->params[i].short_desc, "ALSA device name" ); 00224 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00225 00226 i++; 00227 strcpy ( desc->params[i].name, "rate" ); 00228 desc->params[i].character = 'r'; 00229 desc->params[i].type = JackDriverParamUInt; 00230 desc->params[i].value.ui = 48000U; 00231 strcpy ( desc->params[i].short_desc, "Sample rate" ); 00232 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00233 00234 i++; 00235 strcpy ( desc->params[i].name, "periodsize" ); 00236 desc->params[i].character = 'p'; 00237 desc->params[i].type = JackDriverParamUInt; 00238 desc->params[i].value.ui = 512U; 00239 strcpy ( desc->params[i].short_desc, "Period size" ); 00240 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00241 00242 i++; 00243 strcpy ( desc->params[i].name, "nperiods" ); 00244 desc->params[i].character = 'n'; 00245 desc->params[i].type = JackDriverParamUInt; 00246 desc->params[i].value.ui = 2U; 00247 strcpy ( desc->params[i].short_desc, "Number of periods of playback latency" ); 00248 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00249 00250 i++; 00251 strcpy ( desc->params[i].name, "duplex" ); 00252 desc->params[i].character = 'D'; 00253 desc->params[i].type = JackDriverParamBool; 00254 desc->params[i].value.i = true; 00255 strcpy ( desc->params[i].short_desc, 00256 "Provide both capture and playback ports" ); 00257 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00258 00259 i++; 00260 strcpy ( desc->params[i].name, "inchannels" ); 00261 desc->params[i].character = 'i'; 00262 desc->params[i].type = JackDriverParamUInt; 00263 desc->params[i].value.i = 0; 00264 strcpy ( desc->params[i].short_desc, 00265 "Number of capture channels (defaults to hardware max)" ); 00266 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00267 00268 i++; 00269 strcpy ( desc->params[i].name, "outchannels" ); 00270 desc->params[i].character = 'o'; 00271 desc->params[i].type = JackDriverParamUInt; 00272 desc->params[i].value.i = 0; 00273 strcpy ( desc->params[i].short_desc, 00274 "Number of playback channels (defaults to hardware max)" ); 00275 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00276 00277 i++; 00278 strcpy(desc->params[i].name, "quality"); 00279 desc->params[i].character = 'q'; 00280 desc->params[i].type = JackDriverParamInt; 00281 desc->params[i].value.ui = 0; 00282 strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); 00283 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00284 00285 i++; 00286 strcpy(desc->params[i].name, "ring-buffer"); 00287 desc->params[i].character = 'g'; 00288 desc->params[i].type = JackDriverParamInt; 00289 desc->params[i].value.ui = 32768; 00290 strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); 00291 strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); 00292 00293 return desc; 00294 } 00295 00296 #ifdef __cplusplus 00297 } 00298 #endif 00299