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