Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2001 Paul Davis 00003 Copyright (C) 2004-2008 Grame 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 00019 */ 00020 00021 #include "JackSystemDeps.h" 00022 #include "JackServerGlobals.h" 00023 #include "JackTime.h" 00024 #include "JackFreewheelDriver.h" 00025 #include "JackThreadedDriver.h" 00026 #include "JackGlobals.h" 00027 #include "JackLockedEngine.h" 00028 #include "JackAudioDriver.h" 00029 #include "JackChannel.h" 00030 #include "JackClientControl.h" 00031 #include "JackEngineControl.h" 00032 #include "JackGraphManager.h" 00033 #include "JackInternalClient.h" 00034 #include "JackError.h" 00035 #include "JackMessageBuffer.h" 00036 00037 const char * jack_get_self_connect_mode_description(char mode); 00038 00039 namespace Jack 00040 { 00041 00042 //---------------- 00043 // Server control 00044 //---------------- 00045 JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int priority, int port_max, bool verbose, jack_timer_type_t clock, char self_connect_mode, const char* server_name) 00046 { 00047 if (rt) { 00048 jack_info("JACK server starting in realtime mode with priority %ld", priority); 00049 } else { 00050 jack_info("JACK server starting in non-realtime mode"); 00051 } 00052 00053 jack_info("self-connect-mode is \"%s\"", jack_get_self_connect_mode_description(self_connect_mode)); 00054 00055 fGraphManager = JackGraphManager::Allocate(port_max); 00056 fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name); 00057 fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl, self_connect_mode); 00058 00059 // A distinction is made between the threaded freewheel driver and the 00060 // regular freewheel driver because the freewheel driver needs to run in 00061 // threaded mode when freewheel mode is active and needs to run as a slave 00062 // when freewheel mode isn't active. 00063 JackFreewheelDriver* freewheelDriver = new JackFreewheelDriver(fEngine, GetSynchroTable()); 00064 fThreadedFreewheelDriver = new JackThreadedDriver(freewheelDriver); 00065 00066 fFreewheelDriver = freewheelDriver; 00067 fDriverInfo = new JackDriverInfo(); 00068 fAudioDriver = NULL; 00069 fFreewheel = false; 00070 JackServerGlobals::fInstance = this; // Unique instance 00071 JackServerGlobals::fUserCount = 1; // One user 00072 JackGlobals::fVerbose = verbose; 00073 } 00074 00075 JackServer::~JackServer() 00076 { 00077 JackGraphManager::Destroy(fGraphManager); 00078 delete fDriverInfo; 00079 delete fThreadedFreewheelDriver; 00080 delete fEngine; 00081 delete fEngineControl; 00082 } 00083 00084 int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) 00085 { 00086 // TODO: move that in reworked JackServerGlobals::Init() 00087 if (!JackMessageBuffer::Create()) { 00088 jack_error("Cannot create message buffer"); 00089 } 00090 00091 if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) { 00092 jack_error("Cannot initialize driver"); 00093 goto fail_close1; 00094 } 00095 00096 if (fRequestChannel.Open(fEngineControl->fServerName, this) < 0) { 00097 jack_error("Server channel open error"); 00098 goto fail_close2; 00099 } 00100 00101 if (fEngine->Open() < 0) { 00102 jack_error("Cannot open engine"); 00103 goto fail_close3; 00104 } 00105 00106 if (fFreewheelDriver->Open() < 0) { 00107 jack_error("Cannot open freewheel driver"); 00108 goto fail_close4; 00109 } 00110 00111 if (fAudioDriver->Attach() < 0) { 00112 jack_error("Cannot attach audio driver"); 00113 goto fail_close5; 00114 } 00115 00116 fFreewheelDriver->SetMaster(false); 00117 fAudioDriver->SetMaster(true); 00118 fAudioDriver->AddSlave(fFreewheelDriver); 00119 InitTime(); 00120 SetClockSource(fEngineControl->fClockSource); 00121 return 0; 00122 00123 fail_close5: 00124 fFreewheelDriver->Close(); 00125 00126 fail_close4: 00127 fEngine->Close(); 00128 00129 fail_close3: 00130 fRequestChannel.Close(); 00131 00132 fail_close2: 00133 fAudioDriver->Close(); 00134 00135 fail_close1: 00136 JackMessageBuffer::Destroy(); 00137 return -1; 00138 } 00139 00140 int JackServer::Close() 00141 { 00142 jack_log("JackServer::Close"); 00143 fRequestChannel.Close(); 00144 fAudioDriver->Detach(); 00145 fAudioDriver->Close(); 00146 fFreewheelDriver->Close(); 00147 fEngine->Close(); 00148 // TODO: move that in reworked JackServerGlobals::Destroy() 00149 JackMessageBuffer::Destroy(); 00150 EndTime(); 00151 return 0; 00152 } 00153 00154 int JackServer::Start() 00155 { 00156 jack_log("JackServer::Start"); 00157 if (fAudioDriver->Start() < 0) { 00158 return -1; 00159 } 00160 return fRequestChannel.Start(); 00161 } 00162 00163 int JackServer::Stop() 00164 { 00165 jack_log("JackServer::Stop"); 00166 int res = -1; 00167 00168 if (fFreewheel) { 00169 if (fThreadedFreewheelDriver) { 00170 res = fThreadedFreewheelDriver->Stop(); 00171 } 00172 } else { 00173 if (fAudioDriver) { 00174 res = fAudioDriver->Stop(); 00175 } 00176 } 00177 00178 fEngine->NotifyQuit(); 00179 fRequestChannel.Stop(); 00180 fEngine->NotifyFailure(JackFailure | JackServerError, JACK_SERVER_FAILURE); 00181 00182 return res; 00183 } 00184 00185 bool JackServer::IsRunning() 00186 { 00187 jack_log("JackServer::IsRunning"); 00188 assert(fAudioDriver); 00189 return fAudioDriver->IsRunning(); 00190 } 00191 00192 //------------------ 00193 // Internal clients 00194 //------------------ 00195 00196 int JackServer::InternalClientLoad1(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status) 00197 { 00198 JackLoadableInternalClient* client = new JackLoadableInternalClient1(JackServerGlobals::fInstance, GetSynchroTable(), objet_data); 00199 assert(client); 00200 return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status); 00201 } 00202 00203 int JackServer::InternalClientLoad2(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status) 00204 { 00205 JackLoadableInternalClient* client = new JackLoadableInternalClient2(JackServerGlobals::fInstance, GetSynchroTable(), parameters); 00206 assert(client); 00207 return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status); 00208 } 00209 00210 int JackServer::InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int uuid, int* status) 00211 { 00212 // Clear status 00213 *status = 0; 00214 00215 // Client object is internally kept in JackEngine 00216 if ((client->Init(so_name) < 0) || (client->Open(JackTools::DefaultServerName(), client_name, uuid, (jack_options_t)options, (jack_status_t*)status) < 0)) { 00217 delete client; 00218 int my_status1 = *status | JackFailure; 00219 *status = (jack_status_t)my_status1; 00220 *int_ref = 0; 00221 return -1; 00222 } else { 00223 *int_ref = client->GetClientControl()->fRefNum; 00224 return 0; 00225 } 00226 } 00227 00228 //--------------------------- 00229 // From request thread : API 00230 //--------------------------- 00231 00232 int JackServer::SetBufferSize(jack_nframes_t buffer_size) 00233 { 00234 jack_log("JackServer::SetBufferSize nframes = %ld", buffer_size); 00235 jack_nframes_t current_buffer_size = fEngineControl->fBufferSize; 00236 00237 if (current_buffer_size == buffer_size) { 00238 jack_log("SetBufferSize: requirement for new buffer size equals current value"); 00239 return 0; 00240 } 00241 00242 if (fAudioDriver->IsFixedBufferSize()) { 00243 jack_log("SetBufferSize: driver only supports a fixed buffer size"); 00244 return -1; 00245 } 00246 00247 if (fAudioDriver->Stop() != 0) { 00248 jack_error("Cannot stop audio driver"); 00249 return -1; 00250 } 00251 00252 if (fAudioDriver->SetBufferSize(buffer_size) == 0) { 00253 fEngine->NotifyBufferSize(buffer_size); 00254 return fAudioDriver->Start(); 00255 } else { // Failure: try to restore current value 00256 jack_error("Cannot SetBufferSize for audio driver, restore current value %ld", current_buffer_size); 00257 fAudioDriver->SetBufferSize(current_buffer_size); 00258 fAudioDriver->Start(); 00259 // SetBufferSize actually failed, so return an error... 00260 return -1; 00261 } 00262 } 00263 00264 /* 00265 Freewheel mode is implemented by switching from the (audio [slaves] + freewheel) driver to the freewheel driver only: 00266 00267 - "global" connection state is saved 00268 - all audio driver and slaves ports are deconnected, thus there is no more dependancies with the audio driver and slaves 00269 - the freewheel driver will be synchronized with the end of graph execution : all clients are connected to the freewheel driver 00270 - the freewheel driver becomes the "master" 00271 00272 Normal mode is restored with the connections state valid before freewheel mode was done. Thus one consider that 00273 no graph state change can be done during freewheel mode. 00274 */ 00275 00276 int JackServer::SetFreewheel(bool onoff) 00277 { 00278 jack_log("JackServer::SetFreewheel is = %ld want = %ld", fFreewheel, onoff); 00279 00280 if (fFreewheel) { 00281 if (onoff) { 00282 return -1; 00283 } else { 00284 fFreewheel = false; 00285 fThreadedFreewheelDriver->Stop(); 00286 fGraphManager->Restore(&fConnectionState); // Restore connection state 00287 fEngine->NotifyFreewheel(onoff); 00288 fFreewheelDriver->SetMaster(false); 00289 fAudioDriver->SetMaster(true); 00290 return fAudioDriver->Start(); 00291 } 00292 } else { 00293 if (onoff) { 00294 fFreewheel = true; 00295 fAudioDriver->Stop(); 00296 fGraphManager->Save(&fConnectionState); // Save connection state 00297 // Disconnect all slaves 00298 std::list<JackDriverInterface*> slave_list = fAudioDriver->GetSlaves(); 00299 std::list<JackDriverInterface*>::const_iterator it; 00300 for (it = slave_list.begin(); it != slave_list.end(); it++) { 00301 JackDriver* slave = dynamic_cast<JackDriver*>(*it); 00302 assert(slave); 00303 fGraphManager->DisconnectAllPorts(slave->GetClientControl()->fRefNum); 00304 } 00305 // Disconnect master 00306 fGraphManager->DisconnectAllPorts(fAudioDriver->GetClientControl()->fRefNum); 00307 fEngine->NotifyFreewheel(onoff); 00308 fAudioDriver->SetMaster(false); 00309 fFreewheelDriver->SetMaster(true); 00310 return fThreadedFreewheelDriver->Start(); 00311 } else { 00312 return -1; 00313 } 00314 } 00315 } 00316 00317 //--------------------------- 00318 // Coming from the RT thread 00319 //--------------------------- 00320 00321 void JackServer::Notify(int refnum, int notify, int value) 00322 { 00323 switch (notify) { 00324 00325 case kGraphOrderCallback: 00326 fEngine->NotifyGraphReorder(); 00327 break; 00328 00329 case kXRunCallback: 00330 fEngine->NotifyClientXRun(refnum); 00331 break; 00332 } 00333 } 00334 00335 //-------------------- 00336 // Backend management 00337 //-------------------- 00338 00339 JackDriverInfo* JackServer::AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params) 00340 { 00341 JackDriverInfo* info = new JackDriverInfo(); 00342 JackDriverClientInterface* slave = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params); 00343 00344 if (!slave) { 00345 goto error1; 00346 } 00347 if (slave->Attach() < 0) { 00348 goto error2; 00349 } 00350 00351 slave->SetMaster(false); 00352 fAudioDriver->AddSlave(slave); 00353 return info; 00354 00355 error2: 00356 slave->Close(); 00357 00358 error1: 00359 delete info; 00360 return NULL; 00361 } 00362 00363 void JackServer::RemoveSlave(JackDriverInfo* info) 00364 { 00365 JackDriverClientInterface* slave = info->GetBackend(); 00366 fAudioDriver->RemoveSlave(slave); 00367 slave->Detach(); 00368 slave->Close(); 00369 } 00370 00371 int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params) 00372 { 00373 std::list<JackDriverInterface*> slave_list; 00374 std::list<JackDriverInterface*>::const_iterator it; 00375 00376 // Remove current master 00377 fAudioDriver->Stop(); 00378 fAudioDriver->Detach(); 00379 fAudioDriver->Close(); 00380 00381 // Open new master 00382 JackDriverInfo* info = new JackDriverInfo(); 00383 JackDriverClientInterface* master = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params); 00384 00385 if (!master) { 00386 goto error; 00387 } 00388 00389 // Get slaves list 00390 slave_list = fAudioDriver->GetSlaves(); 00391 00392 // Move slaves in new master 00393 for (it = slave_list.begin(); it != slave_list.end(); it++) { 00394 JackDriverInterface* slave = *it; 00395 master->AddSlave(slave); 00396 } 00397 00398 // Delete old master 00399 delete fDriverInfo; 00400 00401 // Activate master 00402 fAudioDriver = master; 00403 fDriverInfo = info; 00404 00405 if (fAudioDriver->Attach() < 0) { 00406 goto error; 00407 } 00408 00409 // Notify clients of new values 00410 fEngine->NotifyBufferSize(fEngineControl->fBufferSize); 00411 fEngine->NotifySampleRate(fEngineControl->fSampleRate); 00412 00413 // And finally start 00414 fAudioDriver->SetMaster(true); 00415 return fAudioDriver->Start(); 00416 00417 error: 00418 delete info; 00419 return -1; 00420 } 00421 00422 //---------------------- 00423 // Transport management 00424 //---------------------- 00425 00426 int JackServer::ReleaseTimebase(int refnum) 00427 { 00428 return fEngineControl->fTransport.ResetTimebase(refnum); 00429 } 00430 00431 int JackServer::SetTimebaseCallback(int refnum, int conditional) 00432 { 00433 return fEngineControl->fTransport.SetTimebaseMaster(refnum, conditional); 00434 } 00435 00436 JackLockedEngine* JackServer::GetEngine() 00437 { 00438 return fEngine; 00439 } 00440 00441 JackSynchro* JackServer::GetSynchroTable() 00442 { 00443 return fSynchroTable; 00444 } 00445 00446 JackEngineControl* JackServer::GetEngineControl() 00447 { 00448 return fEngineControl; 00449 } 00450 00451 JackGraphManager* JackServer::GetGraphManager() 00452 { 00453 return fGraphManager; 00454 } 00455 00456 } // end of namespace 00457