2
Copyright (C) 2001 Paul Davis
3
Copyright (C) 2004-2008 Grame
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
#include "JackSystemDeps.h"
22
#include "JackServerGlobals.h"
24
#include "JackFreewheelDriver.h"
25
#include "JackDummyDriver.h"
26
#include "JackThreadedDriver.h"
27
#include "JackGlobals.h"
28
#include "JackLockedEngine.h"
29
#include "JackAudioDriver.h"
30
#include "JackChannel.h"
31
#include "JackClientControl.h"
32
#include "JackEngineControl.h"
33
#include "JackGraphManager.h"
34
#include "JackInternalClient.h"
35
#include "JackError.h"
36
#include "JackMessageBuffer.h"
41
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)
44
jack_info("JACK server starting in realtime mode with priority %ld", priority);
46
jack_info("JACK server starting in non-realtime mode");
49
fGraphManager = JackGraphManager::Allocate(port_max);
50
fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name);
51
fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl);
53
// A distinction is made between the threaded freewheel driver and the
54
// regular freewheel driver because the freewheel driver needs to run in
55
// threaded mode when freewheel mode is active and needs to run as a slave
56
// when freewheel mode isn't active.
57
JackFreewheelDriver *freewheelDriver =
58
new JackFreewheelDriver(fEngine, GetSynchroTable());
59
fThreadedFreewheelDriver = new JackThreadedDriver(freewheelDriver);
61
fFreewheelDriver = freewheelDriver;
62
fDriverInfo = new JackDriverInfo();
65
JackServerGlobals::fInstance = this; // Unique instance
66
JackServerGlobals::fUserCount = 1; // One user
67
JackGlobals::fVerbose = verbose;
70
JackServer::~JackServer()
72
JackGraphManager::Destroy(fGraphManager);
74
delete fThreadedFreewheelDriver;
76
delete fEngineControl;
79
int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params)
81
// TODO: move that in reworked JackServerGlobals::Init()
82
JackMessageBuffer::Create();
84
if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) {
85
jack_error("Cannot initialize driver");
89
if (fChannel.Open(fEngineControl->fServerName, this) < 0) {
90
jack_error("Server channel open error");
94
if (fEngine->Open() < 0) {
95
jack_error("Cannot open engine");
99
if (fFreewheelDriver->Open() < 0) {
100
jack_error("Cannot open freewheel driver");
104
if (fAudioDriver->Attach() < 0) {
105
jack_error("Cannot attach audio driver");
109
fFreewheelDriver->SetMaster(false);
110
fAudioDriver->SetMaster(true);
111
fAudioDriver->AddSlave(fFreewheelDriver);
113
SetClockSource(fEngineControl->fClockSource);
117
fFreewheelDriver->Close();
126
fAudioDriver->Close();
129
JackMessageBuffer::Destroy();
133
int JackServer::Close()
135
jack_log("JackServer::Close");
136
fEngine->NotifyQuit();
138
fAudioDriver->Detach();
139
fAudioDriver->Close();
140
fFreewheelDriver->Close();
142
// TODO: move that in reworked JackServerGlobals::Destroy()
143
JackMessageBuffer::Destroy();
147
int JackServer::InternalClientLoad1(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status)
149
JackLoadableInternalClient* client = new JackLoadableInternalClient1(JackServerGlobals::fInstance, GetSynchroTable(), objet_data);
151
return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status);
154
int JackServer::InternalClientLoad2(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status)
156
JackLoadableInternalClient* client = new JackLoadableInternalClient2(JackServerGlobals::fInstance, GetSynchroTable(), parameters);
158
return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status);
161
int JackServer::InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int uuid, int* status)
166
// Client object is internally kept in JackEngine
167
if ((client->Init(so_name) < 0) || (client->Open(JACK_DEFAULT_SERVER_NAME, client_name, uuid, (jack_options_t)options, (jack_status_t*)status) < 0)) {
169
int my_status1 = *status | JackFailure;
170
*status = (jack_status_t)my_status1;
174
*int_ref = client->GetClientControl()->fRefNum;
179
int JackServer::Start()
181
jack_log("JackServer::Start");
182
if (fAudioDriver->Start() < 0) {
185
return fChannel.Start();
188
int JackServer::Stop()
190
jack_log("JackServer::Stop");
192
return fThreadedFreewheelDriver->Stop();
194
return fAudioDriver->Stop();
198
bool JackServer::IsRunning()
200
jack_log("JackServer::IsRunning");
201
assert(fAudioDriver);
202
return fAudioDriver->IsRunning();
205
int JackServer::SetBufferSize(jack_nframes_t buffer_size)
207
jack_log("JackServer::SetBufferSize nframes = %ld", buffer_size);
208
jack_nframes_t current_buffer_size = fEngineControl->fBufferSize;
210
if (current_buffer_size == buffer_size) {
211
jack_log("SetBufferSize: requirement for new buffer size equals current value");
215
if (fAudioDriver->IsFixedBufferSize()) {
216
jack_log("SetBufferSize: driver only supports a fixed buffer size");
220
if (fAudioDriver->Stop() != 0) {
221
jack_error("Cannot stop audio driver");
225
if (fAudioDriver->SetBufferSize(buffer_size) == 0) {
226
fFreewheelDriver->SetBufferSize(buffer_size);
227
fEngine->NotifyBufferSize(buffer_size);
228
return fAudioDriver->Start();
229
} else { // Failure: try to restore current value
230
jack_error("Cannot SetBufferSize for audio driver, restore current value %ld", current_buffer_size);
231
fAudioDriver->SetBufferSize(current_buffer_size);
232
fFreewheelDriver->SetBufferSize(current_buffer_size);
233
fAudioDriver->Start();
234
// SetBufferSize actually failed, so return an error...
240
Freewheel mode is implemented by switching from the (audio + freewheel) driver to the freewheel driver only:
242
- "global" connection state is saved
243
- all audio driver ports are deconnected, thus there is no more dependancies with the audio driver
244
- the freewheel driver will be synchronized with the end of graph execution : all clients are connected to the freewheel driver
245
- the freewheel driver becomes the "master"
247
Normal mode is restored with the connections state valid before freewheel mode was done. Thus one consider that
248
no graph state change can be done during freewheel mode.
251
int JackServer::SetFreewheel(bool onoff)
253
jack_log("JackServer::SetFreewheel is = %ld want = %ld", fFreewheel, onoff);
260
fThreadedFreewheelDriver->Stop();
261
fGraphManager->Restore(&fConnectionState); // Restore previous connection state
262
fEngine->NotifyFreewheel(onoff);
263
fFreewheelDriver->SetMaster(false);
264
fAudioDriver->SetMaster(true);
265
return fAudioDriver->Start();
270
fAudioDriver->Stop();
271
fGraphManager->Save(&fConnectionState); // Save connection state
272
fGraphManager->DisconnectAllPorts(fAudioDriver->GetClientControl()->fRefNum);
273
fEngine->NotifyFreewheel(onoff);
274
fAudioDriver->SetMaster(false);
275
fFreewheelDriver->SetMaster(true);
276
return fThreadedFreewheelDriver->Start();
283
// Coming from the RT thread
284
void JackServer::Notify(int refnum, int notify, int value)
288
case kGraphOrderCallback:
289
fEngine->NotifyGraphReorder();
293
fEngine->NotifyXRun(refnum);
298
void JackServer::ClientKill(int refnum)
300
jack_log("JackServer::ClientKill ref = %ld", refnum);
301
if (fEngine->ClientDeactivate(refnum) < 0) {
302
jack_error("JackServer::ClientKill ref = %ld cannot be removed from the graph !!", refnum);
304
if (fEngine->ClientExternalClose(refnum) < 0) {
305
jack_error("JackServer::ClientKill ref = %ld cannot be closed", refnum);
309
//----------------------
310
// Backend management
311
//----------------------
313
JackDriverInfo* JackServer::AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params)
315
JackDriverInfo* info = new JackDriverInfo();
316
JackDriverClientInterface* slave = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params);
322
slave->SetMaster(false);
323
fAudioDriver->AddSlave(slave);
327
void JackServer::RemoveSlave(JackDriverInfo* info)
329
JackDriverClientInterface* slave = info->GetBackend();
330
fAudioDriver->RemoveSlave(slave);
335
int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params)
337
/// Remove current master
338
fAudioDriver->Stop();
339
fAudioDriver->Detach();
340
fAudioDriver->Close();
343
JackDriverInfo* info = new JackDriverInfo();
344
JackDriverClientInterface* master = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params);
346
if (master == NULL) {
352
std::list<JackDriverInterface*> slave_list = fAudioDriver->GetSlaves();
353
std::list<JackDriverInterface*>::const_iterator it;
355
// Move slaves in new master
356
for (it = slave_list.begin(); it != slave_list.end(); it++) {
357
JackDriverInterface* slave = *it;
358
master->AddSlave(slave);
365
fAudioDriver = master;
367
fAudioDriver->Attach();
368
fAudioDriver->SetMaster(true);
369
return fAudioDriver->Start();
372
//----------------------
373
// Transport management
374
//----------------------
376
int JackServer::ReleaseTimebase(int refnum)
378
return fEngineControl->fTransport.ResetTimebase(refnum);
381
int JackServer::SetTimebaseCallback(int refnum, int conditional)
383
return fEngineControl->fTransport.SetTimebaseMaster(refnum, conditional);
386
JackLockedEngine* JackServer::GetEngine()
391
JackSynchro* JackServer::GetSynchroTable()
393
return fSynchroTable;
396
JackEngineControl* JackServer::GetEngineControl()
398
return fEngineControl;
401
JackGraphManager* JackServer::GetGraphManager()
403
return fGraphManager;
407
} // end of namespace