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