|
CLAM-Development
1.3
|
00001 00002 #include "JACKNetworkPlayer.hxx" 00003 #include "PushFlowControl.hxx" 00004 #include "AudioSource.hxx" 00005 #include "AudioSink.hxx" 00006 00007 #include <iostream> 00008 00009 namespace CLAM 00010 { 00011 00012 //JACK CODE 00013 inline int JackProcessingCallback (jack_nframes_t nframes, void *arg) 00014 { 00015 JACKNetworkPlayer* player=(JACKNetworkPlayer*)arg; 00016 player->Do(nframes); 00017 return 0; 00018 } 00019 00020 inline void JackShutdownCallback (void *arg) 00021 { 00022 JACKNetworkPlayer* player=(JACKNetworkPlayer*)arg; 00023 player->OnShutdown(); 00024 } 00025 00026 JACKNetworkPlayer::JACKNetworkPlayer(const std::string & name) 00027 : _jackClient(0) 00028 , _jackClientName(name) 00029 { 00030 _autoConnect=false; 00031 _jackClient=0; 00032 InitClient(); 00033 } 00034 00035 JACKNetworkPlayer::~JACKNetworkPlayer() 00036 { 00037 Stop(); 00038 00039 if (not _jackClient) return; 00040 bool error = jack_client_close (_jackClient); 00041 if (error) 00042 { 00043 std::cerr << "JACK ERROR: cannot close client" << std::endl; 00044 exit(1); 00045 } 00046 } 00047 00048 bool JACKNetworkPlayer::IsWorking() 00049 { 00050 return _jackClient != 0; 00051 } 00052 00053 std::string JACKNetworkPlayer::NonWorkingReason() 00054 { 00055 if (_jackClient) return ""; 00056 return "No connection to JACK server available"; 00057 } 00058 00059 void JACKNetworkPlayer::InitClient() 00060 { 00061 unsigned jackClientNameMaxSize=jack_client_name_size(); 00062 if (jackClientNameMaxSize<=_jackClientName.size()) // the = is because the 0 of the c string... 00063 { 00064 std::cerr << "JACK WARNING: jack client name \"" << _jackClientName 00065 <<"\" truncated to " << jackClientNameMaxSize << " characters"<<std::endl; 00066 _jackClientName.resize(jackClientNameMaxSize-1); 00067 } 00068 00069 CLAM_ASSERT(not _jackClient, "JACKNetworkPlayer: Initializing a client without closing the previous one"); 00070 jack_status_t jackStatus; 00071 _jackClient = jack_client_open ( _jackClientName.c_str(), JackNullOption, &jackStatus ); 00072 if (not _jackClient) 00073 { 00074 // TODO: Check jackStatus to be more informative 00075 std::cerr << "JACK ERROR: server not running?"<< std::endl; 00076 return; 00077 } 00078 00079 //Register callback method for processing 00080 bool err = jack_set_process_callback (_jackClient, JackProcessingCallback, this); 00081 CLAM_ASSERT(not err, "JACK ERROR: registering process callbacks"); 00082 00083 //Register shutdown callback 00084 jack_on_shutdown (_jackClient, JackShutdownCallback, this); 00085 00086 //Get JACK information 00087 _jackSampleRate=(int)jack_get_sample_rate (_jackClient); 00088 _jackBufferSize=(int)jack_get_buffer_size (_jackClient); 00089 } 00090 00091 00092 void JACKNetworkPlayer::RegisterPorts() 00093 { 00094 RegisterInputPorts( GetNetwork() ); 00095 RegisterOutputPorts( GetNetwork() ); 00096 } 00097 00098 void JACKNetworkPlayer::RegisterInputPorts(const Network& net) 00099 { 00100 CLAM_ASSERT( _sourceJackPorts.empty(), 00101 "JACKNetworkPlayer::RegisterInputPorts() : there are already registered input ports"); 00102 unsigned nPorts = GetNSources(); 00103 _sourceJackPorts.resize(nPorts); 00104 for (unsigned i=0; i<nPorts; i++) 00105 { 00106 _sourceJackPorts[i] = jack_port_register( 00107 _jackClient, SourceName(i).c_str(), 00108 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); 00109 SetSourceFrameSize(i,_jackBufferSize); 00110 } 00111 } 00112 00113 void JACKNetworkPlayer::RegisterOutputPorts(const Network& net) 00114 { 00115 CLAM_ASSERT( _sinkJackPorts.empty(), 00116 "JACKNetworkPlayer::RegisterOutputPorts() : there are already registered output ports"); 00117 unsigned nPorts = GetNSinks(); 00118 _sinkJackPorts.resize(nPorts); 00119 for(unsigned i = 0; i < nPorts; ++i) 00120 { 00121 _sinkJackPorts[i] = jack_port_register( 00122 _jackClient, SinkName(i).c_str(), 00123 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); 00124 SetSinkFrameSize(i, _jackBufferSize); 00125 } 00126 } 00127 00128 void JACKNetworkPlayer::UnRegisterPorts() 00129 { 00130 for (unsigned i=0; i<_sinkJackPorts.size(); i++) 00131 { 00132 if ( jack_port_unregister ( _jackClient, _sinkJackPorts[i]) ) 00133 { 00134 std::cerr << "JACK ERROR: unregistering port " << PortName(_sinkJackPorts[i]) << std::endl; 00135 exit(1); 00136 } 00137 } 00138 _sinkJackPorts.clear(); 00139 00140 for (unsigned i=0; i<_sourceJackPorts.size(); i++) 00141 { 00142 if ( jack_port_unregister ( _jackClient, _sourceJackPorts[i]) ) 00143 { 00144 std::cerr << "JACK ERROR: unregistering port " << PortName(_sourceJackPorts[i]) << std::endl; 00145 exit(1); 00146 } 00147 } 00148 _sourceJackPorts.clear(); 00149 } 00150 00151 void JACKNetworkPlayer::CopyJackBuffersToSources(const jack_nframes_t nframes) 00152 { 00153 for (unsigned i=0; i<_sourceJackPorts.size(); i++) 00154 { 00155 jack_default_audio_sample_t *jackInBuffer = 00156 (jack_default_audio_sample_t*) jack_port_get_buffer(_sourceJackPorts[i], nframes); 00157 SetSourceBuffer(i, jackInBuffer, nframes); 00158 } 00159 } 00160 00161 void JACKNetworkPlayer::CopySinksToJackBuffers(const jack_nframes_t nframes) 00162 { 00163 for (unsigned i=0; i<_sinkJackPorts.size(); i++) 00164 { 00165 jack_default_audio_sample_t* jackOutBuffer = 00166 (jack_default_audio_sample_t*) jack_port_get_buffer(_sinkJackPorts[i], nframes); 00167 SetSinkBuffer(i, jackOutBuffer, nframes); 00168 } 00169 } 00170 00171 void JACKNetworkPlayer::BlankJackBuffers(const jack_nframes_t nframes) 00172 { 00173 for (unsigned i=0; i<_sinkJackPorts.size(); i++) 00174 { 00175 jack_default_audio_sample_t *jackOutBuffer = 00176 (jack_default_audio_sample_t*) jack_port_get_buffer ( _sinkJackPorts[i], nframes); 00177 std::memset(jackOutBuffer, 0, nframes*sizeof(jack_default_audio_sample_t)); 00178 } 00179 } 00180 00181 void JACKNetworkPlayer::Start() 00182 { 00183 if (IsPlaying()) return; 00184 if (IsPaused()) 00185 { 00186 BePlaying(); 00187 return; 00188 } 00189 if (!_jackClient) InitClient(); 00190 if (!_jackClient) return; 00191 00192 CacheSourcesAndSinks(); 00193 00194 BePlaying(); 00195 UnRegisterPorts(); 00196 RegisterPorts(); 00197 GetNetwork().Start(); 00198 00199 //JACK CODE (the init order of network, ... should be decided) 00200 if (jack_activate (_jackClient)) { 00201 std::cerr << "JACK ERROR: cannot activate client" << std::endl; 00202 exit(1); 00203 } 00204 00205 if (_autoConnect) 00206 AutoConnectPorts(); 00207 else 00208 RestoreConnections(); 00209 } 00210 void JACKNetworkPlayer::Init() 00211 { 00212 if (not _jackClient) InitClient(); 00213 } 00214 void JACKNetworkPlayer::OnShutdown() 00215 { 00216 if (not _jackClient) return; 00217 BeStopped(); 00218 GetNetwork().Stop(); 00219 _sinkJackPorts.clear(); // TODO: May we save them? 00220 _sourceJackPorts.clear(); // TODO: May we save them?; 00221 _jackClient=0; 00222 } 00223 00224 void JACKNetworkPlayer::Stop() 00225 { 00226 if (IsStopped()) return; 00227 StoreConnections(); 00228 if ( jack_deactivate (_jackClient) ) 00229 { 00230 std::cerr << "JACK ERROR: cannot deactivate client" << std::endl; 00231 exit(1); 00232 } 00233 BeStopped(); 00234 GetNetwork().Stop(); 00235 } 00236 00237 void JACKNetworkPlayer::Do(const jack_nframes_t nframes) 00238 { 00239 if (IsStopped()) return; 00240 if (IsPaused()) 00241 { 00242 BlankJackBuffers(nframes); 00243 return; 00244 } 00245 00246 CopyJackBuffersToSources(nframes); 00247 CopySinksToJackBuffers(nframes); 00248 GetNetwork().Do(); 00249 } 00250 00251 //Saves the connections made to our local in/out jack ports 00252 void JACKNetworkPlayer::StoreConnections() 00253 { 00254 for (unsigned i=0; i<_sourceJackPorts.size(); i++) 00255 { 00256 JackConnection connection; 00257 connection.processingName = PortName(_sourceJackPorts[i]); 00258 connection.outsideConnections = jack_port_get_connections ( _sourceJackPorts[i] ); 00259 _incomingJackConnections.push_back(connection); 00260 } 00261 00262 for (unsigned i=0; i<_sinkJackPorts.size(); i++) 00263 { 00264 JackConnection connection; 00265 connection.processingName = PortName(_sinkJackPorts[i]); 00266 connection.outsideConnections = jack_port_get_connections ( _sinkJackPorts[i] ); 00267 _outgoingJackConnections.push_back(connection); 00268 } 00269 } 00270 00271 //Loads the connections made to our local in/out jack ports 00272 void JACKNetworkPlayer::RestoreConnections() 00273 { 00274 for (JackConnections::iterator it=_incomingJackConnections.begin(); it!=_incomingJackConnections.end(); it++) 00275 { 00276 if (not it->outsideConnections) continue; 00277 for (unsigned i=0; it->outsideConnections[i]; i++) 00278 { 00279 bool error = jack_connect ( _jackClient, it->outsideConnections[i], it->processingName.c_str() ); 00280 if (error) 00281 std::cerr << "JACK WARNING: could not reconnect ports ( " << 00282 it->processingName << " , " << it->outsideConnections[i] << " )" <<std::endl; 00283 } 00284 free(it->outsideConnections); 00285 } 00286 _incomingJackConnections.clear(); 00287 00288 for (JackConnections::iterator it=_outgoingJackConnections.begin(); it!=_outgoingJackConnections.end(); it++) 00289 { 00290 if (not it->outsideConnections) continue; 00291 for (unsigned i=0; it->outsideConnections[i]; i++) 00292 { 00293 bool error = jack_connect ( _jackClient, it->processingName.c_str(), it->outsideConnections[i] ); 00294 if (error) 00295 std::cerr << "JACK WARNING: could not reconnect ports ( " << 00296 it->outsideConnections[i] << " , " << it->processingName << " )" <<std::endl; 00297 } 00298 free(it->outsideConnections); 00299 } 00300 _outgoingJackConnections.clear(); 00301 } 00302 00303 void JACKNetworkPlayer::AutoConnectPorts() 00304 { 00305 //Automatically connect the ports to external jack ports 00306 00307 //CONNECT JACK OUTPUT PORTS TO CLAM EXTERNGENERATORS 00308 const char ** portnames= jack_get_ports ( _jackClient , _jackOutPortAutoConnectList.c_str(), NULL, JackPortIsOutput); 00309 if (not portnames) 00310 { 00311 std::cout << " -WARNING: couldn't locate any JACK output port <" 00312 << _jackOutPortAutoConnectList << ">"<<std::endl; 00313 } 00314 else 00315 { 00316 for (unsigned i=0; i<_sourceJackPorts.size() && portnames[i]; i++) 00317 { 00318 jack_port_t * port = _sourceJackPorts[i]; 00319 std::cout << "- Connecting " << portnames[i] << " -> " 00320 << PortName(port) << std::endl; 00321 00322 if ( jack_connect( _jackClient, portnames[i], PortName(port) ) !=0 ) 00323 std::cerr << " -WARNING: couldn't connect" << std::endl; 00324 } 00325 free(portnames); 00326 } 00327 00328 //CONNECT CLAM EXTERNSINKS TO JACK INPUT PORTS 00329 portnames= jack_get_ports ( _jackClient , _jackInPortAutoConnectList.c_str(), NULL, JackPortIsInput); 00330 if ( not portnames) 00331 { 00332 std::cout << " -WARNING: couldn't locate any JACK input port <" 00333 << _jackInPortAutoConnectList << ">"<<std::endl; 00334 } 00335 else 00336 { 00337 for (unsigned i=0; i<_sinkJackPorts.size() && portnames[i]; i++) 00338 { 00339 const char * localPortName = PortName(_sinkJackPorts[i]); 00340 std::cout << "- Connecting "<< localPortName 00341 << " -> " << portnames[i] << std::endl; 00342 00343 if ( jack_connect( _jackClient, localPortName, portnames[i]) != 0) 00344 std::cerr << " -WARNING: couldn't connect" << std::endl; 00345 } 00346 free(portnames); 00347 } 00348 } 00349 00350 } //namespace CLAM 00351 00352
1.7.6.1