/*
* Klang – a node+text-based synthesizer library
*
* This file is part of the *wellen* library (https://github.com/dennisppaul/wellen).
* Copyright (c) 2022 Dennis P Paul.
*
* This library 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, version 3.
*
* This library 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef ConnectionPool_hpp
#define ConnectionPool_hpp
#include <vector>
namespace klang {
class ConnectionPool {
public:
static ConnectionPool& instance() {
static ConnectionPool instance;
return instance;
}
CONNECTION_ID connect(Node& pOutputNode,
CHANNEL_ID pOutputChannel,
Node& pInputNode,
CHANNEL_ID pInputChannel) {
/* check existing connections */
for (uint8_t i = 0; i < mConnections.size(); i++) {
Connection* m = mConnections[i];
uint16_t mNodeID = m->output_node.ID();
CHANNEL_ID mOutputChannel = m->output_channel_id;
if (mNodeID == pOutputNode.ID() && mOutputChannel == pOutputChannel && !pOutputNode.ouput_allow_multiple_connections()) {
KLANG_LOG_ERR("+++ NODE_%02i(OUT%02i) already connected +++", pOutputNode.ID(), pOutputChannel);
return KLANG_CONNECTION_ERROR;
}
}
// if (pOutputChannel >= pOutputNode.max_out_channels()) {
// KLANG_LOG_ERR("+++ NODE_%02i(OUT%02i) is not valid … %i", pOutputNode.ID(), pOutputChannel, pOutputNode.CH_OUT_SIGNAL);
// return KLANG_CONNECTION_ERROR;
// }
bool mStatus;
Connection* c = new Connection(pOutputNode,
pOutputChannel,
pInputNode,
pInputChannel,
mStatus);
if (!mStatus) {
KLANG_LOG_ERR("+++ NODE_%02i(OUT%02i) <CONNECT_%02i> NODE_%02i(IN%02i) error connecting, rejected by node. might be invalid `CHANNEL_ID`",
pOutputNode.ID(), pOutputChannel,
c->ID(),
pInputNode.ID(), pInputChannel);
}
mConnections.push_back(c);
#ifdef DEBUG_CONNECTION_POOL
KLANG_LOG("+++ NODE_%02i(OUT%02i) <CONNECT_%02i> NODE_%02i(IN%02i) +++",
pOutputNode.ID(), pOutputChannel,
c->ID(),
pInputNode.ID(), pInputChannel);
#endif
return c->ID();
}
bool disconnect(Node& pOutputNode,
CHANNEL_ID pOutputChannel,
Node& pInputNode,
CHANNEL_ID pInputChannel) {
std::vector<Connection*>::iterator it = mConnections.begin();
while (it != mConnections.end()) {
Connection* m = *it;
uint16_t mNodeID = m->output_node.ID();
CHANNEL_ID mOutputChannel = m->output_channel_id;
if (mNodeID == pOutputNode.ID() && mOutputChannel == pOutputChannel) {
#ifdef DEBUG_CONNECTION_POOL
KLANG_LOG("+++ NODE_%02i(OUT%02i) disconnected +++", pOutputNode.ID(), pOutputChannel);
#endif
it = mConnections.erase(it);
delete m;
return true;
} else {
++it;
}
}
return false;
}
bool disconnect(CONNECTION_ID pConnectionID) {
std::vector<Connection*>::iterator it = mConnections.begin();
while (it != mConnections.end()) {
Connection* m = *it;
if (m->ID() == pConnectionID) {
it = mConnections.erase(it);
delete m;
return true;
}
}
return false;
}
void reset() {
for (uint16_t i = 0; i < mConnections.size(); i++) {
delete mConnections[i];
}
mConnections.clear();
Connection::reset();
}
private:
ConnectionPool(ConnectionPool const&);
void operator=(ConnectionPool const&);
ConnectionPool() {
#ifdef DEBUG_CONNECTION_POOL
KLANG_LOG("++++++++++++++++++++++++++++++++++++++++++++++++++");
KLANG_LOG("+++ @ConnectionPool +++");
#endif
}
std::vector<Connection*> mConnections;
};
} // namespace klang
#endif /* ConnectionPool_hpp */