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