JackDriver.cpp 12.2 KB
Newer Older
sletz's avatar
sletz committed
1
/*
sletz's avatar
sletz committed
2
Copyright (C) 2001 Paul Davis
sletz's avatar
sletz committed
3
Copyright (C) 2004-2008 Grame
sletz's avatar
sletz committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

sletz's avatar
Typo    
sletz committed
19
20
*/

21
#include "JackSystemDeps.h"
sletz's avatar
sletz committed
22
23
24
25
26
27
28
29
#include "JackDriver.h"
#include "JackTime.h"
#include "JackError.h"
#include "JackPort.h"
#include "JackGraphManager.h"
#include "JackGlobals.h"
#include "JackEngineControl.h"
#include "JackClientControl.h"
sletz's avatar
sletz committed
30
#include "JackLockedEngine.h"
sletz's avatar
sletz committed
31
32
33
34
35
36
37
38
#include <math.h>
#include <assert.h>

using namespace std;

namespace Jack
{

sletz's avatar
sletz committed
39
JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
40
    :fClientControl(name)
sletz's avatar
sletz committed
41
42
43
{
    assert(strlen(name) < JACK_CLIENT_NAME_SIZE);
    fSynchroTable = table;
44
    strcpy(fAliasName, alias);
sletz's avatar
sletz committed
45
46
    fEngine = engine;
    fGraphManager = NULL;
sletz's avatar
sletz committed
47
    fBeginDateUst = 0;
48
    fDelayedUsecs = 0.f;
sletz's avatar
sletz committed
49
    fIsMaster = true;
50
    fIsRunning = false;
51
 }
sletz's avatar
sletz committed
52
53
54
55
56
57

JackDriver::JackDriver()
{
    fSynchroTable = NULL;
    fEngine = NULL;
    fGraphManager = NULL;
sletz's avatar
sletz committed
58
    fBeginDateUst = 0;
sletz's avatar
sletz committed
59
    fDelayedUsecs = 0.f;
sletz's avatar
sletz committed
60
    fIsMaster = true;
61
    fIsRunning = false;
sletz's avatar
sletz committed
62
63
64
65
}

JackDriver::~JackDriver()
{
sletz's avatar
sletz committed
66
    jack_log("~JackDriver");
sletz's avatar
sletz committed
67
68
69
70
71
72
}

int JackDriver::Open()
{
    int refnum = -1;

73
    if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
74
        jack_error("Cannot allocate internal client for driver");
sletz's avatar
sletz committed
75
76
77
        return -1;
    }

78
79
    fClientControl.fRefNum = refnum;
    fClientControl.fActive = true;
80
    fEngineControl->fDriverNum++;
81
82
    fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
    SetupDriverSync(fClientControl.fRefNum, false);
sletz's avatar
sletz committed
83
84
85
    return 0;
}

86
int JackDriver::Open(bool capturing,
87
88
89
90
91
92
93
94
95
96
97
98
                     bool playing,
                     int inchannels,
                     int outchannels,
                     bool monitor,
                     const char* capture_driver_name,
                     const char* playback_driver_name,
                     jack_nframes_t capture_latency,
                     jack_nframes_t playback_latency)
{
    jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name);
    jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name);
    int refnum = -1;
99
100
101
102
103
104
105
106
107
    char name_res[JACK_CLIENT_NAME_SIZE + 1];
    int status;

    // Check name and possibly rename
    if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) {
        jack_error("Client name = %s conflits with another running client", fClientControl.fName);
        return -1;
    }
    strcpy(fClientControl.fName, name_res);
108
109
110
111
112
113
114
115

    if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
        jack_error("Cannot allocate internal client for driver");
        return -1;
    }

    fClientControl.fRefNum = refnum;
    fClientControl.fActive = true;
116
    fEngineControl->fDriverNum++;
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    fCaptureLatency = capture_latency;
    fPlaybackLatency = playback_latency;

    assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE);
    assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE);

    strcpy(fCaptureDriverName, capture_driver_name);
    strcpy(fPlaybackDriverName, playback_driver_name);

    fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec
    if (!fEngineControl->fTimeOut)
        fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs);

    fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
    SetupDriverSync(fClientControl.fRefNum, false);
    return 0;
}

sletz's avatar
sletz committed
135
int JackDriver::Open(jack_nframes_t buffer_size,
sletz's avatar
sletz committed
136
                     jack_nframes_t samplerate,
sletz's avatar
sletz committed
137
138
                     bool capturing,
                     bool playing,
sletz's avatar
sletz committed
139
140
141
142
143
144
145
146
                     int inchannels,
                     int outchannels,
                     bool monitor,
                     const char* capture_driver_name,
                     const char* playback_driver_name,
                     jack_nframes_t capture_latency,
                     jack_nframes_t playback_latency)
{
sletz's avatar
sletz committed
147
148
    jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name);
    jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name);
sletz's avatar
sletz committed
149
    int refnum = -1;
150
151
152
153
154
155
156
157
158
    char name_res[JACK_CLIENT_NAME_SIZE + 1];
    int status;

    // Check name and possibly rename
    if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) {
        jack_error("Client name = %s conflits with another running client", fClientControl.fName);
        return -1;
    }
    strcpy(fClientControl.fName, name_res);
sletz's avatar
sletz committed
159

160
    if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
161
        jack_error("Cannot allocate internal client for driver");
sletz's avatar
sletz committed
162
163
164
        return -1;
    }

165
166
    fClientControl.fRefNum = refnum;
    fClientControl.fActive = true;
167
    fEngineControl->fDriverNum++;
sletz's avatar
sletz committed
168
    fEngineControl->fBufferSize = buffer_size;
sletz's avatar
sletz committed
169
170
171
172
173
174
175
176
177
178
    fEngineControl->fSampleRate = samplerate;
    fCaptureLatency = capture_latency;
    fPlaybackLatency = playback_latency;

    assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE);
    assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE);

    strcpy(fCaptureDriverName, capture_driver_name);
    strcpy(fPlaybackDriverName, playback_driver_name);

179
    fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec
180
    if (!fEngineControl->fTimeOut)
181
        fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs);
sletz's avatar
sletz committed
182

sletz's avatar
sletz committed
183
    fGraphManager->SetBufferSize(buffer_size);
184
185
    fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
    SetupDriverSync(fClientControl.fRefNum, false);
sletz's avatar
sletz committed
186
187
188
189
190
    return 0;
}

int JackDriver::Close()
{
191
    if (fClientControl.fRefNum >= 0) {
192
193
194
195
196
197
198
199
        jack_log("JackDriver::Close");
        fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync
        fClientControl.fActive = false;
        fEngineControl->fDriverNum--;
        return fEngine->ClientInternalClose(fClientControl.fRefNum, false);
    } else {
        return -1;
    }
sletz's avatar
sletz committed
200
201
}

202
203
204
205
206
207
208
/*!
	In "async" mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations.
	The synchronization primitives for drivers are setup in "flush" mode that to not keep unneeded activations.
	Drivers synchro are setup in "flush" mode if server is "async" and NOT freewheel.
*/
void JackDriver::SetupDriverSync(int ref, bool freewheel)
{
sletz's avatar
sletz committed
209
    if (!freewheel && !fEngineControl->fSyncMode) {
sletz's avatar
sletz committed
210
        jack_log("JackDriver::SetupDriverSync driver sem in flush mode");
211
        fSynchroTable[ref].SetFlush(true);
212
    } else {
sletz's avatar
sletz committed
213
        jack_log("JackDriver::SetupDriverSync driver sem in normal mode");
214
        fSynchroTable[ref].SetFlush(false);
sletz's avatar
sletz committed
215
    }
216
217
}

218
int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
219
{
220
221
    jack_log("JackDriver::ClientNotify ref = %ld driver = %s name = %s notify = %ld", refnum, fClientControl.fName, name, notify);

sletz's avatar
sletz committed
222
223
224
    switch (notify) {

        case kStartFreewheelCallback:
sletz's avatar
sletz committed
225
            jack_log("JackDriver::kStartFreewheel");
226
            SetupDriverSync(fClientControl.fRefNum, true);
sletz's avatar
sletz committed
227
            break;
228

sletz's avatar
sletz committed
229
        case kStopFreewheelCallback:
sletz's avatar
sletz committed
230
            jack_log("JackDriver::kStopFreewheel");
231
            SetupDriverSync(fClientControl.fRefNum, false);
sletz's avatar
sletz committed
232
            break;
233
    }
sletz's avatar
sletz committed
234
235

    return 0;
236
237
}

sletz's avatar
sletz committed
238
bool JackDriver::IsRealTime() const
sletz's avatar
sletz committed
239
240
241
242
{
    return fEngineControl->fRealTime;
}

243
244
void JackDriver::CycleIncTime()
{
245
    fEngineControl->CycleIncTime(fBeginDateUst);
246
}
sletz's avatar
sletz committed
247
248

void JackDriver::CycleTakeBeginTime()
249
{
sletz's avatar
sletz committed
250
251
252
253
254
    fBeginDateUst = GetMicroSeconds();  // Take callback date here
    fEngineControl->CycleIncTime(fBeginDateUst);
}

void JackDriver::CycleTakeEndTime()
255
{
sletz's avatar
sletz committed
256
    fEndDateUst = GetMicroSeconds();    // Take end date here
257
258
}

sletz's avatar
sletz committed
259
260
JackClientControl* JackDriver::GetClientControl() const
{
261
    return (JackClientControl*)&fClientControl;
sletz's avatar
sletz committed
262
263
}

sletz's avatar
sletz committed
264
void JackDriver::NotifyXRun(jack_time_t cur_cycle_begin, float delayed_usecs)
sletz's avatar
sletz committed
265
{
sletz's avatar
sletz committed
266
    fEngine->NotifyXRun(cur_cycle_begin, delayed_usecs);
sletz's avatar
sletz committed
267
268
}

269
270
271
272
273
274
275
276
277
278
279
void JackDriver::NotifyBufferSize(jack_nframes_t buffer_size)
{
    fEngine->NotifyBufferSize(buffer_size);
    fEngineControl->InitFrameTime();
}

void JackDriver::NotifySampleRate(jack_nframes_t sample_rate)
{
    fEngine->NotifySampleRate(sample_rate);
    fEngineControl->InitFrameTime();
}
280

281
282
283
284
void JackDriver::NotifyFailure(int code, const char* reason)
{
    fEngine->NotifyFailure(code, reason);
}
285

sletz's avatar
sletz committed
286
void JackDriver::SetMaster(bool onoff)
sletz's avatar
sletz committed
287
288
289
290
{
    fIsMaster = onoff;
}

sletz's avatar
sletz committed
291
bool JackDriver::GetMaster()
sletz's avatar
sletz committed
292
293
294
295
{
    return fIsMaster;
}

sletz's avatar
sletz committed
296
void JackDriver::AddSlave(JackDriverInterface* slave)
sletz's avatar
sletz committed
297
298
299
300
{
    fSlaveList.push_back(slave);
}

sletz's avatar
sletz committed
301
void JackDriver::RemoveSlave(JackDriverInterface* slave)
sletz's avatar
sletz committed
302
303
304
305
{
    fSlaveList.remove(slave);
}

306
int JackDriver::ProcessReadSlaves()
sletz's avatar
sletz committed
307
{
sletz's avatar
sletz committed
308
    int res = 0;
sletz's avatar
sletz committed
309
310
311
    list<JackDriverInterface*>::const_iterator it;
    for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
        JackDriverInterface* slave = *it;
312
        if (slave->ProcessRead() < 0)
sletz's avatar
sletz committed
313
            res = -1;
314

sletz's avatar
sletz committed
315
    }
sletz's avatar
sletz committed
316
    return res;
sletz's avatar
sletz committed
317
318
}

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
int JackDriver::ProcessWriteSlaves()
{
    int res = 0;
    list<JackDriverInterface*>::const_iterator it;
    for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
        JackDriverInterface* slave = *it;
        if (slave->ProcessWrite() < 0)
            res = -1;

    }
    return res;
}

int JackDriver::ProcessRead()
{
    return 0;
}

int JackDriver::ProcessWrite()
{
    return 0;
}

sletz's avatar
sletz committed
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
int JackDriver::Process()
{
    return 0;
}

int JackDriver::ProcessNull()
{
    return 0;
}

int JackDriver::Attach()
{
    return 0;
}

int JackDriver::Detach()
{
    return 0;
}

int JackDriver::Read()
{
    return 0;
}

int JackDriver::Write()
{
    return 0;
}

int JackDriver::Start()
{
374
375
376
    if (fIsMaster) {
        fEngineControl->InitFrameTime();
    }
377
    fIsRunning = true;
sletz's avatar
sletz committed
378
379
380
    return 0;
}

sletz's avatar
sletz committed
381
382
383
384
385
386
int JackDriver::Stop()
{
    fIsRunning = false;
    return 0;
}

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
int JackDriver::StartSlaves()
{
    int res = 0;
    list<JackDriverInterface*>::const_iterator it;
    for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
        JackDriverInterface* slave = *it;
        if (slave->Start() < 0) {
            res = -1;

            // XXX: We should attempt to stop all of the slaves that we've
            // started here.

            break;
        }
    }
    return res;
}

int JackDriver::StopSlaves()
{
    int res = 0;
    list<JackDriverInterface*>::const_iterator it;
    for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
        JackDriverInterface* slave = *it;
        if (slave->Stop() < 0)
            res = -1;
    }
    return res;
}

417
418
419
420
421
bool JackDriver::IsFixedBufferSize()
{
    return true;
}

sletz's avatar
sletz committed
422
423
int JackDriver::SetBufferSize(jack_nframes_t buffer_size)
{
424
425
426
427
428
429
430
431
432
433
    int res = 0;

    list<JackDriverInterface*>::const_iterator it;
    for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
        JackDriverInterface* slave = *it;
        if (slave->SetBufferSize(buffer_size) < 0)
            res = -1;
    }

    return res;
sletz's avatar
sletz committed
434
435
436
437
}

int JackDriver::SetSampleRate(jack_nframes_t sample_rate)
{
438
439
440
441
442
443
444
445
    int res = 0;
    list<JackDriverInterface*>::const_iterator it;
    for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
        JackDriverInterface* slave = *it;
        if (slave->SetSampleRate(sample_rate) < 0)
            res = -1;
    }
    return res;
sletz's avatar
sletz committed
446
447
}

448
bool JackDriver::Initialize()
sletz's avatar
sletz committed
449
450
451
452
453
{
    return true;
}


sletz's avatar
sletz committed
454
} // end of namespace