~ubuntu-branches/debian/sid/jackd2/sid

« back to all changes in this revision

Viewing changes to .pc/no-selfconnect.patch/common/JackServer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adrian Knoth
  • Date: 2011-03-31 13:54:50 UTC
  • mfrom: (1.1.3 upstream) (2.1.4 experimental)
  • Revision ID: james.westby@ubuntu.com-20110331135450-zafc1di024kzeu31
Tags: 1.9.7~dfsg-1
* New upstream version 1.9.7 (ALSA resume, new latency API)
* Build with --mixed on i386 to be compatible with amd64.
* Don't patch jack_connect for fast consecutive calls anymore, it's now
  using the same code as in jackd1 and waits for the port connection to
  appear.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (C) 2001 Paul Davis
 
3
Copyright (C) 2004-2008 Grame
 
4
 
 
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.
 
9
 
 
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.
 
14
 
 
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.
 
18
 
 
19
*/
 
20
 
 
21
#include "JackSystemDeps.h"
 
22
#include "JackServerGlobals.h"
 
23
#include "JackTime.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"
 
37
 
 
38
namespace Jack
 
39
{
 
40
 
 
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)
 
42
{
 
43
    if (rt) {
 
44
        jack_info("JACK server starting in realtime mode with priority %ld", priority);
 
45
    } else {
 
46
        jack_info("JACK server starting in non-realtime mode");
 
47
    }
 
48
 
 
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);
 
52
 
 
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);
 
60
 
 
61
   fFreewheelDriver = freewheelDriver;
 
62
    fDriverInfo = new JackDriverInfo();
 
63
    fAudioDriver = NULL;
 
64
    fFreewheel = false;
 
65
    JackServerGlobals::fInstance = this;   // Unique instance
 
66
    JackServerGlobals::fUserCount = 1;     // One user
 
67
    JackGlobals::fVerbose = verbose;
 
68
}
 
69
 
 
70
JackServer::~JackServer()
 
71
{
 
72
    JackGraphManager::Destroy(fGraphManager);
 
73
    delete fDriverInfo;
 
74
    delete fThreadedFreewheelDriver;
 
75
    delete fEngine;
 
76
    delete fEngineControl;
 
77
}
 
78
 
 
79
int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params)
 
80
{
 
81
    // TODO: move that in reworked JackServerGlobals::Init()
 
82
    JackMessageBuffer::Create();
 
83
 
 
84
     if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) {
 
85
        jack_error("Cannot initialize driver");
 
86
        goto fail_close1;
 
87
    }
 
88
 
 
89
    if (fChannel.Open(fEngineControl->fServerName, this) < 0) {
 
90
        jack_error("Server channel open error");
 
91
        goto fail_close2;
 
92
    }
 
93
 
 
94
    if (fEngine->Open() < 0) {
 
95
        jack_error("Cannot open engine");
 
96
        goto fail_close3;
 
97
    }
 
98
 
 
99
    if (fFreewheelDriver->Open() < 0) {
 
100
        jack_error("Cannot open freewheel driver");
 
101
        goto fail_close4;
 
102
    }
 
103
 
 
104
    if (fAudioDriver->Attach() < 0) {
 
105
        jack_error("Cannot attach audio driver");
 
106
        goto fail_close5;
 
107
    }
 
108
 
 
109
    fFreewheelDriver->SetMaster(false);
 
110
    fAudioDriver->SetMaster(true);
 
111
    fAudioDriver->AddSlave(fFreewheelDriver);
 
112
    InitTime();
 
113
    SetClockSource(fEngineControl->fClockSource);
 
114
    return 0;
 
115
 
 
116
fail_close5:
 
117
    fFreewheelDriver->Close();
 
118
 
 
119
fail_close4:
 
120
    fEngine->Close();
 
121
 
 
122
fail_close3:
 
123
    fChannel.Close();
 
124
 
 
125
fail_close2:
 
126
    fAudioDriver->Close();
 
127
 
 
128
fail_close1:
 
129
    JackMessageBuffer::Destroy();
 
130
    return -1;
 
131
}
 
132
 
 
133
int JackServer::Close()
 
134
{
 
135
    jack_log("JackServer::Close");
 
136
    fEngine->NotifyQuit();
 
137
    fChannel.Close();
 
138
    fAudioDriver->Detach();
 
139
    fAudioDriver->Close();
 
140
    fFreewheelDriver->Close();
 
141
    fEngine->Close();
 
142
    // TODO: move that in reworked JackServerGlobals::Destroy()
 
143
    JackMessageBuffer::Destroy();
 
144
    return 0;
 
145
}
 
146
 
 
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)
 
148
{
 
149
    JackLoadableInternalClient* client = new JackLoadableInternalClient1(JackServerGlobals::fInstance, GetSynchroTable(), objet_data);
 
150
    assert(client);
 
151
    return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status);
 
152
 }
 
153
 
 
154
int JackServer::InternalClientLoad2(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status)
 
155
{
 
156
    JackLoadableInternalClient* client = new JackLoadableInternalClient2(JackServerGlobals::fInstance, GetSynchroTable(), parameters);
 
157
    assert(client);
 
158
    return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status);
 
159
}
 
160
 
 
161
int JackServer::InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int uuid, int* status)
 
162
{
 
163
    // Clear status
 
164
    *status = 0;
 
165
 
 
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)) {
 
168
        delete client;
 
169
        int my_status1 = *status | JackFailure;
 
170
        *status = (jack_status_t)my_status1;
 
171
        *int_ref = 0;
 
172
        return -1;
 
173
    } else {
 
174
        *int_ref = client->GetClientControl()->fRefNum;
 
175
        return 0;
 
176
    }
 
177
 }
 
178
 
 
179
int JackServer::Start()
 
180
{
 
181
    jack_log("JackServer::Start");
 
182
    if (fAudioDriver->Start() < 0) {
 
183
        return -1;
 
184
    }
 
185
    return fChannel.Start();
 
186
}
 
187
 
 
188
int JackServer::Stop()
 
189
{
 
190
    jack_log("JackServer::Stop");
 
191
    if (fFreewheel) {
 
192
        return fThreadedFreewheelDriver->Stop();
 
193
    } else {
 
194
        return fAudioDriver->Stop();
 
195
    }
 
196
}
 
197
 
 
198
bool JackServer::IsRunning()
 
199
{
 
200
    jack_log("JackServer::IsRunning");
 
201
    assert(fAudioDriver);
 
202
    return fAudioDriver->IsRunning();
 
203
}
 
204
 
 
205
int JackServer::SetBufferSize(jack_nframes_t buffer_size)
 
206
{
 
207
    jack_log("JackServer::SetBufferSize nframes = %ld", buffer_size);
 
208
    jack_nframes_t current_buffer_size = fEngineControl->fBufferSize;
 
209
 
 
210
    if (current_buffer_size == buffer_size) {
 
211
        jack_log("SetBufferSize: requirement for new buffer size equals current value");
 
212
        return 0;
 
213
    }
 
214
 
 
215
    if (fAudioDriver->IsFixedBufferSize()) {
 
216
        jack_log("SetBufferSize: driver only supports a fixed buffer size");
 
217
        return -1;
 
218
    }
 
219
 
 
220
    if (fAudioDriver->Stop() != 0) {
 
221
        jack_error("Cannot stop audio driver");
 
222
        return -1;
 
223
    }
 
224
 
 
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...
 
235
        return -1;
 
236
    }
 
237
}
 
238
 
 
239
/*
 
240
Freewheel mode is implemented by switching from the (audio + freewheel) driver to the freewheel driver only:
 
241
 
 
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"
 
246
 
 
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.
 
249
*/
 
250
 
 
251
int JackServer::SetFreewheel(bool onoff)
 
252
{
 
253
    jack_log("JackServer::SetFreewheel is = %ld want = %ld", fFreewheel, onoff);
 
254
 
 
255
    if (fFreewheel) {
 
256
        if (onoff) {
 
257
            return -1;
 
258
        } else {
 
259
            fFreewheel = false;
 
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();
 
266
        }
 
267
    } else {
 
268
        if (onoff) {
 
269
            fFreewheel = true;
 
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();
 
277
        } else {
 
278
            return -1;
 
279
        }
 
280
    }
 
281
}
 
282
 
 
283
// Coming from the RT thread
 
284
void JackServer::Notify(int refnum, int notify, int value)
 
285
{
 
286
    switch (notify) {
 
287
 
 
288
        case kGraphOrderCallback:
 
289
            fEngine->NotifyGraphReorder();
 
290
            break;
 
291
 
 
292
        case kXRunCallback:
 
293
            fEngine->NotifyXRun(refnum);
 
294
            break;
 
295
    }
 
296
}
 
297
 
 
298
void JackServer::ClientKill(int refnum)
 
299
{
 
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);
 
303
    }
 
304
    if (fEngine->ClientExternalClose(refnum) < 0) {
 
305
        jack_error("JackServer::ClientKill ref = %ld cannot be closed", refnum);
 
306
    }
 
307
}
 
308
 
 
309
//----------------------
 
310
// Backend management
 
311
//----------------------
 
312
 
 
313
JackDriverInfo* JackServer::AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params)
 
314
{
 
315
    JackDriverInfo* info = new JackDriverInfo();
 
316
    JackDriverClientInterface* slave = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params);
 
317
    if (slave == NULL) {
 
318
        delete info;
 
319
        return NULL;
 
320
    }
 
321
    slave->Attach();
 
322
    slave->SetMaster(false);
 
323
    fAudioDriver->AddSlave(slave);
 
324
    return info;
 
325
}
 
326
 
 
327
void JackServer::RemoveSlave(JackDriverInfo* info)
 
328
{
 
329
    JackDriverClientInterface* slave = info->GetBackend();
 
330
    fAudioDriver->RemoveSlave(slave);
 
331
    slave->Detach();
 
332
    slave->Close();
 
333
}
 
334
 
 
335
int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params)
 
336
{
 
337
    /// Remove current master
 
338
    fAudioDriver->Stop();
 
339
    fAudioDriver->Detach();
 
340
    fAudioDriver->Close();
 
341
 
 
342
    // Open new master
 
343
    JackDriverInfo* info = new JackDriverInfo();
 
344
    JackDriverClientInterface* master = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params);
 
345
 
 
346
    if (master == NULL) {
 
347
        delete info;
 
348
        return -1;
 
349
    }
 
350
 
 
351
    // Get slaves list
 
352
    std::list<JackDriverInterface*> slave_list = fAudioDriver->GetSlaves();
 
353
    std::list<JackDriverInterface*>::const_iterator it;
 
354
 
 
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);
 
359
    }
 
360
 
 
361
    // Delete old master
 
362
    delete fDriverInfo;
 
363
 
 
364
    // Activate master
 
365
    fAudioDriver = master;
 
366
    fDriverInfo = info;
 
367
    fAudioDriver->Attach();
 
368
    fAudioDriver->SetMaster(true);
 
369
    return fAudioDriver->Start();
 
370
}
 
371
 
 
372
//----------------------
 
373
// Transport management
 
374
//----------------------
 
375
 
 
376
int JackServer::ReleaseTimebase(int refnum)
 
377
{
 
378
    return fEngineControl->fTransport.ResetTimebase(refnum);
 
379
}
 
380
 
 
381
int JackServer::SetTimebaseCallback(int refnum, int conditional)
 
382
{
 
383
    return fEngineControl->fTransport.SetTimebaseMaster(refnum, conditional);
 
384
}
 
385
 
 
386
JackLockedEngine* JackServer::GetEngine()
 
387
{
 
388
    return fEngine;
 
389
}
 
390
 
 
391
JackSynchro* JackServer::GetSynchroTable()
 
392
{
 
393
    return fSynchroTable;
 
394
}
 
395
 
 
396
JackEngineControl* JackServer::GetEngineControl()
 
397
{
 
398
    return fEngineControl;
 
399
}
 
400
 
 
401
JackGraphManager* JackServer::GetGraphManager()
 
402
{
 
403
    return fGraphManager;
 
404
}
 
405
 
 
406
 
 
407
} // end of namespace
 
408