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