summaryrefslogtreecommitdiff
path: root/common/JackConnectionManager.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/JackConnectionManager.h')
-rw-r--r--common/JackConnectionManager.h468
1 files changed, 468 insertions, 0 deletions
diff --git a/common/JackConnectionManager.h b/common/JackConnectionManager.h
new file mode 100644
index 00000000..652cefc5
--- /dev/null
+++ b/common/JackConnectionManager.h
@@ -0,0 +1,468 @@
+/*
+Copyright (C) 2004-2006 Grame
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __JackConnectionManager__
+#define __JackConnectionManager__
+
+#include "JackConstants.h"
+#include "JackActivationCount.h"
+#include <assert.h>
+
+namespace Jack
+{
+
+#define NO_PORT 0xFFFE
+
+#define EMPTY 0xFFFD
+#define FREE 0xFFFC
+
+typedef uint16_t jack_int_t; // Internal type for ports and refnum
+
+struct JackClientControl;
+
+typedef enum {
+ NotTriggered,
+ Triggered,
+ Running,
+ Finished,
+} jack_client_state_t;
+
+/*!
+\brief Utility class.
+*/
+
+template <int SIZE>
+class JackFixedArray
+{
+
+ private:
+
+ jack_int_t fTable[SIZE];
+ uint32_t fCounter;
+
+ public:
+
+ JackFixedArray()
+ {
+ Init();
+ }
+
+ virtual ~JackFixedArray()
+ {}
+
+ void Init()
+ {
+ for (int i = 0; i < SIZE; i++)
+ fTable[i] = EMPTY;
+ fCounter = 0;
+ }
+
+ bool AddItem(jack_int_t index)
+ {
+ for (int i = 0; i < SIZE; i++) {
+ if (fTable[i] == EMPTY) {
+ fTable[i] = index;
+ fCounter++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool RemoveItem(jack_int_t index)
+ {
+ for (int i = 0; i < SIZE; i++) {
+ if (fTable[i] == index) {
+ fCounter--;
+ // Shift all indexes
+ if (i == SIZE - 1) {
+ fTable[i] = EMPTY;
+ } else {
+ int j;
+ for (j = i; j <= SIZE - 2 && fTable[j] != EMPTY; j++) {
+ fTable[j] = fTable[j + 1];
+ }
+ fTable[j] = EMPTY;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ jack_int_t GetItem(jack_int_t index) const
+ {
+ return (index < SIZE) ? fTable[index] : EMPTY;
+ }
+
+ const jack_int_t* GetItems() const
+ {
+ return fTable;
+ }
+
+ bool CheckItem(jack_int_t index) const
+ {
+ for (int i = 0; i < SIZE && fTable[i] != EMPTY; i++) {
+ if (fTable[i] == index)
+ return true;
+ }
+ return false;
+ }
+
+ uint32_t GetItemCount() const
+ {
+ return fCounter;
+ }
+
+};
+
+/*!
+\brief Utility class.
+*/
+
+template <int SIZE>
+class JackFixedArray1 : public JackFixedArray<SIZE>
+{
+ private:
+
+ bool fUsed;
+
+ public:
+
+ JackFixedArray1()
+ {
+ Init();
+ }
+
+ virtual ~JackFixedArray1()
+ {}
+
+ void Init()
+ {
+ JackFixedArray<SIZE>::Init();
+ fUsed = false;
+ }
+
+ bool IsAvailable()
+ {
+ if (fUsed) {
+ return false;
+ } else {
+ fUsed = true;
+ return true;
+ }
+ }
+};
+
+/*!
+\brief Utility class.
+*/
+
+template <int SIZE>
+class JackFixedMatrix
+{
+ private:
+
+ jack_int_t fTable[SIZE][SIZE];
+
+ public:
+
+ JackFixedMatrix()
+ {}
+
+ virtual ~JackFixedMatrix()
+ {}
+
+ void Init(jack_int_t index)
+ {
+ for (int i = 0; i < SIZE; i++) {
+ fTable[index][i] = 0;
+ fTable[i][index] = 0;
+ }
+ }
+
+ const jack_int_t* GetItems(jack_int_t index) const
+ {
+ return fTable[index];
+ }
+
+ jack_int_t IncItem(jack_int_t index1, jack_int_t index2)
+ {
+ fTable[index1][index2]++;
+ return fTable[index1][index2];
+ }
+
+ jack_int_t DecItem(jack_int_t index1, jack_int_t index2)
+ {
+ fTable[index1][index2]--;
+ return fTable[index1][index2];
+ }
+
+ jack_int_t GetItemCount(jack_int_t index1, jack_int_t index2) const
+ {
+ return fTable[index1][index2];
+ }
+
+ /*!
+ \brief Get the output indexes of a given index.
+ */
+ void GetOutputTable(jack_int_t index, jack_int_t* output) const
+ {
+ int i, j;
+
+ for (i = 0; i < SIZE; i++)
+ output[i] = EMPTY;
+
+ for (i = 0, j = 0; i < SIZE; i++) {
+ if (fTable[index][i] > 0) {
+ output[j] = i;
+ j++;
+ }
+ }
+ }
+
+ bool IsInsideTable(jack_int_t index, jack_int_t* output) const
+ {
+ for (int i = 0; i < SIZE && output[i] != EMPTY; i++) {
+ if (output[i] == index)
+ return true;
+ }
+ return false;
+ }
+
+};
+
+/*!
+\brief Utility class.
+*/
+
+template <int SIZE>
+class JackLoopFeedback
+{
+ private:
+
+ int fTable[SIZE][3];
+
+ /*!
+ \brief Add a feedback connection between 2 refnum.
+ */
+ bool AddConnectionAux(int ref1, int ref2)
+ {
+ for (int i = 0; i < SIZE; i++) {
+ if (fTable[i][0] == EMPTY) {
+ fTable[i][0] = ref1;
+ fTable[i][1] = ref2;
+ fTable[i][2] = 1;
+ JackLog("JackLoopFeedback::AddConnectionAux ref1 = %ld ref2 = %ld\n", ref1, ref2);
+ return true;
+ }
+ }
+ jack_error("Feedback table is full !!\n");
+ return false;
+ }
+
+ /*!
+ \brief Remove a feedback connection between 2 refnum.
+ */
+ bool RemoveConnectionAux(int ref1, int ref2)
+ {
+ for (int i = 0; i < SIZE; i++) {
+ if (fTable[i][0] == ref1 && fTable[i][1] == ref2) {
+ fTable[i][0] = EMPTY;
+ fTable[i][1] = EMPTY;
+ fTable[i][2] = 0;
+ JackLog("JackLoopFeedback::RemoveConnectionAux ref1 = %ld ref2 = %ld\n", ref1, ref2);
+ return true;
+ }
+ }
+ jack_error("Feedback connection not found\n");
+ return false;
+ }
+
+ int IncConnection(int index)
+ {
+ fTable[index][2]++;
+ return fTable[index][2];
+ }
+
+ int DecConnection(int index)
+ {
+ fTable[index][2]--;
+ return fTable[index][2];
+ }
+
+ public:
+
+ JackLoopFeedback()
+ {
+ Init();
+ }
+ virtual ~JackLoopFeedback()
+ {}
+
+ void Init()
+ {
+ for (int i = 0; i < SIZE; i++) {
+ fTable[i][0] = EMPTY;
+ fTable[i][1] = EMPTY;
+ fTable[i][2] = 0;
+ }
+ }
+
+ bool IncConnection(int ref1, int ref2)
+ {
+ int index = GetConnectionIndex(ref1, ref2);
+
+ if (index >= 0) { // Feedback connection is already added, increment counter
+ IncConnection(index);
+ return true;
+ } else {
+ return AddConnectionAux(ref1, ref2); // Add the feedback connection
+ }
+ }
+
+ bool DecConnection(int ref1, int ref2)
+ {
+ int index = GetConnectionIndex(ref1, ref2);
+
+ if (index >= 0) {
+ JackLog("JackLoopFeedback::DecConnection ref1 = %ld ref2 = %ld index = %ld\n", ref1, ref2, index);
+ return (DecConnection(index) == 0) ? RemoveConnectionAux(ref1, ref2) : true;
+ } else {
+ return false;
+ }
+ }
+
+ /*!
+ \brief Test if a connection between 2 refnum is a feedback connection.
+ */
+ int GetConnectionIndex(int ref1, int ref2) const
+ {
+ for (int i = 0; i < SIZE; i++) {
+ if (fTable[i][0] == ref1 && fTable[i][1] == ref2)
+ return i;
+ }
+ return -1;
+ }
+
+};
+
+/*!
+\brief For client timing measurements.
+*/
+
+struct JackClientTiming
+{
+ jack_time_t fSignaledAt;
+ jack_time_t fAwakeAt;
+ jack_time_t fFinishedAt;
+ jack_client_state_t fStatus;
+
+ JackClientTiming():fSignaledAt(0), fAwakeAt(0), fFinishedAt(0), fStatus(NotTriggered)
+ {}
+ ~JackClientTiming()
+ {}
+};
+
+/*!
+\brief Connection manager.
+
+<UL>
+<LI>The <B>fConnection</B> array contains the list (array line) of connected ports for a given port.
+<LI>The <B>fConnectionCount</B> array contains the number of connected ports to a given port.
+<LI>The <B>fInputPort</B> array contains the list (array line) of input connected ports for a given client.
+<LI>The <B>fOutputPort</B> array contains the list (array line) of ouput connected ports for a given client.
+<LI>The <B>fConnectionRef</B> array contains the number of ports connected between two clients.
+<LI>The <B>fInputRef</B> array contains the number of input clients connected to a given client.
+<LI>The <B>fInputCounter</B> array contains the number of input clients connected to a given for activation purpose.
+</UL>
+*/
+
+class JackConnectionManager
+{
+
+ private:
+
+ JackFixedArray<CONNECTION_NUM> fConnection[PORT_NUM]; /*! Connection matrix: list of connected ports for a given port: needed to compute Mix buffer */
+ JackFixedArray1<PORT_NUM_FOR_CLIENT> fInputPort[CLIENT_NUM]; /*! Table of input port per refnum : to find a refnum for a given port */
+ JackFixedArray<PORT_NUM_FOR_CLIENT> fOutputPort[CLIENT_NUM]; /*! Table of output port per refnum : to find a refnum for a given port */
+ JackFixedMatrix<CLIENT_NUM> fConnectionRef; /*! Table of port connections by (refnum , refnum) */
+ JackActivationCount fInputCounter[CLIENT_NUM]; /*! Activation counter per refnum */
+ JackLoopFeedback<CONNECTION_NUM> fLoopFeedback; /*! Loop feedback connections */
+
+ bool IsLoopPathAux(int ref1, int ref2) const;
+ void InitClient(int refnum);
+
+ public:
+
+ JackConnectionManager();
+ virtual ~JackConnectionManager();
+
+ // Connections management
+ int Connect(jack_port_id_t port_src, jack_port_id_t port_dst);
+ int Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst);
+ bool IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const;
+
+ jack_int_t Connections(jack_port_id_t port_index) const;
+ jack_port_id_t GetPort(jack_port_id_t port_index, int connection) const;
+ const jack_int_t* GetConnections(jack_port_id_t port_index) const;
+
+ bool IncFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
+ bool DecFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
+ bool IsFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst) const;
+
+ bool IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const;
+ void IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
+ void DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst);
+
+ // Ports management
+ int AddInputPort(int refnum, jack_port_id_t port_index);
+ int AddOutputPort(int refnum, jack_port_id_t port_index);
+
+ int RemoveInputPort(int refnum, jack_port_id_t port_index);
+ int RemoveOutputPort(int refnum, jack_port_id_t port_index);
+
+ const jack_int_t* GetInputPorts(int refnum);
+ const jack_int_t* GetOutputPorts(int refnum);
+
+ // Client management
+ int AllocateRefNum();
+ void ReleaseRefNum(int refnum);
+
+ int GetInputRefNum(jack_port_id_t port_index) const;
+ int GetOutputRefNum(jack_port_id_t port_index) const;
+
+ // Connect/Disconnect 2 refnum "directly"
+ bool IsDirectConnection(int ref1, int ref2) const;
+ void DirectConnect(int ref1, int ref2);
+ void DirectDisconnect(int ref1, int ref2);
+
+ int GetActivation(int refnum) const;
+
+ // Graph
+ void ResetGraph(JackClientTiming* timing);
+ int ResumeRefNum(JackClientControl* control, JackSynchro** table, JackClientTiming* timing);
+ int SuspendRefNum(JackClientControl* control, JackSynchro** table, JackClientTiming* timing, long time_out_usec);
+
+};
+
+} // end of namespace
+
+#endif
+