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