diff options
Diffstat (limited to 'src/clients/PatchModel.cpp')
-rw-r--r-- | src/clients/PatchModel.cpp | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/src/clients/PatchModel.cpp b/src/clients/PatchModel.cpp new file mode 100644 index 00000000..829c9ca5 --- /dev/null +++ b/src/clients/PatchModel.cpp @@ -0,0 +1,229 @@ +/* This file is part of Om. Copyright (C) 2005 Dave Robillard. + * + * Om 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. + * + * Om 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 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., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PatchModel.h" +#include "NodeModel.h" +#include "ConnectionModel.h" +#include <cassert> +#include <iostream> + +using std::cerr; using std::cout; using std::endl; + +namespace LibOmClient { + + +void +PatchModel::set_path(const Path& new_path) +{ + // FIXME: haack + if (new_path == "") { + m_path = ""; + return; + } + + NodeModel::set_path(new_path); + for (NodeModelMap::iterator i = m_nodes.begin(); i != m_nodes.end(); ++i) + (*i).second->set_path(m_path +"/"+ (*i).second->name()); + +#ifdef DEBUG + // Be sure connection paths are updated and sane + for (list<ConnectionModel*>::iterator j = m_connections.begin(); + j != m_connections.end(); ++j) { + assert((*j)->src_port_path().parent().parent() == new_path); + assert((*j)->src_port_path().parent().parent() == new_path); + } +#endif +} + + +NodeModel* +PatchModel::get_node(const string& name) +{ + assert(name.find("/") == string::npos); + NodeModelMap::iterator i = m_nodes.find(name); + return ((i != m_nodes.end()) ? (*i).second : NULL); +} + + +void +PatchModel::add_node(NodeModel* nm) +{ + assert(nm != NULL); + assert(nm->name().find("/") == string::npos); + assert(nm->parent() == NULL); + + m_nodes[nm->name()] = nm; + nm->set_parent(this); +} + + +void +PatchModel::remove_node(const string& name) +{ + assert(name.find("/") == string::npos); + NodeModelMap::iterator i = m_nodes.find(name); + if (i != m_nodes.end()) { + delete i->second; + m_nodes.erase(i); + return; + } + + cerr << "[PatchModel::remove_node] " << m_path << ": failed to find node " << name << endl; +} + + +void +PatchModel::clear() +{ + for (list<ConnectionModel*>::iterator j = m_connections.begin(); j != m_connections.end(); ++j) + delete (*j); + + for (NodeModelMap::iterator i = m_nodes.begin(); i != m_nodes.end(); ++i) { + (*i).second->clear(); + delete (*i).second; + } + + m_nodes.clear(); + m_connections.clear(); + + NodeModel::clear(); + + assert(m_nodes.empty()); + assert(m_connections.empty()); + assert(m_ports.empty()); +} + + +/** Updated the map key of the given node. + * + * The NodeModel must already have it's new path set to @a new_path, or this will + * abort with a fatal error. + */ +void +PatchModel::rename_node(const Path& old_path, const Path& new_path) +{ + assert(old_path.parent() == path()); + assert(new_path.parent() == path()); + + NodeModelMap::iterator i = m_nodes.find(old_path.name()); + NodeModel* nm = NULL; + + if (i != m_nodes.end()) { + nm = (*i).second; + for (list<ConnectionModel*>::iterator j = m_connections.begin(); j != m_connections.end(); ++j) { + if ((*j)->src_port_path().parent() == old_path) + (*j)->src_port_path(new_path.base_path() + (*j)->src_port_path().name()); + if ((*j)->dst_port_path().parent() == old_path) + (*j)->dst_port_path(new_path.base_path() + (*j)->dst_port_path().name()); + } + m_nodes.erase(i); + assert(nm->path() == new_path); + m_nodes[new_path.name()] = nm; + return; + } + + cerr << "[PatchModel::rename_node] " << m_path << ": failed to find node " << old_path << endl; +} + + +ConnectionModel* +PatchModel::get_connection(const string& src_port_path, const string& dst_port_path) +{ + for (list<ConnectionModel*>::iterator i = m_connections.begin(); i != m_connections.end(); ++i) + if ((*i)->src_port_path() == src_port_path && (*i)->dst_port_path() == dst_port_path) + return (*i); + return NULL; +} + + +/** Add a connection to this patch. + * + * Ownership of @a cm is taken, it will be deleted along with this PatchModel. + * If @a cm only contains paths (not pointers to the actual ports), the ports + * will be found and set. The ports referred to not existing as children of + * this patch is a fatal error. + */ +void +PatchModel::add_connection(ConnectionModel* cm) +{ + assert(cm != NULL); + assert(cm->src_port_path().parent().parent() == m_path); + assert(cm->dst_port_path().parent().parent() == m_path); + assert(cm->patch_path() == path()); + + ConnectionModel* existing = get_connection(cm->src_port_path(), cm->dst_port_path()); + + if (existing != NULL) { + delete cm; + return; + } + + NodeModel* src_node = get_node(cm->src_port_path().parent().name()); + PortModel* src_port = (src_node == NULL) ? NULL : src_node->get_port(cm->src_port_path().name()); + NodeModel* dst_node = get_node(cm->dst_port_path().parent().name()); + PortModel* dst_port = (dst_node == NULL) ? NULL : dst_node->get_port(cm->dst_port_path().name()); + + assert(src_port != NULL); + assert(dst_port != NULL); + + // Find source port pointer to 'resolve' connection if necessary + if (cm->src_port() != NULL) + assert(cm->src_port() == src_port); + else + cm->set_src_port(src_port); + + // Find dest port pointer to 'resolve' connection if necessary + if (cm->dst_port() != NULL) + assert(cm->dst_port() == dst_port); + else + cm->set_dst_port(dst_port); + + assert(cm->src_port() != NULL); + assert(cm->dst_port() != NULL); + + m_connections.push_back(cm); +} + + +void +PatchModel::remove_connection(const string& src_port_path, const string& dst_port_path) +{ + ConnectionModel* cm = NULL; + for (list<ConnectionModel*>::iterator i = m_connections.begin(); i != m_connections.end(); ++i) { + cm = (*i); + if (cm->src_port_path() == src_port_path && cm->dst_port_path() == dst_port_path) { + delete cm; + m_connections.erase(i); + assert(get_connection(src_port_path, dst_port_path) == NULL); // no duplicates + return; + } + } + cerr << "[PatchModel::remove_connection] WARNING: Failed to find connection " << + src_port_path << " -> " << dst_port_path << endl; + return; +} + + +bool +PatchModel::polyphonic() const +{ + return (m_parent == NULL) + ? (m_poly > 1) + : (m_poly > 1) && m_poly == parent_patch()->poly() && m_poly > 1; +} + + +} // namespace LibOmClient |