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 "JackGlobals.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 if (strncmp(param->value.str,"none",4) != 0) {
00058 fAudioInterface.fCaptureName = strdup ( param->value.str );
00059 }
00060 break;
00061 case 'P':
00062 if (strncmp(param->value.str,"none",4) != 0) {
00063 fAudioInterface.fPlaybackName = strdup ( param->value.str );
00064 }
00065 break;
00066 case 'D':
00067 break;
00068 case 'n':
00069 fAudioInterface.fPeriod = param->value.ui;
00070 break;
00071 case 'd':
00072 fAudioInterface.fCardName = strdup ( param->value.str );
00073 break;
00074 case 'r':
00075 fAudioInterface.fFrequency = param->value.ui;
00076 SetAdaptedSampleRate ( param->value.ui );
00077 break;
00078 case 'p':
00079 fAudioInterface.fBuffering = param->value.ui;
00080 SetAdaptedBufferSize ( param->value.ui );
00081 break;
00082 case 'q':
00083 fQuality = param->value.ui;
00084 break;
00085 case 'g':
00086 fRingbufferCurSize = param->value.ui;
00087 fAdaptative = false;
00088 break;
00089 }
00090 }
00091
00092 fAudioInterface.setInputs ( fCaptureChannels );
00093 fAudioInterface.setOutputs ( fPlaybackChannels );
00094 }
00095
00096 int JackAlsaAdapter::Open()
00097 {
00098
00099 if ( fAudioInterface.open() )
00100 return -1;
00101
00102
00103 if ( fThread.StartSync() < 0 )
00104 {
00105 jack_error ( "Cannot start audioadapter thread" );
00106 return -1;
00107 }
00108
00109
00110 fAudioInterface.longinfo();
00111
00112
00113 fThread.AcquireRealTime(GetEngineControl()->fClientPriority);
00114 return 0;
00115 }
00116
00117 int JackAlsaAdapter::Close()
00118 {
00119 #ifdef JACK_MONITOR
00120 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
00121 #endif
00122 switch ( fThread.GetStatus() )
00123 {
00124
00125
00126 case JackThread::kStarting:
00127 case JackThread::kIniting:
00128 if ( fThread.Kill() < 0 )
00129 {
00130 jack_error ( "Cannot kill thread" );
00131 return -1;
00132 }
00133 break;
00134
00135
00136 case JackThread::kRunning:
00137 if ( fThread.Stop() < 0 )
00138 {
00139 jack_error ( "Cannot stop thread" );
00140 return -1;
00141 }
00142 break;
00143
00144 default:
00145 break;
00146 }
00147 return fAudioInterface.close();
00148 }
00149
00150 bool JackAlsaAdapter::Init()
00151 {
00152
00153 for ( unsigned int i = 0; i < fAudioInterface.fPeriod; i++ )
00154 fAudioInterface.write();
00155 return true;
00156 }
00157
00158 bool JackAlsaAdapter::Execute()
00159 {
00160
00161 if (fAudioInterface.read() < 0)
00162 return false;
00163
00164 PushAndPull(fAudioInterface.fInputSoftChannels, fAudioInterface.fOutputSoftChannels, fAdaptedBufferSize);
00165
00166
00167 if (fAudioInterface.write() < 0)
00168 return false;
00169
00170 return true;
00171 }
00172
00173 int JackAlsaAdapter::SetSampleRate ( jack_nframes_t sample_rate )
00174 {
00175 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
00176 Close();
00177 return Open();
00178 }
00179
00180 int JackAlsaAdapter::SetBufferSize ( jack_nframes_t buffer_size )
00181 {
00182 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
00183 Close();
00184 return Open();
00185 }
00186
00187 }
00188
00189 #ifdef __cplusplus
00190 extern "C"
00191 {
00192 #endif
00193
00194 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00195 {
00196 jack_driver_desc_t * desc;
00197 jack_driver_desc_filler_t filler;
00198 jack_driver_param_value_t value;
00199
00200 desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler);
00201
00202 strcpy(value.str, "none");
00203 jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set device", NULL);
00204 jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set device", NULL);
00205
00206 strcpy(value.str, "hw:0");
00207 jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "ALSA device name", NULL);
00208
00209 value.ui = 48000U;
00210 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
00211
00212 value.ui = 512U;
00213 jack_driver_descriptor_add_parameter(desc, &filler, "periodsize", 'p', JackDriverParamUInt, &value, NULL, "Period size", NULL);
00214
00215 value.ui = 2U;
00216 jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods of playback latency", NULL);
00217
00218 value.i = true;
00219 jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
00220
00221 value.i = 0;
00222 jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Number of capture channels (defaults to hardware max)", NULL);
00223 jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Number of playback channels (defaults to hardware max)", NULL);
00224
00225 value.ui = 0;
00226 jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamUInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
00227
00228 value.ui = 32768;
00229 jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamUInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
00230
00231 return desc;
00232 }
00233
00234 #ifdef __cplusplus
00235 }
00236 #endif
00237