Jack2 1.9.6

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