Jack2: JackDriver.cpp Source File

Jack2 1.9.12

JackDriver.cpp
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 "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 "JackTime.h"
32 #include <math.h>
33 #include <assert.h>
34
35 using namespace std;
36
37 namespace Jack
38 {
39
40 JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
41 :fCaptureChannels(0),
42 fPlaybackChannels(0),
43 fClientControl(name),
44 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 fEndDateUst = 0;
52 fDelayedUsecs = 0.f;
53 fIsMaster = true;
54 fIsRunning = false;
55 }
56
57 JackDriver::~JackDriver()
58 {
59 jack_log("~JackDriver");
60 }
61
62 int JackDriver::Open()
63 {
64 int refnum = -1;
65
66 if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
67 jack_error("Cannot allocate internal client for driver");
68 return -1;
69 }
70
71 fClientControl.fRefNum = refnum;
72 fClientControl.fActive = true;
73 fEngineControl->fDriverNum++;
74 fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
75 SetupDriverSync(fClientControl.fRefNum, false);
76 return 0;
77 }
78
79 int JackDriver::Open(jack_nframes_t buffer_size,
80 jack_nframes_t sample_rate,
81 bool capturing,
82 bool playing,
83 int inchannels,
84 int outchannels,
85 bool monitor,
86 const char* capture_driver_name,
87 const char* playback_driver_name,
88 jack_nframes_t capture_latency,
89 jack_nframes_t playback_latency)
90 {
91 jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name);
92 jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name);
93 int refnum = -1;
94 char name_res[JACK_CLIENT_NAME_SIZE + 1];
95 int status;
96
97 // Check name and possibly rename
98 if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) {
99 jack_error("Client name = %s conflits with another running client", fClientControl.fName);
100 return -1;
101 }
102 strcpy(fClientControl.fName, name_res);
103
104 if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
105 jack_error("Cannot allocate internal client for driver");
106 return -1;
107 }
108
109 fClientControl.fRefNum = refnum;
110 fClientControl.fActive = true;
111 fEngineControl->fDriverNum++;
112 if (buffer_size > 0) {
113 fEngineControl->fBufferSize = buffer_size;
114 }
115 if (sample_rate > 0) {
116 fEngineControl->fSampleRate = sample_rate;
117 }
118 fCaptureLatency = capture_latency;
119 fPlaybackLatency = playback_latency;
120
121 assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE);
122 assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE);
123
124 strcpy(fCaptureDriverName, capture_driver_name);
125 strcpy(fPlaybackDriverName, playback_driver_name);
126
127 fEngineControl->UpdateTimeOut();
128
129 fGraphManager->SetBufferSize(fEngineControl->fBufferSize);
130 fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
131 SetupDriverSync(fClientControl.fRefNum, false);
132 return 0;
133 }
134
135 int JackDriver::Close()
136 {
137 if (fClientControl.fRefNum >= 0) {
138 jack_log("JackDriver::Close");
139 fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync
140 fClientControl.fActive = false;
141 fEngineControl->fDriverNum--;
142 return fEngine->ClientInternalClose(fClientControl.fRefNum, false);
143 } else {
144 return -1;
145 }
146 }
147
153 void JackDriver::SetupDriverSync(int ref, bool freewheel)
154 {
155 if (!freewheel && !fEngineControl->fSyncMode) {
156 jack_log("JackDriver::SetupDriverSync driver sem in flush mode");
157 fSynchroTable[ref].SetFlush(true);
158 } else {
159 jack_log("JackDriver::SetupDriverSync driver sem in normal mode");
160 fSynchroTable[ref].SetFlush(false);
161 }
162 }
163
164 int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
165 {
166 jack_log("JackDriver::ClientNotify ref = %ld driver = %s name = %s notify = %ld", refnum, fClientControl.fName, name, notify);
167
168 switch (notify) {
169
170 case kStartFreewheelCallback:
171 jack_log("JackDriver::kStartFreewheel");
172 SetupDriverSync(fClientControl.fRefNum, true);
173 break;
174
175 case kStopFreewheelCallback:
176 jack_log("JackDriver::kStopFreewheel");
177 SetupDriverSync(fClientControl.fRefNum, false);
178 break;
179 }
180
181 return 0;
182 }
183
184 bool JackDriver::IsRealTime() const
185 {
186 return fEngineControl->fRealTime;
187 }
188
189 void JackDriver::CycleIncTime()
190 {
191 fEngineControl->CycleIncTime(fBeginDateUst);
192 }
193
194 void JackDriver::CycleTakeBeginTime()
195 {
196 fBeginDateUst = GetMicroSeconds(); // Take callback date here
197 fEngineControl->CycleIncTime(fBeginDateUst);
198 }
199
200 void JackDriver::CycleTakeEndTime()
201 {
202 fEndDateUst = GetMicroSeconds(); // Take end date here
203 }
204
205 JackClientControl* JackDriver::GetClientControl() const
206 {
207 return (JackClientControl*)&fClientControl;
208 }
209
210 void JackDriver::NotifyXRun(jack_time_t cur_cycle_begin, float delayed_usecs)
211 {
212 fEngineControl->NotifyXRun(cur_cycle_begin, delayed_usecs);
213 fEngine->NotifyDriverXRun();
214 }
215
216 void JackDriver::NotifyBufferSize(jack_nframes_t buffer_size)
217 {
218 fEngine->NotifyBufferSize(buffer_size);
219 fEngineControl->InitFrameTime();
220 }
221
222 void JackDriver::NotifySampleRate(jack_nframes_t sample_rate)
223 {
224 fEngine->NotifySampleRate(sample_rate);
225 fEngineControl->InitFrameTime();
226 }
227
228 void JackDriver::NotifyFailure(int code, const char* reason)
229 {
230 fEngine->NotifyFailure(code, reason);
231 }
232
233 void JackDriver::SetMaster(bool onoff)
234 {
235 fIsMaster = onoff;
236 }
237
238 bool JackDriver::GetMaster()
239 {
240 return fIsMaster;
241 }
242
243 void JackDriver::AddSlave(JackDriverInterface* slave)
244 {
245 fSlaveList.push_back(slave);
246 }
247
248 void JackDriver::RemoveSlave(JackDriverInterface* slave)
249 {
250 fSlaveList.remove(slave);
251 }
252
253 int JackDriver::ProcessReadSlaves()
254 {
255 int res = 0;
256 list<JackDriverInterface*>::const_iterator it;
257 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
258 JackDriverInterface* slave = *it;
259 if (slave->IsRunning()) {
260 if (slave->ProcessRead() < 0) {
261 res = -1;
262 }
263 }
264 }
265 return res;
266 }
267
268 int JackDriver::ProcessWriteSlaves()
269 {
270 int res = 0;
271 list<JackDriverInterface*>::const_iterator it;
272 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
273 JackDriverInterface* slave = *it;
274 if (slave->IsRunning()) {
275 if (slave->ProcessWrite() < 0) {
276 res = -1;
277 }
278 }
279 }
280 return res;
281 }
282
283 int JackDriver::ProcessRead()
284 {
285 return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
286 }
287
288 int JackDriver::ProcessWrite()
289 {
290 return (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
291 }
292
293 int JackDriver::ProcessReadSync()
294 {
295 return 0;
296 }
297
298 int JackDriver::ProcessWriteSync()
299 {
300 return 0;
301 }
302
303 int JackDriver::ProcessReadAsync()
304 {
305 return 0;
306 }
307
308 int JackDriver::ProcessWriteAsync()
309 {
310 return 0;
311 }
312
313 int JackDriver::Process()
314 {
315 return 0;
316 }
317
318 int JackDriver::Attach()
319 {
320 return 0;
321 }
322
323 int JackDriver::Detach()
324 {
325 return 0;
326 }
327
328 int JackDriver::Read()
329 {
330 return 0;
331 }
332
333 int JackDriver::Write()
334 {
335 return 0;
336 }
337
338 int JackDriver::Start()
339 {
340 if (fIsMaster) {
341 fEngineControl->InitFrameTime();
342 }
343 fIsRunning = true;
344 return StartSlaves();
345 }
346
347 int JackDriver::Stop()
348 {
349 fIsRunning = false;
350 return StopSlaves();
351 }
352
353 int JackDriver::StartSlaves()
354 {
355 int res = 0;
356 list<JackDriverInterface*>::const_iterator it;
357 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
358 JackDriverInterface* slave = *it;
359 if (slave->Start() < 0) {
360 res = -1;
361 // XXX: We should attempt to stop all of the slaves that we've
362 // started here.
363 break;
364 }
365 }
366 return res;
367 }
368
369 int JackDriver::StopSlaves()
370 {
371 int res = 0;
372 list<JackDriverInterface*>::const_iterator it;
373 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
374 JackDriverInterface* slave = *it;
375 if (slave->Stop() < 0) {
376 res = -1;
377 }
378 }
379 return res;
380 }
381
382 bool JackDriver::IsFixedBufferSize()
383 {
384 return true;
385 }
386
387 int JackDriver::SetBufferSize(jack_nframes_t buffer_size)
388 {
389 int res = 0;
390 list<JackDriverInterface*>::const_iterator it;
391 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
392 JackDriverInterface* slave = *it;
393 if (slave->SetBufferSize(buffer_size) < 0) {
394 res = -1;
395 }
396 }
397 return res;
398 }
399
400 int JackDriver::SetSampleRate(jack_nframes_t sample_rate)
401 {
402 int res = 0;
403 list<JackDriverInterface*>::const_iterator it;
404 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
405 JackDriverInterface* slave = *it;
406 if (slave->SetSampleRate(sample_rate) < 0) {
407 res = -1;
408 }
409 }
410 return res;
411 }
412
413 bool JackDriver::Initialize()
414 {
415 return true;
416 }
417
418 static string RemoveLast(const string& name)
419 {
420 return name.substr(0, name.find_last_of(':')); // Remove end of name after last ":"
421 }
422
423 void JackDriver::SaveConnections(int alias)
424 {
425 const char** connections;
426 char alias1[REAL_JACK_PORT_NAME_SIZE+1];
427 char alias2[REAL_JACK_PORT_NAME_SIZE+1];
428 char system_alias1[REAL_JACK_PORT_NAME_SIZE+1];
429 char system_alias2[REAL_JACK_PORT_NAME_SIZE+1];
430 char* aliases[2];
431 char* system_aliases[2];
432
433 aliases[0] = alias1;
434 aliases[1] = alias2;
435
436 system_aliases[0] = system_alias1;
437 system_aliases[1] = system_alias2;
438
439 fConnections.clear();
440
441 for (int i = 0; i < fCaptureChannels; ++i) {
442 if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fCapturePortList[i])) != 0) {
443 if (alias == 0) {
444 for (int j = 0; connections[j]; j++) {
445 JackPort* port_id = fGraphManager->GetPort(fCapturePortList[i]);
446 fConnections.push_back(make_pair(port_id->GetType(), make_pair(port_id->GetName(), connections[j])));
447 jack_info("Save connection: %s %s", fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j]);
448 }
449 } else {
450 int res1 = fGraphManager->GetPort(fCapturePortList[i])->GetAliases(aliases);
451 string sub_system_name;
452 if (res1 >= alias) {
453 sub_system_name = aliases[alias-1];
454 } else {
455 sub_system_name = fGraphManager->GetPort(fCapturePortList[i])->GetName();
456 }
457 for (int j = 0; connections[j]; j++) {
458 JackPort* port_id = fGraphManager->GetPort(fGraphManager->GetPort(connections[j]));
459 int res2 = port_id->GetAliases(system_aliases);
460 string sub_system;
461 if (res2 >= alias) {
462 sub_system = system_aliases[alias-1];
463 } else {
464 sub_system = connections[j];
465 }
466 fConnections.push_back(make_pair(port_id->GetType(), make_pair(sub_system_name, sub_system)));
467 jack_info("Save connection: %s %s", sub_system_name.c_str(), sub_system.c_str());
468 }
469 }
470 free(connections);
471 }
472 }
473
474 for (int i = 0; i < fPlaybackChannels; ++i) {
475 if (fPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fPlaybackPortList[i])) != 0) {
476 if (alias == 0) {
477 for (int j = 0; connections[j]; j++) {
478 JackPort* port_id = fGraphManager->GetPort(fPlaybackPortList[i]);
479 fConnections.push_back(make_pair(port_id->GetType(), make_pair(connections[j], port_id->GetName())));
480 jack_info("Save connection: %s %s", connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName());
481 }
482 } else {
483 int res1 = fGraphManager->GetPort(fPlaybackPortList[i])->GetAliases(aliases);
484 string sub_system_name;
485 if (res1 >= alias) {
486 sub_system_name = aliases[alias-1];
487 } else {
488 sub_system_name = fGraphManager->GetPort(fPlaybackPortList[i])->GetName();
489 }
490 for (int j = 0; connections[j]; j++) {
491 JackPort* port_id = fGraphManager->GetPort(fGraphManager->GetPort(connections[j]));
492 int res2 = port_id->GetAliases(system_aliases);
493 string sub_name;
494 if (res2 >= alias) {
495 sub_name = system_aliases[alias-1];
496 } else {
497 sub_name = connections[j];
498 }
499 fConnections.push_back(make_pair(port_id->GetType(), make_pair(sub_name, sub_system_name)));
500 jack_info("Save connection: %s %s", sub_name.c_str(), sub_system_name.c_str());
501 }
502 }
503 free(connections);
504 }
505 }
506 }
507
508 string JackDriver::MatchPortName(const char* name, const char** ports, int alias, const std::string& type)
509 {
510 char alias1[REAL_JACK_PORT_NAME_SIZE+1];
511 char alias2[REAL_JACK_PORT_NAME_SIZE+1];
512 char* aliases[2];
513
514 aliases[0] = alias1;
515 aliases[1] = alias2;
516
517 for (int i = 0; ports && ports[i]; ++i) {
518
519 jack_port_id_t port_id2 = fGraphManager->GetPort(ports[i]);
520 JackPort* port2 = (port_id2 != NO_PORT) ? fGraphManager->GetPort(port_id2) : NULL;
521
522 if (port2) {
523 int res = port2->GetAliases(aliases);
524 string name_str;
525 if (res >= alias) {
526 name_str = string(aliases[alias-1]);
527 } else {
528 name_str = string(ports[i]);
529 }
530 string sub_name = RemoveLast(name);
531 if ((name_str.find(sub_name) != string::npos) && (type == string(port2->GetType()))) {
532 return name_str;
533 }
534 }
535 }
536
537 return "";
538 }
539
540 void JackDriver::LoadConnections(int alias, bool full_name)
541 {
542 list<pair<string, pair<string, string> > >::const_iterator it;
543
544 if (full_name) {
545 for (it = fConnections.begin(); it != fConnections.end(); it++) {
546 pair<string, string> connection = (*it).second;
547 jack_info("Load connection: %s %s", connection.first.c_str(), connection.second.c_str());
548 fEngine->PortConnect(fClientControl.fRefNum, connection.first.c_str(), connection.second.c_str());
549 }
550 } else {
551 const char** inputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsInput);
552 const char** outputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsOutput);
553
554 for (it = fConnections.begin(); it != fConnections.end(); it++) {
555 pair<string, string> connection = (*it).second;
556 string real_input = MatchPortName(connection.first.c_str(), outputs, alias, (*it).first);
557 string real_output = MatchPortName(connection.second.c_str(), inputs, alias, (*it).first);
558 if ((real_input != "") && (real_output != "")) {
559 jack_info("Load connection: %s %s", real_input.c_str(), real_output.c_str());
560 fEngine->PortConnect(fClientControl.fRefNum, real_input.c_str(), real_output.c_str());
561 }
562 }
563
564 // Wait for connection change
565 if (fGraphManager->IsPendingChange()) {
566 JackSleep(int(fEngineControl->fPeriodUsecs * 1.1f));
567 }
568
569 if (inputs) {
570 free(inputs);
571 }
572 if (outputs) {
573 free(outputs);
574 }
575 }
576 }
577
578 int JackDriver::ResumeRefNum()
579 {
580 return fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
581 }
582
583 int JackDriver::SuspendRefNum()
584 {
585 return fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs);
586 }
587
588 } // end of namespace
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
jack_info
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:100
jack_log
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108
Jack::JackDriver::SetupDriverSync
void SetupDriverSync(int ref, bool freewheel)
Definition: JackDriver.cpp:153