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 }
00076 return false;
00077 }
00078 }
00079 }
00080
00081
00082
00083
00084
00088 int JackConnectionManager::Connect(jack_port_id_t port_src, jack_port_id_t port_dst)
00089 {
00090 jack_log("JackConnectionManager::Connect port_src = %ld port_dst = %ld", port_src, port_dst);
00091
00092 if (fConnection[port_src].AddItem(port_dst)) {
00093 return 0;
00094 } else {
00095 jack_error("Connection table is full !!");
00096 return -1;
00097 }
00098 }
00099
00103 int JackConnectionManager::Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst)
00104 {
00105 jack_log("JackConnectionManager::Disconnect port_src = %ld port_dst = %ld", port_src, port_dst);
00106
00107 if (fConnection[port_src].RemoveItem(port_dst)) {
00108 return 0;
00109 } else {
00110 jack_error("Connection not found !!");
00111 return -1;
00112 }
00113 }
00114
00118 bool JackConnectionManager::IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const
00119 {
00120 return fConnection[port_src].CheckItem(port_dst);
00121 }
00122
00126 const jack_int_t* JackConnectionManager::GetConnections(jack_port_id_t port_index) const
00127 {
00128 return fConnection[port_index].GetItems();
00129 }
00130
00131
00132
00133
00134
00138 int JackConnectionManager::AddInputPort(int refnum, jack_port_id_t port_index)
00139 {
00140 if (fInputPort[refnum].AddItem(port_index)) {
00141 jack_log("JackConnectionManager::AddInputPort ref = %ld port = %ld", refnum, port_index);
00142 return 0;
00143 } else {
00144 jack_error("Maximum number of input ports is reached for application ref = %ld", refnum);
00145 return -1;
00146 }
00147 }
00148
00152 int JackConnectionManager::AddOutputPort(int refnum, jack_port_id_t port_index)
00153 {
00154 if (fOutputPort[refnum].AddItem(port_index)) {
00155 jack_log("JackConnectionManager::AddOutputPort ref = %ld port = %ld", refnum, port_index);
00156 return 0;
00157 } else {
00158 jack_error("Maximum number of output ports is reached for application ref = %ld", refnum);
00159 return -1;
00160 }
00161 }
00162
00166 int JackConnectionManager::RemoveInputPort(int refnum, jack_port_id_t port_index)
00167 {
00168 jack_log("JackConnectionManager::RemoveInputPort ref = %ld port_index = %ld ", refnum, port_index);
00169
00170 if (fInputPort[refnum].RemoveItem(port_index)) {
00171 return 0;
00172 } else {
00173 jack_error("Input port index = %ld not found for application ref = %ld", port_index, refnum);
00174 return -1;
00175 }
00176 }
00177
00181 int JackConnectionManager::RemoveOutputPort(int refnum, jack_port_id_t port_index)
00182 {
00183 jack_log("JackConnectionManager::RemoveOutputPort ref = %ld port_index = %ld ", refnum, port_index);
00184
00185 if (fOutputPort[refnum].RemoveItem(port_index)) {
00186 return 0;
00187 } else {
00188 jack_error("Output port index = %ld not found for application ref = %ld", port_index, refnum);
00189 return -1;
00190 }
00191 }
00192
00196 const jack_int_t* JackConnectionManager::GetInputPorts(int refnum)
00197 {
00198 return fInputPort[refnum].GetItems();
00199 }
00200
00204 const jack_int_t* JackConnectionManager::GetOutputPorts(int refnum)
00205 {
00206 return fOutputPort[refnum].GetItems();
00207 }
00208
00212 void JackConnectionManager::InitRefNum(int refnum)
00213 {
00214 fInputPort[refnum].Init();
00215 fOutputPort[refnum].Init();
00216 fConnectionRef.Init(refnum);
00217 fInputCounter[refnum].SetValue(0);
00218 }
00219
00223 void JackConnectionManager::ResetGraph(JackClientTiming* timing)
00224 {
00225
00226 for (int i = 0; i < CLIENT_NUM; i++) {
00227 fInputCounter[i].Reset();
00228 timing[i].fStatus = NotTriggered;
00229 }
00230 }
00231
00235 int JackConnectionManager::SuspendRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing, long time_out_usec)
00236 {
00237 bool res;
00238 if ((res = table[control->fRefNum].TimedWait(time_out_usec))) {
00239 timing[control->fRefNum].fStatus = Running;
00240 timing[control->fRefNum].fAwakeAt = GetMicroSeconds();
00241 }
00242 return (res) ? 0 : -1;
00243 }
00244
00248 int JackConnectionManager::ResumeRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing)
00249 {
00250 jack_time_t current_date = GetMicroSeconds();
00251 const jack_int_t* output_ref = fConnectionRef.GetItems(control->fRefNum);
00252 int res = 0;
00253
00254
00255 timing[control->fRefNum].fStatus = Finished;
00256 timing[control->fRefNum].fFinishedAt = current_date;
00257
00258 for (int i = 0; i < CLIENT_NUM; i++) {
00259
00260
00261 if (output_ref[i] > 0) {
00262
00263
00264 timing[i].fStatus = Triggered;
00265 timing[i].fSignaledAt = current_date;
00266
00267 if (!fInputCounter[i].Signal(table + i, control)) {
00268 jack_log("JackConnectionManager::ResumeRefNum error: ref = %ld output = %ld ", control->fRefNum, i);
00269 res = -1;
00270 }
00271 }
00272 }
00273
00274 return res;
00275 }
00276
00277 static bool HasNoConnection(jack_int_t* table)
00278 {
00279 for (int ref = 0; ref < CLIENT_NUM; ref++) {
00280 if (table[ref] > 0) return false;
00281 }
00282 return true;
00283 }
00284
00285
00286
00287 void JackConnectionManager::TopologicalSort(std::vector<jack_int_t>& sorted)
00288 {
00289 JackFixedMatrix<CLIENT_NUM> tmp;
00290 std::set<jack_int_t> level;
00291
00292 fConnectionRef.Copy(tmp);
00293
00294
00295 level.insert(AUDIO_DRIVER_REFNUM);
00296 level.insert(FREEWHEEL_DRIVER_REFNUM);
00297
00298 while (level.size() > 0) {
00299 jack_int_t refnum = *level.begin();
00300 sorted.push_back(refnum);
00301 level.erase(level.begin());
00302 const jack_int_t* output_ref1 = tmp.GetItems(refnum);
00303 for (int dst = 0; dst < CLIENT_NUM; dst++) {
00304 if (output_ref1[dst] > 0) {
00305 tmp.ClearItem(refnum, dst);
00306 jack_int_t output_ref2[CLIENT_NUM];
00307 tmp.GetOutputTable1(dst, output_ref2);
00308 if (HasNoConnection(output_ref2)) {
00309 level.insert(dst);
00310 }
00311 }
00312 }
00313 }
00314 }
00315
00319 void JackConnectionManager::IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
00320 {
00321 int ref1 = GetOutputRefNum(port_src);
00322 int ref2 = GetInputRefNum(port_dst);
00323
00324 assert(ref1 >= 0 && ref2 >= 0);
00325
00326 DirectConnect(ref1, ref2);
00327 jack_log("JackConnectionManager::IncConnectionRef: ref1 = %ld ref2 = %ld", ref1, ref2);
00328 }
00329
00333 void JackConnectionManager::DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
00334 {
00335 int ref1 = GetOutputRefNum(port_src);
00336 int ref2 = GetInputRefNum(port_dst);
00337
00338 assert(ref1 >= 0 && ref2 >= 0);
00339
00340 DirectDisconnect(ref1, ref2);
00341 jack_log("JackConnectionManager::DecConnectionRef: ref1 = %ld ref2 = %ld", ref1, ref2);
00342 }
00343
00347 void JackConnectionManager::DirectConnect(int ref1, int ref2)
00348 {
00349 assert(ref1 >= 0 && ref2 >= 0);
00350
00351 if (fConnectionRef.IncItem(ref1, ref2) == 1) {
00352 jack_log("JackConnectionManager::DirectConnect first: ref1 = %ld ref2 = %ld", ref1, ref2);
00353 fInputCounter[ref2].IncValue();
00354 }
00355 }
00356
00360 void JackConnectionManager::DirectDisconnect(int ref1, int ref2)
00361 {
00362 assert(ref1 >= 0 && ref2 >= 0);
00363
00364 if (fConnectionRef.DecItem(ref1, ref2) == 0) {
00365 jack_log("JackConnectionManager::DirectDisconnect last: ref1 = %ld ref2 = %ld", ref1, ref2);
00366 fInputCounter[ref2].DecValue();
00367 }
00368 }
00369
00373 bool JackConnectionManager::IsDirectConnection(int ref1, int ref2) const
00374 {
00375 assert(ref1 >= 0 && ref2 >= 0);
00376 return (fConnectionRef.GetItemCount(ref1, ref2) > 0);
00377 }
00378
00382 int JackConnectionManager::GetInputRefNum(jack_port_id_t port_index) const
00383 {
00384 for (int i = 0; i < CLIENT_NUM; i++) {
00385 if (fInputPort[i].CheckItem(port_index)) {
00386 return i;
00387 }
00388 }
00389
00390 return -1;
00391 }
00392
00396 int JackConnectionManager::GetOutputRefNum(jack_port_id_t port_index) const
00397 {
00398 for (int i = 0; i < CLIENT_NUM; i++) {
00399 if (fOutputPort[i].CheckItem(port_index)) {
00400 return i;
00401 }
00402 }
00403
00404 return -1;
00405 }
00406
00410 bool JackConnectionManager::IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const
00411 {
00412 return IsLoopPathAux(GetInputRefNum(port_dst), GetOutputRefNum(port_src));
00413 }
00414
00415 bool JackConnectionManager::IsFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst) const
00416 {
00417 return (fLoopFeedback.GetConnectionIndex(GetOutputRefNum(port_src), GetInputRefNum(port_dst)) >= 0);
00418 }
00419
00420 bool JackConnectionManager::IncFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
00421 {
00422 int ref1 = GetOutputRefNum(port_src);
00423 int ref2 = GetInputRefNum(port_dst);
00424
00425
00426 jack_log("JackConnectionManager::IncFeedbackConnection ref1 = %ld ref2 = %ld", ref1, ref2);
00427 assert(ref1 >= 0 && ref2 >= 0);
00428
00429 if (ref1 != ref2) {
00430 DirectConnect(ref2, ref1);
00431 }
00432
00433 return fLoopFeedback.IncConnection(ref1, ref2);
00434 }
00435
00436 bool JackConnectionManager::DecFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
00437 {
00438 int ref1 = GetOutputRefNum(port_src);
00439 int ref2 = GetInputRefNum(port_dst);
00440
00441
00442 jack_log("JackConnectionManager::DecFeedbackConnection ref1 = %ld ref2 = %ld", ref1, ref2);
00443 assert(ref1 >= 0 && ref2 >= 0);
00444
00445 if (ref1 != ref2) {
00446 DirectDisconnect(ref2, ref1);
00447 }
00448
00449 return fLoopFeedback.DecConnection(ref1, ref2);
00450 }
00451
00452 }
00453
00454