| 
							- /*
 - Copyright (C) 2004-2008 Grame
 - 
 - This program is free software; you can redistribute it and/or modify
 - it under the terms of the GNU Lesser General Public License as published by
 - the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
 - 
 - You should have received a copy of the GNU Lesser General Public License
 - along with this program; if not, write to the Free Software 
 - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 - 
 - */
 - 
 - #include <iostream>
 - #include <assert.h>
 - #include "JackConnectionManager.h"
 - #include "JackClientControl.h"
 - #include "JackError.h"
 - 
 - namespace Jack
 - {
 - 
 - JackConnectionManager::JackConnectionManager()
 - {
 -     int i;
 -     jack_log("JackConnectionManager::InitConnections size = %ld ", sizeof(JackConnectionManager));
 - 
 -     for (i = 0; i < PORT_NUM; i++) {
 -         fConnection[i].Init();
 -     }
 - 
 -     fLoopFeedback.Init();
 - 
 -     jack_log("JackConnectionManager::InitClients");
 -     for (i = 0; i < CLIENT_NUM; i++) {
 -         InitRefNum(i);
 -     }
 - }
 - 
 - JackConnectionManager::~JackConnectionManager()
 - {}
 - 
 - //--------------
 - // Internal API
 - //--------------
 - 
 - bool JackConnectionManager::IsLoopPathAux(int ref1, int ref2) const
 - {
 -     jack_log("JackConnectionManager::IsLoopPathAux ref1 = %ld ref2 = %ld", ref1, ref2);
 - 
 -     if (ref1 == AUDIO_DRIVER_REFNUM // Driver is reached
 -             || ref2 == AUDIO_DRIVER_REFNUM
 -             || ref1 == FREEWHEEL_DRIVER_REFNUM
 -             || ref2 == FREEWHEEL_DRIVER_REFNUM
 -             || ref1 == LOOPBACK_DRIVER_REFNUM
 -             || ref2 == LOOPBACK_DRIVER_REFNUM) {
 -         return false;
 -     } else if (ref1 == ref2) {	// Same refnum
 -         return true;
 -     } else {
 -         jack_int_t output[CLIENT_NUM];
 -         fConnectionRef.GetOutputTable(ref1, output);
 - 
 -         if (fConnectionRef.IsInsideTable(ref2, output)) { // If ref2 is contained in the outputs of ref1
 -             return true;
 -         } else {
 -             for (int i = 0; i < CLIENT_NUM && output[i] != EMPTY; i++) { // Otherwise recurse for all ref1 outputs
 -                 if (IsLoopPathAux(output[i], ref2))
 -                     return true; // Stop when a path is found
 -             }
 -             return false;
 -         }
 -     }
 - }
 - 
 - //--------------
 - // External API
 - //--------------
 - 
 - int JackConnectionManager::GetActivation(int refnum) const
 - {
 -     return fInputCounter[refnum].GetValue();
 - }
 - 
 - /*!
 - \brief Connect port_src to port_dst.
 - */
 - int JackConnectionManager::Connect(jack_port_id_t port_src, jack_port_id_t port_dst)
 - {
 -     jack_log("JackConnectionManager::Connect port_src = %ld port_dst = %ld", port_src, port_dst);
 - 
 -     if (fConnection[port_src].AddItem(port_dst)) {
 -         return 0;
 -     } else {
 -         jack_error("Connection table is full !!");
 -         return -1;
 -     }
 - }
 - 
 - /*!
 - \brief Disconnect port_src from port_dst.
 - */
 - int JackConnectionManager::Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst)
 - {
 -     jack_log("JackConnectionManager::Disconnect port_src = %ld port_dst = %ld", port_src, port_dst);
 - 
 -     if (fConnection[port_src].RemoveItem(port_dst)) {
 -         return 0;
 -     } else {
 -         jack_error("Connection not found !!");
 -         return -1;
 -     }
 - }
 - 
 - /*!
 - \brief Check if port_src and port_dst are connected.
 - */
 - bool JackConnectionManager::IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const
 - {
 -     return fConnection[port_src].CheckItem(port_dst);
 - }
 - 
 - /*!
 - \brief Get the connection number of a given port.
 - */
 - jack_int_t JackConnectionManager::Connections(jack_port_id_t port_index) const
 - {
 -     return fConnection[port_index].GetItemCount();
 - }
 - 
 - jack_port_id_t JackConnectionManager::GetPort(jack_port_id_t port_index, int connection) const
 - {
 -     assert(connection < CONNECTION_NUM);
 -     return (jack_port_id_t)fConnection[port_index].GetItem(connection);
 - }
 - 
 - /*!
 - \brief Get the connection port array.
 - */
 - const jack_int_t* JackConnectionManager::GetConnections(jack_port_id_t port_index) const
 - {
 -     return fConnection[port_index].GetItems();
 - }
 - 
 - //------------------------
 - // Client port management
 - //------------------------
 - 
 - /*!
 - \brief Add an input port to a client.
 - */
 - int JackConnectionManager::AddInputPort(int refnum, jack_port_id_t port_index)
 - {
 -     if (fInputPort[refnum].AddItem(port_index)) {
 -         jack_log("JackConnectionManager::AddInputPort ref = %ld port = %ld", refnum, port_index);
 -         return 0;
 -     } else {
 -         jack_error("Maximum number of input ports is reached for application ref = %ld", refnum);
 -         return -1;
 -     }
 - }
 - 
 - /*!
 - \brief Add an output port to a client.
 - */
 - int JackConnectionManager::AddOutputPort(int refnum, jack_port_id_t port_index)
 - {
 -     if (fOutputPort[refnum].AddItem(port_index)) {
 -         jack_log("JackConnectionManager::AddOutputPort ref = %ld port = %ld", refnum, port_index);
 -         return 0;
 -     } else {
 -         jack_error("Maximum number of output ports is reached for application ref = %ld", refnum);
 -         return -1;
 -     }
 - }
 - 
 - /*!
 - \brief Remove an input port from a client.
 - */
 - int JackConnectionManager::RemoveInputPort(int refnum, jack_port_id_t port_index)
 - {
 -     jack_log("JackConnectionManager::RemoveInputPort ref = %ld port_index = %ld ", refnum, port_index);
 - 
 -     if (fInputPort[refnum].RemoveItem(port_index)) {
 -         return 0;
 -     } else {
 -         jack_error("Input port index = %ld not found for application ref = %ld", port_index, refnum);
 -         return -1;
 -     }
 - }
 - 
 - /*!
 - \brief Remove an output port from a client.
 - */
 - int JackConnectionManager::RemoveOutputPort(int refnum, jack_port_id_t port_index)
 - {
 -     jack_log("JackConnectionManager::RemoveOutputPort ref = %ld port_index = %ld ", refnum, port_index);
 - 
 -     if (fOutputPort[refnum].RemoveItem(port_index)) {
 -         return 0;
 -     } else {
 -         jack_error("Output port index = %ld not found for application ref = %ld", port_index, refnum);
 -         return -1;
 -     }
 - }
 - 
 - /*!
 - \brief Get the input port array of a given refnum.
 - */
 - const jack_int_t* JackConnectionManager::GetInputPorts(int refnum)
 - {
 -     return fInputPort[refnum].GetItems();
 - }
 - 
 - /*!
 - \brief Get the output port array of a given refnum.
 - */
 - const jack_int_t* JackConnectionManager::GetOutputPorts(int refnum)
 - {
 -     return fOutputPort[refnum].GetItems();
 - }
 - 
 - /*!
 - \brief Init the refnum.
 - */
 - void JackConnectionManager::InitRefNum(int refnum)
 - {
 -     fInputPort[refnum].Init();
 -     fOutputPort[refnum].Init();
 -     fConnectionRef.Init(refnum);
 -     fInputCounter[refnum].SetValue(0);
 - }
 - 
 - /*!
 - \brief Reset all clients activation.
 - */
 - void JackConnectionManager::ResetGraph(JackClientTiming* timing)
 - {
 -     // Reset activation counter : must be done *before* starting to resume clients
 -     for (int i = 0; i < CLIENT_NUM; i++) {
 -         fInputCounter[i].Reset();
 -         timing[i].fStatus = NotTriggered;
 -     }
 - }
 - 
 - /*!
 - \brief Wait on the input synchro.
 - */
 - int JackConnectionManager::SuspendRefNum(JackClientControl* control, JackSynchro** table, JackClientTiming* timing, long time_out_usec)
 - {
 -     bool res;
 -     if ((res = table[control->fRefNum]->TimedWait(time_out_usec))) {
 -         timing[control->fRefNum].fStatus = Running;
 -         timing[control->fRefNum].fAwakeAt = GetMicroSeconds();
 -     }
 -     return (res) ? 0 : -1;
 - }
 - 
 - /*!
 - \brief Signal clients connected to the given client.
 - */
 - int JackConnectionManager::ResumeRefNum(JackClientControl* control, JackSynchro** table, JackClientTiming* timing)
 - {
 -     jack_time_t current_date = GetMicroSeconds();
 -     const jack_int_t* outputRef = fConnectionRef.GetItems(control->fRefNum);
 -     int res = 0;
 - 
 -     // Update state and timestamp of current client
 -     timing[control->fRefNum].fStatus = Finished;
 -     timing[control->fRefNum].fFinishedAt = current_date;
 - 
 -     for (int i = 0; i < CLIENT_NUM; i++) {
 - 
 -         // Signal connected clients or drivers
 -         if (outputRef[i] > 0) {
 - 
 -             // Update state and timestamp of destination clients
 -             timing[i].fStatus = Triggered;
 -             timing[i].fSignaledAt = current_date;
 - 
 -             if (!fInputCounter[i].Signal(table[i], control)) {
 -                 jack_log("JackConnectionManager::ResumeRefNum error: ref = %ld output = %ld ", control->fRefNum, i);
 -                 res = -1;
 -             }
 -         }
 -     }
 - 
 -     return res;
 - }
 - 
 - /*!
 - \brief Increment the number of ports between 2 clients, if the 2 clients become connected, then the Activation counter is updated.
 - */
 - void JackConnectionManager::IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
 - {
 -     int ref1 = GetOutputRefNum(port_src);
 -     int ref2 = GetInputRefNum(port_dst);
 - 
 -     assert(ref1 >= 0 && ref2 >= 0);
 - 
 -     DirectConnect(ref1, ref2);
 -     jack_log("JackConnectionManager::IncConnectionRef: ref1 = %ld ref2 = %ld", ref1, ref2);
 - }
 - 
 - /*!
 - \brief Decrement the number of ports between 2 clients, if the 2 clients become disconnected, then the Activation counter is updated.
 - */
 - void JackConnectionManager::DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
 - {
 -     int ref1 = GetOutputRefNum(port_src);
 -     int ref2 = GetInputRefNum(port_dst);
 - 
 -     assert(ref1 >= 0 && ref2 >= 0);
 - 
 -     DirectDisconnect(ref1, ref2);
 -     jack_log("JackConnectionManager::DecConnectionRef: ref1 = %ld ref2 = %ld", ref1, ref2);
 - }
 - 
 - /*!
 - \brief Directly connect 2 reference numbers.
 - */
 - void JackConnectionManager::DirectConnect(int ref1, int ref2)
 - {
 -     assert(ref1 >= 0 && ref2 >= 0);
 - 
 -     if (fConnectionRef.IncItem(ref1, ref2) == 1) { // First connection between client ref1 and client ref2
 -         jack_log("JackConnectionManager::DirectConnect first: ref1 = %ld ref2 = %ld", ref1, ref2);
 -         fInputCounter[ref2].IncValue();
 -     }
 - }
 - 
 - /*!
 - \brief Directly disconnect 2 reference numbers.
 - */
 - void JackConnectionManager::DirectDisconnect(int ref1, int ref2)
 - {
 -     assert(ref1 >= 0 && ref2 >= 0);
 - 
 -     if (fConnectionRef.DecItem(ref1, ref2) == 0) { // Last connection between client ref1 and client ref2
 -         jack_log("JackConnectionManager::DirectDisconnect last: ref1 = %ld ref2 = %ld", ref1, ref2);
 -         fInputCounter[ref2].DecValue();
 -     }
 - }
 - 
 - /*!
 - \brief Returns the connections state between 2 refnum.
 - */
 - bool JackConnectionManager::IsDirectConnection(int ref1, int ref2) const
 - {
 -     assert(ref1 >= 0 && ref2 >= 0);
 -     return fConnectionRef.GetItemCount(ref1, ref2);
 - }
 - 
 - /*!
 - \brief Get the client refnum of a given input port.
 - */
 - int JackConnectionManager::GetInputRefNum(jack_port_id_t port_index) const
 - {
 -     for (int i = 0; i < CLIENT_NUM; i++) {
 -         if (fInputPort[i].CheckItem(port_index))
 -             return i;
 -     }
 - 
 -     return -1;
 - }
 - 
 - /*!
 - \brief Get the client refnum of a given ouput port.
 - */
 - int JackConnectionManager::GetOutputRefNum(jack_port_id_t port_index) const
 - {
 -     for (int i = 0; i < CLIENT_NUM; i++) {
 -         if (fOutputPort[i].CheckItem(port_index))
 -             return i;
 -     }
 - 
 -     return -1;
 - }
 - 
 - /*!
 - \brief Test is a connection path exists between port_src and port_dst.
 - */
 - bool JackConnectionManager::IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const
 - {
 -     return IsLoopPathAux(GetInputRefNum(port_dst), GetOutputRefNum(port_src));
 - }
 - 
 - bool JackConnectionManager::IsFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst) const
 - {
 -     return (fLoopFeedback.GetConnectionIndex(GetOutputRefNum(port_src), GetInputRefNum(port_dst)) >= 0);
 - }
 - 
 - bool JackConnectionManager::IncFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
 - {
 -     int ref1 = GetOutputRefNum(port_src);
 -     int ref2 = GetInputRefNum(port_dst);
 - 
 -     // Add an activation connection in the other direction
 -     jack_log("JackConnectionManager::IncFeedbackConnection ref1 = %ld ref2 = %ld", ref1, ref2);
 -     assert(ref1 >= 0 && ref2 >= 0);
 - 
 -     if (ref1 != ref2)
 -         DirectConnect(ref2, ref1);
 - 
 -     return fLoopFeedback.IncConnection(ref1, ref2); // Add the feedback connection
 - }
 - 
 - bool JackConnectionManager::DecFeedbackConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
 - {
 -     int ref1 = GetOutputRefNum(port_src);
 -     int ref2 = GetInputRefNum(port_dst);
 - 
 -     // Remove an activation connection in the other direction
 -     jack_log("JackConnectionManager::DecFeedbackConnection ref1 = %ld ref2 = %ld", ref1, ref2);
 -     assert(ref1 >= 0 && ref2 >= 0);
 - 
 -     if (ref1 != ref2)
 -         DirectDisconnect(ref2, ref1);
 - 
 -     return fLoopFeedback.DecConnection(ref1, ref2); // Remove the feedback connection
 - }
 - 
 - } // end of namespace
 - 
 
 
  |