Jack2
1.9.10
|
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 "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 //open audio interface 00099 if ( fAudioInterface.open() ) 00100 return -1; 00101 00102 //start adapter thread 00103 if ( fThread.StartSync() < 0 ) 00104 { 00105 jack_error ( "Cannot start audioadapter thread" ); 00106 return -1; 00107 } 00108 00109 //display card info 00110 fAudioInterface.longinfo(); 00111 00112 //turn the thread realtime 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 // Kill the thread in Init phase 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 // Stop when the thread cycle is finished 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 //fill the hardware buffers 00153 for ( unsigned int i = 0; i < fAudioInterface.fPeriod; i++ ) 00154 fAudioInterface.write(); 00155 return true; 00156 } 00157 00158 bool JackAlsaAdapter::Execute() 00159 { 00160 //read data from audio interface 00161 if (fAudioInterface.read() < 0) 00162 return false; 00163 00164 PushAndPull(fAudioInterface.fInputSoftChannels, fAudioInterface.fOutputSoftChannels, fAdaptedBufferSize); 00165 00166 //write data to audio interface 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 } // namespace 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