Jack2 1.9.7

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 "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 

Generated for Jack2 by doxygen 1.7.3