Version 0.61. Move client allocation in JackEngine
[jack2.git] / common / JackConnectionManager.h
blob74f46281c51d44c559ee77b43990bf9468f203cd
1 /*
2 Copyright (C) 2004-2006 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 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 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifndef __JackConnectionManager__
21 #define __JackConnectionManager__
23 #include "JackConstants.h"
24 #include "JackActivationCount.h"
25 #include <assert.h>
27 namespace Jack
30 #define NO_PORT 0xFFFE
32 #define EMPTY 0xFFFD
33 #define FREE 0xFFFC
35 typedef uint16_t jack_int_t; // Internal type for ports and refnum
37 struct JackClientControl;
39 typedef enum {
40 NotTriggered,
41 Triggered,
42 Running,
43 Finished,
44 } jack_client_state_t;
46 /*!
47 \brief Utility class.
50 template <int SIZE>
51 class JackFixedArray
54 private:
56 jack_int_t fTable[SIZE];
57 uint32_t fCounter;
59 public:
61 JackFixedArray()
63 Init();
66 virtual ~JackFixedArray()
69 void Init()
71 for (int i = 0; i < SIZE; i++)
72 fTable[i] = EMPTY;
73 fCounter = 0;
76 bool AddItem(jack_int_t index)
78 for (int i = 0; i < SIZE; i++) {
79 if (fTable[i] == EMPTY) {
80 fTable[i] = index;
81 fCounter++;
82 return true;
85 return false;
88 bool RemoveItem(jack_int_t index)
90 for (int i = 0; i < SIZE; i++) {
91 if (fTable[i] == index) {
92 fCounter--;
93 // Shift all indexes
94 if (i == SIZE - 1) {
95 fTable[i] = EMPTY;
96 } else {
97 int j;
98 for (j = i; j <= SIZE - 2 && fTable[j] != EMPTY; j++) {
99 fTable[j] = fTable[j + 1];
101 fTable[j] = EMPTY;
103 return true;
106 return false;
109 jack_int_t GetItem(jack_int_t index) const
111 return (index < SIZE) ? fTable[index] : EMPTY;
114 const jack_int_t* GetItems() const
116 return fTable;
119 bool CheckItem(jack_int_t index) const
121 for (int i = 0; i < SIZE && fTable[i] != EMPTY; i++) {
122 if (fTable[i] == index)
123 return true;
125 return false;
128 uint32_t GetItemCount() const
130 return fCounter;
136 \brief Utility class.
139 template <int SIZE>
140 class JackFixedArray1 : public JackFixedArray<SIZE>
142 private:
144 bool fUsed;
146 public:
148 JackFixedArray1()
150 Init();
153 virtual ~JackFixedArray1()
156 void Init()
158 JackFixedArray<SIZE>::Init();
159 fUsed = false;
162 bool IsAvailable()
164 if (fUsed) {
165 return false;
166 } else {
167 fUsed = true;
168 return true;
174 \brief Utility class.
177 template <int SIZE>
178 class JackFixedMatrix
180 private:
182 jack_int_t fTable[SIZE][SIZE];
184 public:
186 JackFixedMatrix()
189 virtual ~JackFixedMatrix()
192 void Init(jack_int_t index)
194 for (int i = 0; i < SIZE; i++) {
195 fTable[index][i] = 0;
196 fTable[i][index] = 0;
200 const jack_int_t* GetItems(jack_int_t index) const
202 return fTable[index];
205 jack_int_t IncItem(jack_int_t index1, jack_int_t index2)
207 fTable[index1][index2]++;
208 return fTable[index1][index2];
211 jack_int_t DecItem(jack_int_t index1, jack_int_t index2)
213 fTable[index1][index2]--;
214 return fTable[index1][index2];
217 jack_int_t GetItemCount(jack_int_t index1, jack_int_t index2) const
219 return fTable[index1][index2];
223 \brief Get the output indexes of a given index.
225 void GetOutputTable(jack_int_t index, jack_int_t* output) const
227 int i, j;
229 for (i = 0; i < SIZE; i++)
230 output[i] = EMPTY;
232 for (i = 0, j = 0; i < SIZE; i++) {
233 if (fTable[index][i] > 0) {
234 output[j] = i;
235 j++;
240 bool IsInsideTable(jack_int_t index, jack_int_t* output) const
242 for (int i = 0; i < SIZE && output[i] != EMPTY; i++) {
243 if (output[i] == index)
244 return true;
246 return false;
252 \brief Utility class.
255 template <int SIZE>
256 class JackLoopFeedback
258 private:
260 int fTable[SIZE][3];
263 \brief Add a feedback connection between 2 refnum.
265 bool AddConnectionAux(int ref1, int ref2)
267 for (int i = 0; i < SIZE; i++) {
268 if (fTable[i][0] == EMPTY) {
269 fTable[i][0] = ref1;
270 fTable[i][1] = ref2;
271 fTable[i][2] = 1;
272 JackLog("JackLoopFeedback::AddConnectionAux ref1 = %ld ref2 = %ld\n", ref1, ref2);
273 return true;
276 jack_error("Feedback table is full !!\n");
277 return false;
281 \brief Remove a feedback connection between 2 refnum.
283 bool RemoveConnectionAux(int ref1, int ref2)
285 for (int i = 0; i < SIZE; i++) {
286 if (fTable[i][0] == ref1 && fTable[i][1] == ref2) {
287 fTable[i][0] = EMPTY;
288 fTable[i][1] = EMPTY;
289 fTable[i][2] = 0;
290 JackLog("JackLoopFeedback::RemoveConnectionAux ref1 = %ld ref2 = %ld\n", ref1, ref2);
291 return true;
294 jack_error("Feedback connection not found\n");
295 return false;
298 int IncConnection(int index)
300 fTable[index][2]++;
301 return fTable[index][2];
304 int DecConnection(int index)
306 fTable[index][2]--;
307 return fTable[index][2];
310 public:
312 JackLoopFeedback()
314 Init();
316 virtual ~JackLoopFeedback()
319 void Init()
321 for (int i = 0; i < SIZE; i++) {
322 fTable[i][0] = EMPTY;
323 fTable[i][1] = EMPTY;
324 fTable[i][2] = 0;
328 bool IncConnection(int ref1, int ref2)
330 int index = GetConnectionIndex(ref1, ref2);
332 if (index >= 0) { // Feedback connection is already added, increment counter
333 IncConnection(index);
334 return true;
335 } else {
336 return AddConnectionAux(ref1, ref2); // Add the feedback connection
340 bool DecConnection(int ref1, int ref2)
342 int index = GetConnectionIndex(ref1, ref2);
344 if (index >= 0) {
345 JackLog("JackLoopFeedback::DecConnection ref1 = %ld ref2 = %ld index = %ld\n", ref1, ref2, index);
346 return (DecConnection(index) == 0) ? RemoveConnectionAux(ref1, ref2) : true;
347 } else {
348 return false;
353 \brief Test if a connection between 2 refnum is a feedback connection.
355 int GetConnectionIndex(int ref1, int ref2) const
357 for (int i = 0; i < SIZE; i++) {
358 if (fTable[i][0] == ref1 && fTable[i][1] == ref2)
359 return i;
361 return -1;
367 \brief For client timing measurements.
370 struct JackClientTiming
372 jack_time_t fSignaledAt;
373 jack_time_t fAwakeAt;
374 jack_time_t fFinishedAt;
375 jack_client_state_t fStatus;
377 JackClientTiming():fSignaledAt(0), fAwakeAt(0), fFinishedAt(0), fStatus(NotTriggered)
379 ~JackClientTiming()
384 \brief Connection manager.
386 <UL>
387 <LI>The <B>fConnection</B> array contains the list (array line) of connected ports for a given port.
388 <LI>The <B>fConnectionCount</B> array contains the number of connected ports to a given port.
389 <LI>The <B>fInputPort</B> array contains the list (array line) of input connected ports for a given client.
390 <LI>The <B>fOutputPort</B> array contains the list (array line) of ouput connected ports for a given client.
391 <LI>The <B>fConnectionRef</B> array contains the number of ports connected between two clients.
392 <LI>The <B>fInputRef</B> array contains the number of input clients connected to a given client.
393 <LI>The <B>fInputCounter</B> array contains the number of input clients connected to a given for activation purpose.
394 </UL>
397 class JackConnectionManager
400 private:
402 JackFixedArray<CONNECTION_NUM> fConnection[PORT_NUM]; /*! Connection matrix: list of connected ports for a given port: needed to compute Mix buffer */
403 JackFixedArray1<PORT_NUM_FOR_CLIENT> fInputPort[CLIENT_NUM]; /*! Table of input port per refnum : to find a refnum for a given port */
404 JackFixedArray<PORT_NUM_FOR_CLIENT> fOutputPort[CLIENT_NUM]; /*! Table of output port per refnum : to find a refnum for a given port */
405 JackFixedMatrix<CLIENT_NUM> fConnectionRef; /*! Table of port connections by (refnum , refnum) */
406 JackActivationCount fInputCounter[CLIENT_NUM]; /*! Activation counter per refnum */
407 JackLoopFeedback<CONNECTION_NUM> fLoopFeedback; /*! Loop feedback connections */
409 bool IsLoopPathAux(int ref1, int ref2) const;
410 //void InitClient(int refnum);
412 public:
414 JackConnectionManager();
415 virtual ~JackConnectionManager();
417 // Connections management
418 int Connect(jack_port_id_t port_src, jack_port_id_t port_dst);
419 int Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst);
420 bool IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const;
422 jack_int_t Connections(jack_port_id_t port_index) const;
423 jack_port_id_t GetPort(jack_port_id_t port_index, int connection) const;
424 const jack_int_t* GetConnections(jack_port_id_t port_index) const;
426 bool IncFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
427 bool DecFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
428 bool IsFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst) const;
430 bool IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const;
431 void IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
432 void DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
434 // Ports management
435 int AddInputPort(int refnum, jack_port_id_t port_index);
436 int AddOutputPort(int refnum, jack_port_id_t port_index);
438 int RemoveInputPort(int refnum, jack_port_id_t port_index);
439 int RemoveOutputPort(int refnum, jack_port_id_t port_index);
441 const jack_int_t* GetInputPorts(int refnum);
442 const jack_int_t* GetOutputPorts(int refnum);
444 // Client management
445 //int AllocateRefNum();
446 //void ReleaseRefNum(int refnum);
447 void InitRefNum(int refnum);
449 int GetInputRefNum(jack_port_id_t port_index) const;
450 int GetOutputRefNum(jack_port_id_t port_index) const;
452 // Connect/Disconnect 2 refnum "directly"
453 bool IsDirectConnection(int ref1, int ref2) const;
454 void DirectConnect(int ref1, int ref2);
455 void DirectDisconnect(int ref1, int ref2);
457 int GetActivation(int refnum) const;
459 // Graph
460 void ResetGraph(JackClientTiming* timing);
461 int ResumeRefNum(JackClientControl* control, JackSynchro** table, JackClientTiming* timing);
462 int SuspendRefNum(JackClientControl* control, JackSynchro** table, JackClientTiming* timing, long time_out_usec);
466 } // end of namespace
468 #endif