Jack2  1.9.13
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, 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 
58 JackDriver::~JackDriver()
59 {
60  jack_log("~JackDriver");
61 }
62 
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 
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 
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 
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 
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 
185 bool JackDriver::IsRealTime() const
186 {
187  return fEngineControl->fRealTime;
188 }
189 
190 void JackDriver::CycleIncTime()
191 {
192  fEngineControl->CycleIncTime(fBeginDateUst);
193 }
194 
195 void JackDriver::CycleTakeBeginTime()
196 {
197  fBeginDateUst = GetMicroSeconds(); // Take callback date here
198  fEngineControl->CycleIncTime(fBeginDateUst);
199 }
200 
201 void JackDriver::CycleTakeEndTime()
202 {
203  fEndDateUst = GetMicroSeconds(); // Take end date here
204 }
205 
206 JackClientControl* JackDriver::GetClientControl() const
207 {
208  return (JackClientControl*)&fClientControl;
209 }
210 
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 
217 void JackDriver::NotifyBufferSize(jack_nframes_t buffer_size)
218 {
219  fEngine->NotifyBufferSize(buffer_size);
220  fEngineControl->InitFrameTime();
221 }
222 
223 void JackDriver::NotifySampleRate(jack_nframes_t sample_rate)
224 {
225  fEngine->NotifySampleRate(sample_rate);
226  fEngineControl->InitFrameTime();
227 }
228 
229 void JackDriver::NotifyFailure(int code, const char* reason)
230 {
231  fEngine->NotifyFailure(code, reason);
232 }
233 
234 void JackDriver::SetMaster(bool onoff)
235 {
236  fIsMaster = onoff;
237 }
238 
239 bool JackDriver::GetMaster()
240 {
241  return fIsMaster;
242 }
243 
244 void JackDriver::AddSlave(JackDriverInterface* slave)
245 {
246  fSlaveList.push_back(slave);
247 }
248 
249 void JackDriver::RemoveSlave(JackDriverInterface* slave)
250 {
251  fSlaveList.remove(slave);
252 }
253 
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 
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 
284 int JackDriver::ProcessRead()
285 {
286  return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
287 }
288 
289 int JackDriver::ProcessWrite()
290 {
291  return (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
292 }
293 
294 int JackDriver::ProcessReadSync()
295 {
296  return 0;
297 }
298 
299 int JackDriver::ProcessWriteSync()
300 {
301  return 0;
302 }
303 
304 int JackDriver::ProcessReadAsync()
305 {
306  return 0;
307 }
308 
309 int JackDriver::ProcessWriteAsync()
310 {
311  return 0;
312 }
313 
314 int JackDriver::Process()
315 {
316  return 0;
317 }
318 
319 int JackDriver::Attach()
320 {
321  return 0;
322 }
323 
324 int JackDriver::Detach()
325 {
326  return 0;
327 }
328 
329 int JackDriver::Read()
330 {
331  return 0;
332 }
333 
334 int JackDriver::Write()
335 {
336  return 0;
337 }
338 
339 int JackDriver::Start()
340 {
341  if (fIsMaster) {
342  fEngineControl->InitFrameTime();
343  }
344  fIsRunning = true;
345  return StartSlaves();
346 }
347 
348 int JackDriver::Stop()
349 {
350  fIsRunning = false;
351  return StopSlaves();
352 }
353 
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 
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 
383 bool JackDriver::IsFixedBufferSize()
384 {
385  return true;
386 }
387 
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 
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 
414 bool JackDriver::Initialize()
415 {
416  return true;
417 }
418 
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 
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 
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 
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 
579 int JackDriver::ResumeRefNum()
580 {
581  return fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
582 }
583 
584 int JackDriver::SuspendRefNum()
585 {
586  return fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs);
587 }
588 
589 } // end of namespace
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:100
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108
void SetupDriverSync(int ref, bool freewheel)
Definition: JackDriver.cpp:154