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"
33 struct JackClientControl
;
46 jack_int_t fTable
[SIZE
];
58 for (int i
= 0; i
< SIZE
; i
++)
63 bool AddItem(jack_int_t index
)
65 for (int i
= 0; i
< SIZE
; i
++) {
66 if (fTable
[i
] == EMPTY
) {
75 bool RemoveItem(jack_int_t index
)
77 for (int i
= 0; i
< SIZE
; i
++) {
78 if (fTable
[i
] == index
) {
85 for (j
= i
; j
<= SIZE
- 2 && fTable
[j
] != EMPTY
; j
++) {
86 fTable
[j
] = fTable
[j
+ 1];
96 jack_int_t
GetItem(jack_int_t index
) const
98 return (index
< SIZE
) ? fTable
[index
] : EMPTY
;
101 const jack_int_t
* GetItems() const
106 bool CheckItem(jack_int_t index
) const
108 for (int i
= 0; i
< SIZE
&& fTable
[i
] != EMPTY
; i
++) {
109 if (fTable
[i
] == index
)
115 uint32_t GetItemCount() const
120 } POST_PACKED_STRUCTURE
;
123 \brief Utility class.
128 class JackFixedArray1
: public JackFixedArray
<SIZE
>
143 JackFixedArray
<SIZE
>::Init();
157 } POST_PACKED_STRUCTURE
;
160 \brief Utility class.
165 class JackFixedMatrix
169 jack_int_t fTable
[SIZE
][SIZE
];
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
218 for (i
= 0; i
< SIZE
; i
++)
221 for (i
= 0, j
= 0; i
< SIZE
; i
++) {
222 if (fTable
[index
][i
] > 0) {
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
)
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.
261 class JackLoopFeedback
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
) {
277 jack_log("JackLoopFeedback::AddConnectionAux ref1 = %ld ref2 = %ld", ref1
, ref2
);
281 jack_error("Feedback table is full !!\n");
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
;
295 jack_log("JackLoopFeedback::RemoveConnectionAux ref1 = %ld ref2 = %ld", ref1
, ref2
);
299 jack_error("Feedback connection not found\n");
303 int IncConnection(int index
)
306 return fTable
[index
][2];
309 int DecConnection(int index
)
312 return fTable
[index
][2];
324 for (int i
= 0; i
< SIZE
; i
++) {
325 fTable
[i
][0] = EMPTY
;
326 fTable
[i
][1] = EMPTY
;
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
);
339 return AddConnectionAux(ref1
, ref2
); // Add the feedback connection
343 bool DecConnection(int ref1
, int ref2
)
345 int index
= GetConnectionIndex(ref1
, ref2
);
348 jack_log("JackLoopFeedback::DecConnection ref1 = %ld ref2 = %ld index = %ld", ref1
, ref2
, index
);
349 return (DecConnection(index
) == 0) ? RemoveConnectionAux(ref1
, ref2
) : true;
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
)
367 } POST_PACKED_STRUCTURE
;
370 \brief For client timing measurements.
374 struct JackClientTiming
376 jack_time_t fSignaledAt
;
377 jack_time_t fAwakeAt
;
378 jack_time_t fFinishedAt
;
379 jack_client_state_t fStatus
;
393 fStatus
= NotTriggered
;
396 } POST_PACKED_STRUCTURE
;
399 \brief Connection manager.
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.
411 class SERVER_EXPORT JackConnectionManager
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;
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
);
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
);
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();
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