Jack2  1.9.9
JackConnectionManager.h
1 /*
2 Copyright (C) 2004-2008 Grame
3 
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.
8 
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.
13 
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.
17 
18 */
19 
20 #ifndef __JackConnectionManager__
21 #define __JackConnectionManager__
22 
23 #include "JackConstants.h"
24 #include "JackActivationCount.h"
25 #include "JackError.h"
26 #include "JackCompilerDeps.h"
27 #include <vector>
28 #include <assert.h>
29 
30 namespace Jack
31 {
32 
33 struct JackClientControl;
34 
39 PRE_PACKED_STRUCTURE
40 template <int SIZE>
42 {
43 
44  private:
45 
46  jack_int_t fTable[SIZE];
47  uint32_t fCounter;
48 
49  public:
50 
52  {
53  Init();
54  }
55 
56  void Init()
57  {
58  for (int i = 0; i < SIZE; i++)
59  fTable[i] = EMPTY;
60  fCounter = 0;
61  }
62 
63  bool AddItem(jack_int_t index)
64  {
65  for (int i = 0; i < SIZE; i++) {
66  if (fTable[i] == EMPTY) {
67  fTable[i] = index;
68  fCounter++;
69  return true;
70  }
71  }
72  return false;
73  }
74 
75  bool RemoveItem(jack_int_t index)
76  {
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];
87  }
88  fTable[j] = EMPTY;
89  }
90  return true;
91  }
92  }
93  return false;
94  }
95 
96  jack_int_t GetItem(jack_int_t index) const
97  {
98  return (index < SIZE) ? fTable[index] : EMPTY;
99  }
100 
101  const jack_int_t* GetItems() const
102  {
103  return fTable;
104  }
105 
106  bool CheckItem(jack_int_t index) const
107  {
108  for (int i = 0; i < SIZE && fTable[i] != EMPTY; i++) {
109  if (fTable[i] == index)
110  return true;
111  }
112  return false;
113  }
114 
115  uint32_t GetItemCount() const
116  {
117  return fCounter;
118  }
119 
120 } POST_PACKED_STRUCTURE;
121 
126 PRE_PACKED_STRUCTURE
127 template <int SIZE>
128 class JackFixedArray1 : public JackFixedArray<SIZE>
129 {
130  private:
131 
132  bool fUsed;
133 
134  public:
135 
137  {
138  Init();
139  }
140 
141  void Init()
142  {
144  fUsed = false;
145  }
146 
147  bool IsAvailable()
148  {
149  if (fUsed) {
150  return false;
151  } else {
152  fUsed = true;
153  return true;
154  }
155  }
156 
157 } POST_PACKED_STRUCTURE;
158 
163 PRE_PACKED_STRUCTURE
164 template <int SIZE>
166 {
167  private:
168 
169  jack_int_t fTable[SIZE][SIZE];
170 
171  public:
172 
174  {}
175 
176  void Init(jack_int_t index)
177  {
178  for (int i = 0; i < SIZE; i++) {
179  fTable[index][i] = 0;
180  fTable[i][index] = 0;
181  }
182  }
183 
184  const jack_int_t* GetItems(jack_int_t index) const
185  {
186  return fTable[index];
187  }
188 
189  jack_int_t IncItem(jack_int_t index1, jack_int_t index2)
190  {
191  fTable[index1][index2]++;
192  return fTable[index1][index2];
193  }
194 
195  jack_int_t DecItem(jack_int_t index1, jack_int_t index2)
196  {
197  fTable[index1][index2]--;
198  return fTable[index1][index2];
199  }
200 
201  jack_int_t GetItemCount(jack_int_t index1, jack_int_t index2) const
202  {
203  return fTable[index1][index2];
204  }
205 
206  void ClearItem(jack_int_t index1, jack_int_t index2)
207  {
208  fTable[index1][index2] = 0;
209  }
210 
214  void GetOutputTable(jack_int_t index, jack_int_t* output) const
215  {
216  int i, j;
217 
218  for (i = 0; i < SIZE; i++)
219  output[i] = EMPTY;
220 
221  for (i = 0, j = 0; i < SIZE; i++) {
222  if (fTable[index][i] > 0) {
223  output[j] = i;
224  j++;
225  }
226  }
227  }
228 
229  void GetOutputTable1(jack_int_t index, jack_int_t* output) const
230  {
231  for (int i = 0; i < SIZE; i++) {
232  output[i] = fTable[i][index];
233  }
234  }
235 
236  bool IsInsideTable(jack_int_t index, jack_int_t* output) const
237  {
238  for (int i = 0; i < SIZE && output[i] != EMPTY; i++) {
239  if (output[i] == index)
240  return true;
241  }
242  return false;
243  }
244 
245  void Copy(JackFixedMatrix& copy)
246  {
247  for (int i = 0; i < SIZE; i++) {
248  memcpy(copy.fTable[i], fTable[i], sizeof(jack_int_t) * SIZE);
249  }
250  }
251 
252 
253 } POST_PACKED_STRUCTURE;
254 
259 PRE_PACKED_STRUCTURE
260 template <int SIZE>
262 {
263  private:
264 
265  int fTable[SIZE][3];
266 
270  bool AddConnectionAux(int ref1, int ref2)
271  {
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;
279  }
280  }
281  jack_error("Feedback table is full !!\n");
282  return false;
283  }
284 
288  bool RemoveConnectionAux(int ref1, int ref2)
289  {
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;
297  }
298  }
299  jack_error("Feedback connection not found\n");
300  return false;
301  }
302 
303  int IncConnection(int index)
304  {
305  fTable[index][2]++;
306  return fTable[index][2];
307  }
308 
309  int DecConnection(int index)
310  {
311  fTable[index][2]--;
312  return fTable[index][2];
313  }
314 
315  public:
316 
318  {
319  Init();
320  }
321 
322  void Init()
323  {
324  for (int i = 0; i < SIZE; i++) {
325  fTable[i][0] = EMPTY;
326  fTable[i][1] = EMPTY;
327  fTable[i][2] = 0;
328  }
329  }
330 
331  bool IncConnection(int ref1, int ref2)
332  {
333  int index = GetConnectionIndex(ref1, ref2);
334 
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
340  }
341  }
342 
343  bool DecConnection(int ref1, int ref2)
344  {
345  int index = GetConnectionIndex(ref1, ref2);
346 
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;
352  }
353  }
354 
358  int GetConnectionIndex(int ref1, int ref2) const
359  {
360  for (int i = 0; i < SIZE; i++) {
361  if (fTable[i][0] == ref1 && fTable[i][1] == ref2)
362  return i;
363  }
364  return -1;
365  }
366 
367 } POST_PACKED_STRUCTURE;
368 
373 PRE_PACKED_STRUCTURE
375 {
376  jack_time_t fSignaledAt;
377  jack_time_t fAwakeAt;
378  jack_time_t fFinishedAt;
379  jack_client_state_t fStatus;
380 
382  {
383  Init();
384  }
386  {}
387 
388  void Init()
389  {
390  fSignaledAt = 0;
391  fAwakeAt = 0;
392  fFinishedAt = 0;
393  fStatus = NotTriggered;
394  }
395 
396 } POST_PACKED_STRUCTURE;
397 
410 PRE_PACKED_STRUCTURE
411 class SERVER_EXPORT JackConnectionManager
412 {
413 
414  private:
415 
416  JackFixedArray<CONNECTION_NUM_FOR_PORT> fConnection[PORT_NUM_MAX];
417  JackFixedArray1<PORT_NUM_FOR_CLIENT> fInputPort[CLIENT_NUM];
418  JackFixedArray<PORT_NUM_FOR_CLIENT> fOutputPort[CLIENT_NUM];
419  JackFixedMatrix<CLIENT_NUM> fConnectionRef;
420  JackActivationCount fInputCounter[CLIENT_NUM];
423  bool IsLoopPathAux(int ref1, int ref2) const;
424 
425  public:
426 
429 
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;
434 
438  jack_int_t Connections(jack_port_id_t port_index) const
439  {
440  return fConnection[port_index].GetItemCount();
441  }
442 
443  jack_port_id_t GetPort(jack_port_id_t port_index, int connection) const
444  {
445  assert(connection < CONNECTION_NUM_FOR_PORT);
446  return (jack_port_id_t)fConnection[port_index].GetItem(connection);
447  }
448 
449  const jack_int_t* GetConnections(jack_port_id_t port_index) const;
450 
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;
454 
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);
458 
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);
462 
463  int RemoveInputPort(int refnum, jack_port_id_t port_index);
464  int RemoveOutputPort(int refnum, jack_port_id_t port_index);
465 
466  const jack_int_t* GetInputPorts(int refnum);
467  const jack_int_t* GetOutputPorts(int refnum);
468 
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;
473 
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);
478 
479  int GetActivation(int refnum) const
480  {
481  return fInputCounter[refnum].GetValue();
482  }
483 
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);
489 
490 } POST_PACKED_STRUCTURE;
491 
492 } // end of namespace
493 
494 #endif
495 
Client activation counter.
int GetConnectionIndex(int ref1, int ref2) const
Test if a connection between 2 refnum is a feedback connection.
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:91
void GetOutputTable(jack_int_t index, jack_int_t *output) const
Get the output indexes of a given index.
For client timing measurements.
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:107
jack_int_t Connections(jack_port_id_t port_index) const
Get the connection number of a given port.