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