Jack2  1.9.10
JackConnectionManager.h
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