21 #include "JackSystemDeps.h"
22 #include "JackDriver.h"
24 #include "JackError.h"
26 #include "JackGraphManager.h"
27 #include "JackGlobals.h"
28 #include "JackEngineControl.h"
29 #include "JackClientControl.h"
30 #include "JackLockedEngine.h"
40 JackDriver::JackDriver(
const char* name,
const char* alias, JackLockedEngine* engine, JackSynchro* table)
43 fClientControl(name, jack_client_uuid_generate()),
44 fWithMonitorPorts(false)
46 assert(strlen(name) < JACK_CLIENT_NAME_SIZE);
47 fSynchroTable = table;
48 strcpy(fAliasName, alias);
58 JackDriver::~JackDriver()
63 int JackDriver::Open()
67 if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager,
this,
false) != 0) {
68 jack_error(
"Cannot allocate internal client for driver");
72 fClientControl.fRefNum = refnum;
73 fClientControl.fActive =
true;
74 fEngineControl->fDriverNum++;
75 fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum);
80 int JackDriver::Open(jack_nframes_t buffer_size,
81 jack_nframes_t sample_rate,
87 const char* capture_driver_name,
88 const char* playback_driver_name,
89 jack_nframes_t capture_latency,
90 jack_nframes_t playback_latency)
92 jack_log(
"JackDriver::Open capture_driver_name = %s", capture_driver_name);
93 jack_log(
"JackDriver::Open playback_driver_name = %s", playback_driver_name);
95 char name_res[JACK_CLIENT_NAME_SIZE + 1];
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);
103 strcpy(fClientControl.fName, name_res);
105 if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager,
this,
false) != 0) {
106 jack_error(
"Cannot allocate internal client for driver");
110 fClientControl.fRefNum = refnum;
111 fClientControl.fActive =
true;
112 fEngineControl->fDriverNum++;
113 if (buffer_size > 0) {
114 fEngineControl->fBufferSize = buffer_size;
116 if (sample_rate > 0) {
117 fEngineControl->fSampleRate = sample_rate;
119 fCaptureLatency = capture_latency;
120 fPlaybackLatency = playback_latency;
122 assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE);
123 assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE);
125 strcpy(fCaptureDriverName, capture_driver_name);
126 strcpy(fPlaybackDriverName, playback_driver_name);
128 fEngineControl->UpdateTimeOut();
130 fGraphManager->SetBufferSize(fEngineControl->fBufferSize);
131 fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum);
136 int JackDriver::Close()
138 if (fClientControl.fRefNum >= 0) {
140 fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum);
141 fClientControl.fActive =
false;
142 fEngineControl->fDriverNum--;
143 return fEngine->ClientInternalClose(fClientControl.fRefNum,
false);
156 if (!freewheel && !fEngineControl->fSyncMode) {
157 jack_log(
"JackDriver::SetupDriverSync driver sem in flush mode");
158 fSynchroTable[ref].SetFlush(
true);
160 jack_log(
"JackDriver::SetupDriverSync driver sem in normal mode");
161 fSynchroTable[ref].SetFlush(
false);
165 int JackDriver::ClientNotify(
int refnum,
const char* name,
int notify,
int sync,
const char* message,
int value1,
int value2)
167 jack_log(
"JackDriver::ClientNotify ref = %ld driver = %s name = %s notify = %ld", refnum, fClientControl.fName, name, notify);
171 case kStartFreewheelCallback:
172 jack_log(
"JackDriver::kStartFreewheel");
176 case kStopFreewheelCallback:
177 jack_log(
"JackDriver::kStopFreewheel");
185 bool JackDriver::IsRealTime()
const
187 return fEngineControl->fRealTime;
190 void JackDriver::CycleIncTime()
192 fEngineControl->CycleIncTime(fBeginDateUst);
195 void JackDriver::CycleTakeBeginTime()
197 fBeginDateUst = GetMicroSeconds();
198 fEngineControl->CycleIncTime(fBeginDateUst);
201 void JackDriver::CycleTakeEndTime()
203 fEndDateUst = GetMicroSeconds();
206 JackClientControl* JackDriver::GetClientControl()
const
208 return (JackClientControl*)&fClientControl;
211 void JackDriver::NotifyXRun(jack_time_t cur_cycle_begin,
float delayed_usecs)
213 fEngineControl->NotifyXRun(cur_cycle_begin, delayed_usecs);
214 fEngine->NotifyDriverXRun();
217 void JackDriver::NotifyBufferSize(jack_nframes_t buffer_size)
219 fEngine->NotifyBufferSize(buffer_size);
220 fEngineControl->InitFrameTime();
223 void JackDriver::NotifySampleRate(jack_nframes_t sample_rate)
225 fEngine->NotifySampleRate(sample_rate);
226 fEngineControl->InitFrameTime();
229 void JackDriver::NotifyFailure(
int code,
const char* reason)
231 fEngine->NotifyFailure(code, reason);
234 void JackDriver::SetMaster(
bool onoff)
239 bool JackDriver::GetMaster()
244 void JackDriver::AddSlave(JackDriverInterface* slave)
246 fSlaveList.push_back(slave);
249 void JackDriver::RemoveSlave(JackDriverInterface* slave)
251 fSlaveList.remove(slave);
254 int JackDriver::ProcessReadSlaves()
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) {
269 int JackDriver::ProcessWriteSlaves()
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) {
284 int JackDriver::ProcessRead()
286 return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
289 int JackDriver::ProcessWrite()
291 return (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
294 int JackDriver::ProcessReadSync()
299 int JackDriver::ProcessWriteSync()
304 int JackDriver::ProcessReadAsync()
309 int JackDriver::ProcessWriteAsync()
314 int JackDriver::Process()
319 int JackDriver::Attach()
324 int JackDriver::Detach()
329 int JackDriver::Read()
334 int JackDriver::Write()
339 int JackDriver::Start()
342 fEngineControl->InitFrameTime();
345 return StartSlaves();
348 int JackDriver::Stop()
354 int JackDriver::StartSlaves()
357 list<JackDriverInterface*>::const_iterator it;
358 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
359 JackDriverInterface* slave = *it;
360 if (slave->Start() < 0) {
370 int JackDriver::StopSlaves()
373 list<JackDriverInterface*>::const_iterator it;
374 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
375 JackDriverInterface* slave = *it;
376 if (slave->Stop() < 0) {
383 bool JackDriver::IsFixedBufferSize()
388 int JackDriver::SetBufferSize(jack_nframes_t buffer_size)
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) {
401 int JackDriver::SetSampleRate(jack_nframes_t sample_rate)
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) {
414 bool JackDriver::Initialize()
419 static string RemoveLast(
const string& name)
421 return name.substr(0, name.find_last_of(
':'));
424 void JackDriver::SaveConnections(
int alias)
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];
432 char* system_aliases[2];
437 system_aliases[0] = system_alias1;
438 system_aliases[1] = system_alias2;
440 fConnections.clear();
442 for (
int i = 0; i < fCaptureChannels; ++i) {
443 if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fCapturePortList[i])) != 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]);
451 int res1 = fGraphManager->GetPort(fCapturePortList[i])->GetAliases(aliases);
452 string sub_system_name;
454 sub_system_name = aliases[alias-1];
456 sub_system_name = fGraphManager->GetPort(fCapturePortList[i])->GetName();
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);
463 sub_system = system_aliases[alias-1];
465 sub_system = connections[j];
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());
475 for (
int i = 0; i < fPlaybackChannels; ++i) {
476 if (fPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fPlaybackPortList[i])) != 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());
484 int res1 = fGraphManager->GetPort(fPlaybackPortList[i])->GetAliases(aliases);
485 string sub_system_name;
487 sub_system_name = aliases[alias-1];
489 sub_system_name = fGraphManager->GetPort(fPlaybackPortList[i])->GetName();
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);
496 sub_name = system_aliases[alias-1];
498 sub_name = connections[j];
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());
509 string JackDriver::MatchPortName(
const char* name,
const char** ports,
int alias,
const std::string& type)
511 char alias1[REAL_JACK_PORT_NAME_SIZE+1];
512 char alias2[REAL_JACK_PORT_NAME_SIZE+1];
518 for (
int i = 0; ports && ports[i]; ++i) {
520 jack_port_id_t port_id2 = fGraphManager->GetPort(ports[i]);
521 JackPort* port2 = (port_id2 != NO_PORT) ? fGraphManager->GetPort(port_id2) : NULL;
524 int res = port2->GetAliases(aliases);
527 name_str = string(aliases[alias-1]);
529 name_str = string(ports[i]);
531 string sub_name = RemoveLast(name);
532 if ((name_str.find(sub_name) != string::npos) && (type ==
string(port2->GetType()))) {
541 void JackDriver::LoadConnections(
int alias,
bool full_name)
543 list<pair<string, pair<string, string> > >::const_iterator it;
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());
552 const char** inputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsInput);
553 const char** outputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsOutput);
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());
566 if (fGraphManager->IsPendingChange()) {
567 JackSleep(
int(fEngineControl->fPeriodUsecs * 1.1f));
579 int JackDriver::ResumeRefNum()
581 return fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
584 int JackDriver::SuspendRefNum()
586 return fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs);
SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_info(const char *fmt,...)
SERVER_EXPORT void jack_log(const char *fmt,...)
void SetupDriverSync(int ref, bool freewheel)