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