00001
00002 #include "JACKNetworkPlayer.hxx"
00003
00004 #include "PushFlowControl.hxx"
00005 #include "XMLStorage.hxx"
00006
00007 namespace CLAM
00008 {
00009
00010
00011 inline int JackProcessingCallback (jack_nframes_t nframes, void *arg)
00012 {
00013 JACKNetworkPlayer* player=(JACKNetworkPlayer*)arg;
00014 player->Do(nframes);
00015 return 0;
00016 }
00017
00018 inline void JackShutdownCallback (void *arg)
00019 {
00020 JACKNetworkPlayer* player=(JACKNetworkPlayer*)arg;
00021 player->OnShutdown();
00022 }
00023
00024 JACKNetworkPlayer::JACKNetworkPlayer(const std::string & name)
00025 : _jackClientName(name)
00026 {
00027 _autoConnect=false;
00028 _jackClient=0;
00029 InitClient();
00030 }
00031
00032 JACKNetworkPlayer::~JACKNetworkPlayer()
00033 {
00034 Stop();
00035
00036 if (not _jackClient) return;
00037 bool error = jack_client_close (_jackClient);
00038 if (error)
00039 {
00040 std::cerr << "JACK ERROR: cannot close client" << std::endl;
00041 exit(1);
00042 }
00043 }
00044
00045 bool JACKNetworkPlayer::IsWorking() const
00046 {
00047 return _jackClient != 0;
00048 }
00049
00050 std::string JACKNetworkPlayer::NonWorkingReason() const
00051 {
00052 if (_jackClient) return "";
00053 return "No connection to JACK server available";
00054 }
00055
00056 void JACKNetworkPlayer::InitClient()
00057 {
00058 jack_status_t jackStatus;
00059 _jackClient = jack_client_open ( _jackClientName.c_str(), JackNullOption, &jackStatus );
00060 if (not _jackClient)
00061 {
00062
00063 std::cerr << "JACK ERROR: server not running?"<< std::endl;
00064 return;
00065 }
00066
00067
00068 bool err = jack_set_process_callback (_jackClient, JackProcessingCallback, this);
00069 CLAM_ASSERT(not err, "JACK ERROR: registering process callbacks");
00070
00071
00072 jack_on_shutdown (_jackClient, JackShutdownCallback, this);
00073
00074
00075 _jackSampleRate=(int)jack_get_sample_rate (_jackClient);
00076 _jackBufferSize=(int)jack_get_buffer_size (_jackClient);
00077 }
00078
00079
00080 void JACKNetworkPlayer::RegisterPorts()
00081 {
00082 RegisterInputPorts( GetNetwork() );
00083 RegisterOutputPorts( GetNetwork() );
00084 }
00085
00086 void JACKNetworkPlayer::RegisterInputPorts(const Network& net)
00087 {
00088 CLAM_ASSERT( _sourceJackBindings.empty(), "JACKNetworkPlayer::RegisterInputPorts() : there are already registered input ports");
00089
00090 SourceJackBinding pair;
00091
00092
00093 for (Network::ProcessingsMap::const_iterator it=net.BeginProcessings(); it!=net.EndProcessings(); it++)
00094 {
00095 std::string processingClass = it->second->GetClassName();
00096 if (processingClass != "AudioSource") continue;
00097
00098
00099 pair.source=(AudioSource*)it->second;
00100 pair.source->SetFrameAndHopSize(_jackBufferSize);
00101
00102
00103 const std::string & processingName = it->first;
00104 pair.jackPort=jack_port_register (_jackClient,
00105 processingName.c_str(),
00106 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
00107
00108
00109 _sourceJackBindings.push_back(pair);
00110 }
00111 }
00112
00113 void JACKNetworkPlayer::RegisterOutputPorts(const Network& net)
00114 {
00115 CLAM_ASSERT( _sinkJackBindings.empty(), "JACKNetworkPlayer::RegisterOutputPorts() : there are already registered output ports");
00116
00117 SinkJackBinding pair;
00118
00119
00120 for (Network::ProcessingsMap::const_iterator it=net.BeginProcessings(); it!=net.EndProcessings(); it++)
00121 {
00122 std::string processingClass = it->second->GetClassName();
00123 if (processingClass != "AudioSink") continue;
00124
00125
00126 pair.sink=(AudioSink*)it->second;
00127 pair.sink->SetFrameAndHopSize(_jackBufferSize);
00128
00129
00130 const std::string & processingName = it->first;
00131 pair.jackPort=jack_port_register (_jackClient,
00132 processingName.c_str(),
00133 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
00134
00135
00136 _sinkJackBindings.push_back(pair);
00137 }
00138 }
00139
00140 void JACKNetworkPlayer::UnRegisterPorts()
00141 {
00142 for (SinkJackBindings::iterator it=_sinkJackBindings.begin(); it!=_sinkJackBindings.end(); it++)
00143 {
00144 if ( jack_port_unregister ( _jackClient, it->jackPort) )
00145 {
00146 std::cerr << "JACK ERROR: unregistering port " << it->PortName() << std::endl;
00147 exit(1);
00148 }
00149 }
00150 _sinkJackBindings.clear();
00151
00152 for (SourceJackBindings::iterator it=_sourceJackBindings.begin(); it!=_sourceJackBindings.end(); it++)
00153 {
00154 if ( jack_port_unregister ( _jackClient, it->jackPort) )
00155 {
00156 std::cerr << "JACK ERROR: unregistering port " << it->PortName() << std::endl;
00157 exit(1);
00158 }
00159 }
00160 _sourceJackBindings.clear();
00161 }
00162
00163 void JACKNetworkPlayer::CopyJackBuffersToGenerators(const jack_nframes_t nframes)
00164 {
00165 for (SourceJackBindings::iterator it=_sourceJackBindings.begin(); it!=_sourceJackBindings.end(); it++)
00166 {
00167
00168 jack_default_audio_sample_t *jackInBuffer =
00169 (jack_default_audio_sample_t*) jack_port_get_buffer ( it->jackPort, nframes);
00170
00171 it->source->SetExternalBuffer( jackInBuffer, nframes );
00172
00173 }
00174
00175 }
00176
00177 void JACKNetworkPlayer::CopySinksToJackBuffers(const jack_nframes_t nframes)
00178 {
00179 for (SinkJackBindings::iterator it=_sinkJackBindings.begin(); it!=_sinkJackBindings.end(); it++)
00180 {
00181
00182 jack_default_audio_sample_t *jackOutBuffer =
00183 (jack_default_audio_sample_t*) jack_port_get_buffer ( it->jackPort, nframes);
00184
00185 it->sink->SetExternalBuffer( jackOutBuffer, nframes);
00186 }
00187 }
00188
00189 void JACKNetworkPlayer::Start()
00190 {
00191 if (!IsStopped()) return;
00192
00193 if (!_jackClient) InitClient();
00194 if (!_jackClient) return;
00195
00196 SetStopped(false);
00197
00198 UnRegisterPorts();
00199 RegisterPorts();
00200
00201
00202 if (jack_activate (_jackClient)) {
00203 std::cerr << "JACK ERROR: cannot activate client" << std::endl;
00204 exit(1);
00205 }
00206
00207 if (_autoConnect)
00208 AutoConnectPorts();
00209 else
00210 RestoreConnections();
00211 }
00212 void JACKNetworkPlayer::Init()
00213 {
00214 InitClient();
00215 }
00216 void JACKNetworkPlayer::OnShutdown()
00217 {
00218 if (not _jackClient) return;
00219 SetStopped(true);
00220 GetNetwork().Stop();
00221 _sinkJackBindings.clear();
00222 _sourceJackBindings.clear();
00223 _jackClient=0;
00224 }
00225
00226 void JACKNetworkPlayer::Stop()
00227 {
00228 if (IsStopped()) return;
00229 SetStopped(true);
00230
00231 StoreConnections();
00232
00233 if ( jack_deactivate (_jackClient) )
00234 {
00235 std::cerr << "JACK ERROR: cannot deactivate client" << std::endl;
00236 exit(1);
00237 }
00238 }
00239
00240 void JACKNetworkPlayer::Do(const jack_nframes_t nframes)
00241 {
00242 if (IsStopped()) return;
00243
00244 CopyJackBuffersToGenerators(nframes);
00245 CopySinksToJackBuffers(nframes);
00246 GetNetwork().Do();
00247 }
00248
00249
00250 void JACKNetworkPlayer::StoreConnections()
00251 {
00252 for (SourceJackBindings::iterator it=_sourceJackBindings.begin(); it!=_sourceJackBindings.end(); it++)
00253 {
00254 JackConnection connection;
00255 connection.processingName = it->PortName();
00256 connection.outsideConnections = jack_port_get_connections ( it->jackPort );
00257 _incomingJackConnections.push_back(connection);
00258 }
00259
00260 for (SinkJackBindings::iterator it=_sinkJackBindings.begin(); it!=_sinkJackBindings.end(); it++)
00261 {
00262 JackConnection connection;
00263 connection.processingName = it->PortName();
00264 connection.outsideConnections = jack_port_get_connections ( it->jackPort );
00265 _outgoingJackConnections.push_back(connection);
00266 }
00267 }
00268
00269
00270 void JACKNetworkPlayer::RestoreConnections()
00271 {
00272 for (JackConnections::iterator it=_incomingJackConnections.begin(); it!=_incomingJackConnections.end(); it++)
00273 {
00274 if (not it->outsideConnections) continue;
00275 for (unsigned i=0; it->outsideConnections[i]; i++)
00276 {
00277 bool error = jack_connect ( _jackClient, it->outsideConnections[i], it->processingName.c_str() );
00278 if (error)
00279 std::cerr << "JACK WARNING: could not reconnect ports ( " <<
00280 it->processingName << " , " << it->outsideConnections[i] << " )" <<std::endl;
00281 }
00282 free(it->outsideConnections);
00283 }
00284 _incomingJackConnections.clear();
00285
00286 for (JackConnections::iterator it=_outgoingJackConnections.begin(); it!=_outgoingJackConnections.end(); it++)
00287 {
00288 if (not it->outsideConnections) continue;
00289 for (unsigned i=0; it->outsideConnections[i]; i++)
00290 {
00291 bool error = jack_connect ( _jackClient, it->processingName.c_str(), it->outsideConnections[i] );
00292 if (error)
00293 std::cerr << "JACK WARNING: could not reconnect ports ( " <<
00294 it->outsideConnections[i] << " , " << it->processingName << " )" <<std::endl;
00295 }
00296 free(it->outsideConnections);
00297 }
00298 _outgoingJackConnections.clear();
00299 }
00300
00301 void JACKNetworkPlayer::AutoConnectPorts()
00302 {
00303
00304 std::cout << "Automatically connecting to JACK input and output ports" << std::endl;
00305
00306
00307 const char ** portnames= jack_get_ports ( _jackClient , _jackOutPortAutoConnectList.c_str(), NULL, JackPortIsOutput);
00308
00309 if (portnames==NULL)
00310 {
00311 std::cout << " -WARNING: couldn't locate any JACK output port <"
00312 << _jackOutPortAutoConnectList << ">"<<std::endl;
00313 }
00314 else
00315 {
00316 int i=0;
00317
00318
00319 for ( SourceJackBindings::iterator it= _sourceJackBindings.begin(); it!=_sourceJackBindings.end(); it++)
00320 {
00321 std::cout << "- Connecting " << portnames[i] << " -> "
00322 << it->PortName() << std::endl;
00323
00324 if ( jack_connect( _jackClient, portnames[i],
00325 it->PortName() ) !=0 )
00326 {
00327 std::cerr << " -WARNING: couldn't connect" << std::endl;
00328 }
00329
00330 i++;
00331 if (portnames[i]==NULL) break;
00332 }
00333 }
00334 free(portnames);
00335
00336
00337 portnames= jack_get_ports ( _jackClient , _jackInPortAutoConnectList.c_str(), NULL, JackPortIsInput);
00338
00339 if (portnames==NULL)
00340 {
00341 std::cout << " -WARNING: couldn't locate any JACK input port <"
00342 << _jackInPortAutoConnectList << ">"<<std::endl;
00343 }
00344 else
00345 {
00346 int i=0;
00347
00348
00349 for (SinkJackBindings::iterator it= _sinkJackBindings.begin(); it!=_sinkJackBindings.end(); it++)
00350 {
00351 std::cout << "- Connecting "<< it->PortName()
00352 << " -> " << portnames[i] << std::endl;
00353
00354 if ( jack_connect( _jackClient, it->PortName(),
00355 portnames[i]) != 0)
00356 {
00357 std::cerr << " -WARNING: couldn't connect" << std::endl;
00358 }
00359
00360 i++;
00361 if (portnames[i]==NULL) break;
00362 }
00363 }
00364 free(portnames);
00365 }
00366
00367
00368
00369 }
00370
00371