Jack2
1.9.10
|
00001 /* 00002 Copyright (C) 2004-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 */ 00019 00020 #ifndef __JackConnectionManager__ 00021 #define __JackConnectionManager__ 00022 00023 #include "JackConstants.h" 00024 #include "JackActivationCount.h" 00025 #include "JackError.h" 00026 #include "JackCompilerDeps.h" 00027 #include <vector> 00028 #include <assert.h> 00029 00030 namespace Jack 00031 { 00032 00033 struct JackClientControl; 00034 00039 PRE_PACKED_STRUCTURE 00040 template <int SIZE> 00041 class JackFixedArray 00042 { 00043 00044 private: 00045 00046 jack_int_t fTable[SIZE]; 00047 uint32_t fCounter; 00048 00049 public: 00050 00051 JackFixedArray() 00052 { 00053 Init(); 00054 } 00055 00056 void Init() 00057 { 00058 for (int i = 0; i < SIZE; i++) 00059 fTable[i] = EMPTY; 00060 fCounter = 0; 00061 } 00062 00063 bool AddItem(jack_int_t index) 00064 { 00065 for (int i = 0; i < SIZE; i++) { 00066 if (fTable[i] == EMPTY) { 00067 fTable[i] = index; 00068 fCounter++; 00069 return true; 00070 } 00071 } 00072 return false; 00073 } 00074 00075 bool RemoveItem(jack_int_t index) 00076 { 00077 for (int i = 0; i < SIZE; i++) { 00078 if (fTable[i] == index) { 00079 fCounter--; 00080 // Shift all indexes 00081 if (i == SIZE - 1) { 00082 fTable[i] = EMPTY; 00083 } else { 00084 int j; 00085 for (j = i; j <= SIZE - 2 && fTable[j] != EMPTY; j++) { 00086 fTable[j] = fTable[j + 1]; 00087 } 00088 fTable[j] = EMPTY; 00089 } 00090 return true; 00091 } 00092 } 00093 return false; 00094 } 00095 00096 jack_int_t GetItem(jack_int_t index) const 00097 { 00098 return (index < SIZE) ? fTable[index] : EMPTY; 00099 } 00100 00101 const jack_int_t* GetItems() const 00102 { 00103 return fTable; 00104 } 00105 00106 bool CheckItem(jack_int_t index) const 00107 { 00108 for (int i = 0; i < SIZE && fTable[i] != EMPTY; i++) { 00109 if (fTable[i] == index) 00110 return true; 00111 } 00112 return false; 00113 } 00114 00115 uint32_t GetItemCount() const 00116 { 00117 return fCounter; 00118 } 00119 00120 } POST_PACKED_STRUCTURE; 00121 00126 PRE_PACKED_STRUCTURE 00127 template <int SIZE> 00128 class JackFixedArray1 : public JackFixedArray<SIZE> 00129 { 00130 private: 00131 00132 bool fUsed; 00133 00134 public: 00135 00136 JackFixedArray1() 00137 { 00138 Init(); 00139 } 00140 00141 void Init() 00142 { 00143 JackFixedArray<SIZE>::Init(); 00144 fUsed = false; 00145 } 00146 00147 bool IsAvailable() 00148 { 00149 if (fUsed) { 00150 return false; 00151 } else { 00152 fUsed = true; 00153 return true; 00154 } 00155 } 00156 00157 } POST_PACKED_STRUCTURE; 00158 00163 PRE_PACKED_STRUCTURE 00164 template <int SIZE> 00165 class JackFixedMatrix 00166 { 00167 private: 00168 00169 jack_int_t fTable[SIZE][SIZE]; 00170 00171 public: 00172 00173 JackFixedMatrix() 00174 {} 00175 00176 void Init(jack_int_t index) 00177 { 00178 for (int i = 0; i < SIZE; i++) { 00179 fTable[index][i] = 0; 00180 fTable[i][index] = 0; 00181 } 00182 } 00183 00184 const jack_int_t* GetItems(jack_int_t index) const 00185 { 00186 return fTable[index]; 00187 } 00188 00189 jack_int_t IncItem(jack_int_t index1, jack_int_t index2) 00190 { 00191 fTable[index1][index2]++; 00192 return fTable[index1][index2]; 00193 } 00194 00195 jack_int_t DecItem(jack_int_t index1, jack_int_t index2) 00196 { 00197 fTable[index1][index2]--; 00198 return fTable[index1][index2]; 00199 } 00200 00201 jack_int_t GetItemCount(jack_int_t index1, jack_int_t index2) const 00202 { 00203 return fTable[index1][index2]; 00204 } 00205 00206 void ClearItem(jack_int_t index1, jack_int_t index2) 00207 { 00208 fTable[index1][index2] = 0; 00209 } 00210 00214 void GetOutputTable(jack_int_t index, jack_int_t* output) const 00215 { 00216 int i, j; 00217 00218 for (i = 0; i < SIZE; i++) 00219 output[i] = EMPTY; 00220 00221 for (i = 0, j = 0; i < SIZE; i++) { 00222 if (fTable[index][i] > 0) { 00223 output[j] = i; 00224 j++; 00225 } 00226 } 00227 } 00228 00229 void GetOutputTable1(jack_int_t index, jack_int_t* output) const 00230 { 00231 for (int i = 0; i < SIZE; i++) { 00232 output[i] = fTable[i][index]; 00233 } 00234 } 00235 00236 bool IsInsideTable(jack_int_t index, jack_int_t* output) const 00237 { 00238 for (int i = 0; i < SIZE && output[i] != EMPTY; i++) { 00239 if (output[i] == index) 00240 return true; 00241 } 00242 return false; 00243 } 00244 00245 void Copy(JackFixedMatrix& copy) 00246 { 00247 for (int i = 0; i < SIZE; i++) { 00248 memcpy(copy.fTable[i], fTable[i], sizeof(jack_int_t) * SIZE); 00249 } 00250 } 00251 00252 00253 } POST_PACKED_STRUCTURE; 00254 00259 PRE_PACKED_STRUCTURE 00260 template <int SIZE> 00261 class JackLoopFeedback 00262 { 00263 private: 00264 00265 int fTable[SIZE][3]; 00266 00270 bool AddConnectionAux(int ref1, int ref2) 00271 { 00272 for (int i = 0; i < SIZE; i++) { 00273 if (fTable[i][0] == EMPTY) { 00274 fTable[i][0] = ref1; 00275 fTable[i][1] = ref2; 00276 fTable[i][2] = 1; 00277 jack_log("JackLoopFeedback::AddConnectionAux ref1 = %ld ref2 = %ld", ref1, ref2); 00278 return true; 00279 } 00280 } 00281 jack_error("Feedback table is full !!\n"); 00282 return false; 00283 } 00284 00288 bool RemoveConnectionAux(int ref1, int ref2) 00289 { 00290 for (int i = 0; i < SIZE; i++) { 00291 if (fTable[i][0] == ref1 && fTable[i][1] == ref2) { 00292 fTable[i][0] = EMPTY; 00293 fTable[i][1] = EMPTY; 00294 fTable[i][2] = 0; 00295 jack_log("JackLoopFeedback::RemoveConnectionAux ref1 = %ld ref2 = %ld", ref1, ref2); 00296 return true; 00297 } 00298 } 00299 jack_error("Feedback connection not found\n"); 00300 return false; 00301 } 00302 00303 int IncConnection(int index) 00304 { 00305 fTable[index][2]++; 00306 return fTable[index][2]; 00307 } 00308 00309 int DecConnection(int index) 00310 { 00311 fTable[index][2]--; 00312 return fTable[index][2]; 00313 } 00314 00315 public: 00316 00317 JackLoopFeedback() 00318 { 00319 Init(); 00320 } 00321 00322 void Init() 00323 { 00324 for (int i = 0; i < SIZE; i++) { 00325 fTable[i][0] = EMPTY; 00326 fTable[i][1] = EMPTY; 00327 fTable[i][2] = 0; 00328 } 00329 } 00330 00331 bool IncConnection(int ref1, int ref2) 00332 { 00333 int index = GetConnectionIndex(ref1, ref2); 00334 00335 if (index >= 0) { // Feedback connection is already added, increment counter 00336 IncConnection(index); 00337 return true; 00338 } else { 00339 return AddConnectionAux(ref1, ref2); // Add the feedback connection 00340 } 00341 } 00342 00343 bool DecConnection(int ref1, int ref2) 00344 { 00345 int index = GetConnectionIndex(ref1, ref2); 00346 00347 if (index >= 0) { 00348 jack_log("JackLoopFeedback::DecConnection ref1 = %ld ref2 = %ld index = %ld", ref1, ref2, index); 00349 return (DecConnection(index) == 0) ? RemoveConnectionAux(ref1, ref2) : true; 00350 } else { 00351 return false; 00352 } 00353 } 00354 00358 int GetConnectionIndex(int ref1, int ref2) const 00359 { 00360 for (int i = 0; i < SIZE; i++) { 00361 if (fTable[i][0] == ref1 && fTable[i][1] == ref2) 00362 return i; 00363 } 00364 return -1; 00365 } 00366 00367 } POST_PACKED_STRUCTURE; 00368 00373 PRE_PACKED_STRUCTURE 00374 struct JackClientTiming 00375 { 00376 jack_time_t fSignaledAt; 00377 jack_time_t fAwakeAt; 00378 jack_time_t fFinishedAt; 00379 jack_client_state_t fStatus; 00380 00381 JackClientTiming() 00382 { 00383 Init(); 00384 } 00385 ~JackClientTiming() 00386 {} 00387 00388 void Init() 00389 { 00390 fSignaledAt = 0; 00391 fAwakeAt = 0; 00392 fFinishedAt = 0; 00393 fStatus = NotTriggered; 00394 } 00395 00396 } POST_PACKED_STRUCTURE; 00397 00410 PRE_PACKED_STRUCTURE 00411 class SERVER_EXPORT JackConnectionManager 00412 { 00413 00414 private: 00415 00416 JackFixedArray<CONNECTION_NUM_FOR_PORT> fConnection[PORT_NUM_MAX]; 00417 JackFixedArray1<PORT_NUM_FOR_CLIENT> fInputPort[CLIENT_NUM]; 00418 JackFixedArray<PORT_NUM_FOR_CLIENT> fOutputPort[CLIENT_NUM]; 00419 JackFixedMatrix<CLIENT_NUM> fConnectionRef; 00420 JackActivationCount fInputCounter[CLIENT_NUM]; 00421 JackLoopFeedback<CONNECTION_NUM_FOR_PORT> fLoopFeedback; 00423 bool IsLoopPathAux(int ref1, int ref2) const; 00424 00425 public: 00426 00427 JackConnectionManager(); 00428 ~JackConnectionManager(); 00429 00430 // Connections management 00431 int Connect(jack_port_id_t port_src, jack_port_id_t port_dst); 00432 int Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst); 00433 bool IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const; 00434 00438 jack_int_t Connections(jack_port_id_t port_index) const 00439 { 00440 return fConnection[port_index].GetItemCount(); 00441 } 00442 00443 jack_port_id_t GetPort(jack_port_id_t port_index, int connection) const 00444 { 00445 assert(connection < CONNECTION_NUM_FOR_PORT); 00446 return (jack_port_id_t)fConnection[port_index].GetItem(connection); 00447 } 00448 00449 const jack_int_t* GetConnections(jack_port_id_t port_index) const; 00450 00451 bool IncFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00452 bool DecFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00453 bool IsFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst) const; 00454 00455 bool IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const; 00456 void IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00457 void DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00458 00459 // Ports management 00460 int AddInputPort(int refnum, jack_port_id_t port_index); 00461 int AddOutputPort(int refnum, jack_port_id_t port_index); 00462 00463 int RemoveInputPort(int refnum, jack_port_id_t port_index); 00464 int RemoveOutputPort(int refnum, jack_port_id_t port_index); 00465 00466 const jack_int_t* GetInputPorts(int refnum); 00467 const jack_int_t* GetOutputPorts(int refnum); 00468 00469 // Client management 00470 void InitRefNum(int refnum); 00471 int GetInputRefNum(jack_port_id_t port_index) const; 00472 int GetOutputRefNum(jack_port_id_t port_index) const; 00473 00474 // Connect/Disconnect 2 refnum "directly" 00475 bool IsDirectConnection(int ref1, int ref2) const; 00476 void DirectConnect(int ref1, int ref2); 00477 void DirectDisconnect(int ref1, int ref2); 00478 00479 int GetActivation(int refnum) const 00480 { 00481 return fInputCounter[refnum].GetValue(); 00482 } 00483 00484 // Graph 00485 void ResetGraph(JackClientTiming* timing); 00486 int ResumeRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing); 00487 int SuspendRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing, long time_out_usec); 00488 void TopologicalSort(std::vector<jack_int_t>& sorted); 00489 00490 } POST_PACKED_STRUCTURE; 00491 00492 } // end of namespace 00493 00494 #endif 00495