Jack2 1.9.8
|
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 namespace Jack 00038 { 00039 00040 JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int priority, int port_max, bool verbose, jack_timer_type_t clock, const char* server_name) 00041 { 00042 if (rt) { 00043 jack_info("JACK server starting in realtime mode with priority %ld", priority); 00044 } else { 00045 jack_info("JACK server starting in non-realtime mode"); 00046 } 00047 00048 fGraphManager = JackGraphManager::Allocate(port_max); 00049 fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name); 00050 fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl); 00051 00052 // A distinction is made between the threaded freewheel driver and the 00053 // regular freewheel driver because the freewheel driver needs to run in 00054 // threaded mode when freewheel mode is active and needs to run as a slave 00055 // when freewheel mode isn't active. 00056 JackFreewheelDriver *freewheelDriver = 00057 new JackFreewheelDriver(fEngine, GetSynchroTable()); 00058 fThreadedFreewheelDriver = new JackThreadedDriver(freewheelDriver); 00059 00060 fFreewheelDriver = freewheelDriver; 00061 fDriverInfo = new JackDriverInfo(); 00062 fAudioDriver = NULL; 00063 fFreewheel = false; 00064 JackServerGlobals::fInstance = this; // Unique instance 00065 JackServerGlobals::fUserCount = 1; // One user 00066 JackGlobals::fVerbose = verbose; 00067 } 00068 00069 JackServer::~JackServer() 00070 { 00071 JackGraphManager::Destroy(fGraphManager); 00072 delete fDriverInfo; 00073 delete fThreadedFreewheelDriver; 00074 delete fEngine; 00075 delete fEngineControl; 00076 } 00077 00078 int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) 00079 { 00080 // TODO: move that in reworked JackServerGlobals::Init() 00081 JackMessageBuffer::Create(); 00082 00083 if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) { 00084 jack_error("Cannot initialize driver"); 00085 goto fail_close1; 00086 } 00087 00088 if (fChannel.Open(fEngineControl->fServerName, this) < 0) { 00089 jack_error("Server channel open error"); 00090 goto fail_close2; 00091 } 00092 00093 if (fEngine->Open() < 0) { 00094 jack_error("Cannot open engine"); 00095 goto fail_close3; 00096 } 00097 00098 if (fFreewheelDriver->Open() < 0) { 00099 jack_error("Cannot open freewheel driver"); 00100 goto fail_close4; 00101 } 00102 00103 if (fAudioDriver->Attach() < 0) { 00104 jack_error("Cannot attach audio driver"); 00105 goto fail_close5; 00106 } 00107 00108 fFreewheelDriver->SetMaster(false); 00109 fAudioDriver->SetMaster(true); 00110 fAudioDriver->AddSlave(fFreewheelDriver); 00111 InitTime(); 00112 SetClockSource(fEngineControl->fClockSource); 00113 return 0; 00114 00115 fail_close5: 00116 fFreewheelDriver->Close(); 00117 00118 fail_close4: 00119 fEngine->Close(); 00120 00121 fail_close3: 00122 fChannel.Close(); 00123 00124 fail_close2: 00125 fAudioDriver->Close(); 00126 00127 fail_close1: 00128 JackMessageBuffer::Destroy(); 00129 return -1; 00130 } 00131 00132 int JackServer::Close() 00133 { 00134 jack_log("JackServer::Close"); 00135 fEngine->NotifyQuit(); 00136 fChannel.Close(); 00137 fAudioDriver->Detach(); 00138 fAudioDriver->Close(); 00139 fFreewheelDriver->Close(); 00140 fEngine->Close(); 00141 // TODO: move that in reworked JackServerGlobals::Destroy() 00142 JackMessageBuffer::Destroy(); 00143 return 0; 00144 } 00145 00146 int JackServer::InternalClientLoad1(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status) 00147 { 00148 JackLoadableInternalClient* client = new JackLoadableInternalClient1(JackServerGlobals::fInstance, GetSynchroTable(), objet_data); 00149 assert(client); 00150 return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status); 00151 } 00152 00153 int JackServer::InternalClientLoad2(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status) 00154 { 00155 JackLoadableInternalClient* client = new JackLoadableInternalClient2(JackServerGlobals::fInstance, GetSynchroTable(), parameters); 00156 assert(client); 00157 return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status); 00158 } 00159 00160 int JackServer::InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int uuid, int* status) 00161 { 00162 // Clear status 00163 *status = 0; 00164 00165 // Client object is internally kept in JackEngine 00166 if ((client->Init(so_name) < 0) || (client->Open(JACK_DEFAULT_SERVER_NAME, client_name, uuid, (jack_options_t)options, (jack_status_t*)status) < 0)) { 00167 delete client; 00168 int my_status1 = *status | JackFailure; 00169 *status = (jack_status_t)my_status1; 00170 *int_ref = 0; 00171 return -1; 00172 } else { 00173 *int_ref = client->GetClientControl()->fRefNum; 00174 return 0; 00175 } 00176 } 00177 00178 int JackServer::Start() 00179 { 00180 jack_log("JackServer::Start"); 00181 if (fAudioDriver->Start() < 0) { 00182 return -1; 00183 } 00184 return fChannel.Start(); 00185 } 00186 00187 int JackServer::Stop() 00188 { 00189 jack_log("JackServer::Stop"); 00190 fChannel.Stop(); 00191 00192 if (fFreewheel) { 00193 return fThreadedFreewheelDriver->Stop(); 00194 } else { 00195 return fAudioDriver->Stop(); 00196 } 00197 } 00198 00199 bool JackServer::IsRunning() 00200 { 00201 jack_log("JackServer::IsRunning"); 00202 assert(fAudioDriver); 00203 return fAudioDriver->IsRunning(); 00204 } 00205 00206 int JackServer::SetBufferSize(jack_nframes_t buffer_size) 00207 { 00208 jack_log("JackServer::SetBufferSize nframes = %ld", buffer_size); 00209 jack_nframes_t current_buffer_size = fEngineControl->fBufferSize; 00210 00211 if (current_buffer_size == buffer_size) { 00212 jack_log("SetBufferSize: requirement for new buffer size equals current value"); 00213 return 0; 00214 } 00215 00216 if (fAudioDriver->IsFixedBufferSize()) { 00217 jack_log("SetBufferSize: driver only supports a fixed buffer size"); 00218 return -1; 00219 } 00220 00221 if (fAudioDriver->Stop() != 0) { 00222 jack_error("Cannot stop audio driver"); 00223 return -1; 00224 } 00225 00226 if (fAudioDriver->SetBufferSize(buffer_size) == 0) { 00227 fEngine->NotifyBufferSize(buffer_size); 00228 return fAudioDriver->Start(); 00229 } else { // Failure: try to restore current value 00230 jack_error("Cannot SetBufferSize for audio driver, restore current value %ld", current_buffer_size); 00231 fAudioDriver->SetBufferSize(current_buffer_size); 00232 fAudioDriver->Start(); 00233 // SetBufferSize actually failed, so return an error... 00234 return -1; 00235 } 00236 } 00237 00238 /* 00239 Freewheel mode is implemented by switching from the (audio + freewheel) driver to the freewheel driver only: 00240 00241 - "global" connection state is saved 00242 - all audio driver ports are deconnected, thus there is no more dependancies with the audio driver 00243 - the freewheel driver will be synchronized with the end of graph execution : all clients are connected to the freewheel driver 00244 - the freewheel driver becomes the "master" 00245 00246 Normal mode is restored with the connections state valid before freewheel mode was done. Thus one consider that 00247 no graph state change can be done during freewheel mode. 00248 */ 00249 00250 int JackServer::SetFreewheel(bool onoff) 00251 { 00252 jack_log("JackServer::SetFreewheel is = %ld want = %ld", fFreewheel, onoff); 00253 00254 if (fFreewheel) { 00255 if (onoff) { 00256 return -1; 00257 } else { 00258 fFreewheel = false; 00259 fThreadedFreewheelDriver->Stop(); 00260 fGraphManager->Restore(&fConnectionState); // Restore previous connection state 00261 fEngine->NotifyFreewheel(onoff); 00262 fFreewheelDriver->SetMaster(false); 00263 fAudioDriver->SetMaster(true); 00264 return fAudioDriver->Start(); 00265 } 00266 } else { 00267 if (onoff) { 00268 fFreewheel = true; 00269 fAudioDriver->Stop(); 00270 fGraphManager->Save(&fConnectionState); // Save connection state 00271 fGraphManager->DisconnectAllPorts(fAudioDriver->GetClientControl()->fRefNum); 00272 fEngine->NotifyFreewheel(onoff); 00273 fAudioDriver->SetMaster(false); 00274 fFreewheelDriver->SetMaster(true); 00275 return fThreadedFreewheelDriver->Start(); 00276 } else { 00277 return -1; 00278 } 00279 } 00280 } 00281 00282 // Coming from the RT thread 00283 void JackServer::Notify(int refnum, int notify, int value) 00284 { 00285 switch (notify) { 00286 00287 case kGraphOrderCallback: 00288 fEngine->NotifyGraphReorder(); 00289 break; 00290 00291 case kXRunCallback: 00292 fEngine->NotifyXRun(refnum); 00293 break; 00294 } 00295 } 00296 00297 void JackServer::ClientKill(int refnum) 00298 { 00299 jack_log("JackServer::ClientKill ref = %ld", refnum); 00300 if (fEngine->ClientDeactivate(refnum) < 0) { 00301 jack_error("JackServer::ClientKill ref = %ld cannot be removed from the graph !!", refnum); 00302 } 00303 if (fEngine->ClientExternalClose(refnum) < 0) { 00304 jack_error("JackServer::ClientKill ref = %ld cannot be closed", refnum); 00305 } 00306 } 00307 00308 //---------------------- 00309 // Backend management 00310 //---------------------- 00311 00312 JackDriverInfo* JackServer::AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params) 00313 { 00314 JackDriverInfo* info = new JackDriverInfo(); 00315 JackDriverClientInterface* slave = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params); 00316 if (slave == NULL) { 00317 delete info; 00318 return NULL; 00319 } 00320 slave->Attach(); 00321 slave->SetMaster(false); 00322 fAudioDriver->AddSlave(slave); 00323 return info; 00324 } 00325 00326 void JackServer::RemoveSlave(JackDriverInfo* info) 00327 { 00328 JackDriverClientInterface* slave = info->GetBackend(); 00329 fAudioDriver->RemoveSlave(slave); 00330 slave->Detach(); 00331 slave->Close(); 00332 } 00333 00334 int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params) 00335 { 00337 fAudioDriver->Stop(); 00338 fAudioDriver->Detach(); 00339 fAudioDriver->Close(); 00340 00341 // Open new master 00342 JackDriverInfo* info = new JackDriverInfo(); 00343 JackDriverClientInterface* master = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params); 00344 00345 if (master == NULL) { 00346 delete info; 00347 return -1; 00348 } 00349 00350 // Get slaves list 00351 std::list<JackDriverInterface*> slave_list = fAudioDriver->GetSlaves(); 00352 std::list<JackDriverInterface*>::const_iterator it; 00353 00354 // Move slaves in new master 00355 for (it = slave_list.begin(); it != slave_list.end(); it++) { 00356 JackDriverInterface* slave = *it; 00357 master->AddSlave(slave); 00358 } 00359 00360 // Delete old master 00361 delete fDriverInfo; 00362 00363 // Activate master 00364 fAudioDriver = master; 00365 fDriverInfo = info; 00366 fAudioDriver->Attach(); 00367 fAudioDriver->SetMaster(true); 00368 return fAudioDriver->Start(); 00369 } 00370 00371 //---------------------- 00372 // Transport management 00373 //---------------------- 00374 00375 int JackServer::ReleaseTimebase(int refnum) 00376 { 00377 return fEngineControl->fTransport.ResetTimebase(refnum); 00378 } 00379 00380 int JackServer::SetTimebaseCallback(int refnum, int conditional) 00381 { 00382 return fEngineControl->fTransport.SetTimebaseMaster(refnum, conditional); 00383 } 00384 00385 JackLockedEngine* JackServer::GetEngine() 00386 { 00387 return fEngine; 00388 } 00389 00390 JackSynchro* JackServer::GetSynchroTable() 00391 { 00392 return fSynchroTable; 00393 } 00394 00395 JackEngineControl* JackServer::GetEngineControl() 00396 { 00397 return fEngineControl; 00398 } 00399 00400 JackGraphManager* JackServer::GetGraphManager() 00401 { 00402 return fGraphManager; 00403 } 00404 00405 00406 } // end of namespace 00407