Jack2 1.9.6
|
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 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 00206 void GetOutputTable(jack_int_t index, jack_int_t* output) const 00207 { 00208 int i, j; 00209 00210 for (i = 0; i < SIZE; i++) 00211 output[i] = EMPTY; 00212 00213 for (i = 0, j = 0; i < SIZE; i++) { 00214 if (fTable[index][i] > 0) { 00215 output[j] = i; 00216 j++; 00217 } 00218 } 00219 } 00220 00221 bool IsInsideTable(jack_int_t index, jack_int_t* output) const 00222 { 00223 for (int i = 0; i < SIZE && output[i] != EMPTY; i++) { 00224 if (output[i] == index) 00225 return true; 00226 } 00227 return false; 00228 } 00229 00230 } POST_PACKED_STRUCTURE; 00231 00236 template <int SIZE> 00237 class JackLoopFeedback 00238 { 00239 private: 00240 00241 int fTable[SIZE][3]; 00242 00246 bool AddConnectionAux(int ref1, int ref2) 00247 { 00248 for (int i = 0; i < SIZE; i++) { 00249 if (fTable[i][0] == EMPTY) { 00250 fTable[i][0] = ref1; 00251 fTable[i][1] = ref2; 00252 fTable[i][2] = 1; 00253 jack_log("JackLoopFeedback::AddConnectionAux ref1 = %ld ref2 = %ld", ref1, ref2); 00254 return true; 00255 } 00256 } 00257 jack_error("Feedback table is full !!\n"); 00258 return false; 00259 } 00260 00264 bool RemoveConnectionAux(int ref1, int ref2) 00265 { 00266 for (int i = 0; i < SIZE; i++) { 00267 if (fTable[i][0] == ref1 && fTable[i][1] == ref2) { 00268 fTable[i][0] = EMPTY; 00269 fTable[i][1] = EMPTY; 00270 fTable[i][2] = 0; 00271 jack_log("JackLoopFeedback::RemoveConnectionAux ref1 = %ld ref2 = %ld", ref1, ref2); 00272 return true; 00273 } 00274 } 00275 jack_error("Feedback connection not found\n"); 00276 return false; 00277 } 00278 00279 int IncConnection(int index) 00280 { 00281 fTable[index][2]++; 00282 return fTable[index][2]; 00283 } 00284 00285 int DecConnection(int index) 00286 { 00287 fTable[index][2]--; 00288 return fTable[index][2]; 00289 } 00290 00291 public: 00292 00293 JackLoopFeedback() 00294 { 00295 Init(); 00296 } 00297 00298 void Init() 00299 { 00300 for (int i = 0; i < SIZE; i++) { 00301 fTable[i][0] = EMPTY; 00302 fTable[i][1] = EMPTY; 00303 fTable[i][2] = 0; 00304 } 00305 } 00306 00307 bool IncConnection(int ref1, int ref2) 00308 { 00309 int index = GetConnectionIndex(ref1, ref2); 00310 00311 if (index >= 0) { // Feedback connection is already added, increment counter 00312 IncConnection(index); 00313 return true; 00314 } else { 00315 return AddConnectionAux(ref1, ref2); // Add the feedback connection 00316 } 00317 } 00318 00319 bool DecConnection(int ref1, int ref2) 00320 { 00321 int index = GetConnectionIndex(ref1, ref2); 00322 00323 if (index >= 0) { 00324 jack_log("JackLoopFeedback::DecConnection ref1 = %ld ref2 = %ld index = %ld", ref1, ref2, index); 00325 return (DecConnection(index) == 0) ? RemoveConnectionAux(ref1, ref2) : true; 00326 } else { 00327 return false; 00328 } 00329 } 00330 00334 int GetConnectionIndex(int ref1, int ref2) const 00335 { 00336 for (int i = 0; i < SIZE; i++) { 00337 if (fTable[i][0] == ref1 && fTable[i][1] == ref2) 00338 return i; 00339 } 00340 return -1; 00341 } 00342 00343 } POST_PACKED_STRUCTURE; 00344 00349 struct JackClientTiming 00350 { 00351 jack_time_t fSignaledAt; 00352 jack_time_t fAwakeAt; 00353 jack_time_t fFinishedAt; 00354 jack_client_state_t fStatus; 00355 00356 JackClientTiming() 00357 { 00358 Init(); 00359 } 00360 ~JackClientTiming() 00361 {} 00362 00363 void Init() 00364 { 00365 fSignaledAt = 0; 00366 fAwakeAt = 0; 00367 fFinishedAt = 0; 00368 fStatus = NotTriggered; 00369 } 00370 00371 } POST_PACKED_STRUCTURE; 00372 00387 class SERVER_EXPORT JackConnectionManager 00388 { 00389 00390 private: 00391 00392 JackFixedArray<CONNECTION_NUM_FOR_PORT> fConnection[PORT_NUM_MAX]; 00393 JackFixedArray1<PORT_NUM_FOR_CLIENT> fInputPort[CLIENT_NUM]; 00394 JackFixedArray<PORT_NUM_FOR_CLIENT> fOutputPort[CLIENT_NUM]; 00395 JackFixedMatrix<CLIENT_NUM> fConnectionRef; 00396 JackActivationCount fInputCounter[CLIENT_NUM]; 00397 JackLoopFeedback<CONNECTION_NUM_FOR_PORT> fLoopFeedback; 00399 bool IsLoopPathAux(int ref1, int ref2) const; 00400 00401 public: 00402 00403 JackConnectionManager(); 00404 ~JackConnectionManager(); 00405 00406 // Connections management 00407 int Connect(jack_port_id_t port_src, jack_port_id_t port_dst); 00408 int Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst); 00409 bool IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const; 00410 00414 jack_int_t Connections(jack_port_id_t port_index) const 00415 { 00416 return fConnection[port_index].GetItemCount(); 00417 } 00418 00419 jack_port_id_t GetPort(jack_port_id_t port_index, int connection) const 00420 { 00421 assert(connection < CONNECTION_NUM_FOR_PORT); 00422 return (jack_port_id_t)fConnection[port_index].GetItem(connection); 00423 } 00424 00425 const jack_int_t* GetConnections(jack_port_id_t port_index) const; 00426 00427 bool IncFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00428 bool DecFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00429 bool IsFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst) const; 00430 00431 bool IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const; 00432 void IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00433 void DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst); 00434 00435 // Ports management 00436 int AddInputPort(int refnum, jack_port_id_t port_index); 00437 int AddOutputPort(int refnum, jack_port_id_t port_index); 00438 00439 int RemoveInputPort(int refnum, jack_port_id_t port_index); 00440 int RemoveOutputPort(int refnum, jack_port_id_t port_index); 00441 00442 const jack_int_t* GetInputPorts(int refnum); 00443 const jack_int_t* GetOutputPorts(int refnum); 00444 00445 // Client management 00446 void InitRefNum(int refnum); 00447 int GetInputRefNum(jack_port_id_t port_index) const; 00448 int GetOutputRefNum(jack_port_id_t port_index) const; 00449 00450 // Connect/Disconnect 2 refnum "directly" 00451 bool IsDirectConnection(int ref1, int ref2) const; 00452 void DirectConnect(int ref1, int ref2); 00453 void DirectDisconnect(int ref1, int ref2); 00454 00455 int GetActivation(int refnum) const 00456 { 00457 return fInputCounter[refnum].GetValue(); 00458 } 00459 00460 // Graph 00461 void ResetGraph(JackClientTiming* timing); 00462 int ResumeRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing); 00463 int SuspendRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing, long time_out_usec); 00464 00465 } POST_PACKED_STRUCTURE; 00466 00467 } // end of namespace 00468 00469 #endif 00470