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