Jack2 1.9.8

JackServer.cpp

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