Jack2
1.9.10
|
00001 /* 00002 Copyright (C) 2001 Paul Davis 00003 Copyright (C) 2004-2008 Grame 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 00019 */ 00020 00021 #include "JackSystemDeps.h" 00022 #include "JackDriver.h" 00023 #include "JackTime.h" 00024 #include "JackError.h" 00025 #include "JackPort.h" 00026 #include "JackGraphManager.h" 00027 #include "JackGlobals.h" 00028 #include "JackEngineControl.h" 00029 #include "JackClientControl.h" 00030 #include "JackLockedEngine.h" 00031 #include "JackTime.h" 00032 #include <math.h> 00033 #include <assert.h> 00034 00035 using namespace std; 00036 00037 namespace Jack 00038 { 00039 00040 JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) 00041 :fCaptureChannels(0), 00042 fPlaybackChannels(0), 00043 fClientControl(name), 00044 fWithMonitorPorts(false){ 00045 assert(strlen(name) < JACK_CLIENT_NAME_SIZE); 00046 fSynchroTable = table; 00047 strcpy(fAliasName, alias); 00048 fEngine = engine; 00049 fGraphManager = NULL; 00050 fBeginDateUst = 0; 00051 fDelayedUsecs = 0.f; 00052 fIsMaster = true; 00053 fIsRunning = false; 00054 } 00055 00056 JackDriver::~JackDriver() 00057 { 00058 jack_log("~JackDriver"); 00059 } 00060 00061 int JackDriver::Open() 00062 { 00063 int refnum = -1; 00064 00065 if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { 00066 jack_error("Cannot allocate internal client for driver"); 00067 return -1; 00068 } 00069 00070 fClientControl.fRefNum = refnum; 00071 fClientControl.fActive = true; 00072 fEngineControl->fDriverNum++; 00073 fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode 00074 SetupDriverSync(fClientControl.fRefNum, false); 00075 return 0; 00076 } 00077 00078 int JackDriver::Open(jack_nframes_t buffer_size, 00079 jack_nframes_t samplerate, 00080 bool capturing, 00081 bool playing, 00082 int inchannels, 00083 int outchannels, 00084 bool monitor, 00085 const char* capture_driver_name, 00086 const char* playback_driver_name, 00087 jack_nframes_t capture_latency, 00088 jack_nframes_t playback_latency) 00089 { 00090 jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name); 00091 jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name); 00092 int refnum = -1; 00093 char name_res[JACK_CLIENT_NAME_SIZE + 1]; 00094 int status; 00095 00096 // Check name and possibly rename 00097 if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) { 00098 jack_error("Client name = %s conflits with another running client", fClientControl.fName); 00099 return -1; 00100 } 00101 strcpy(fClientControl.fName, name_res); 00102 00103 if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { 00104 jack_error("Cannot allocate internal client for driver"); 00105 return -1; 00106 } 00107 00108 fClientControl.fRefNum = refnum; 00109 fClientControl.fActive = true; 00110 fEngineControl->fDriverNum++; 00111 if (buffer_size > 0) { 00112 fEngineControl->fBufferSize = buffer_size; 00113 } 00114 if (samplerate > 0) { 00115 fEngineControl->fSampleRate = samplerate; 00116 } 00117 fCaptureLatency = capture_latency; 00118 fPlaybackLatency = playback_latency; 00119 00120 assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE); 00121 assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE); 00122 00123 strcpy(fCaptureDriverName, capture_driver_name); 00124 strcpy(fPlaybackDriverName, playback_driver_name); 00125 00126 fEngineControl->UpdateTimeOut(); 00127 00128 fGraphManager->SetBufferSize(buffer_size); 00129 fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode 00130 SetupDriverSync(fClientControl.fRefNum, false); 00131 return 0; 00132 } 00133 00134 int JackDriver::Close() 00135 { 00136 if (fClientControl.fRefNum >= 0) { 00137 jack_log("JackDriver::Close"); 00138 fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync 00139 fClientControl.fActive = false; 00140 fEngineControl->fDriverNum--; 00141 return fEngine->ClientInternalClose(fClientControl.fRefNum, false); 00142 } else { 00143 return -1; 00144 } 00145 } 00146 00152 void JackDriver::SetupDriverSync(int ref, bool freewheel) 00153 { 00154 if (!freewheel && !fEngineControl->fSyncMode) { 00155 jack_log("JackDriver::SetupDriverSync driver sem in flush mode"); 00156 fSynchroTable[ref].SetFlush(true); 00157 } else { 00158 jack_log("JackDriver::SetupDriverSync driver sem in normal mode"); 00159 fSynchroTable[ref].SetFlush(false); 00160 } 00161 } 00162 00163 int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) 00164 { 00165 jack_log("JackDriver::ClientNotify ref = %ld driver = %s name = %s notify = %ld", refnum, fClientControl.fName, name, notify); 00166 00167 switch (notify) { 00168 00169 case kStartFreewheelCallback: 00170 jack_log("JackDriver::kStartFreewheel"); 00171 SetupDriverSync(fClientControl.fRefNum, true); 00172 break; 00173 00174 case kStopFreewheelCallback: 00175 jack_log("JackDriver::kStopFreewheel"); 00176 SetupDriverSync(fClientControl.fRefNum, false); 00177 break; 00178 } 00179 00180 return 0; 00181 } 00182 00183 bool JackDriver::IsRealTime() const 00184 { 00185 return fEngineControl->fRealTime; 00186 } 00187 00188 void JackDriver::CycleIncTime() 00189 { 00190 fEngineControl->CycleIncTime(fBeginDateUst); 00191 } 00192 00193 void JackDriver::CycleTakeBeginTime() 00194 { 00195 fBeginDateUst = GetMicroSeconds(); // Take callback date here 00196 fEngineControl->CycleIncTime(fBeginDateUst); 00197 } 00198 00199 void JackDriver::CycleTakeEndTime() 00200 { 00201 fEndDateUst = GetMicroSeconds(); // Take end date here 00202 } 00203 00204 JackClientControl* JackDriver::GetClientControl() const 00205 { 00206 return (JackClientControl*)&fClientControl; 00207 } 00208 00209 void JackDriver::NotifyXRun(jack_time_t cur_cycle_begin, float delayed_usecs) 00210 { 00211 fEngineControl->NotifyXRun(cur_cycle_begin, delayed_usecs); 00212 fEngine->NotifyDriverXRun(); 00213 } 00214 00215 void JackDriver::NotifyBufferSize(jack_nframes_t buffer_size) 00216 { 00217 fEngine->NotifyBufferSize(buffer_size); 00218 fEngineControl->InitFrameTime(); 00219 } 00220 00221 void JackDriver::NotifySampleRate(jack_nframes_t sample_rate) 00222 { 00223 fEngine->NotifySampleRate(sample_rate); 00224 fEngineControl->InitFrameTime(); 00225 } 00226 00227 void JackDriver::NotifyFailure(int code, const char* reason) 00228 { 00229 fEngine->NotifyFailure(code, reason); 00230 } 00231 00232 void JackDriver::SetMaster(bool onoff) 00233 { 00234 fIsMaster = onoff; 00235 } 00236 00237 bool JackDriver::GetMaster() 00238 { 00239 return fIsMaster; 00240 } 00241 00242 void JackDriver::AddSlave(JackDriverInterface* slave) 00243 { 00244 fSlaveList.push_back(slave); 00245 } 00246 00247 void JackDriver::RemoveSlave(JackDriverInterface* slave) 00248 { 00249 fSlaveList.remove(slave); 00250 } 00251 00252 int JackDriver::ProcessReadSlaves() 00253 { 00254 int res = 0; 00255 list<JackDriverInterface*>::const_iterator it; 00256 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { 00257 JackDriverInterface* slave = *it; 00258 if (slave->IsRunning()) { 00259 if (slave->ProcessRead() < 0) { 00260 res = -1; 00261 } 00262 } 00263 } 00264 return res; 00265 } 00266 00267 int JackDriver::ProcessWriteSlaves() 00268 { 00269 int res = 0; 00270 list<JackDriverInterface*>::const_iterator it; 00271 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { 00272 JackDriverInterface* slave = *it; 00273 if (slave->IsRunning()) { 00274 if (slave->ProcessWrite() < 0) { 00275 res = -1; 00276 } 00277 } 00278 } 00279 return res; 00280 } 00281 00282 int JackDriver::ProcessRead() 00283 { 00284 return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync(); 00285 } 00286 00287 int JackDriver::ProcessWrite() 00288 { 00289 return (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync(); 00290 } 00291 00292 int JackDriver::ProcessReadSync() 00293 { 00294 return 0; 00295 } 00296 00297 int JackDriver::ProcessWriteSync() 00298 { 00299 return 0; 00300 } 00301 00302 int JackDriver::ProcessReadAsync() 00303 { 00304 return 0; 00305 } 00306 00307 int JackDriver::ProcessWriteAsync() 00308 { 00309 return 0; 00310 } 00311 00312 int JackDriver::Process() 00313 { 00314 return 0; 00315 } 00316 00317 int JackDriver::Attach() 00318 { 00319 return 0; 00320 } 00321 00322 int JackDriver::Detach() 00323 { 00324 return 0; 00325 } 00326 00327 int JackDriver::Read() 00328 { 00329 return 0; 00330 } 00331 00332 int JackDriver::Write() 00333 { 00334 return 0; 00335 } 00336 00337 int JackDriver::Start() 00338 { 00339 if (fIsMaster) { 00340 fEngineControl->InitFrameTime(); 00341 } 00342 fIsRunning = true; 00343 return StartSlaves(); 00344 } 00345 00346 int JackDriver::Stop() 00347 { 00348 fIsRunning = false; 00349 return StopSlaves(); 00350 } 00351 00352 int JackDriver::StartSlaves() 00353 { 00354 int res = 0; 00355 list<JackDriverInterface*>::const_iterator it; 00356 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { 00357 JackDriverInterface* slave = *it; 00358 if (slave->Start() < 0) { 00359 res = -1; 00360 // XXX: We should attempt to stop all of the slaves that we've 00361 // started here. 00362 break; 00363 } 00364 } 00365 return res; 00366 } 00367 00368 int JackDriver::StopSlaves() 00369 { 00370 int res = 0; 00371 list<JackDriverInterface*>::const_iterator it; 00372 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { 00373 JackDriverInterface* slave = *it; 00374 if (slave->Stop() < 0) { 00375 res = -1; 00376 } 00377 } 00378 return res; 00379 } 00380 00381 bool JackDriver::IsFixedBufferSize() 00382 { 00383 return true; 00384 } 00385 00386 int JackDriver::SetBufferSize(jack_nframes_t buffer_size) 00387 { 00388 int res = 0; 00389 list<JackDriverInterface*>::const_iterator it; 00390 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { 00391 JackDriverInterface* slave = *it; 00392 if (slave->SetBufferSize(buffer_size) < 0) { 00393 res = -1; 00394 } 00395 } 00396 return res; 00397 } 00398 00399 int JackDriver::SetSampleRate(jack_nframes_t sample_rate) 00400 { 00401 int res = 0; 00402 list<JackDriverInterface*>::const_iterator it; 00403 for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { 00404 JackDriverInterface* slave = *it; 00405 if (slave->SetSampleRate(sample_rate) < 0) { 00406 res = -1; 00407 } 00408 } 00409 return res; 00410 } 00411 00412 bool JackDriver::Initialize() 00413 { 00414 return true; 00415 } 00416 00417 static string RemoveLast(const string& name) 00418 { 00419 return name.substr(0, name.find_last_of(':')); // Remove end of name after last ":" 00420 } 00421 00422 void JackDriver::SaveConnections(int alias) 00423 { 00424 const char** connections; 00425 char alias1[REAL_JACK_PORT_NAME_SIZE]; 00426 char alias2[REAL_JACK_PORT_NAME_SIZE]; 00427 char system_alias1[REAL_JACK_PORT_NAME_SIZE]; 00428 char system_alias2[REAL_JACK_PORT_NAME_SIZE]; 00429 char* aliases[2]; 00430 char* system_aliases[2]; 00431 00432 aliases[0] = alias1; 00433 aliases[1] = alias2; 00434 00435 system_aliases[0] = system_alias1; 00436 system_aliases[1] = system_alias2; 00437 00438 fConnections.clear(); 00439 00440 for (int i = 0; i < fCaptureChannels; ++i) { 00441 if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fCapturePortList[i])) != 0) { 00442 if (alias == 0) { 00443 for (int j = 0; connections[j]; j++) { 00444 JackPort* port_id = fGraphManager->GetPort(fCapturePortList[i]); 00445 fConnections.push_back(make_pair(port_id->GetType(), make_pair(port_id->GetName(), connections[j]))); 00446 jack_info("Save connection: %s %s", fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j]); 00447 } 00448 } else { 00449 int res1 = fGraphManager->GetPort(fCapturePortList[i])->GetAliases(aliases); 00450 string sub_system_name; 00451 if (res1 >= alias) { 00452 sub_system_name = aliases[alias-1]; 00453 } else { 00454 sub_system_name = fGraphManager->GetPort(fCapturePortList[i])->GetName(); 00455 } 00456 for (int j = 0; connections[j]; j++) { 00457 JackPort* port_id = fGraphManager->GetPort(fGraphManager->GetPort(connections[j])); 00458 int res2 = port_id->GetAliases(system_aliases); 00459 string sub_system; 00460 if (res2 >= alias) { 00461 sub_system = system_aliases[alias-1]; 00462 } else { 00463 sub_system = connections[j]; 00464 } 00465 fConnections.push_back(make_pair(port_id->GetType(), make_pair(sub_system_name, sub_system))); 00466 jack_info("Save connection: %s %s", sub_system_name.c_str(), sub_system.c_str()); 00467 } 00468 } 00469 free(connections); 00470 } 00471 } 00472 00473 for (int i = 0; i < fPlaybackChannels; ++i) { 00474 if (fPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fPlaybackPortList[i])) != 0) { 00475 if (alias == 0) { 00476 for (int j = 0; connections[j]; j++) { 00477 JackPort* port_id = fGraphManager->GetPort(fPlaybackPortList[i]); 00478 fConnections.push_back(make_pair(port_id->GetType(), make_pair(connections[j], port_id->GetName()))); 00479 jack_info("Save connection: %s %s", connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName()); 00480 } 00481 } else { 00482 int res1 = fGraphManager->GetPort(fPlaybackPortList[i])->GetAliases(aliases); 00483 string sub_system_name; 00484 if (res1 >= alias) { 00485 sub_system_name = aliases[alias-1]; 00486 } else { 00487 sub_system_name = fGraphManager->GetPort(fPlaybackPortList[i])->GetName(); 00488 } 00489 for (int j = 0; connections[j]; j++) { 00490 JackPort* port_id = fGraphManager->GetPort(fGraphManager->GetPort(connections[j])); 00491 int res2 = port_id->GetAliases(system_aliases); 00492 string sub_name; 00493 if (res2 >= alias) { 00494 sub_name = system_aliases[alias-1]; 00495 } else { 00496 sub_name = connections[j]; 00497 } 00498 fConnections.push_back(make_pair(port_id->GetType(), make_pair(sub_name, sub_system_name))); 00499 jack_info("Save connection: %s %s", sub_name.c_str(), sub_system_name.c_str()); 00500 } 00501 } 00502 free(connections); 00503 } 00504 } 00505 } 00506 00507 string JackDriver::MatchPortName(const char* name, const char** ports, int alias, const std::string& type) 00508 { 00509 char alias1[REAL_JACK_PORT_NAME_SIZE]; 00510 char alias2[REAL_JACK_PORT_NAME_SIZE]; 00511 char* aliases[2]; 00512 00513 aliases[0] = alias1; 00514 aliases[1] = alias2; 00515 00516 for (int i = 0; ports && ports[i]; ++i) { 00517 00518 jack_port_id_t port_id2 = fGraphManager->GetPort(ports[i]); 00519 JackPort* port2 = (port_id2 != NO_PORT) ? fGraphManager->GetPort(port_id2) : NULL; 00520 00521 if (port2) { 00522 int res = port2->GetAliases(aliases); 00523 string name_str; 00524 if (res >= alias) { 00525 name_str = string(aliases[alias-1]); 00526 } else { 00527 name_str = string(ports[i]); 00528 } 00529 string sub_name = RemoveLast(name); 00530 if ((name_str.find(sub_name) != string::npos) && (type == string(port2->GetType()))) { 00531 return name_str; 00532 } 00533 } 00534 } 00535 00536 return ""; 00537 } 00538 00539 void JackDriver::LoadConnections(int alias, bool full_name) 00540 { 00541 list<pair<string, pair<string, string> > >::const_iterator it; 00542 00543 if (full_name) { 00544 for (it = fConnections.begin(); it != fConnections.end(); it++) { 00545 pair<string, string> connection = (*it).second; 00546 jack_info("Load connection: %s %s", connection.first.c_str(), connection.second.c_str()); 00547 fEngine->PortConnect(fClientControl.fRefNum, connection.first.c_str(), connection.second.c_str()); 00548 } 00549 } else { 00550 const char** inputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsInput); 00551 const char** outputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsOutput); 00552 00553 for (it = fConnections.begin(); it != fConnections.end(); it++) { 00554 pair<string, string> connection = (*it).second; 00555 string real_input = MatchPortName(connection.first.c_str(), outputs, alias, (*it).first); 00556 string real_output = MatchPortName(connection.second.c_str(), inputs, alias, (*it).first); 00557 if ((real_input != "") && (real_output != "")) { 00558 jack_info("Load connection: %s %s", real_input.c_str(), real_output.c_str()); 00559 fEngine->PortConnect(fClientControl.fRefNum, real_input.c_str(), real_output.c_str()); 00560 } 00561 } 00562 00563 // Wait for connection change 00564 if (fGraphManager->IsPendingChange()) { 00565 JackSleep(int(fEngineControl->fPeriodUsecs * 1.1f)); 00566 } 00567 00568 if (inputs) { 00569 free(inputs); 00570 } 00571 if (outputs) { 00572 free(outputs); 00573 } 00574 } 00575 } 00576 00577 int JackDriver::ResumeRefNum() 00578 { 00579 return fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); 00580 } 00581 00582 int JackDriver::SuspendRefNum() 00583 { 00584 return fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs); 00585 } 00586 00587 } // end of namespace