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