00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <iostream>
00021 #include <fstream>
00022 #include <set>
00023 #include <assert.h>
00024 #include <ctype.h>
00025
00026 #include "JackSystemDeps.h"
00027 #include "JackLockedEngine.h"
00028 #include "JackExternalClient.h"
00029 #include "JackInternalClient.h"
00030 #include "JackEngineControl.h"
00031 #include "JackClientControl.h"
00032 #include "JackServerGlobals.h"
00033 #include "JackGlobals.h"
00034 #include "JackChannel.h"
00035 #include "JackError.h"
00036
00037 namespace Jack
00038 {
00039
00040 JackEngine::JackEngine(JackGraphManager* manager,
00041 JackSynchro* table,
00042 JackEngineControl* control,
00043 char self_connect_mode)
00044 : JackLockAble(control->fServerName),
00045 fSignal(control->fServerName)
00046 {
00047 fGraphManager = manager;
00048 fSynchroTable = table;
00049 fEngineControl = control;
00050 fSelfConnectMode = self_connect_mode;
00051 for (int i = 0; i < CLIENT_NUM; i++) {
00052 fClientTable[i] = NULL;
00053 }
00054 fLastSwitchUsecs = 0;
00055 fMaxUUID = 0;
00056 fSessionPendingReplies = 0;
00057 fSessionTransaction = NULL;
00058 fSessionResult = NULL;
00059 }
00060
00061 JackEngine::~JackEngine()
00062 {}
00063
00064 int JackEngine::Open()
00065 {
00066 jack_log("JackEngine::Open");
00067
00068
00069 if (fChannel.Open(fEngineControl->fServerName) < 0) {
00070 jack_error("Cannot connect to server");
00071 return -1;
00072 } else {
00073 return 0;
00074 }
00075 }
00076
00077 int JackEngine::Close()
00078 {
00079 jack_log("JackEngine::Close");
00080 fChannel.Close();
00081
00082
00083 for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
00084 if (JackLoadableInternalClient* loadable_client = dynamic_cast<JackLoadableInternalClient*>(fClientTable[i])) {
00085 jack_log("JackEngine::Close loadable client = %s", loadable_client->GetClientControl()->fName);
00086 loadable_client->Close();
00087 fClientTable[i] = NULL;
00088 delete loadable_client;
00089 } else if (JackExternalClient* external_client = dynamic_cast<JackExternalClient*>(fClientTable[i])) {
00090 jack_log("JackEngine::Close external client = %s", external_client->GetClientControl()->fName);
00091 external_client->Close();
00092 fClientTable[i] = NULL;
00093 delete external_client;
00094 }
00095 }
00096
00097 return 0;
00098 }
00099
00100 void JackEngine::NotifyQuit()
00101 {
00102 fChannel.NotifyQuit();
00103 }
00104
00105
00106
00107
00108
00109 int JackEngine::AllocateRefnum()
00110 {
00111 for (int i = 0; i < CLIENT_NUM; i++) {
00112 if (!fClientTable[i]) {
00113 jack_log("JackEngine::AllocateRefNum ref = %ld", i);
00114 return i;
00115 }
00116 }
00117 return -1;
00118 }
00119
00120 void JackEngine::ReleaseRefnum(int refnum)
00121 {
00122 fClientTable[refnum] = NULL;
00123
00124 if (fEngineControl->fTemporary) {
00125 int i;
00126 for (i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
00127 if (fClientTable[i]) {
00128 break;
00129 }
00130 }
00131 if (i == CLIENT_NUM) {
00132
00133 jack_log("JackEngine::ReleaseRefnum server quit");
00134 fEngineControl->fTemporary = false;
00135 throw JackTemporaryException();
00136 }
00137 }
00138 }
00139
00140
00141
00142
00143
00144 void JackEngine::ProcessNext(jack_time_t cur_cycle_begin)
00145 {
00146 fLastSwitchUsecs = cur_cycle_begin;
00147 if (fGraphManager->RunNextGraph()) {
00148 fChannel.Notify(ALL_CLIENTS, kGraphOrderCallback, 0);
00149 }
00150 fSignal.Signal();
00151 }
00152
00153 void JackEngine::ProcessCurrent(jack_time_t cur_cycle_begin)
00154 {
00155 if (cur_cycle_begin < fLastSwitchUsecs + 2 * fEngineControl->fPeriodUsecs) {
00156 CheckXRun(cur_cycle_begin);
00157 }
00158 fGraphManager->RunCurrentGraph();
00159 }
00160
00161 bool JackEngine::Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end)
00162 {
00163 bool res = true;
00164
00165
00166 fEngineControl->CycleBegin(fClientTable, fGraphManager, cur_cycle_begin, prev_cycle_end);
00167
00168
00169 if (fGraphManager->IsFinishedGraph()) {
00170 ProcessNext(cur_cycle_begin);
00171 res = true;
00172 } else {
00173 jack_log("Process: graph not finished!");
00174 if (cur_cycle_begin > fLastSwitchUsecs + fEngineControl->fTimeOutUsecs) {
00175 jack_log("Process: switch to next state delta = %ld", long(cur_cycle_begin - fLastSwitchUsecs));
00176 ProcessNext(cur_cycle_begin);
00177 res = true;
00178 } else {
00179 jack_log("Process: waiting to switch delta = %ld", long(cur_cycle_begin - fLastSwitchUsecs));
00180 ProcessCurrent(cur_cycle_begin);
00181 res = false;
00182 }
00183 }
00184
00185
00186 fEngineControl->CycleEnd(fClientTable);
00187 return res;
00188 }
00189
00190
00191
00192
00193
00194
00195 static const char* State2String(jack_client_state_t state)
00196 {
00197 switch (state) {
00198 case NotTriggered:
00199 return "NotTriggered";
00200 case Triggered:
00201 return "Triggered";
00202 case Running:
00203 return "Running";
00204 case Finished:
00205 return "Finished";
00206 default:
00207 return "";
00208 }
00209 }
00210
00211 void JackEngine::CheckXRun(jack_time_t callback_usecs)
00212 {
00213 for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
00214 JackClientInterface* client = fClientTable[i];
00215 if (client && client->GetClientControl()->fActive) {
00216 JackClientTiming* timing = fGraphManager->GetClientTiming(i);
00217 jack_client_state_t status = timing->fStatus;
00218 jack_time_t finished_date = timing->fFinishedAt;
00219
00220 if (status != NotTriggered && status != Finished) {
00221 jack_error("JackEngine::XRun: client = %s was not finished, state = %s", client->GetClientControl()->fName, State2String(status));
00222 fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);
00223 }
00224
00225 if (status == Finished && (long)(finished_date - callback_usecs) > 0) {
00226 jack_error("JackEngine::XRun: client %s finished after current callback", client->GetClientControl()->fName);
00227 fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);
00228 }
00229 }
00230 }
00231 }
00232
00233 int JackEngine::ComputeTotalLatencies()
00234 {
00235 std::vector<jack_int_t> sorted;
00236 std::vector<jack_int_t>::iterator it;
00237 std::vector<jack_int_t>::reverse_iterator rit;
00238
00239 fGraphManager->TopologicalSort(sorted);
00240
00241
00242
00243
00244
00245 for (it = sorted.begin(); it != sorted.end(); it++) {
00246 NotifyClient(*it, kLatencyCallback, true, "", 0, 0);
00247 }
00248
00249
00250
00251 for (rit = sorted.rbegin(); rit != sorted.rend(); rit++) {
00252 NotifyClient(*rit, kLatencyCallback, true, "", 1, 0);
00253 }
00254
00255 return 0;
00256 }
00257
00258
00259
00260
00261
00262 int JackEngine::ClientNotify(JackClientInterface* client, int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
00263 {
00264
00265 if (!client->GetClientControl()->fCallback[notify]) {
00266 jack_log("JackEngine::ClientNotify: no callback for notification = %ld", notify);
00267 return 0;
00268 }
00269
00270 int res1;
00271
00272
00273 if (dynamic_cast<JackExternalClient*>(client)) {
00274 res1 = client->ClientNotify(refnum, name, notify, sync, message, value1, value2);
00275
00276 } else {
00277 bool res2 = Unlock();
00278 res1 = client->ClientNotify(refnum, name, notify, sync, message, value1, value2);
00279 if (res2) {
00280 Lock();
00281 }
00282 }
00283
00284 if (res1 < 0) {
00285 jack_error("ClientNotify fails name = %s notification = %ld val1 = %ld val2 = %ld", name, notify, value1, value2);
00286 }
00287 return res1;
00288 }
00289
00290 void JackEngine::NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2)
00291 {
00292 JackClientInterface* client = fClientTable[refnum];
00293 if (client) {
00294 ClientNotify(client, refnum, client->GetClientControl()->fName, event, sync, message, value1, value2);
00295 }
00296 }
00297
00298 void JackEngine::NotifyClients(int event, int sync, const char* message, int value1, int value2)
00299 {
00300 for (int i = 0; i < CLIENT_NUM; i++) {
00301 NotifyClient(i, event, sync, message, value1, value2);
00302 }
00303 }
00304
00305 int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* new_name, int refnum)
00306 {
00307 jack_log("JackEngine::NotifyAddClient: name = %s", new_name);
00308
00309
00310 for (int i = 0; i < CLIENT_NUM; i++) {
00311 JackClientInterface* old_client = fClientTable[i];
00312 if (old_client && old_client != new_client) {
00313 char* old_name = old_client->GetClientControl()->fName;
00314 if (ClientNotify(old_client, refnum, new_name, kAddClient, false, "", 0, 0) < 0) {
00315 jack_error("NotifyAddClient old_client fails name = %s", old_name);
00316
00317 }
00318 if (ClientNotify(new_client, i, old_name, kAddClient, true, "", 0, 0) < 0) {
00319 jack_error("NotifyAddClient new_client fails name = %s", new_name);
00320 return -1;
00321 }
00322 }
00323 }
00324
00325 return 0;
00326 }
00327
00328 void JackEngine::NotifyRemoveClient(const char* name, int refnum)
00329 {
00330
00331 for (int i = 0; i < CLIENT_NUM; i++) {
00332 JackClientInterface* client = fClientTable[i];
00333 if (client) {
00334 ClientNotify(client, refnum, name, kRemoveClient, false, "", 0, 0);
00335 }
00336 }
00337 }
00338
00339
00340 void JackEngine::NotifyDriverXRun()
00341 {
00342
00343 fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);
00344 }
00345
00346 void JackEngine::NotifyClientXRun(int refnum)
00347 {
00348 if (refnum == ALL_CLIENTS) {
00349 NotifyClients(kXRunCallback, false, "", 0, 0);
00350 } else {
00351 NotifyClient(refnum, kXRunCallback, false, "", 0, 0);
00352 }
00353 }
00354
00355 void JackEngine::NotifyGraphReorder()
00356 {
00357 ComputeTotalLatencies();
00358 NotifyClients(kGraphOrderCallback, false, "", 0, 0);
00359 }
00360
00361 void JackEngine::NotifyBufferSize(jack_nframes_t buffer_size)
00362 {
00363 NotifyClients(kBufferSizeCallback, true, "", buffer_size, 0);
00364 }
00365
00366 void JackEngine::NotifySampleRate(jack_nframes_t sample_rate)
00367 {
00368 NotifyClients(kSampleRateCallback, true, "", sample_rate, 0);
00369 }
00370
00371 void JackEngine::NotifyFailure(int code, const char* reason)
00372 {
00373 NotifyClients(kShutDownCallback, false, reason, code, 0);
00374 }
00375
00376 void JackEngine::NotifyFreewheel(bool onoff)
00377 {
00378 if (onoff) {
00379
00380 fEngineControl->fSavedRealTime = fEngineControl->fRealTime;
00381 fEngineControl->fRealTime = false;
00382 } else {
00383
00384 fEngineControl->fRealTime = fEngineControl->fSavedRealTime;
00385 fEngineControl->fSavedRealTime = false;
00386 }
00387 NotifyClients((onoff ? kStartFreewheelCallback : kStopFreewheelCallback), true, "", 0, 0);
00388 }
00389
00390 void JackEngine::NotifyPortRegistation(jack_port_id_t port_index, bool onoff)
00391 {
00392 NotifyClients((onoff ? kPortRegistrationOnCallback : kPortRegistrationOffCallback), false, "", port_index, 0);
00393 }
00394
00395 void JackEngine::NotifyPortRename(jack_port_id_t port, const char* old_name)
00396 {
00397 NotifyClients(kPortRenameCallback, false, old_name, port, 0);
00398 }
00399
00400 void JackEngine::NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff)
00401 {
00402 NotifyClients((onoff ? kPortConnectCallback : kPortDisconnectCallback), false, "", src, dst);
00403 }
00404
00405 void JackEngine::NotifyActivate(int refnum)
00406 {
00407 NotifyClient(refnum, kActivateClient, true, "", 0, 0);
00408 }
00409
00410
00411
00412
00413
00414 int JackEngine::GetInternalClientName(int refnum, char* name_res)
00415 {
00416 JackClientInterface* client = fClientTable[refnum];
00417 assert(client);
00418 strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE);
00419 return 0;
00420 }
00421
00422 int JackEngine::InternalClientHandle(const char* client_name, int* status, int* int_ref)
00423 {
00424
00425 *status = 0;
00426
00427 for (int i = 0; i < CLIENT_NUM; i++) {
00428 JackClientInterface* client = fClientTable[i];
00429 if (client && dynamic_cast<JackLoadableInternalClient*>(client) && (strcmp(client->GetClientControl()->fName, client_name) == 0)) {
00430 jack_log("InternalClientHandle found client name = %s ref = %ld", client_name, i);
00431 *int_ref = i;
00432 return 0;
00433 }
00434 }
00435
00436 *status |= (JackNoSuchClient | JackFailure);
00437 return -1;
00438 }
00439
00440 int JackEngine::InternalClientUnload(int refnum, int* status)
00441 {
00442 JackClientInterface* client = fClientTable[refnum];
00443 if (client) {
00444 int res = client->Close();
00445 delete client;
00446 *status = 0;
00447 return res;
00448 } else {
00449 *status = (JackNoSuchClient | JackFailure);
00450 return -1;
00451 }
00452 }
00453
00454
00455
00456
00457
00458 int JackEngine::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status)
00459 {
00460
00461 *status = 0;
00462 strcpy(name_res, name);
00463
00464 jack_log("Check protocol client = %ld server = %ld", protocol, JACK_PROTOCOL_VERSION);
00465
00466 if (protocol != JACK_PROTOCOL_VERSION) {
00467 *status |= (JackFailure | JackVersionError);
00468 jack_error("JACK protocol mismatch (%d vs %d)", protocol, JACK_PROTOCOL_VERSION);
00469 return -1;
00470 }
00471
00472 std::map<int,std::string>::iterator res = fReservationMap.find(uuid);
00473
00474 if (res != fReservationMap.end()) {
00475 strncpy(name_res, res->second.c_str(), JACK_CLIENT_NAME_SIZE);
00476 } else if (ClientCheckName(name)) {
00477
00478 *status |= JackNameNotUnique;
00479
00480 if (options & JackUseExactName) {
00481 jack_error("cannot create new client; %s already exists", name);
00482 *status |= JackFailure;
00483 return -1;
00484 }
00485
00486 if (GenerateUniqueName(name_res)) {
00487 *status |= JackFailure;
00488 return -1;
00489 }
00490 }
00491
00492 return 0;
00493 }
00494
00495 bool JackEngine::GenerateUniqueName(char* name)
00496 {
00497 int tens, ones;
00498 int length = strlen(name);
00499
00500 if (length > JACK_CLIENT_NAME_SIZE - 4) {
00501 jack_error("%s exists and is too long to make unique", name);
00502 return true;
00503 }
00504
00505
00506 name[length++] = '-';
00507 tens = length++;
00508 ones = length++;
00509 name[tens] = '0';
00510 name[ones] = '1';
00511 name[length] = '\0';
00512
00513 while (ClientCheckName(name)) {
00514 if (name[ones] == '9') {
00515 if (name[tens] == '9') {
00516 jack_error("client %s has 99 extra instances already", name);
00517 return true;
00518 }
00519 name[tens]++;
00520 name[ones] = '0';
00521 } else {
00522 name[ones]++;
00523 }
00524 }
00525 return false;
00526 }
00527
00528 bool JackEngine::ClientCheckName(const char* name)
00529 {
00530 for (int i = 0; i < CLIENT_NUM; i++) {
00531 JackClientInterface* client = fClientTable[i];
00532 if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) {
00533 return true;
00534 }
00535 }
00536
00537 for (std::map<int,std::string>::iterator i = fReservationMap.begin(); i != fReservationMap.end(); i++) {
00538 if (i->second == name) {
00539 return true;
00540 }
00541 }
00542
00543 return false;
00544 }
00545
00546 int JackEngine::GetNewUUID()
00547 {
00548 return fMaxUUID++;
00549 }
00550
00551 void JackEngine::EnsureUUID(int uuid)
00552 {
00553 if (uuid > fMaxUUID) {
00554 fMaxUUID = uuid + 1;
00555 }
00556
00557 for (int i = 0; i < CLIENT_NUM; i++) {
00558 JackClientInterface* client = fClientTable[i];
00559 if (client && (client->GetClientControl()->fSessionID == uuid)) {
00560 client->GetClientControl()->fSessionID = GetNewUUID();
00561 }
00562 }
00563 }
00564
00565 int JackEngine::GetClientPID(const char* name)
00566 {
00567 for (int i = 0; i < CLIENT_NUM; i++) {
00568 JackClientInterface* client = fClientTable[i];
00569 if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) {
00570 return client->GetClientControl()->fPID;
00571 }
00572 }
00573
00574 return 0;
00575 }
00576
00577 int JackEngine::GetClientRefNum(const char* name)
00578 {
00579 for (int i = 0; i < CLIENT_NUM; i++) {
00580 JackClientInterface* client = fClientTable[i];
00581 if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) {
00582 return client->GetClientControl()->fRefNum;
00583 }
00584 }
00585
00586 return -1;
00587 }
00588
00589
00590 int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager)
00591 {
00592 char real_name[JACK_CLIENT_NAME_SIZE + 1];
00593
00594 if (uuid < 0) {
00595 uuid = GetNewUUID();
00596 strncpy(real_name, name, JACK_CLIENT_NAME_SIZE);
00597 } else {
00598 std::map<int, std::string>::iterator res = fReservationMap.find(uuid);
00599 if (res != fReservationMap.end()) {
00600 strncpy(real_name, res->second.c_str(), JACK_CLIENT_NAME_SIZE);
00601 fReservationMap.erase(uuid);
00602 } else {
00603 strncpy(real_name, name, JACK_CLIENT_NAME_SIZE);
00604 }
00605 EnsureUUID(uuid);
00606 }
00607
00608 jack_log("JackEngine::ClientExternalOpen: uuid = %d, name = %s", uuid, real_name);
00609
00610 int refnum = AllocateRefnum();
00611 if (refnum < 0) {
00612 jack_error("No more refnum available");
00613 return -1;
00614 }
00615
00616 JackExternalClient* client = new JackExternalClient();
00617
00618 if (!fSynchroTable[refnum].Allocate(real_name, fEngineControl->fServerName, 0)) {
00619 jack_error("Cannot allocate synchro");
00620 goto error;
00621 }
00622
00623 if (client->Open(real_name, pid, refnum, uuid, shared_client) < 0) {
00624 jack_error("Cannot open client");
00625 goto error;
00626 }
00627
00628 if (!fSignal.LockedTimedWait(DRIVER_OPEN_TIMEOUT * 1000000)) {
00629
00630 jack_error("Driver is not running");
00631 goto error;
00632 }
00633
00634 fClientTable[refnum] = client;
00635
00636 if (NotifyAddClient(client, real_name, refnum) < 0) {
00637 jack_error("Cannot notify add client");
00638 goto error;
00639 }
00640
00641 fGraphManager->InitRefNum(refnum);
00642 fEngineControl->ResetRollingUsecs();
00643 *shared_engine = fEngineControl->GetShmIndex();
00644 *shared_graph_manager = fGraphManager->GetShmIndex();
00645 *ref = refnum;
00646 return 0;
00647
00648 error:
00649
00650 fSynchroTable[refnum].Destroy();
00651 fClientTable[refnum] = 0;
00652 client->Close();
00653 delete client;
00654 return -1;
00655 }
00656
00657
00658 int JackEngine::ClientInternalOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, bool wait)
00659 {
00660 jack_log("JackEngine::ClientInternalOpen: name = %s", name);
00661
00662 int refnum = AllocateRefnum();
00663 if (refnum < 0) {
00664 jack_error("No more refnum available");
00665 goto error;
00666 }
00667
00668 if (!fSynchroTable[refnum].Allocate(name, fEngineControl->fServerName, 0)) {
00669 jack_error("Cannot allocate synchro");
00670 goto error;
00671 }
00672
00673 if (wait && !fSignal.LockedTimedWait(DRIVER_OPEN_TIMEOUT * 1000000)) {
00674
00675 jack_error("Driver is not running");
00676 goto error;
00677 }
00678
00679 fClientTable[refnum] = client;
00680
00681 if (NotifyAddClient(client, name, refnum) < 0) {
00682 jack_error("Cannot notify add client");
00683 goto error;
00684 }
00685
00686 fGraphManager->InitRefNum(refnum);
00687 fEngineControl->ResetRollingUsecs();
00688 *shared_engine = fEngineControl;
00689 *shared_manager = fGraphManager;
00690 *ref = refnum;
00691 return 0;
00692
00693 error:
00694
00695 fSynchroTable[refnum].Destroy();
00696 fClientTable[refnum] = 0;
00697 return -1;
00698 }
00699
00700
00701 int JackEngine::ClientExternalClose(int refnum)
00702 {
00703 jack_log("JackEngine::ClientExternalClose ref = %ld", refnum);
00704 JackClientInterface* client = fClientTable[refnum];
00705 assert(client);
00706 int res = ClientCloseAux(refnum, true);
00707 client->Close();
00708 delete client;
00709 return res;
00710 }
00711
00712
00713 int JackEngine::ClientInternalClose(int refnum, bool wait)
00714 {
00715 jack_log("JackEngine::ClientInternalClose ref = %ld", refnum);
00716 return ClientCloseAux(refnum, wait);
00717 }
00718
00719 int JackEngine::ClientCloseAux(int refnum, bool wait)
00720 {
00721 jack_log("JackEngine::ClientCloseAux ref = %ld", refnum);
00722
00723 JackClientInterface* client = fClientTable[refnum];
00724 fEngineControl->fTransport.ResetTimebase(refnum);
00725
00726
00727 jack_int_t ports[PORT_NUM_FOR_CLIENT];
00728 int i;
00729
00730 fGraphManager->GetInputPorts(refnum, ports);
00731 for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) {
00732 PortUnRegister(refnum, ports[i]);
00733 }
00734
00735 fGraphManager->GetOutputPorts(refnum, ports);
00736 for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) {
00737 PortUnRegister(refnum, ports[i]);
00738 }
00739
00740
00741 ReleaseRefnum(refnum);
00742
00743
00744 fGraphManager->RemoveAllPorts(refnum);
00745
00746
00747 if (wait) {
00748 if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 2)) {
00749 jack_error("JackEngine::ClientCloseAux wait error ref = %ld", refnum);
00750 }
00751 }
00752
00753
00754 NotifyRemoveClient(client->GetClientControl()->fName, refnum);
00755
00756
00757 fSynchroTable[refnum].Destroy();
00758 fEngineControl->ResetRollingUsecs();
00759 return 0;
00760 }
00761
00762 int JackEngine::ClientActivate(int refnum, bool is_real_time)
00763 {
00764 JackClientInterface* client = fClientTable[refnum];
00765 jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName);
00766
00767 if (is_real_time) {
00768 fGraphManager->Activate(refnum);
00769 }
00770
00771
00772 if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) {
00773 jack_error("JackEngine::ClientActivate wait error ref = %ld name = %s", refnum, client->GetClientControl()->fName);
00774 return -1;
00775 } else {
00776 jack_int_t input_ports[PORT_NUM_FOR_CLIENT];
00777 jack_int_t output_ports[PORT_NUM_FOR_CLIENT];
00778 fGraphManager->GetInputPorts(refnum, input_ports);
00779 fGraphManager->GetOutputPorts(refnum, output_ports);
00780
00781
00782 NotifyActivate(refnum);
00783
00784
00785 for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) {
00786 NotifyPortRegistation(input_ports[i], true);
00787 }
00788 for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) {
00789 NotifyPortRegistation(output_ports[i], true);
00790 }
00791
00792 return 0;
00793 }
00794 }
00795
00796
00797 int JackEngine::ClientDeactivate(int refnum)
00798 {
00799 JackClientInterface* client = fClientTable[refnum];
00800 jack_log("JackEngine::ClientDeactivate ref = %ld name = %s", refnum, client->GetClientControl()->fName);
00801
00802 jack_int_t input_ports[PORT_NUM_FOR_CLIENT];
00803 jack_int_t output_ports[PORT_NUM_FOR_CLIENT];
00804 fGraphManager->GetInputPorts(refnum, input_ports);
00805 fGraphManager->GetOutputPorts(refnum, output_ports);
00806
00807
00808 for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) {
00809 PortDisconnect(-1, input_ports[i], ALL_PORTS);
00810 }
00811 for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) {
00812 PortDisconnect(-1, output_ports[i], ALL_PORTS);
00813 }
00814
00815
00816 for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) {
00817 NotifyPortRegistation(input_ports[i], false);
00818 }
00819 for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) {
00820 NotifyPortRegistation(output_ports[i], false);
00821 }
00822
00823 fGraphManager->Deactivate(refnum);
00824 fLastSwitchUsecs = 0;
00825
00826
00827 if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) {
00828 jack_error("JackEngine::ClientDeactivate wait error ref = %ld name = %s", refnum, client->GetClientControl()->fName);
00829 return -1;
00830 } else {
00831 return 0;
00832 }
00833 }
00834
00835 void JackEngine::ClientKill(int refnum)
00836 {
00837 jack_log("JackEngine::ClientKill ref = %ld", refnum);
00838 if (ClientDeactivate(refnum) < 0) {
00839 jack_error("JackEngine::ClientKill ref = %ld cannot be removed from the graph !!", refnum);
00840 }
00841 if (ClientExternalClose(refnum) < 0) {
00842 jack_error("JackEngine::ClientKill ref = %ld cannot be closed", refnum);
00843 }
00844 }
00845
00846
00847
00848
00849
00850 int JackEngine::PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index)
00851 {
00852 jack_log("JackEngine::PortRegister ref = %ld name = %s type = %s flags = %d buffer_size = %d", refnum, name, type, flags, buffer_size);
00853 JackClientInterface* client = fClientTable[refnum];
00854
00855
00856 if (fGraphManager->GetPort(name) != NO_PORT) {
00857 jack_error("port_name \"%s\" already exists", name);
00858 return -1;
00859 }
00860
00861
00862 *port_index = fGraphManager->AllocatePort(refnum, name, type, (JackPortFlags)flags, fEngineControl->fBufferSize);
00863 if (*port_index != NO_PORT) {
00864 if (client->GetClientControl()->fActive) {
00865 NotifyPortRegistation(*port_index, true);
00866 }
00867 return 0;
00868 } else {
00869 return -1;
00870 }
00871 }
00872
00873 int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index)
00874 {
00875 jack_log("JackEngine::PortUnRegister ref = %ld port_index = %ld", refnum, port_index);
00876 JackClientInterface* client = fClientTable[refnum];
00877 assert(client);
00878
00879
00880 PortDisconnect(-1, port_index, ALL_PORTS);
00881
00882 if (fGraphManager->ReleasePort(refnum, port_index) == 0) {
00883 if (client->GetClientControl()->fActive) {
00884 NotifyPortRegistation(port_index, false);
00885 }
00886 return 0;
00887 } else {
00888 return -1;
00889 }
00890 }
00891
00892
00893
00894 int JackEngine::CheckPortsConnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
00895 {
00896 if (fSelfConnectMode == ' ') return 1;
00897
00898 JackPort* src_port = fGraphManager->GetPort(src);
00899 JackPort* dst_port = fGraphManager->GetPort(dst);
00900
00901 jack_log("JackEngine::CheckPortsConnect(ref = %d, src = %d, dst = %d)", refnum, src_port->GetRefNum(), dst_port->GetRefNum());
00902
00903
00904
00905
00906 int src_self = src_port->GetRefNum() == refnum ? 1 : 0;
00907 int dst_self = dst_port->GetRefNum() == refnum ? 1 : 0;
00908
00909
00910
00911
00912
00913
00914
00915 int sum = src_self + dst_self;
00916
00917 if (sum == 0) return 1;
00918 char lmode = tolower(fSelfConnectMode);
00919
00920 if (sum == 2 && lmode == 'e') return 1;
00921 bool fail = lmode != fSelfConnectMode;
00922
00923
00924 jack_info(
00925 "%s port self connect request%s (%s -> %s)",
00926 fail ? "rejecting" : "ignoring",
00927 sum == 1 ? " to external port" : "",
00928 src_port->GetName(),
00929 dst_port->GetName());
00930
00931 return fail ? -1 : 0;
00932 }
00933
00934 int JackEngine::PortConnect(int refnum, const char* src, const char* dst)
00935 {
00936 jack_log("JackEngine::PortConnect ref = %d src = %s dst = %s", refnum, src, dst);
00937 jack_port_id_t port_src, port_dst;
00938
00939 return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0)
00940 ? -1
00941 : PortConnect(refnum, port_src, port_dst);
00942 }
00943
00944 int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
00945 {
00946 jack_log("JackEngine::PortConnect ref = %d src = %d dst = %d", refnum, src, dst);
00947 JackClientInterface* client;
00948 int ref;
00949
00950 if (fGraphManager->CheckPorts(src, dst) < 0) {
00951 return -1;
00952 }
00953
00954 ref = fGraphManager->GetOutputRefNum(src);
00955 assert(ref >= 0);
00956 client = fClientTable[ref];
00957 assert(client);
00958 if (!client->GetClientControl()->fActive) {
00959 jack_error("Cannot connect ports owned by inactive clients:"
00960 " \"%s\" is not active", client->GetClientControl()->fName);
00961 return -1;
00962 }
00963
00964 ref = fGraphManager->GetInputRefNum(dst);
00965 assert(ref >= 0);
00966 client = fClientTable[ref];
00967 assert(client);
00968 if (!client->GetClientControl()->fActive) {
00969 jack_error("Cannot connect ports owned by inactive clients:"
00970 " \"%s\" is not active", client->GetClientControl()->fName);
00971 return -1;
00972 }
00973
00974 int res = CheckPortsConnect(refnum, src, dst);
00975 if (res != 1) {
00976 return res;
00977 }
00978
00979 res = fGraphManager->Connect(src, dst);
00980 if (res == 0) {
00981 NotifyPortConnect(src, dst, true);
00982 }
00983 return res;
00984 }
00985
00986 int JackEngine::PortDisconnect(int refnum, const char* src, const char* dst)
00987 {
00988 jack_log("JackEngine::PortDisconnect ref = %d src = %s dst = %s", refnum, src, dst);
00989 jack_port_id_t port_src, port_dst;
00990
00991 return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0)
00992 ? -1
00993 : PortDisconnect(refnum, port_src, port_dst);
00994 }
00995
00996 int JackEngine::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
00997 {
00998 jack_log("JackEngine::PortDisconnect ref = %d src = %d dst = %d", refnum, src, dst);
00999
01000 if (dst == ALL_PORTS) {
01001
01002 jack_int_t connections[CONNECTION_NUM_FOR_PORT];
01003 fGraphManager->GetConnections(src, connections);
01004
01005 JackPort* port = fGraphManager->GetPort(src);
01006 int res = 0;
01007 if (port->GetFlags() & JackPortIsOutput) {
01008 for (int i = 0; (i < CONNECTION_NUM_FOR_PORT) && (connections[i] != EMPTY); i++) {
01009 if (PortDisconnect(refnum, src, connections[i]) != 0) {
01010 res = -1;
01011 }
01012 }
01013 } else {
01014 for (int i = 0; (i < CONNECTION_NUM_FOR_PORT) && (connections[i] != EMPTY); i++) {
01015 if (PortDisconnect(refnum, connections[i], src) != 0) {
01016 res = -1;
01017 }
01018 }
01019 }
01020
01021 return res;
01022 }
01023
01024 if (fGraphManager->CheckPorts(src, dst) < 0) {
01025 return -1;
01026 }
01027
01028 int res = CheckPortsConnect(refnum, src, dst);
01029 if (res != 1) {
01030 return res;
01031 }
01032
01033 res = fGraphManager->Disconnect(src, dst);
01034 if (res == 0)
01035 NotifyPortConnect(src, dst, false);
01036 return res;
01037 }
01038
01039 int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name)
01040 {
01041 char old_name[REAL_JACK_PORT_NAME_SIZE];
01042 strcpy(old_name, fGraphManager->GetPort(port)->GetName());
01043 fGraphManager->GetPort(port)->SetName(name);
01044 NotifyPortRename(port, old_name);
01045 return 0;
01046 }
01047
01048
01049
01050
01051
01052 void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, detail::JackChannelTransactionInterface *socket, JackSessionNotifyResult** result)
01053 {
01054 if (fSessionPendingReplies != 0) {
01055 JackSessionNotifyResult res(-1);
01056 res.Write(socket);
01057 jack_log("JackEngine::SessionNotify ... busy");
01058 if (result != NULL) *result = NULL;
01059 return;
01060 }
01061
01062 for (int i = 0; i < CLIENT_NUM; i++) {
01063 JackClientInterface* client = fClientTable[i];
01064 if (client && (client->GetClientControl()->fSessionID < 0)) {
01065 client->GetClientControl()->fSessionID = GetNewUUID();
01066 }
01067 }
01068 fSessionResult = new JackSessionNotifyResult();
01069
01070 for (int i = 0; i < CLIENT_NUM; i++) {
01071 JackClientInterface* client = fClientTable[i];
01072 if (client && client->GetClientControl()->fCallback[kSessionCallback]) {
01073
01074
01075 if (target != NULL && strlen(target) != 0) {
01076 if (strcmp(target, client->GetClientControl()->fName)) {
01077 continue;
01078 }
01079 }
01080
01081 char path_buf[JACK_PORT_NAME_SIZE];
01082 if (path[strlen(path) - 1] == DIR_SEPARATOR) {
01083 snprintf(path_buf, sizeof path_buf, "%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR);
01084 } else {
01085 snprintf(path_buf, sizeof path_buf, "%s%c%s%c", path, DIR_SEPARATOR, client->GetClientControl()->fName, DIR_SEPARATOR);
01086 }
01087
01088 int res = JackTools::MkDir(path_buf);
01089 if (res) jack_error("JackEngine::SessionNotify: can not create session directory '%s'", path_buf);
01090
01091 int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, true, path_buf, (int)type, 0);
01092
01093 if (result == kPendingSessionReply) {
01094 fSessionPendingReplies += 1;
01095 } else if (result == kImmediateSessionReply) {
01096 char uuid_buf[JACK_UUID_SIZE];
01097 snprintf(uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID);
01098 fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf,
01099 client->GetClientControl()->fName,
01100 client->GetClientControl()->fSessionCommand,
01101 client->GetClientControl()->fSessionFlags));
01102 }
01103 }
01104 }
01105
01106 if (result != NULL) *result = fSessionResult;
01107
01108 if (fSessionPendingReplies == 0) {
01109 fSessionResult->Write(socket);
01110 if (result == NULL) delete fSessionResult;
01111 fSessionResult = NULL;
01112 } else {
01113 fSessionTransaction = socket;
01114 }
01115 }
01116
01117 int JackEngine::SessionReply(int refnum)
01118 {
01119 JackClientInterface* client = fClientTable[refnum];
01120 assert(client);
01121 char uuid_buf[JACK_UUID_SIZE];
01122 snprintf(uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID);
01123 fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf,
01124 client->GetClientControl()->fName,
01125 client->GetClientControl()->fSessionCommand,
01126 client->GetClientControl()->fSessionFlags));
01127 fSessionPendingReplies -= 1;
01128
01129 if (fSessionPendingReplies == 0) {
01130 fSessionResult->Write(fSessionTransaction);
01131 if (fSessionTransaction != NULL) {
01132 delete fSessionResult;
01133 }
01134 fSessionResult = NULL;
01135 }
01136
01137 return 0;
01138 }
01139
01140 int JackEngine::GetUUIDForClientName(const char *client_name, char *uuid_res)
01141 {
01142 for (int i = 0; i < CLIENT_NUM; i++) {
01143 JackClientInterface* client = fClientTable[i];
01144
01145 if (client && (strcmp(client_name, client->GetClientControl()->fName) == 0)) {
01146 snprintf(uuid_res, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID);
01147 return 0;
01148 }
01149 }
01150
01151 return -1;
01152 }
01153
01154 int JackEngine::GetClientNameForUUID(const char *uuid, char *name_res)
01155 {
01156 for (int i = 0; i < CLIENT_NUM; i++) {
01157 JackClientInterface* client = fClientTable[i];
01158
01159 if (!client) {
01160 continue;
01161 }
01162
01163 char uuid_buf[JACK_UUID_SIZE];
01164 snprintf(uuid_buf, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID);
01165
01166 if (strcmp(uuid,uuid_buf) == 0) {
01167 strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE);
01168 return 0;
01169 }
01170 }
01171
01172 return -1;
01173 }
01174
01175 int JackEngine::ReserveClientName(const char *name, const char *uuid)
01176 {
01177 jack_log("JackEngine::ReserveClientName ( name = %s, uuid = %s )", name, uuid);
01178
01179 if (ClientCheckName(name)) {
01180 jack_log("name already taken");
01181 return -1;
01182 }
01183
01184 EnsureUUID(atoi(uuid));
01185 fReservationMap[atoi(uuid)] = name;
01186 return 0;
01187 }
01188
01189 int JackEngine::ClientHasSessionCallback(const char *name)
01190 {
01191 JackClientInterface* client = NULL;
01192 for (int i = 0; i < CLIENT_NUM; i++) {
01193 client = fClientTable[i];
01194 if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) {
01195 break;
01196 }
01197 }
01198
01199 if (client) {
01200 return client->GetClientControl()->fCallback[kSessionCallback];
01201 } else {
01202 return -1;
01203 }
01204 }
01205
01206 }
01207