Fix build under mixed mode
[jack2.git] / common / JackConnectionManager.h
blobead32092a1d3f897984c6b78aabc674a7fad9810
1 /*
2 Copyright (C) 2004-2008 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #ifndef __JackConnectionManager__
21 #define __JackConnectionManager__
23 #include "JackConstants.h"
24 #include "JackActivationCount.h"
25 #include "JackError.h"
26 #include "JackCompilerDeps.h"
27 #include <vector>
28 #include <assert.h>
30 namespace Jack
33 struct JackClientControl;
35 /*!
36 \brief Utility class.
39 PRE_PACKED_STRUCTURE
40 template <int SIZE>
41 class JackFixedArray
44 private:
46 jack_int_t fTable[SIZE];
47 uint32_t fCounter;
49 public:
51 JackFixedArray()
53 Init();
56 void Init()
58 for (int i = 0; i < SIZE; i++)
59 fTable[i] = EMPTY;
60 fCounter = 0;
63 bool AddItem(jack_int_t index)
65 for (int i = 0; i < SIZE; i++) {
66 if (fTable[i] == EMPTY) {
67 fTable[i] = index;
68 fCounter++;
69 return true;
72 return false;
75 bool RemoveItem(jack_int_t index)
77 for (int i = 0; i < SIZE; i++) {
78 if (fTable[i] == index) {
79 fCounter--;
80 // Shift all indexes
81 if (i == SIZE - 1) {
82 fTable[i] = EMPTY;
83 } else {
84 int j;
85 for (j = i; j <= SIZE - 2 && fTable[j] != EMPTY; j++) {
86 fTable[j] = fTable[j + 1];
88 fTable[j] = EMPTY;
90 return true;
93 return false;
96 jack_int_t GetItem(jack_int_t index) const
98 return (index < SIZE) ? fTable[index] : EMPTY;
101 const jack_int_t* GetItems() const
103 return fTable;
106 bool CheckItem(jack_int_t index) const
108 for (int i = 0; i < SIZE && fTable[i] != EMPTY; i++) {
109 if (fTable[i] == index)
110 return true;
112 return false;
115 uint32_t GetItemCount() const
117 return fCounter;
120 } POST_PACKED_STRUCTURE;
123 \brief Utility class.
126 PRE_PACKED_STRUCTURE
127 template <int SIZE>
128 class JackFixedArray1 : public JackFixedArray<SIZE>
130 private:
132 bool fUsed;
134 public:
136 JackFixedArray1()
138 Init();
141 void Init()
143 JackFixedArray<SIZE>::Init();
144 fUsed = false;
147 bool IsAvailable()
149 if (fUsed) {
150 return false;
151 } else {
152 fUsed = true;
153 return true;
157 } POST_PACKED_STRUCTURE;
160 \brief Utility class.
163 PRE_PACKED_STRUCTURE
164 template <int SIZE>
165 class JackFixedMatrix
167 private:
169 jack_int_t fTable[SIZE][SIZE];
171 public:
173 JackFixedMatrix()
176 void Init(jack_int_t index)
178 for (int i = 0; i < SIZE; i++) {
179 fTable[index][i] = 0;
180 fTable[i][index] = 0;
184 const jack_int_t* GetItems(jack_int_t index) const
186 return fTable[index];
189 jack_int_t IncItem(jack_int_t index1, jack_int_t index2)
191 fTable[index1][index2]++;
192 return fTable[index1][index2];
195 jack_int_t DecItem(jack_int_t index1, jack_int_t index2)
197 fTable[index1][index2]--;
198 return fTable[index1][index2];
201 jack_int_t GetItemCount(jack_int_t index1, jack_int_t index2) const
203 return fTable[index1][index2];
206 void ClearItem(jack_int_t index1, jack_int_t index2)
208 fTable[index1][index2] = 0;
212 \brief Get the output indexes of a given index.
214 void GetOutputTable(jack_int_t index, jack_int_t* output) const
216 int i, j;
218 for (i = 0; i < SIZE; i++)
219 output[i] = EMPTY;
221 for (i = 0, j = 0; i < SIZE; i++) {
222 if (fTable[index][i] > 0) {
223 output[j] = i;
224 j++;
229 void GetOutputTable1(jack_int_t index, jack_int_t* output) const
231 for (int i = 0; i < SIZE; i++) {
232 output[i] = fTable[i][index];
236 bool IsInsideTable(jack_int_t index, jack_int_t* output) const
238 for (int i = 0; i < SIZE && output[i] != EMPTY; i++) {
239 if (output[i] == index)
240 return true;
242 return false;
245 void Copy(JackFixedMatrix& copy)
247 for (int i = 0; i < SIZE; i++) {
248 memcpy(copy.fTable[i], fTable[i], sizeof(jack_int_t) * SIZE);
253 } POST_PACKED_STRUCTURE;
256 \brief Utility class.
259 PRE_PACKED_STRUCTURE
260 template <int SIZE>
261 class JackLoopFeedback
263 private:
265 int fTable[SIZE][3];
268 \brief Add a feedback connection between 2 refnum.
270 bool AddConnectionAux(int ref1, int ref2)
272 for (int i = 0; i < SIZE; i++) {
273 if (fTable[i][0] == EMPTY) {
274 fTable[i][0] = ref1;
275 fTable[i][1] = ref2;
276 fTable[i][2] = 1;
277 jack_log("JackLoopFeedback::AddConnectionAux ref1 = %ld ref2 = %ld", ref1, ref2);
278 return true;
281 jack_error("Feedback table is full !!\n");
282 return false;
286 \brief Remove a feedback connection between 2 refnum.
288 bool RemoveConnectionAux(int ref1, int ref2)
290 for (int i = 0; i < SIZE; i++) {
291 if (fTable[i][0] == ref1 && fTable[i][1] == ref2) {
292 fTable[i][0] = EMPTY;
293 fTable[i][1] = EMPTY;
294 fTable[i][2] = 0;
295 jack_log("JackLoopFeedback::RemoveConnectionAux ref1 = %ld ref2 = %ld", ref1, ref2);
296 return true;
299 jack_error("Feedback connection not found\n");
300 return false;
303 int IncConnection(int index)
305 fTable[index][2]++;
306 return fTable[index][2];
309 int DecConnection(int index)
311 fTable[index][2]--;
312 return fTable[index][2];
315 public:
317 JackLoopFeedback()
319 Init();
322 void Init()
324 for (int i = 0; i < SIZE; i++) {
325 fTable[i][0] = EMPTY;
326 fTable[i][1] = EMPTY;
327 fTable[i][2] = 0;
331 bool IncConnection(int ref1, int ref2)
333 int index = GetConnectionIndex(ref1, ref2);
335 if (index >= 0) { // Feedback connection is already added, increment counter
336 IncConnection(index);
337 return true;
338 } else {
339 return AddConnectionAux(ref1, ref2); // Add the feedback connection
343 bool DecConnection(int ref1, int ref2)
345 int index = GetConnectionIndex(ref1, ref2);
347 if (index >= 0) {
348 jack_log("JackLoopFeedback::DecConnection ref1 = %ld ref2 = %ld index = %ld", ref1, ref2, index);
349 return (DecConnection(index) == 0) ? RemoveConnectionAux(ref1, ref2) : true;
350 } else {
351 return false;
356 \brief Test if a connection between 2 refnum is a feedback connection.
358 int GetConnectionIndex(int ref1, int ref2) const
360 for (int i = 0; i < SIZE; i++) {
361 if (fTable[i][0] == ref1 && fTable[i][1] == ref2)
362 return i;
364 return -1;
367 } POST_PACKED_STRUCTURE;
370 \brief For client timing measurements.
373 PRE_PACKED_STRUCTURE
374 struct JackClientTiming
376 jack_time_t fSignaledAt;
377 jack_time_t fAwakeAt;
378 jack_time_t fFinishedAt;
379 jack_client_state_t fStatus;
381 JackClientTiming()
383 Init();
385 ~JackClientTiming()
388 void Init()
390 fSignaledAt = 0;
391 fAwakeAt = 0;
392 fFinishedAt = 0;
393 fStatus = NotTriggered;
396 } POST_PACKED_STRUCTURE;
399 \brief Connection manager.
401 <UL>
402 <LI>The <B>fConnection</B> array contains the list (array line) of connected ports for a given port.
403 <LI>The <B>fInputPort</B> array contains the list (array line) of input connected ports for a given client.
404 <LI>The <B>fOutputPort</B> array contains the list (array line) of output connected ports for a given client.
405 <LI>The <B>fConnectionRef</B> array contains the number of ports connected between two clients.
406 <LI>The <B>fInputCounter</B> array contains the number of input clients connected to a given for activation purpose.
407 </UL>
410 PRE_PACKED_STRUCTURE
411 class SERVER_EXPORT JackConnectionManager
414 private:
416 JackFixedArray<CONNECTION_NUM_FOR_PORT> fConnection[PORT_NUM_MAX]; /*! Connection matrix: list of connected ports for a given port: needed to compute Mix buffer */
417 JackFixedArray1<PORT_NUM_FOR_CLIENT> fInputPort[CLIENT_NUM]; /*! Table of input port per refnum : to find a refnum for a given port */
418 JackFixedArray<PORT_NUM_FOR_CLIENT> fOutputPort[CLIENT_NUM]; /*! Table of output port per refnum : to find a refnum for a given port */
419 JackFixedMatrix<CLIENT_NUM> fConnectionRef; /*! Table of port connections by (refnum , refnum) */
420 JackActivationCount fInputCounter[CLIENT_NUM]; /*! Activation counter per refnum */
421 JackLoopFeedback<CONNECTION_NUM_FOR_PORT> fLoopFeedback; /*! Loop feedback connections */
423 bool IsLoopPathAux(int ref1, int ref2) const;
425 public:
427 JackConnectionManager();
428 ~JackConnectionManager();
430 // Connections management
431 int Connect(jack_port_id_t port_src, jack_port_id_t port_dst);
432 int Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst);
433 bool IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const;
436 \brief Get the connection number of a given port.
438 jack_int_t Connections(jack_port_id_t port_index) const
440 return fConnection[port_index].GetItemCount();
443 jack_port_id_t GetPort(jack_port_id_t port_index, int connection) const
445 assert(connection < CONNECTION_NUM_FOR_PORT);
446 return (jack_port_id_t)fConnection[port_index].GetItem(connection);
449 const jack_int_t* GetConnections(jack_port_id_t port_index) const;
451 bool IncFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
452 bool DecFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
453 bool IsFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst) const;
455 bool IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const;
456 void IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
457 void DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
459 // Ports management
460 int AddInputPort(int refnum, jack_port_id_t port_index);
461 int AddOutputPort(int refnum, jack_port_id_t port_index);
463 int RemoveInputPort(int refnum, jack_port_id_t port_index);
464 int RemoveOutputPort(int refnum, jack_port_id_t port_index);
466 const jack_int_t* GetInputPorts(int refnum);
467 const jack_int_t* GetOutputPorts(int refnum);
469 // Client management
470 void InitRefNum(int refnum);
471 int GetInputRefNum(jack_port_id_t port_index) const;
472 int GetOutputRefNum(jack_port_id_t port_index) const;
474 // Connect/Disconnect 2 refnum "directly"
475 bool IsDirectConnection(int ref1, int ref2) const;
476 void DirectConnect(int ref1, int ref2);
477 void DirectDisconnect(int ref1, int ref2);
479 int GetActivation(int refnum) const
481 return fInputCounter[refnum].GetValue();
484 // Graph
485 void ResetGraph(JackClientTiming* timing);
486 int ResumeRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing);
487 int SuspendRefNum(JackClientControl* control, JackSynchro* table, JackClientTiming* timing, long time_out_usec);
488 void TopologicalSort(std::vector<jack_int_t>& sorted);
490 } POST_PACKED_STRUCTURE;
492 } // end of namespace
494 #endif