Jack2 1.9.12

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>
41 class JackFixedArray
42 {
43
44 private:
45
46 jack_int_t fTable[SIZE];
47 uint32_t fCounter;
48
49 public:
50
51 JackFixedArray()
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
136 JackFixedArray1()
137 {
138 Init();
139 }
140
141 void Init()
142 {
143 JackFixedArray<SIZE>::Init();
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>
165 class JackFixedMatrix
166 {
167 private:
168
169 jack_int_t fTable[SIZE][SIZE];
170
171 public:
172
173 JackFixedMatrix()
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>
261 class JackLoopFeedback
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
317 JackLoopFeedback()
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
374 struct JackClientTiming
375 {
376 jack_time_t fSignaledAt;
377 jack_time_t fAwakeAt;
378 jack_time_t fFinishedAt;
379 jack_client_state_t fStatus;
380
381 JackClientTiming()
382 {
383 Init();
384 }
385 ~JackClientTiming()
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];
421 JackLoopFeedback<CONNECTION_NUM_FOR_PORT> fLoopFeedback;
423 bool IsLoopPathAux(int ref1, int ref2) const;
424
425 public:
426
427 JackConnectionManager();
428 ~JackConnectionManager();
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
Jack::JackConnectionManager
Connection manager.
Definition: JackConnectionManager.h:411
Jack::JackFixedArray1
Utility class.
Definition: JackConnectionManager.h:128
Jack::JackLoopFeedback::GetConnectionIndex
int GetConnectionIndex(int ref1, int ref2) const
Test if a connection between 2 refnum is a feedback connection.
Definition: JackConnectionManager.h:358
Jack::JackActivationCount
Client activation counter.
Definition: JackActivationCount.h:37
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
Jack::JackFixedMatrix
Utility class.
Definition: JackConnectionManager.h:165
Jack::JackFixedMatrix::GetOutputTable
void GetOutputTable(jack_int_t index, jack_int_t *output) const
Get the output indexes of a given index.
Definition: JackConnectionManager.h:214
Jack::JackConnectionManager::Connections
jack_int_t Connections(jack_port_id_t port_index) const
Get the connection number of a given port.
Definition: JackConnectionManager.h:438
Jack::JackFixedArray
Utility class.
Definition: JackConnectionManager.h:41
Jack::JackClientTiming
For client timing measurements.
Definition: JackConnectionManager.h:374
Jack::JackLoopFeedback
Utility class.
Definition: JackConnectionManager.h:261
jack_log
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108