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