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 <assert.h>
00023
00024 #include "JackSystemDeps.h"
00025 #include "JackLockedEngine.h"
00026 #include "JackExternalClient.h"
00027 #include "JackInternalClient.h"
00028 #include "JackEngineControl.h"
00029 #include "JackClientControl.h"
00030 #include "JackServerGlobals.h"
00031 #include "JackGlobals.h"
00032 #include "JackChannel.h"
00033 #include "JackError.h"
00034
00035 namespace Jack
00036 {
00037
00038 #define AssertRefnum(ref) assert(ref >= 0 && ref < CLIENT_NUM);
00039
00040 JackEngine::JackEngine(JackGraphManager* manager,
00041 JackSynchro* table,
00042 JackEngineControl* control)
00043 {
00044 fGraphManager = manager;
00045 fSynchroTable = table;
00046 fEngineControl = control;
00047 for (int i = 0; i < CLIENT_NUM; i++)
00048 fClientTable[i] = NULL;
00049 }
00050
00051 JackEngine::~JackEngine()
00052 {
00053 jack_log("JackEngine::~JackEngine");
00054 }
00055
00056 int JackEngine::Open()
00057 {
00058 jack_log("JackEngine::Open");
00059
00060
00061 if (fChannel.Open(fEngineControl->fServerName) < 0) {
00062 jack_error("Cannot connect to server");
00063 return -1;
00064 } else {
00065 return 0;
00066 }
00067 }
00068
00069 int JackEngine::Close()
00070 {
00071 jack_log("JackEngine::Close");
00072 fChannel.Close();
00073
00074
00075 for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
00076 if (JackLoadableInternalClient* loadable_client = dynamic_cast<JackLoadableInternalClient*>(fClientTable[i])) {
00077 jack_log("JackEngine::Close loadable client = %s", loadable_client->GetClientControl()->fName);
00078 loadable_client->Close();
00079
00080 fClientTable[i] = NULL;
00081 delete loadable_client;
00082 } else if (JackExternalClient* external_client = dynamic_cast<JackExternalClient*>(fClientTable[i])) {
00083 jack_log("JackEngine::Close external client = %s", external_client->GetClientControl()->fName);
00084 external_client->Close();
00085
00086 fClientTable[i] = NULL;
00087 }
00088 }
00089
00090 return 0;
00091 }
00092
00093
00094
00095
00096
00097 int JackEngine::AllocateRefnum()
00098 {
00099 for (int i = 0; i < CLIENT_NUM; i++) {
00100 if (!fClientTable[i]) {
00101 jack_log("JackEngine::AllocateRefNum ref = %ld", i);
00102 return i;
00103 }
00104 }
00105 return -1;
00106 }
00107
00108 void JackEngine::ReleaseRefnum(int ref)
00109 {
00110 fClientTable[ref] = NULL;
00111
00112 if (fEngineControl->fTemporary) {
00113 int i;
00114 for (i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
00115 if (fClientTable[i])
00116 break;
00117 }
00118 if (i == CLIENT_NUM) {
00119
00120 jack_log("JackEngine::ReleaseRefnum server quit");
00121 fEngineControl->fTemporary = false;
00122 throw JackTemporaryException();
00123 }
00124 }
00125 }
00126
00127
00128
00129
00130
00131 void JackEngine::ProcessNext(jack_time_t cur_cycle_begin)
00132 {
00133 fLastSwitchUsecs = cur_cycle_begin;
00134 if (fGraphManager->RunNextGraph())
00135 fChannel.Notify(ALL_CLIENTS, kGraphOrderCallback, 0);
00136 fSignal.Signal();
00137 }
00138
00139 void JackEngine::ProcessCurrent(jack_time_t cur_cycle_begin)
00140 {
00141 if (cur_cycle_begin < fLastSwitchUsecs + 2 * fEngineControl->fPeriodUsecs)
00142 CheckXRun(cur_cycle_begin);
00143 fGraphManager->RunCurrentGraph();
00144 }
00145
00146 bool JackEngine::Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end)
00147 {
00148 bool res = true;
00149
00150
00151 fEngineControl->CycleBegin(fClientTable, fGraphManager, cur_cycle_begin, prev_cycle_end);
00152
00153
00154 if (fGraphManager->IsFinishedGraph()) {
00155 ProcessNext(cur_cycle_begin);
00156 res = true;
00157 } else {
00158 jack_log("Process: graph not finished!");
00159 if (cur_cycle_begin > fLastSwitchUsecs + fEngineControl->fTimeOutUsecs) {
00160 jack_log("Process: switch to next state delta = %ld", long(cur_cycle_begin - fLastSwitchUsecs));
00161 ProcessNext(cur_cycle_begin);
00162 res = true;
00163 } else {
00164 jack_log("Process: waiting to switch delta = %ld", long(cur_cycle_begin - fLastSwitchUsecs));
00165 ProcessCurrent(cur_cycle_begin);
00166 res = false;
00167 }
00168 }
00169
00170
00171 fEngineControl->CycleEnd(fClientTable);
00172 return res;
00173 }
00174
00175
00176
00177
00178
00179
00180 void JackEngine::CheckXRun(jack_time_t callback_usecs)
00181 {
00182 for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
00183 JackClientInterface* client = fClientTable[i];
00184 if (client && client->GetClientControl()->fActive) {
00185 JackClientTiming* timing = fGraphManager->GetClientTiming(i);
00186 jack_client_state_t status = timing->fStatus;
00187 jack_time_t finished_date = timing->fFinishedAt;
00188
00189 if (status != NotTriggered && status != Finished) {
00190 jack_error("JackEngine::XRun: client = %s was not run: state = %ld", client->GetClientControl()->fName, status);
00191 fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);
00192 }
00193
00194 if (status == Finished && (long)(finished_date - callback_usecs) > 0) {
00195 jack_error("JackEngine::XRun: client %s finished after current callback", client->GetClientControl()->fName);
00196 fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);
00197 }
00198 }
00199 }
00200 }
00201
00202
00203
00204
00205
00206 void JackEngine::NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2)
00207 {
00208 JackClientInterface* client = fClientTable[refnum];
00209
00210
00211 if (!client) {
00212 jack_log("JackEngine::NotifyClient: client not available anymore");
00213 } else if (client->GetClientControl()->fCallback[event]) {
00214 if (client->ClientNotify(refnum, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0)
00215 jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2);
00216 } else {
00217 jack_log("JackEngine::NotifyClient: no callback for event = %ld", event);
00218 }
00219 }
00220
00221 void JackEngine::NotifyClients(int event, int sync, const char* message, int value1, int value2)
00222 {
00223 for (int i = 0; i < CLIENT_NUM; i++) {
00224 JackClientInterface* client = fClientTable[i];
00225 if (client) {
00226 if (client->GetClientControl()->fCallback[event]) {
00227 if (client->ClientNotify(i, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0)
00228 jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2);
00229 } else {
00230 jack_log("JackEngine::NotifyClients: no callback for event = %ld", event);
00231 }
00232 }
00233 }
00234 }
00235
00236 int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* name, int refnum)
00237 {
00238 jack_log("JackEngine::NotifyAddClient: name = %s", name);
00239
00240 for (int i = 0; i < CLIENT_NUM; i++) {
00241 JackClientInterface* old_client = fClientTable[i];
00242 if (old_client) {
00243 if (old_client->ClientNotify(refnum, name, kAddClient, true, "", 0, 0) < 0) {
00244 jack_error("NotifyAddClient old_client fails name = %s", old_client->GetClientControl()->fName);
00245 return -1;
00246 }
00247 if (new_client->ClientNotify(i, old_client->GetClientControl()->fName, kAddClient, true, "", 0, 0) < 0) {
00248 jack_error("NotifyAddClient new_client fails name = %s", name);
00249 return -1;
00250 }
00251 }
00252 }
00253
00254 return 0;
00255 }
00256
00257 void JackEngine::NotifyRemoveClient(const char* name, int refnum)
00258 {
00259
00260 for (int i = 0; i < CLIENT_NUM; i++) {
00261 JackClientInterface* client = fClientTable[i];
00262 if (client) {
00263 client->ClientNotify(refnum, name, kRemoveClient, true, "",0, 0);
00264 }
00265 }
00266 }
00267
00268
00269 void JackEngine::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs)
00270 {
00271
00272 fEngineControl->ResetFrameTime(callback_usecs);
00273 fEngineControl->NotifyXRun(delayed_usecs);
00274 fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);
00275 }
00276
00277 void JackEngine::NotifyXRun(int refnum)
00278 {
00279 if (refnum == ALL_CLIENTS) {
00280 NotifyClients(kXRunCallback, false, "", 0, 0);
00281 } else {
00282 NotifyClient(refnum, kXRunCallback, false, "", 0, 0);
00283 }
00284 }
00285
00286 void JackEngine::NotifyGraphReorder()
00287 {
00288 NotifyClients(kGraphOrderCallback, false, "", 0, 0);
00289 }
00290
00291 void JackEngine::NotifyBufferSize(jack_nframes_t buffer_size)
00292 {
00293 NotifyClients(kBufferSizeCallback, true, "", buffer_size, 0);
00294 }
00295
00296 void JackEngine::NotifySampleRate(jack_nframes_t sample_rate)
00297 {
00298 NotifyClients(kSampleRateCallback, true, "", sample_rate, 0);
00299 }
00300
00301 void JackEngine::NotifyFailure(int code, const char* reason)
00302 {
00303 NotifyClients(kShutDownCallback, false, reason, code, 0);
00304 }
00305
00306 void JackEngine::NotifyFreewheel(bool onoff)
00307 {
00308 if (onoff) {
00309
00310 fEngineControl->fSavedRealTime = fEngineControl->fRealTime;
00311 fEngineControl->fRealTime = false;
00312 } else {
00313
00314 fEngineControl->fRealTime = fEngineControl->fSavedRealTime;
00315 fEngineControl->fSavedRealTime = false;
00316 }
00317 NotifyClients((onoff ? kStartFreewheelCallback : kStopFreewheelCallback), true, "", 0, 0);
00318 }
00319
00320 void JackEngine::NotifyPortRegistation(jack_port_id_t port_index, bool onoff)
00321 {
00322 NotifyClients((onoff ? kPortRegistrationOnCallback : kPortRegistrationOffCallback), false, "", port_index, 0);
00323 }
00324
00325 void JackEngine::NotifyPortRename(jack_port_id_t port)
00326 {
00327 NotifyClients(kPortRenameCallback, false, "", port, 0);
00328 }
00329
00330 void JackEngine::NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff)
00331 {
00332 NotifyClients((onoff ? kPortConnectCallback : kPortDisconnectCallback), false, "", src, dst);
00333 }
00334
00335 void JackEngine::NotifyActivate(int refnum)
00336 {
00337 NotifyClient(refnum, kActivateClient, true, "", 0, 0);
00338 }
00339
00340
00341
00342
00343
00344 int JackEngine::GetInternalClientName(int refnum, char* name_res)
00345 {
00346 AssertRefnum(refnum);
00347 JackClientInterface* client = fClientTable[refnum];
00348 if (client) {
00349 strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE);
00350 return 0;
00351 } else {
00352 return -1;
00353 }
00354 }
00355
00356 int JackEngine::InternalClientHandle(const char* client_name, int* status, int* int_ref)
00357 {
00358
00359 *status = 0;
00360
00361 for (int i = 0; i < CLIENT_NUM; i++) {
00362 JackClientInterface* client = fClientTable[i];
00363 if (client && dynamic_cast<JackLoadableInternalClient*>(client) && (strcmp(client->GetClientControl()->fName, client_name) == 0)) {
00364 jack_log("InternalClientHandle found client name = %s ref = %ld", client_name, i);
00365 *int_ref = i;
00366 return 0;
00367 }
00368 }
00369
00370 *status |= (JackNoSuchClient | JackFailure);
00371 return -1;
00372 }
00373
00374 int JackEngine::InternalClientUnload(int refnum, int* status)
00375 {
00376 AssertRefnum(refnum);
00377 JackClientInterface* client = fClientTable[refnum];
00378 if (client) {
00379 int res = client->Close();
00380 delete client;
00381 *status = 0;
00382 return res;
00383 } else {
00384 *status = (JackNoSuchClient | JackFailure);
00385 return -1;
00386 }
00387 }
00388
00389
00390
00391
00392
00393 int JackEngine::ClientCheck(const char* name, char* name_res, int protocol, int options, int* status)
00394 {
00395
00396 *status = 0;
00397 strcpy(name_res, name);
00398
00399 jack_log("Check protocol client %ld server = %ld", protocol, JACK_PROTOCOL_VERSION);
00400
00401 if (protocol != JACK_PROTOCOL_VERSION) {
00402 *status |= (JackFailure | JackVersionError);
00403 jack_error("JACK protocol mismatch (%d vs %d)", protocol, JACK_PROTOCOL_VERSION);
00404 return -1;
00405 }
00406
00407 if (ClientCheckName(name)) {
00408
00409 *status |= JackNameNotUnique;
00410
00411 if (options & JackUseExactName) {
00412 jack_error("cannot create new client; %s already exists", name);
00413 *status |= JackFailure;
00414 return -1;
00415 }
00416
00417 if (GenerateUniqueName(name_res)) {
00418 *status |= JackFailure;
00419 return -1;
00420 }
00421 }
00422
00423 return 0;
00424 }
00425
00426 bool JackEngine::GenerateUniqueName(char* name)
00427 {
00428 int tens, ones;
00429 int length = strlen(name);
00430
00431 if (length > JACK_CLIENT_NAME_SIZE - 4) {
00432 jack_error("%s exists and is too long to make unique", name);
00433 return true;
00434 }
00435
00436
00437 name[length++] = '-';
00438 tens = length++;
00439 ones = length++;
00440 name[tens] = '0';
00441 name[ones] = '1';
00442 name[length] = '\0';
00443
00444 while (ClientCheckName(name)) {
00445 if (name[ones] == '9') {
00446 if (name[tens] == '9') {
00447 jack_error("client %s has 99 extra instances already", name);
00448 return true;
00449 }
00450 name[tens]++;
00451 name[ones] = '0';
00452 } else {
00453 name[ones]++;
00454 }
00455 }
00456 return false;
00457 }
00458
00459 bool JackEngine::ClientCheckName(const char* name)
00460 {
00461 for (int i = 0; i < CLIENT_NUM; i++) {
00462 JackClientInterface* client = fClientTable[i];
00463 if (client && (strcmp(client->GetClientControl()->fName, name) == 0))
00464 return true;
00465 }
00466
00467 return false;
00468 }
00469
00470 int JackEngine::GetClientPID(const char* name)
00471 {
00472 for (int i = 0; i < CLIENT_NUM; i++) {
00473 JackClientInterface* client = fClientTable[i];
00474 if (client && (strcmp(client->GetClientControl()->fName, name) == 0))
00475 return client->GetClientControl()->fPID;
00476 }
00477
00478 return 0;
00479 }
00480
00481 int JackEngine::GetClientRefNum(const char* name)
00482 {
00483 for (int i = 0; i < CLIENT_NUM; i++) {
00484 JackClientInterface* client = fClientTable[i];
00485 if (client && (strcmp(client->GetClientControl()->fName, name) == 0))
00486 return client->GetClientControl()->fRefNum;
00487 }
00488
00489 return -1;
00490 }
00491
00492
00493 int JackEngine::ClientExternalOpen(const char* name, int pid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager)
00494 {
00495 jack_log("JackEngine::ClientExternalOpen: name = %s ", name);
00496
00497 int refnum = AllocateRefnum();
00498 if (refnum < 0) {
00499 jack_error("No more refnum available");
00500 return -1;
00501 }
00502
00503 JackExternalClient* client = new JackExternalClient();
00504
00505 if (!fSynchroTable[refnum].Allocate(name, fEngineControl->fServerName, 0)) {
00506 jack_error("Cannot allocate synchro");
00507 goto error;
00508 }
00509
00510 if (client->Open(name, pid, refnum, shared_client) < 0) {
00511 jack_error("Cannot open client");
00512 goto error;
00513 }
00514
00515 if (!fSignal.LockedTimedWait(DRIVER_OPEN_TIMEOUT * 1000000)) {
00516
00517 jack_error("Driver is not running");
00518 goto error;
00519 }
00520
00521 fClientTable[refnum] = client;
00522
00523 if (NotifyAddClient(client, name, refnum) < 0) {
00524 jack_error("Cannot notify add client");
00525 goto error;
00526 }
00527
00528 fGraphManager->InitRefNum(refnum);
00529 fEngineControl->ResetRollingUsecs();
00530 *shared_engine = fEngineControl->GetShmIndex();
00531 *shared_graph_manager = fGraphManager->GetShmIndex();
00532 *ref = refnum;
00533 return 0;
00534
00535 error:
00536
00537 fSynchroTable[refnum].Destroy();
00538 fClientTable[refnum] = 0;
00539 client->Close();
00540 delete client;
00541 return -1;
00542 }
00543
00544
00545 int JackEngine::ClientInternalOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, bool wait)
00546 {
00547 jack_log("JackEngine::ClientInternalOpen: name = %s", name);
00548
00549 int refnum = AllocateRefnum();
00550 if (refnum < 0) {
00551 jack_error("No more refnum available");
00552 goto error;
00553 }
00554
00555 if (!fSynchroTable[refnum].Allocate(name, fEngineControl->fServerName, 0)) {
00556 jack_error("Cannot allocate synchro");
00557 goto error;
00558 }
00559
00560 if (wait && !fSignal.LockedTimedWait(DRIVER_OPEN_TIMEOUT * 1000000)) {
00561
00562 jack_error("Driver is not running");
00563 goto error;
00564 }
00565
00566 fClientTable[refnum] = client;
00567
00568 if (NotifyAddClient(client, name, refnum) < 0) {
00569 jack_error("Cannot notify add client");
00570 goto error;
00571 }
00572
00573 fGraphManager->InitRefNum(refnum);
00574 fEngineControl->ResetRollingUsecs();
00575 *shared_engine = fEngineControl;
00576 *shared_manager = fGraphManager;
00577 *ref = refnum;
00578 return 0;
00579
00580 error:
00581
00582 fSynchroTable[refnum].Destroy();
00583 fClientTable[refnum] = 0;
00584 return -1;
00585 }
00586
00587
00588 int JackEngine::ClientExternalClose(int refnum)
00589 {
00590 AssertRefnum(refnum);
00591 JackClientInterface* client = fClientTable[refnum];
00592
00593 if (client) {
00594 fEngineControl->fTransport.ResetTimebase(refnum);
00595 int res = ClientCloseAux(refnum, client, true);
00596 client->Close();
00597 delete client;
00598 return res;
00599 } else {
00600 return -1;
00601 }
00602 }
00603
00604
00605 int JackEngine::ClientInternalClose(int refnum, bool wait)
00606 {
00607 AssertRefnum(refnum);
00608 JackClientInterface* client = fClientTable[refnum];
00609 return (client) ? ClientCloseAux(refnum, client, wait) : -1;
00610 }
00611
00612 int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wait)
00613 {
00614 jack_log("JackEngine::ClientCloseAux ref = %ld", refnum);
00615
00616
00617 jack_int_t ports[PORT_NUM_FOR_CLIENT];
00618 int i;
00619
00620 fGraphManager->GetInputPorts(refnum, ports);
00621 for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) {
00622 PortUnRegister(refnum, ports[i]);
00623 }
00624
00625 fGraphManager->GetOutputPorts(refnum, ports);
00626 for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) {
00627 PortUnRegister(refnum, ports[i]);
00628 }
00629
00630
00631 ReleaseRefnum(refnum);
00632
00633
00634 fGraphManager->RemoveAllPorts(refnum);
00635
00636
00637 if (wait) {
00638 if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 2)) {
00639 jack_error("JackEngine::ClientCloseAux wait error ref = %ld", refnum);
00640 }
00641 }
00642
00643
00644 NotifyRemoveClient(client->GetClientControl()->fName, client->GetClientControl()->fRefNum);
00645
00646
00647 fSynchroTable[refnum].Destroy();
00648 fEngineControl->ResetRollingUsecs();
00649 return 0;
00650 }
00651
00652 int JackEngine::ClientActivate(int refnum, bool is_real_time)
00653 {
00654 AssertRefnum(refnum);
00655 JackClientInterface* client = fClientTable[refnum];
00656 assert(fClientTable[refnum]);
00657
00658 jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName);
00659 if (is_real_time)
00660 fGraphManager->Activate(refnum);
00661
00662
00663 if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) {
00664 jack_error("JackEngine::ClientActivate wait error ref = %ld name = %s", refnum, client->GetClientControl()->fName);
00665 return -1;
00666 } else {
00667 NotifyActivate(refnum);
00668 return 0;
00669 }
00670 }
00671
00672
00673 int JackEngine::ClientDeactivate(int refnum)
00674 {
00675 AssertRefnum(refnum);
00676 JackClientInterface* client = fClientTable[refnum];
00677 if (client == NULL)
00678 return -1;
00679
00680 jack_log("JackEngine::ClientDeactivate ref = %ld name = %s", refnum, client->GetClientControl()->fName);
00681
00682
00683 jack_int_t ports[PORT_NUM_FOR_CLIENT];
00684 int i;
00685
00686 fGraphManager->GetInputPorts(refnum, ports);
00687 for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) {
00688 PortDisconnect(refnum, ports[i], ALL_PORTS);
00689 }
00690
00691 fGraphManager->GetOutputPorts(refnum, ports);
00692 for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) {
00693 PortDisconnect(refnum, ports[i], ALL_PORTS);
00694 }
00695
00696 fGraphManager->Deactivate(refnum);
00697 fLastSwitchUsecs = 0;
00698
00699
00700 if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) {
00701 jack_error("JackEngine::ClientDeactivate wait error ref = %ld name = %s", refnum, client->GetClientControl()->fName);
00702 return -1;
00703 } else {
00704 return 0;
00705 }
00706 }
00707
00708
00709
00710
00711
00712 int JackEngine::PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index)
00713 {
00714 jack_log("JackEngine::PortRegister ref = %ld name = %s type = %s flags = %d buffer_size = %d", refnum, name, type, flags, buffer_size);
00715 AssertRefnum(refnum);
00716 assert(fClientTable[refnum]);
00717
00718
00719 if (fGraphManager->GetPort(name) != NO_PORT) {
00720 jack_error("port_name \"%s\" already exists", name);
00721 return -1;
00722 }
00723
00724 *port_index = fGraphManager->AllocatePort(refnum, name, type, (JackPortFlags)flags, fEngineControl->fBufferSize);
00725 if (*port_index != NO_PORT) {
00726 NotifyPortRegistation(*port_index, true);
00727 return 0;
00728 } else {
00729 return -1;
00730 }
00731 }
00732
00733 int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index)
00734 {
00735 jack_log("JackEngine::PortUnRegister ref = %ld port_index = %ld", refnum, port_index);
00736 AssertRefnum(refnum);
00737 assert(fClientTable[refnum]);
00738
00739
00740 PortDisconnect(refnum, port_index, ALL_PORTS);
00741
00742 if (fGraphManager->ReleasePort(refnum, port_index) == 0) {
00743 NotifyPortRegistation(port_index, false);
00744 return 0;
00745 } else {
00746 return -1;
00747 }
00748 }
00749
00750 int JackEngine::PortConnect(int refnum, const char* src, const char* dst)
00751 {
00752 jack_log("JackEngine::PortConnect src = %s dst = %s", src, dst);
00753 AssertRefnum(refnum);
00754 jack_port_id_t port_src, port_dst;
00755
00756 return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0)
00757 ? -1
00758 : PortConnect(refnum, port_src, port_dst);
00759 }
00760
00761 int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
00762 {
00763 jack_log("JackEngine::PortConnect src = %d dst = %d", src, dst);
00764 AssertRefnum(refnum);
00765 JackClientInterface* client;
00766 int ref;
00767
00768 if (fGraphManager->CheckPorts(src, dst) < 0)
00769 return -1;
00770
00771 ref = fGraphManager->GetOutputRefNum(src);
00772 assert(ref >= 0);
00773 client = fClientTable[ref];
00774 assert(client);
00775 if (!client->GetClientControl()->fActive) {
00776 jack_error("Cannot connect ports owned by inactive clients:"
00777 " \"%s\" is not active", client->GetClientControl()->fName);
00778 return -1;
00779 }
00780
00781 ref = fGraphManager->GetInputRefNum(dst);
00782 assert(ref >= 0);
00783 client = fClientTable[ref];
00784 assert(client);
00785 if (!client->GetClientControl()->fActive) {
00786 jack_error("Cannot connect ports owned by inactive clients:"
00787 " \"%s\" is not active", client->GetClientControl()->fName);
00788 return -1;
00789 }
00790
00791 int res = fGraphManager->Connect(src, dst);
00792 if (res == 0)
00793 NotifyPortConnect(src, dst, true);
00794 return res;
00795 }
00796
00797 int JackEngine::PortDisconnect(int refnum, const char* src, const char* dst)
00798 {
00799 jack_log("JackEngine::PortDisconnect src = %s dst = %s", src, dst);
00800 AssertRefnum(refnum);
00801 jack_port_id_t port_src, port_dst;
00802
00803 return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0)
00804 ? -1
00805 : PortDisconnect(refnum, port_src, port_dst);
00806 }
00807
00808 int JackEngine::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
00809 {
00810 jack_log("JackEngine::PortDisconnect src = %d dst = %d", src, dst);
00811 AssertRefnum(refnum);
00812
00813 if (dst == ALL_PORTS) {
00814
00815 jack_int_t connections[CONNECTION_NUM_FOR_PORT];
00816 fGraphManager->GetConnections(src, connections);
00817
00818 JackPort* port = fGraphManager->GetPort(src);
00819 int ret = 0;
00820 if (port->GetFlags() & JackPortIsOutput) {
00821 for (int i = 0; (i < CONNECTION_NUM_FOR_PORT) && (connections[i] != EMPTY); i++) {
00822 if (PortDisconnect(refnum, src, connections[i]) != 0) {
00823 ret = -1;
00824 }
00825 }
00826 } else {
00827 for (int i = 0; (i < CONNECTION_NUM_FOR_PORT) && (connections[i] != EMPTY); i++) {
00828 if (PortDisconnect(refnum, connections[i], src) != 0) {
00829 ret = -1;
00830 }
00831 }
00832 }
00833
00834 return ret;
00835 } else if (fGraphManager->CheckPorts(src, dst) < 0) {
00836 return -1;
00837 } else if (fGraphManager->Disconnect(src, dst) == 0) {
00838
00839 NotifyPortConnect(src, dst, false);
00840 return 0;
00841 } else {
00842 return -1;
00843 }
00844 }
00845
00846 int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name)
00847 {
00848 AssertRefnum(refnum);
00849 fGraphManager->GetPort(port)->SetName(name);
00850 NotifyPortRename(port);
00851 return 0;
00852 }
00853
00854 }
00855