Jack2 1.9.6

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 
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