merge new MTDM code from Fons' latest release.
[jack2.git] / common / JackDriver.cpp
blob4e0cbbc3e29eb6e4dfd87d9d79c7100012864328
1 /*
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 "JackDriver.h"
23 #include "JackTime.h"
24 #include "JackError.h"
25 #include "JackPort.h"
26 #include "JackGraphManager.h"
27 #include "JackGlobals.h"
28 #include "JackEngineControl.h"
29 #include "JackClientControl.h"
30 #include "JackLockedEngine.h"
31 #include <math.h>
32 #include <assert.h>
34 using namespace std;
36 namespace Jack
39 JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
40 :fCaptureChannels(0),
41 fPlaybackChannels(0),
42 fClientControl(name),
43 fWithMonitorPorts(false)
45 assert(strlen(name) < JACK_CLIENT_NAME_SIZE);
46 fSynchroTable = table;
47 strcpy(fAliasName, alias);
48 fEngine = engine;
49 fGraphManager = NULL;
50 fBeginDateUst = 0;
51 fDelayedUsecs = 0.f;
52 fIsMaster = true;
53 fIsRunning = false;
56 JackDriver::JackDriver()
58 fSynchroTable = NULL;
59 fEngine = NULL;
60 fGraphManager = NULL;
61 fBeginDateUst = 0;
62 fDelayedUsecs = 0.f;
63 fIsMaster = true;
64 fIsRunning = false;
65 fCaptureChannels = 0;
66 fPlaybackChannels = 0;
67 fWithMonitorPorts = false;
70 JackDriver::~JackDriver()
72 jack_log("~JackDriver");
75 int JackDriver::Open()
77 int refnum = -1;
79 if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
80 jack_error("Cannot allocate internal client for driver");
81 return -1;
84 fClientControl.fRefNum = refnum;
85 fClientControl.fActive = true;
86 fEngineControl->fDriverNum++;
87 fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
88 SetupDriverSync(fClientControl.fRefNum, false);
89 return 0;
92 int JackDriver::Open(bool capturing,
93 bool playing,
94 int inchannels,
95 int outchannels,
96 bool monitor,
97 const char* capture_driver_name,
98 const char* playback_driver_name,
99 jack_nframes_t capture_latency,
100 jack_nframes_t playback_latency)
102 jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name);
103 jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name);
104 int refnum = -1;
105 char name_res[JACK_CLIENT_NAME_SIZE + 1];
106 int status;
108 // Check name and possibly rename
109 if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) {
110 jack_error("Client name = %s conflits with another running client", fClientControl.fName);
111 return -1;
113 strcpy(fClientControl.fName, name_res);
115 if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
116 jack_error("Cannot allocate internal client for driver");
117 return -1;
120 fClientControl.fRefNum = refnum;
121 fClientControl.fActive = true;
122 fEngineControl->fDriverNum++;
123 fCaptureLatency = capture_latency;
124 fPlaybackLatency = playback_latency;
126 assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE);
127 assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE);
129 strcpy(fCaptureDriverName, capture_driver_name);
130 strcpy(fPlaybackDriverName, playback_driver_name);
132 fEngineControl->UpdateTimeOut();
134 fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
135 SetupDriverSync(fClientControl.fRefNum, false);
136 return 0;
139 int JackDriver::Open(jack_nframes_t buffer_size,
140 jack_nframes_t samplerate,
141 bool capturing,
142 bool playing,
143 int inchannels,
144 int outchannels,
145 bool monitor,
146 const char* capture_driver_name,
147 const char* playback_driver_name,
148 jack_nframes_t capture_latency,
149 jack_nframes_t playback_latency)
151 jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name);
152 jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name);
153 int refnum = -1;
154 char name_res[JACK_CLIENT_NAME_SIZE + 1];
155 int status;
157 // Check name and possibly rename
158 if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) {
159 jack_error("Client name = %s conflits with another running client", fClientControl.fName);
160 return -1;
162 strcpy(fClientControl.fName, name_res);
164 if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
165 jack_error("Cannot allocate internal client for driver");
166 return -1;
169 fClientControl.fRefNum = refnum;
170 fClientControl.fActive = true;
171 fEngineControl->fDriverNum++;
172 fEngineControl->fBufferSize = buffer_size;
173 fEngineControl->fSampleRate = samplerate;
174 fCaptureLatency = capture_latency;
175 fPlaybackLatency = playback_latency;
177 assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE);
178 assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE);
180 strcpy(fCaptureDriverName, capture_driver_name);
181 strcpy(fPlaybackDriverName, playback_driver_name);
183 fEngineControl->UpdateTimeOut();
185 fGraphManager->SetBufferSize(buffer_size);
186 fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
187 SetupDriverSync(fClientControl.fRefNum, false);
188 return 0;
191 int JackDriver::Close()
193 if (fClientControl.fRefNum >= 0) {
194 jack_log("JackDriver::Close");
195 fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync
196 fClientControl.fActive = false;
197 fEngineControl->fDriverNum--;
198 return fEngine->ClientInternalClose(fClientControl.fRefNum, false);
199 } else {
200 return -1;
205 In "async" mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations.
206 The synchronization primitives for drivers are setup in "flush" mode that to not keep unneeded activations.
207 Drivers synchro are setup in "flush" mode if server is "async" and NOT freewheel.
209 void JackDriver::SetupDriverSync(int ref, bool freewheel)
211 if (!freewheel && !fEngineControl->fSyncMode) {
212 jack_log("JackDriver::SetupDriverSync driver sem in flush mode");
213 fSynchroTable[ref].SetFlush(true);
214 } else {
215 jack_log("JackDriver::SetupDriverSync driver sem in normal mode");
216 fSynchroTable[ref].SetFlush(false);
220 int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
222 jack_log("JackDriver::ClientNotify ref = %ld driver = %s name = %s notify = %ld", refnum, fClientControl.fName, name, notify);
224 switch (notify) {
226 case kStartFreewheelCallback:
227 jack_log("JackDriver::kStartFreewheel");
228 SetupDriverSync(fClientControl.fRefNum, true);
229 break;
231 case kStopFreewheelCallback:
232 jack_log("JackDriver::kStopFreewheel");
233 SetupDriverSync(fClientControl.fRefNum, false);
234 break;
237 return 0;
240 bool JackDriver::IsRealTime() const
242 return fEngineControl->fRealTime;
245 void JackDriver::CycleIncTime()
247 fEngineControl->CycleIncTime(fBeginDateUst);
250 void JackDriver::CycleTakeBeginTime()
252 fBeginDateUst = GetMicroSeconds(); // Take callback date here
253 fEngineControl->CycleIncTime(fBeginDateUst);
256 void JackDriver::CycleTakeEndTime()
258 fEndDateUst = GetMicroSeconds(); // Take end date here
261 JackClientControl* JackDriver::GetClientControl() const
263 return (JackClientControl*)&fClientControl;
266 void JackDriver::NotifyXRun(jack_time_t cur_cycle_begin, float delayed_usecs)
268 fEngine->NotifyXRun(cur_cycle_begin, delayed_usecs);
271 void JackDriver::NotifyBufferSize(jack_nframes_t buffer_size)
273 fEngine->NotifyBufferSize(buffer_size);
274 fEngineControl->InitFrameTime();
277 void JackDriver::NotifySampleRate(jack_nframes_t sample_rate)
279 fEngine->NotifySampleRate(sample_rate);
280 fEngineControl->InitFrameTime();
283 void JackDriver::NotifyFailure(int code, const char* reason)
285 fEngine->NotifyFailure(code, reason);
288 void JackDriver::SetMaster(bool onoff)
290 fIsMaster = onoff;
293 bool JackDriver::GetMaster()
295 return fIsMaster;
298 void JackDriver::AddSlave(JackDriverInterface* slave)
300 fSlaveList.push_back(slave);
303 void JackDriver::RemoveSlave(JackDriverInterface* slave)
305 fSlaveList.remove(slave);
308 int JackDriver::ProcessReadSlaves()
310 int res = 0;
311 list<JackDriverInterface*>::const_iterator it;
312 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
313 JackDriverInterface* slave = *it;
314 if (slave->IsRunning()) {
315 if (slave->ProcessRead() < 0) {
316 res = -1;
320 return res;
323 int JackDriver::ProcessWriteSlaves()
325 int res = 0;
326 list<JackDriverInterface*>::const_iterator it;
327 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
328 JackDriverInterface* slave = *it;
329 if (slave->IsRunning()) {
330 if (slave->ProcessWrite() < 0) {
331 res = -1;
335 return res;
338 int JackDriver::ProcessRead()
340 return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
343 int JackDriver::ProcessWrite()
345 return (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
348 int JackDriver::ProcessReadSync()
350 return 0;
353 int JackDriver::ProcessWriteSync()
355 return 0;
358 int JackDriver::ProcessReadAsync()
360 return 0;
363 int JackDriver::ProcessWriteAsync()
365 return 0;
368 int JackDriver::Process()
370 return 0;
373 int JackDriver::Attach()
375 return 0;
378 int JackDriver::Detach()
380 return 0;
383 int JackDriver::Read()
385 return 0;
388 int JackDriver::Write()
390 return 0;
393 int JackDriver::Start()
395 if (fIsMaster) {
396 fEngineControl->InitFrameTime();
398 fIsRunning = true;
399 return StartSlaves();
402 int JackDriver::Stop()
404 fIsRunning = false;
405 return StopSlaves();
408 int JackDriver::StartSlaves()
410 int res = 0;
411 list<JackDriverInterface*>::const_iterator it;
412 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
413 JackDriverInterface* slave = *it;
414 if (slave->Start() < 0) {
415 res = -1;
416 // XXX: We should attempt to stop all of the slaves that we've
417 // started here.
418 break;
421 return res;
424 int JackDriver::StopSlaves()
426 int res = 0;
427 list<JackDriverInterface*>::const_iterator it;
428 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
429 JackDriverInterface* slave = *it;
430 if (slave->Stop() < 0) {
431 res = -1;
434 return res;
437 bool JackDriver::IsFixedBufferSize()
439 return true;
442 int JackDriver::SetBufferSize(jack_nframes_t buffer_size)
444 int res = 0;
445 list<JackDriverInterface*>::const_iterator it;
446 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
447 JackDriverInterface* slave = *it;
448 if (slave->SetBufferSize(buffer_size) < 0) {
449 res = -1;
452 return res;
455 int JackDriver::SetSampleRate(jack_nframes_t sample_rate)
457 int res = 0;
458 list<JackDriverInterface*>::const_iterator it;
459 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
460 JackDriverInterface* slave = *it;
461 if (slave->SetSampleRate(sample_rate) < 0) {
462 res = -1;
465 return res;
468 bool JackDriver::Initialize()
470 return true;
473 void JackDriver::SaveConnections()
475 const char** connections;
476 fConnections.clear();
477 char alias1[REAL_JACK_PORT_NAME_SIZE];
478 char alias2[REAL_JACK_PORT_NAME_SIZE];
479 char* aliases[2];
481 aliases[0] = alias1;
482 aliases[1] = alias2;
484 for (int i = 0; i < fCaptureChannels; ++i) {
485 if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fCapturePortList[i])) != 0) {
486 for (int j = 0; connections[j]; j++) {
488 fGraphManager->GetPort(fCapturePortList[i])->GetAliases(aliases);
489 fConnections.push_back(make_pair(aliases[0], connections[j]));
490 jack_info("Save connection: %s %s", aliases[0], connections[j]);
492 fConnections.push_back(make_pair(string(fGraphManager->GetPort(fCapturePortList[i])->GetName()), string(connections[j])));
493 jack_info("Save connection: %s %s", fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j]);
495 free(connections);
499 for (int i = 0; i < fPlaybackChannels; ++i) {
500 if (fPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fPlaybackPortList[i])) != 0) {
501 for (int j = 0; connections[j]; j++) {
503 fGraphManager->GetPort(fPlaybackPortList[i])->GetAliases(aliases);
504 fConnections.push_back(make_pair(connections[j], aliases[0]));
505 jack_info("Save connection: %s %s", connections[j], aliases[0]);
507 fConnections.push_back(make_pair(string(connections[j]), string(fGraphManager->GetPort(fPlaybackPortList[i])->GetName())));
508 jack_info("Save connection: %s %s", connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName());
510 free(connections);
515 void JackDriver::RestoreConnections()
517 list<pair<string, string> >::const_iterator it;
519 for (it = fConnections.begin(); it != fConnections.end(); it++) {
520 pair<string, string> connection = *it;
521 jack_info("Restore connection: %s %s", connection.first.c_str(), connection.second.c_str());
522 fEngine->PortConnect(fClientControl.fRefNum, connection.first.c_str(), connection.second.c_str());
526 int JackDriver::ResumeRefNum()
528 return fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
531 int JackDriver::SuspendRefNum()
533 return fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs);
537 } // end of namespace