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
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())
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
00075 std::cerr << "JACK ERROR: server not running?"<< std::endl;
00076 return;
00077 }
00078
00079
00080 bool err = jack_set_process_callback (_jackClient, JackProcessingCallback, this);
00081 CLAM_ASSERT(not err, "JACK ERROR: registering process callbacks");
00082
00083
00084 jack_on_shutdown (_jackClient, JackShutdownCallback, this);
00085
00086
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
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();
00220 _sourceJackPorts.clear();
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
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
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
00306
00307
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
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 }
00351
00352