00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "JackConnectionManager.h"
00021 #include "JackClientControl.h"
00022 #include "JackEngineControl.h"
00023 #include "JackGlobals.h"
00024 #include "JackError.h"
00025 #include <set>
00026 #include <iostream>
00027 #include <assert.h>
00028
00029 namespace Jack
00030 {
00031
00032 JackConnectionManager::JackConnectionManager()
00033 {
00034 int i;
00035 jack_log("JackConnectionManager::InitConnections size = %ld ", sizeof(JackConnectionManager));
00036
00037 for (i = 0; i < PORT_NUM_MAX; i++) {
00038 fConnection[i].Init();
00039 }
00040
00041 fLoopFeedback.Init();
00042
00043 jack_log("JackConnectionManager::InitClients");
00044 for (i = 0; i < CLIENT_NUM; i++) {
00045 InitRefNum(i);
00046 }
00047 }
00048
00049 JackConnectionManager::~JackConnectionManager()
00050 {}
00051
00052
00053
00054
00055
00056 bool JackConnectionManager::IsLoopPathAux(int ref1, int ref2) const
00057 {
00058 jack_log("JackConnectionManager::IsLoopPathAux ref1 = %ld ref2 = %ld", ref1, ref2);
00059
00060 if (ref1 < GetEngineControl()->fDriverNum || ref2 < GetEngineControl()->fDriverNum) {
00061 return false;
00062 } else if (ref1 == ref2) {
00063 return true;
00064 } else {
00065 jack_int_t output[CLIENT_NUM];
00066 fConnectionRef.GetOutputTable(ref1, output);
00067
00068 if (fConnectionRef.IsInsideTable(ref2, output)) {
00069 return true;
00070 } else {
00071 for (int i = 0; i < CLIENT_NUM && output[i] != EMPTY; i++) {
00072 if (IsLoopPathAux(output[i], ref2))
00073 return true;
00074 }
00075 return false;
00076 }
00077 }
00078 }
00079
00080
00081
00082
00083
00087 int JackConnectionManager::Connect(jack_port_id_t port_src, jack_port_id_t port_dst)
00088 {
00089 jack_log("JackConnectionManager::Connect port_src = %ld port_dst = %ld", port_src, port_dst);
00090
00091 if (fConnection[port_src].AddItem(port_dst)) {
00092 return 0;
00093 } else {
00094 jack_error("Connection table is full !!");
00095 return -1;
00096 }
00097 }
00098
00102 int JackConnectionManager::Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst)
00103 {
00104 jack_log("JackConnectionManager::Disconnect port_src = %ld port_dst = %ld", port_src, port_dst);
00105
00106 if (fConnection[port_src].RemoveItem(port_dst)) {
00107 return 0;
00108 } else {
00109 jack_error("Connection not found !!");
00110 return -1;
00111 }
00112 }
00113
00117 bool JackConnectionManager::IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const
00118 {
00119 return fConnection[port_src].CheckItem(port_dst);
00120 }
00121
00125 const jack_int_t* JackConnectionManager::GetConnections(jack_port_id_t port_index) const
00126 {
00127 return fConnection[port_index].GetItems();
00128 }
00129
00130
00131
00132
00133
00137 int JackConnectionManager::AddInputPort(int refnum, jack_port_id_t port_index)
00138 {
00139 if (fInputPort[refnum].AddItem(port_index)) {
00140 jack_log("JackConnectionManager::AddInputPort ref = %ld port = %ld", refnum, port_index);
00141 return 0;
00142 } else {
00143 jack_error("Maximum number of input ports is reached for application ref = %ld", refnum);
00144 return -1;
00145 }
00146 }
00147
00151 int JackConnectionManager::AddOutputPort(int refnum, jack_port_id_t port_index)
00152 {
00153 if (fOutputPort[refnum].AddItem(port_index)) {
00154 jack_log("JackConnectionManager::AddOutputPort ref = %ld port = %ld", refnum, port_index);
00155 return 0;
00156 } else {
00157 jack_error("Maximum number of output ports is reached for application ref = %ld", refnum);
00158 return -1;
00159 }
00160 }
00161
00165 int JackConnectionManager::RemoveInputPort(int refnum, jack_port_id_t port_index)
00166 {
00167 jack_log("JackConnectionManager::RemoveInputPort ref = %ld port_index = %ld ", refnum, port_index);
00168
00169 if (fInputPort[refnum].RemoveItem(port_index)) {
00170 return 0;
00171 } else {
00172 jack_error("Input port index = %ld not found for application ref = %ld", port_index, refnum);
00173 return -1;
00174 }
00175 }
00176
00180 int JackConnectionManager::RemoveOutputPort(int refnum, jack_port_id_t port_index)
00181 {
00182 jack_log("JackConnectionManager::RemoveOutputPort ref = %ld port_index = %ld ", refnum, port_index);
00183
00184 if (fOutputPort[refnum].RemoveItem(port_index)) {
00185 return 0;
00186 } else {
00187 jack_error("Output port index = %ld not found for application ref = %ld", port_index, refnum);
00188 return -1;
00189 }
00190 }
00191
00195 const jack_int_t* JackConnectionManager::GetInputPorts(int refnum)
00196 {
00197 return fInputPort[refnum].GetItems();
00198 }
00199
00203 const jack_int_t* JackConnectionManager::GetOutputPorts(int refnum)
00204 {
00205 return fOutputPort[refnum].GetItems();
00206 }
00207
00211 void JackConnectionManager::InitRefNum(int refnum)
00212 {
00213 fInputPort[refnum].Init();
00214 fOutputPort[refnum].Init();
00215 fConnectionRef.Init(refnum);
00216 fInputCounter[refnum].SetValue(0);
00217 }
00218
00222 void JackConnectionManager::ResetGraph(JackClientTiming* timing)
00223 {
00224
00225 for (int i = 0; i < CLIENT_NUM; i++) {
00226 fInputCounter[i].Reset();
00227 timing[i].fStatus = NotTriggered;
00228 }
00229 }
00230
00234 int JackConnectionManager::SuspendRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing, long time_out_usec)
00235 {
00236 bool res;
00237 if ((res = table[control->fRefNum].TimedWait(time_out_usec))) {
00238 timing[control->fRefNum].fStatus = Running;
00239 timing[control->fRefNum].fAwakeAt = GetMicroSeconds();
00240 }
00241 return (res) ? 0 : -1;
00242 }
00243
00247 int JackConnectionManager::ResumeRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing)
00248 {
00249 jack_time_t current_date = GetMicroSeconds();
00250 const jack_int_t* output_ref = fConnectionRef.GetItems(control->fRefNum);
00251 int res = 0;
00252
00253
00254 timing[control->fRefNum].fStatus = Finished;
00255 timing[control->fRefNum].fFinishedAt = current_date;
00256
00257 for (int i = 0; i < CLIENT_NUM; i++) {
00258
00259
00260 if (output_ref[i] > 0) {
00261
00262
00263 timing[i].fStatus = Triggered;
00264 timing[i].fSignaledAt = current_date;
00265
00266 if (!fInputCounter[i].Signal(table + i, control)) {
00267 jack_log("JackConnectionManager::ResumeRefNum error: ref = %ld output = %ld ", control->fRefNum, i);
00268 res = -1;
00269 }
00270 }
00271 }
00272
00273 return res;
00274 }
00275
00276 static bool HasNoConnection(jack_int_t* table)
00277 {
00278 for (int ref = 0; ref < CLIENT_NUM; ref++) {
00279 if (table[ref] > 0) return false;
00280 }
00281 return true;
00282 }
00283
00284
00285
00286 void JackConnectionManager::TopologicalSort(std::vector<jack_int_t>& sorted)
00287 {
00288 JackFixedMatrix<CLIENT_NUM> tmp;
00289 std::set<jack_int_t> level;
00290
00291 fConnectionRef.Copy(tmp);
00292
00293
00294 level.insert(AUDIO_DRIVER_REFNUM);
00295 level.insert(FREEWHEEL_DRIVER_REFNUM);
00296
00297 while (level.size() > 0) {
00298 jack_int_t refnum = *level.begin();
00299 sorted.push_back(refnum);
00300 level.erase(level.begin());
00301 const jack_int_t* output_ref1 = tmp.GetItems(refnum);
00302 for (int dst = 0; dst < CLIENT_NUM; dst++) {
00303 if (output_ref1[dst] > 0) {
00304 tmp.ClearItem(refnum, dst);
00305 jack_int_t output_ref2[CLIENT_NUM];
00306 tmp.GetOutputTable1(dst, output_ref2);
00307 if (HasNoConnection(output_ref2))
00308 level.insert(dst);
00309 }
00310 }
00311 }
00312 }
00313
00317 void JackConnectionManager::IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
00318 {
00319 int ref1 = GetOutputRefNum(port_src);
00320 int ref2 = GetInputRefNum(port_dst);
00321
00322 assert(ref1 >= 0 && ref2 >= 0);
00323
00324 DirectConnect(ref1, ref2);
00325 jack_log("JackConnectionManager::IncConnectionRef: ref1 = %ld ref2 = %ld", ref1, ref2);
00326 }
00327
00331 void JackConnectionManager::DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
00332 {
00333 int ref1 = GetOutputRefNum(port_src);
00334 int ref2 = GetInputRefNum(port_dst);
00335
00336 assert(ref1 >= 0 && ref2 >= 0);
00337
00338 DirectDisconnect(ref1, ref2);
00339 jack_log("JackConnectionManager::DecConnectionRef: ref1 = %ld ref2 = %ld", ref1, ref2);
00340 }
00341
00345 void JackConnectionManager::DirectConnect(int ref1, int ref2)
00346 {
00347 assert(ref1 >= 0 && ref2 >= 0);
00348
00349 if (fConnectionRef.IncItem(ref1, ref2) == 1) {
00350 jack_log("JackConnectionManager::DirectConnect first: ref1 = %ld ref2 = %ld", ref1, ref2);
00351 fInputCounter[ref2].IncValue();
00352 }
00353 }
00354
00358 void JackConnectionManager::DirectDisconnect(int ref1, int ref2)
00359 {
00360 assert(ref1 >= 0 && ref2 >= 0);
00361
00362 if (fConnectionRef.DecItem(ref1, ref2) == 0) {
00363 jack_log("JackConnectionManager::DirectDisconnect last: ref1 = %ld ref2 = %ld", ref1, ref2);
00364 fInputCounter[ref2].DecValue();
00365 }
00366 }
00367
00371 bool JackConnectionManager::IsDirectConnection(int ref1, int ref2) const
00372 {
00373 assert(ref1 >= 0 && ref2 >= 0);
00374 return (fConnectionRef.GetItemCount(ref1, ref2) > 0);
00375 }
00376
00380 int JackConnectionManager::GetInputRefNum(jack_port_id_t port_index) const
00381 {
00382 for (int i = 0; i < CLIENT_NUM; i++) {
00383 if (fInputPort[i].CheckItem(port_index))
00384 return i;
00385 }
00386
00387 return -1;
00388 }
00389
00393 int JackConnectionManager::GetOutputRefNum(jack_port_id_t port_index) const
00394 {
00395 for (int i = 0; i < CLIENT_NUM; i++) {
00396 if (fOutputPort[i].CheckItem(port_index))
00397 return i;
00398 }
00399
00400 return -1;
00401 }
00402
00406 bool JackConnectionManager::IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const
00407 {
00408 return IsLoopPathAux(GetInputRefNum(port_dst), GetOutputRefNum(port_src));
00409 }
00410
00411 bool JackConnectionManager::IsFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst) const
00412 {
00413 return (fLoopFeedback.GetConnectionIndex(GetOutputRefNum(port_src), GetInputRefNum(port_dst)) >= 0);
00414 }
00415
00416 bool JackConnectionManager::IncFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
00417 {
00418 int ref1 = GetOutputRefNum(port_src);
00419 int ref2 = GetInputRefNum(port_dst);
00420
00421
00422 jack_log("JackConnectionManager::IncFeedbackConnection ref1 = %ld ref2 = %ld", ref1, ref2);
00423 assert(ref1 >= 0 && ref2 >= 0);
00424
00425 if (ref1 != ref2)
00426 DirectConnect(ref2, ref1);
00427
00428 return fLoopFeedback.IncConnection(ref1, ref2);
00429 }
00430
00431 bool JackConnectionManager::DecFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
00432 {
00433 int ref1 = GetOutputRefNum(port_src);
00434 int ref2 = GetInputRefNum(port_dst);
00435
00436
00437 jack_log("JackConnectionManager::DecFeedbackConnection ref1 = %ld ref2 = %ld", ref1, ref2);
00438 assert(ref1 >= 0 && ref2 >= 0);
00439
00440 if (ref1 != ref2)
00441 DirectDisconnect(ref2, ref1);
00442
00443 return fLoopFeedback.DecConnection(ref1, ref2);
00444 }
00445
00446 }
00447
00448