Jack2 1.9.7
|
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 template <int SIZE> 00040 class JackFixedArray 00041 { 00042 00043 private: 00044 00045 jack_int_t fTable[SIZE]; 00046 uint32_t fCounter; 00047 00048 public: 00049 00050 JackFixedArray() 00051 { 00052 Init(); 00053 } 00054 00055 void Init() 00056 { 00057 for (int i = 0; i < SIZE; i++) 00058 fTable[i] = EMPTY; 00059 fCounter = 0; 00060 } 00061 00062 bool AddItem(jack_int_t index) 00063 { 00064 for (int i = 0; i < SIZE; i++) { 00065 if (fTable[i] == EMPTY) { 00066 fTable[i] = index; 00067 fCounter++; 00068 return true; 00069 } 00070 } 00071 return false; 00072 } 00073 00074 bool RemoveItem(jack_int_t index) 00075 { 00076 for (int i = 0; i < SIZE; i++) { 00077 if (fTable[i] == index) { 00078 fCounter--; 00079 // Shift all indexes 00080 if (i == SIZE - 1) { 00081 fTable[i] = EMPTY; 00082 } else { 00083 int j; 00084 for (j = i; j <= SIZE - 2 && fTable[j] != EMPTY; j++) { 00085 fTable[j] = fTable[j + 1]; 00086 } 00087 fTable[j] = EMPTY; 00088 } 00089 return true; 00090 } 00091 } 00092 return false; 00093 } 00094 00095 jack_int_t GetItem(jack_int_t index) const 00096 { 00097 return (index < SIZE) ? fTable[index] : EMPTY; 00098 } 00099 00100 const jack_int_t* GetItems() const 00101 { 00102 return fTable; 00103 } 00104 00105 bool CheckItem(jack_int_t index) const 00106 { 00107 for (int i = 0; i < SIZE && fTable[i] != EMPTY; i++) { 00108 if (fTable[i] == index) 00109 return true; 00110 } 00111 return false; 00112 } 00113 00114 uint32_t GetItemCount() const 00115 { 00116 return fCounter; 00117 } 00118 00119 } POST_PACKED_STRUCTURE; 00120 00125 template <int SIZE> 00126 class JackFixedArray1 : public JackFixedArray<SIZE> 00127 { 00128 private: 00129 00130 bool fUsed; 00131 00132 public: 00133 00134 JackFixedArray1() 00135 { 00136 Init(); 00137 } 00138 00139 void Init() 00140 { 00141 JackFixedArray<SIZE>::Init(); 00142 fUsed = false; 00143 } 00144 00145 bool IsAvailable() 00146 { 00147 if (fUsed) { 00148 return false; 00149 } else { 00150 fUsed = true; 00151 return true; 00152 } 00153 } 00154 00155 } POST_PACKED_STRUCTURE; 00156 00161 template <int SIZE> 00162 class JackFixedMatrix 00163 { 00164 private: 00165 00166 jack_int_t fTable[SIZE][SIZE]; 00167 00168 public: 00169 00170 JackFixedMatrix() 00171 {} 00172 00173 void Init(jack_int_t index) 00174 { 00175 for (int i = 0; i < SIZE; i++) { 00176 fTable[index][i] = 0; 00177 fTable[i][index] = 0; 00178 } 00179 } 00180 00181 const jack_int_t* GetItems(jack_int_t index) const 00182 { 00183 return fTable[index]; 00184 } 00185 00186 jack_int_t IncItem(jack_int_t index1, jack_int_t index2) 00187 { 00188 fTable[index1][index2]++; 00189 return fTable[index1][index2]; 00190 } 00191 00192 jack_int_t DecItem(jack_int_t index1, jack_int_t index2) 00193 { 00194 fTable[index1][index2]--; 00195 return fTable[index1][index2]; 00196 } 00197 00198 jack_int_t GetItemCount(jack_int_t index1, jack_int_t index2) const 00199 { 00200 return fTable[index1][index2]; 00201 } 00202 00203 void ClearItem(jack_int_t index1, jack_int_t index2) 00204 { 00205 fTable[index1][index2] = 0; 00206 } 00207 00211 void GetOutputTable(jack_int_t index, jack_int_t* output) const 00212 { 00213 int i, j; 00214 00215 for (i = 0; i < SIZE; i++) 00216 output[i] = EMPTY; 00217 00218 for (i = 0, j = 0; i < SIZE; i++) { 00219 if (fTable[index][i] > 0) { 00220 output[j] = i; 00221 j++; 00222 } 00223 } 00224 } 00225 00226 void GetOutputTable1(jack_int_t index, jack_int_t* output) const 00227 { 00228 for (int i = 0; i < SIZE; i++) { 00229 output[i] = fTable[i][index]; 00230 } 00231 } 00232 00233 bool IsInsideTable(jack_int_t index, jack_int_t* output) const 00234 { 00235 for (int i = 0; i < SIZE && output[i] != EMPTY; i++) { 00236 if (output[i] == index) 00237 return true; 00238 } 00239 return false; 00240 } 00241 00242 void Copy(JackFixedMatrix& copy) 00243 { 00244 for (int i = 0; i < SIZE; i++) { 00245 memcpy(copy.fTable[i], fTable[i], sizeof(jack_int_t) * SIZE); 00246 } 00247 } 00248 00249 00250 } POST_PACKED_STRUCTURE; 00251 00256 template <int SIZE> 00257 class JackLoopFeedback 00258 { 00259 private: 00260 00261 int fTable[SIZE][3]; 00262 00266 bool AddConnectionAux(int ref1, int ref2) 00267 { 00268 for (int i = 0; i < SIZE; i++) { 00269 if (fTable[i][0] == EMPTY) { 00270 fTable[i][0] = ref1; 00271 fTable[i][1] = ref2; 00272 fTable[i][2] = 1; 00273 jack_log("JackLoopFeedback::AddConnectionAux ref1 = %ld ref2 = %ld", ref1, ref2); 00274 return true; 00275 } 00276 } 00277 jack_error("Feedback table is full !!\n"); 00278 return false; 00279 } 00280 00284 bool RemoveConnectionAux(int ref1, int ref2) 00285 { 00286 for (int i = 0; i < SIZE; i++) { 00287 if (fTable[i][0] == ref1 && fTable[i][1] == ref2) { 00288 fTable[i][0] = EMPTY; 00289 fTable[i][1] = EMPTY; 00290 fTable[i][2] = 0; 00291 jack_log("JackLoopFeedback::RemoveConnectionAux ref1 = %ld ref2 = %ld", ref1, ref2); 00292 return true; 00293 } 00294 } 00295 jack_error("Feedback connection not found\n"); 00296 return false; 00297 } 00298 00299 int IncConnection(int index) 00300 { 00301 fTable[index][2]++; 00302 return fTable[index][2]; 00303 } 00304 00305 int DecConnection(int index) 00306 { 00307 fTable[index][2]--; 00308 return fTable[index][2]; 00309 } 00310 00311 public: 00312 00313 JackLoopFeedback() 00314 { 00315 Init(); 00316 } 00317 00318 void Init() 00319 { 00320 for (int i = 0; i < SIZE; i++) { 00321 fTable[i][0] = EMPTY; 00322 fTable[i][1] = EMPTY; 00323 fTable[i][2] = 0; 00324 } 00325 } 00326 00327 bool IncConnection(int ref1, int ref2) 00328 { 00329 int index = GetConnectionIndex(ref1, ref2); 00330 00331 if (index >= 0) { // Feedback connection is already added, increment counter 00332 IncConnection(index); 00333 return true; 00334 } else { 00335 return AddConnectionAux(ref1, ref2); // Add the feedback connection 00336 } 00337 } 00338 00339 bool DecConnection(int ref1, int ref2) 00340 { 00341 int index = GetConnectionIndex(ref1, ref2); 00342 00343 if (index >= 0) { 00344 jack_log("JackLoopFeedback::DecConnection ref1 = %ld ref2 = %ld index = %ld", ref1, ref2, index); 00345 return (DecConnection(index) == 0) ? RemoveConnectionAux(ref1, ref2) : true; 00346 } else { 00347 return false; 00348 } 00349 } 00350 00354 int GetConnectionIndex(int ref1, int ref2) const 00355 { 00356 for (int i = 0; i < SIZE; i++) { 00357 if (fTable[i][0] == ref1 && fTable[i][1] == ref2) 00358 return i; 00359 } 00360 return -1; 00361 } 00362 00363 } POST_PACKED_STRUCTURE; 00364 00369 struct JackClientTiming 00370 { 00371 jack_time_t fSignaledAt; 00372 jack_time_t fAwakeAt; 00373 jack_time_t fFinishedAt; 00374 jack_client_state_t fStatus; 00375 00376 JackClientTiming() 00377 { 00378 Init(); 00379 } 00380 ~JackClientTiming() 00381 {} 00382 00383 void Init() 00384 { 00385 fSignaledAt = 0; 00386 fAwakeAt = 0; 00387 fFinishedAt = 0; 00388 fStatus = NotTriggered; 00389 } 00390 00391 } POST_PACKED_STRUCTURE; 00392 00405 class SERVER_EXPORT JackConnectionManager 00406 { 00407 00408 private: 00409 00410 JackFixedArray<CONNECTION_NUM_FOR_PORT> fConnection[PORT_NUM_MAX]; 00411 JackFixedArray1<PORT_NUM_FOR_CLIENT> fInputPort[CLIENT_NUM]; 00412 JackFixedArray<PORT_NUM_FOR_CLIENT> fOutputPort[CLIENT_NUM]; 00413 JackFixedMatrix<CLIENT_NUM> fConnectionRef; 00414 JackActivationCount fInputCounter[CLIENT_NUM]; 00415 JackLoopFeedback<CONNECTION_NUM_FOR_PORT> fLoopFeedback; 00417 bool IsLoopPathAux(int ref1, int ref2) const; 00418 00419 public: 00420 00421 JackConnectionManager(); 00422 ~JackConnectionManager(); 00423 00424 // Connections management 00425 int Connect(jack_port_id_t port_src, jack_port_id_t port_dst); 00426 int Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst); 00427 bool IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const; 00428 00432 jack_int_t Connections(jack_port_id_t port_index) const 00433 { 00434 return fConnection[port_index].GetItemCount(); 00435 } 00436 00437 jack_port_id_t GetPort(jack_port_id_t port_index, int connection) const 00438 { 00439 assert(connection < CONNECTION_NUM_FOR_PORT); 00440 return (jack_port_id_t)fConnection[port_index].GetItem(connection); 00441 } 00442 00443 const jack_int_t* GetConnections(jack_port_id_t port_index) const; 00444 00445 bool IncFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00446 bool DecFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00447 bool IsFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst) const; 00448 00449 bool IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const; 00450 void IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00451 void DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00452 00453 // Ports management 00454 int AddInputPort(int refnum, jack_port_id_t port_index); 00455 int AddOutputPort(int refnum, jack_port_id_t port_index); 00456 00457 int RemoveInputPort(int refnum, jack_port_id_t port_index); 00458 int RemoveOutputPort(int refnum, jack_port_id_t port_index); 00459 00460 const jack_int_t* GetInputPorts(int refnum); 00461 const jack_int_t* GetOutputPorts(int refnum); 00462 00463 // Client management 00464 void InitRefNum(int refnum); 00465 int GetInputRefNum(jack_port_id_t port_index) const; 00466 int GetOutputRefNum(jack_port_id_t port_index) const; 00467 00468 // Connect/Disconnect 2 refnum "directly" 00469 bool IsDirectConnection(int ref1, int ref2) const; 00470 void DirectConnect(int ref1, int ref2); 00471 void DirectDisconnect(int ref1, int ref2); 00472 00473 int GetActivation(int refnum) const 00474 { 00475 return fInputCounter[refnum].GetValue(); 00476 } 00477 00478 // Graph 00479 void ResetGraph(JackClientTiming* timing); 00480 int ResumeRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing); 00481 int SuspendRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing, long time_out_usec); 00482 void TopologicalSort(std::vector<jack_int_t>& sorted); 00483 00484 } POST_PACKED_STRUCTURE; 00485 00486 } // end of namespace 00487 00488 #endif 00489