diff options
103 files changed, 1623 insertions, 2526 deletions
diff --git a/src/common/interface/ClientInterface.h b/src/common/interface/ClientInterface.h index 3adc76f4..5d56fa8e 100644 --- a/src/common/interface/ClientInterface.h +++ b/src/common/interface/ClientInterface.h @@ -18,6 +18,7 @@ #define CLIENTINTERFACE_H #include <inttypes.h> +#include "util/Atom.h" #include <string> using std::string; @@ -91,7 +92,7 @@ public: virtual void metadata_update(string subject_path, string predicate, - string value) = 0; + Atom value) = 0; virtual void control_change(string port_path, float value) = 0; diff --git a/src/common/interface/EngineInterface.h b/src/common/interface/EngineInterface.h index 46f6fa99..c86340c5 100644 --- a/src/common/interface/EngineInterface.h +++ b/src/common/interface/EngineInterface.h @@ -112,7 +112,7 @@ public: virtual void set_metadata(const string& path, const string& predicate, - const string& value) = 0; + const Atom& value) = 0; // Requests // diff --git a/src/common/util/Path.h b/src/common/util/Path.h index 6c6d54be..2fcf5774 100644 --- a/src/common/util/Path.h +++ b/src/common/util/Path.h @@ -76,6 +76,10 @@ public: assert(path.find_last_of("/") != string::npos); + // Double slash not allowed + if (path.find("//") != string::npos) + return false; + // All characters must be printable ASCII for (size_t i=0; i < path.length(); ++i) if (path.at(i) < 32 || path.at(i) > 126) diff --git a/src/libs/client/ModelClientInterface.cpp b/src/libs/client/ModelClientInterface.cpp index deb37187..d29395e7 100644 --- a/src/libs/client/ModelClientInterface.cpp +++ b/src/libs/client/ModelClientInterface.cpp @@ -86,17 +86,17 @@ ModelClientInterface::new_patch(string path, uint32_t poly) void -ModelClientInterface::new_node(string plugin_type, - string plugin_uri, - string node_path, - bool is_polyphonic, - uint32_t num_ports) +ModelClientInterface::new_node(string plugin_type, + string plugin_uri, + string node_path, + bool is_polyphonic, + uint32_t num_ports) { cerr << "FIXME: NEW NODE\n"; CountedPtr<PluginModel> plugin(new PluginModel(plugin_type, plugin_uri)); - CountedPtr<NodeModel> nm(new NodeModel(plugin, node_path)); + CountedPtr<NodeModel> nm(new NodeModel(plugin, node_path, is_polyphonic)); new_node_model(nm); } diff --git a/src/libs/client/ModelEngineInterface.cpp b/src/libs/client/ModelEngineInterface.cpp index ca92b1ac..7cc2ae22 100644 --- a/src/libs/client/ModelEngineInterface.cpp +++ b/src/libs/client/ModelEngineInterface.cpp @@ -65,8 +65,8 @@ ModelEngineInterface::create_patch_from_model(const PatchModel* pm) void ModelEngineInterface::set_all_metadata(const ObjectModel* m) { - for (map<string, string>::const_iterator i = m->metadata().begin(); i != m->metadata().end(); ++i) - set_metadata(m->path(), (*i).first, (*i).second.c_str()); + for (MetadataMap::const_iterator i = m->metadata().begin(); i != m->metadata().end(); ++i) + set_metadata(m->path(), i->first, i->second); } diff --git a/src/libs/client/NodeModel.cpp b/src/libs/client/NodeModel.cpp index 8d9d8697..55f70130 100644 --- a/src/libs/client/NodeModel.cpp +++ b/src/libs/client/NodeModel.cpp @@ -22,22 +22,18 @@ namespace Ingen { namespace Client { -NodeModel::NodeModel(CountedPtr<PluginModel> plugin, const Path& path) +NodeModel::NodeModel(CountedPtr<PluginModel> plugin, const Path& path, bool polyphonic) : ObjectModel(path), - m_polyphonic(false), + m_polyphonic(polyphonic), m_plugin_uri(plugin->uri()), - m_plugin(plugin), - m_x(0.0f), - m_y(0.0f) + m_plugin(plugin) { } -NodeModel::NodeModel(const string& plugin_uri, const Path& path) +NodeModel::NodeModel(const string& plugin_uri, const Path& path, bool polyphonic) : ObjectModel(path), - m_polyphonic(false), - m_plugin_uri(plugin_uri), - m_x(0.0f), - m_y(0.0f) + m_polyphonic(polyphonic), + m_plugin_uri(plugin_uri) { } @@ -52,6 +48,7 @@ void NodeModel::remove_port(CountedPtr<PortModel> port) { m_ports.remove(port); + removed_port_sig.emit(port); } @@ -78,12 +75,13 @@ NodeModel::clear() void NodeModel::set_path(const Path& p) { - const string old_path = m_path; + const string old_path = _path; ObjectModel::set_path(p); - for (PortModelList::iterator i = m_ports.begin(); i != m_ports.end(); ++i) - (*i)->set_path(m_path + "/" + (*i)->path().name()); + // FIXME: rename +// for (PortModelList::iterator i = m_ports.begin(); i != m_ports.end(); ++i) +// (*i)->set_path(_path + "/" + (*i)->path().name()); //if (m_parent && old_path.length() > 0) // parent_patch()->rename_node(old_path, p); @@ -104,7 +102,7 @@ NodeModel::add_child(CountedPtr<ObjectModel> c) void NodeModel::remove_child(CountedPtr<ObjectModel> c) { - assert(c->path().is_child_of(m_path)); + assert(c->path().is_child_of(_path)); assert(c->parent().get() == this); CountedPtr<PortModel> pm = PtrCast<PortModel>(c); @@ -117,7 +115,7 @@ void NodeModel::add_port(CountedPtr<PortModel> pm) { assert(pm); - assert(pm->path().is_child_of(m_path)); + assert(pm->path().is_child_of(_path)); assert(pm->parent().get() == this); PortModelList::iterator existing = m_ports.end(); @@ -129,7 +127,7 @@ NodeModel::add_port(CountedPtr<PortModel> pm) } if (existing != m_ports.end()) { - cerr << "Warning: port clash, assimilating old port " << m_path << endl; + cerr << "Warning: port clash, assimilating old port " << _path << endl; pm->assimilate(*existing); *existing = pm; } else { @@ -140,10 +138,10 @@ NodeModel::add_port(CountedPtr<PortModel> pm) CountedPtr<PortModel> -NodeModel::get_port(const string& port_name) +NodeModel::get_port(const string& port_name) const { assert(port_name.find("/") == string::npos); - for (PortModelList::iterator i = m_ports.begin(); i != m_ports.end(); ++i) + for (PortModelList::const_iterator i = m_ports.begin(); i != m_ports.end(); ++i) if ((*i)->path().name() == port_name) return (*i); return CountedPtr<PortModel>(); @@ -166,29 +164,5 @@ NodeModel::remove_program(int bank, int program) } -void -NodeModel::x(float a) -{ - if (m_x != a) { - m_x = a; - char temp_buf[16]; - snprintf(temp_buf, 16, "%f", a); - set_metadata("module-x", temp_buf); - } -} - - -void -NodeModel::y(float a) -{ - if (m_y != a) { - m_y = a; - char temp_buf[16]; - snprintf(temp_buf, 16, "%f", a); - set_metadata("module-y", temp_buf); - } -} - - } // namespace Client } // namespace Ingen diff --git a/src/libs/client/NodeModel.h b/src/libs/client/NodeModel.h index 60973d95..f9c87f6e 100644 --- a/src/libs/client/NodeModel.h +++ b/src/libs/client/NodeModel.h @@ -44,55 +44,50 @@ class PluginModel; class NodeModel : public ObjectModel { public: - NodeModel(const string& plugin_uri, const Path& path); - NodeModel(CountedPtr<PluginModel> plugin, const Path& path); + NodeModel(const string& plugin_uri, const Path& path, bool polyphonic); + NodeModel(CountedPtr<PluginModel> plugin, const Path& path, bool polyphonic); virtual ~NodeModel(); - - void add_child(CountedPtr<ObjectModel> c); - void remove_child(CountedPtr<ObjectModel> c); - - CountedPtr<PortModel> get_port(const string& port_name); - void add_port(CountedPtr<PortModel> pm); - void remove_port(CountedPtr<PortModel> pm); - void remove_port(const string& port_path); - - virtual void clear(); - - const map<int, map<int, string> >& get_programs() const { return m_banks; } - void add_program(int bank, int program, const string& name); - void remove_program(int bank, int program); - - string plugin_uri() { return m_plugin_uri; } - CountedPtr<PluginModel> plugin() const { return m_plugin; } - //void plugin(CountedPtr<PluginModel> p) { m_plugin = p; } + CountedPtr<PortModel> get_port(const string& port_name) const; - virtual void set_path(const Path& p); - - int num_ports() const { return m_ports.size(); } - const PortModelList& ports() const { return m_ports; } - virtual bool polyphonic() const { return m_polyphonic; } - void polyphonic(bool b) { m_polyphonic = b; } - float x() const { return m_x; } - float y() const { return m_y; } - void x(float a); - void y(float a); + const map<int, map<int, string> >& get_programs() const { return m_banks; } + const string& plugin_uri() const { return m_plugin_uri; } + CountedPtr<PluginModel> plugin() const { return m_plugin; } + int num_ports() const { return m_ports.size(); } + const PortModelList& ports() const { return m_ports; } + virtual bool polyphonic() const { return m_polyphonic; } // Signals sigc::signal<void, CountedPtr<PortModel> > new_port_sig; + sigc::signal<void, CountedPtr<PortModel> > removed_port_sig; protected: + friend class Store; NodeModel(const Path& path); + void add_child(CountedPtr<ObjectModel> c); + void remove_child(CountedPtr<ObjectModel> c); + void add_port(CountedPtr<PortModel> pm); + void remove_port(CountedPtr<PortModel> pm); + void remove_port(const string& port_path); + void add_program(int bank, int program, const string& name); + void remove_program(int bank, int program); + + + //void plugin(CountedPtr<PluginModel> p) { m_plugin = p; } + virtual void clear(); + + friend class PatchModel; + void set_path(const Path& p); bool m_polyphonic; - PortModelList m_ports; ///< List of ports (instead of map to preserve order) - string m_plugin_uri; ///< Plugin URI (not redundant if PluginModel unknown - CountedPtr<PluginModel> m_plugin; ///< The plugin this node is an instance of - float m_x; ///< Just metadata, here as an optimization for GUI - float m_y; ///< Just metadata, here as an optimization for GUI - map<int, map<int, string> > m_banks; ///< DSSI banks + PortModelList m_ports; ///< List of ports (not a map to preserve order) + string m_plugin_uri; ///< Plugin URI (if PluginModel is unknown) + CountedPtr<PluginModel> m_plugin; ///< The plugin this node is an instance of + map<int, map<int, string> > m_banks; ///< DSSI banks private: + friend class PatchLibrarian; // FIXME: remove + // Prevent copies (undefined) NodeModel(const NodeModel& copy); NodeModel& operator=(const NodeModel& copy); diff --git a/src/libs/client/OSCClientReceiver.cpp b/src/libs/client/OSCClientReceiver.cpp index ae607af1..4c715c76 100644 --- a/src/libs/client/OSCClientReceiver.cpp +++ b/src/libs/client/OSCClientReceiver.cpp @@ -15,8 +15,7 @@ */ #include "OSCClientReceiver.h" -//#include "NodeModel.h" -//#include "PluginModel.h" +#include "util/LibloAtom.h" #include <list> #include <cassert> #include <cstring> @@ -154,7 +153,7 @@ OSCClientReceiver::setup_callbacks() lo_server_thread_add_method(_st, "/om/disconnection", "ss", disconnection_cb, this); lo_server_thread_add_method(_st, "/om/new_node", "sssii", new_node_cb, this); lo_server_thread_add_method(_st, "/om/new_port", "ssi", new_port_cb, this); - lo_server_thread_add_method(_st, "/om/metadata/update", "sss", metadata_update_cb, this); + lo_server_thread_add_method(_st, "/om/metadata/update", NULL, metadata_update_cb, this); lo_server_thread_add_method(_st, "/om/control_change", "sf", control_change_cb, this); lo_server_thread_add_method(_st, "/om/program_add", "siis", program_add_cb, this); lo_server_thread_add_method(_st, "/om/program_remove", "sii", program_remove_cb, this); @@ -337,9 +336,13 @@ OSCClientReceiver::m_new_port_cb(const char* path, const char* types, lo_arg** a int OSCClientReceiver::m_metadata_update_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { + if (argc != 3 || types[0] != 's' || types[1] != 's') + return 1; + const char* obj_path = &argv[0]->s; const char* key = &argv[1]->s; - const char* value = &argv[2]->s; + + Atom value = LibloAtom::lo_arg_to_atom(types[2], argv[2]); metadata_update(obj_path, key, value); diff --git a/src/libs/client/OSCEngineSender.cpp b/src/libs/client/OSCEngineSender.cpp index 10d9ab2e..447fa934 100644 --- a/src/libs/client/OSCEngineSender.cpp +++ b/src/libs/client/OSCEngineSender.cpp @@ -17,6 +17,7 @@ #include <iostream> #include "OSCEngineSender.h" #include "interface/ClientKey.h" +#include "util/LibloAtom.h" using std::cout; using std::cerr; using std::endl; namespace Ingen { @@ -374,14 +375,16 @@ OSCEngineSender::midi_learn(const string& node_path) void OSCEngineSender::set_metadata(const string& obj_path, const string& predicate, - const string& value) + const Atom& value) { + assert(_engine_addr); - lo_send(_engine_addr, "/om/metadata/set", "isss", - next_id(), - obj_path.c_str(), - predicate.c_str(), - value.c_str()); + lo_message m = lo_message_new(); + lo_message_add_int32(m, next_id()); + lo_message_add_string(m, obj_path.c_str()); + lo_message_add_string(m, predicate.c_str()); + LibloAtom::lo_message_add_atom(m, value); + lo_send_message(_engine_addr, "/om/metadata/set", m); } diff --git a/src/libs/client/OSCEngineSender.h b/src/libs/client/OSCEngineSender.h index 2603667a..f514097d 100644 --- a/src/libs/client/OSCEngineSender.h +++ b/src/libs/client/OSCEngineSender.h @@ -126,7 +126,7 @@ public: void set_metadata(const string& obj_path, const string& predicate, - const string& value); + const Atom& value); // Requests // diff --git a/src/libs/client/ObjectController.h b/src/libs/client/ObjectController.h deleted file mode 100644 index fca59a80..00000000 --- a/src/libs/client/ObjectController.h +++ /dev/null @@ -1,45 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef OBJECTCONTROLLER_H -#define OBJECTCONTROLLER_H - -namespace Ingen { -namespace Client { - - -/** A trivial base class for controllers of an ObjectModel. - * - * This is so ObjectModels can have pointers to app-specified controllers, - * and the pointer relationships in models (ie PatchModel has pointers to - * all it's NodeModel children, etc) can be used to find controllers of - * Models, rather than having a parallel structure of pointers in the - * app's controllers. - * - * \ingroup IngenClient - */ -class ObjectController -{ -public: - virtual ~ObjectController() {} -}; - - -} // namespace Client -} // namespace Ingen - - -#endif // OBJECTCONTROLLER_H diff --git a/src/libs/client/ObjectModel.cpp b/src/libs/client/ObjectModel.cpp index 4a0eca0d..6e18e680 100644 --- a/src/libs/client/ObjectModel.cpp +++ b/src/libs/client/ObjectModel.cpp @@ -21,34 +21,38 @@ namespace Client { ObjectModel::ObjectModel(const Path& path) -: m_path(path) +: _path(path) { } + ObjectModel::~ObjectModel() { - m_controller.reset(); } -/** Get a piece of metadata for this objeect. +/** Get a piece of metadata for this object. * * @return Metadata value with key @a key, empty string otherwise. */ -string +const Atom& ObjectModel::get_metadata(const string& key) const { - map<string,string>::const_iterator i = m_metadata.find(key); - if (i != m_metadata.end()) + static const Atom null_atom; + + MetadataMap::const_iterator i = _metadata.find(key); + if (i != _metadata.end()) return i->second; else - return ""; + return null_atom; } void -ObjectModel::set_controller(CountedPtr<ObjectController> c) +ObjectModel::add_metadata(const MetadataMap& data) { - m_controller = c; + for (MetadataMap::const_iterator i = data.begin(); i != data.end(); ++i) { + _metadata[i->first] = i->second; + } } @@ -60,13 +64,13 @@ ObjectModel::set_controller(CountedPtr<ObjectController> c) void ObjectModel::assimilate(CountedPtr<ObjectModel> model) { - assert(m_path == model->path()); + assert(_path == model->path()); - for (map<string,string>::const_iterator i = model->metadata().begin(); + for (MetadataMap::const_iterator i = model->metadata().begin(); i != model->metadata().end(); ++i) { - map<string,string>::const_iterator i = m_metadata.find(i->first); - if (i == m_metadata.end()) - m_metadata[i->first] = i->second; + MetadataMap::const_iterator i = _metadata.find(i->first); + if (i == _metadata.end()) + _metadata[i->first] = i->second; } } diff --git a/src/libs/client/ObjectModel.h b/src/libs/client/ObjectModel.h index da3764d1..79d551f5 100644 --- a/src/libs/client/ObjectModel.h +++ b/src/libs/client/ObjectModel.h @@ -24,59 +24,66 @@ #include <algorithm> #include <cassert> #include <sigc++/sigc++.h> +#include "util/Atom.h" #include "util/Path.h" #include "util/CountedPtr.h" -#include "ObjectController.h" using std::string; using std::map; using std::find; using std::cout; using std::cerr; using std::endl; namespace Ingen { namespace Client { -class ObjectController; +typedef map<string, Atom> MetadataMap; + - /** Base class for all GraphObject models (NodeModel, PatchModel, PortModel). * + * There are no non-const public methods intentionally, models are not allowed + * to be manipulated directly by anything (but the Store) because of the + * asynchronous nature of engine control. To change something, use the + * controller (which the model probably shouldn't have a reference to but oh + * well, it reduces Collection Hell) and wait for the result (as a signal + * from this Model). + * * \ingroup IngenClient */ class ObjectModel { public: ObjectModel(const Path& path); - ObjectModel() : m_path("/UNINITIALIZED") {} // FIXME: remove virtual ~ObjectModel(); - - const map<string, string>& metadata() const { return m_metadata; } - string get_metadata(const string& key) const; - void set_metadata(const string& key, const string& value) - { assert(value.length() > 0); m_metadata[key] = value; metadata_update_sig.emit(key, value); } - - inline const Path& path() const { return m_path; } - virtual void set_path(const Path& p) { m_path = p; } - - CountedPtr<ObjectModel> parent() const { return m_parent; } - virtual void set_parent(CountedPtr<ObjectModel> p) { m_parent = p; } - - virtual void add_child(CountedPtr<ObjectModel> c) = 0; - virtual void remove_child(CountedPtr<ObjectModel> c) = 0; - CountedPtr<ObjectController> controller() const { return m_controller; } - - void set_controller(CountedPtr<ObjectController> c); + const Atom& get_metadata(const string& key) const; + void add_metadata(const MetadataMap& data); + + const MetadataMap& metadata() const { return _metadata; } + inline const Path& path() const { return _path; } + CountedPtr<ObjectModel> parent() const { return _parent; } void assimilate(CountedPtr<ObjectModel> model); // Signals - sigc::signal<void, const string&, const string&> metadata_update_sig; - sigc::signal<void> destroyed_sig; + sigc::signal<void, const string&, const Atom&> metadata_update_sig; + sigc::signal<void> destroyed_sig; + + // FIXME: make private + void set_metadata(const string& key, const Atom& value) + { _metadata[key] = value; metadata_update_sig.emit(key, value); } + + protected: - Path m_path; - CountedPtr<ObjectModel> m_parent; - CountedPtr<ObjectController> m_controller; + friend class Store; + friend class PatchLibrarian; // FIXME: remove + virtual void set_path(const Path& p) { _path = p; } + virtual void set_parent(CountedPtr<ObjectModel> p) { _parent = p; } + virtual void add_child(CountedPtr<ObjectModel> c) = 0; + virtual void remove_child(CountedPtr<ObjectModel> c) = 0; + + Path _path; + CountedPtr<ObjectModel> _parent; - map<string,string> m_metadata; + MetadataMap _metadata; private: // Prevent copies (undefined) diff --git a/src/libs/client/PatchLibrarian.cpp b/src/libs/client/PatchLibrarian.cpp index 07a98526..4db47b5b 100644 --- a/src/libs/client/PatchLibrarian.cpp +++ b/src/libs/client/PatchLibrarian.cpp @@ -136,7 +136,7 @@ PatchLibrarian::save_patch(CountedPtr<PatchModel> patch_model, const string& fil xmlNodePtr xml_root_node = NULL; xmlNodePtr xml_node = NULL; xmlNodePtr xml_child_node = NULL; - xmlNodePtr xml_grandchild_node = NULL; + //xmlNodePtr xml_grandchild_node = NULL; xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_root_node = xmlNewNode(NULL, (xmlChar*)"patch"); @@ -164,13 +164,14 @@ PatchLibrarian::save_patch(CountedPtr<PatchModel> patch_model, const string& fil xml_node = xmlNewChild(xml_root_node, NULL, (xmlChar*)"polyphony", (xmlChar*)temp_buf); // Write metadata - for (map<string, string>::const_iterator i = patch_model->metadata().begin(); + for (MetadataMap::const_iterator i = patch_model->metadata().begin(); i != patch_model->metadata().end(); ++i) { + cerr << "FIXME: metadata save" << endl; // Dirty hack, don't save coordinates in patch file - if ((*i).first != "module-x" && (*i).first != "module-y" - && (*i).first != "filename") - xml_node = xmlNewChild(xml_root_node, NULL, - (xmlChar*)(*i).first.c_str(), (xmlChar*)(*i).second.c_str()); + //if (i->first != "module-x" && i->first != "module-y" + // && i->first != "filename") + // xml_node = xmlNewChild(xml_root_node, NULL, + // (xmlChar*)(*i).first.c_str(), (xmlChar*)(*i).second.c_str()); assert((*i).first != "node"); assert((*i).first != "subpatch"); @@ -215,13 +216,14 @@ PatchLibrarian::save_patch(CountedPtr<PatchModel> patch_model, const string& fil xml_child_node = xmlNewChild(xml_node, NULL, (xmlChar*)"polyphony", (xmlChar*)temp_buf); // Write metadata - for (map<string, string>::const_iterator i = nm->metadata().begin(); + for (MetadataMap::const_iterator i = nm->metadata().begin(); i != nm->metadata().end(); ++i) { + cerr << "FIXME: save metadata\n"; // Dirty hack, don't save metadata that would be in patch file - if ((*i).first != "polyphony" && (*i).first != "filename" + /*if ((*i).first != "polyphony" && (*i).first != "filename" && (*i).first != "author" && (*i).first != "description") xml_child_node = xmlNewChild(xml_node, NULL, - (xmlChar*)(*i).first.c_str(), (xmlChar*)(*i).second.c_str()); + (xmlChar*)(*i).first.c_str(), (xmlChar*)(*i).second.c_str());*/ } if (recursive) @@ -251,7 +253,9 @@ PatchLibrarian::save_patch(CountedPtr<PatchModel> patch_model, const string& fil (xmlChar*)(nm->plugin()->uri().c_str())); // Write metadata - for (map<string, string>::const_iterator i = nm->metadata().begin(); i != nm->metadata().end(); ++i) { + for (MetadataMap::const_iterator i = nm->metadata().begin(); i != nm->metadata().end(); ++i) { + cerr << "FIXME: Save metadata\n"; + /* // DSSI _hack_ (FIXME: fix OSC to be more like this and not smash DSSI into metadata?) if ((*i).first.substr(0, 16) == "dssi-configure--") { xml_child_node = xmlNewChild(xml_node, NULL, (xmlChar*)"dssi-configure", NULL); @@ -269,11 +273,14 @@ PatchLibrarian::save_patch(CountedPtr<PatchModel> patch_model, const string& fil xml_child_node = xmlNewChild(xml_node, NULL, (xmlChar*)(*i).first.c_str(), (xmlChar*)(*i).second.c_str()); } + */ } // Write port metadata, if necessary for (PortModelList::const_iterator i = nm->ports().begin(); i != nm->ports().end(); ++i) { - const PortModel* const pm = (*i).get(); + cerr << "FIXME: save metadata\n"; + /* + const PortModel* const pm = i->get(); if (pm->is_input() && pm->user_min() != pm->min_val() || pm->user_max() != pm->max_val()) { xml_child_node = xmlNewChild(xml_node, NULL, (xmlChar*)"port", NULL); xml_grandchild_node = xmlNewChild(xml_child_node, NULL, (xmlChar*)"name", @@ -282,7 +289,7 @@ PatchLibrarian::save_patch(CountedPtr<PatchModel> patch_model, const string& fil xml_grandchild_node = xmlNewChild(xml_child_node, NULL, (xmlChar*)"user-min", (xmlChar*)temp_buf); snprintf(temp_buf, temp_buf_length, "%f", pm->user_max()); xml_grandchild_node = xmlNewChild(xml_child_node, NULL, (xmlChar*)"user-max", (xmlChar*)temp_buf); - } + }*/ } } } @@ -385,8 +392,8 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) //cerr << "[PatchLibrarian] Loading patch " << filename << "" << endl; - const size_t temp_buf_length = 255; - char temp_buf[temp_buf_length]; + //const size_t temp_buf_length = 255; + //char temp_buf[temp_buf_length]; bool load_name = (pm->path() == ""); bool load_poly = (poly == 0); @@ -447,8 +454,11 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) // Don't know what this tag is, add it as metadata without overwriting // (so caller can set arbitrary parameters which will be preserved) if (key != NULL) + cerr << "FIXME: save metadata\n"; + /* if (pm->get_metadata((const char*)cur->name) == "") pm->set_metadata((const char*)cur->name, (const char*)key); + */ } xmlFree(key); @@ -483,7 +493,7 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) // This isn't so good, considering multiple clients on multiple machines, and // absolute filesystem paths obviously aren't going to be correct. But for now // this is all I can figure out to have Save/Save As work properly for subpatches - _engine->set_metadata(pm->path(), "filename", pm->filename()); + _engine->set_metadata(pm->path(), "filename", Atom(pm->filename().c_str())); // Load nodes cur = xmlDocGetRootElement(doc)->xmlChildrenNode; @@ -494,13 +504,15 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) if (nm) { _engine->create_node_from_model(nm.get()); _engine->set_all_metadata(nm.get()); - for (PortModelList::const_iterator j = nm->ports().begin(); j != nm->ports().end(); ++j) { + cerr << "FIXME: max min\n"; + /* + //for (PortModelList::const_iterator j = nm->ports().begin(); j != nm->ports().end(); ++j) { // FIXME: ew snprintf(temp_buf, temp_buf_length, "%f", (*j)->user_min()); _engine->set_metadata((*j)->path(), "user-min", temp_buf); snprintf(temp_buf, temp_buf_length, "%f", (*j)->user_max()); _engine->set_metadata((*j)->path(), "user-max", temp_buf); - } + }*/ } } cur = cur->next; @@ -562,19 +574,23 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) CountedPtr<NodeModel> PatchLibrarian::parse_node(const CountedPtr<const PatchModel> parent, xmlDocPtr doc, const xmlNodePtr node) { +cerr << "FIXME: load node\n"; +#if 0 CountedPtr<PluginModel> plugin(new PluginModel()); - CountedPtr<NodeModel> nm(new NodeModel(plugin, "/UNINITIALIZED")); // FIXME: ew xmlChar* key; xmlNodePtr cur = node->xmlChildrenNode; + string path = ""' + bool polyphonic = false; + while (cur != NULL) { key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if ((!xmlStrcmp(cur->name, (const xmlChar*)"name"))) { - nm->set_path(parent->path().base() + Path::nameify((char*)key)); + path = parent->path().base() + Path::nameify((char*)key)); } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"polyphonic"))) { - nm->polyphonic(!strcmp((char*)key, "true")); + polyphonic = !strcmp((char*)key, "true"); } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"type"))) { plugin->set_type((const char*)key); } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"library-name"))) { @@ -586,7 +602,7 @@ PatchLibrarian::parse_node(const CountedPtr<const PatchModel> parent, xmlDocPtr } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"port"))) { xmlNodePtr child = cur->xmlChildrenNode; - string path; + string port_name; float user_min = 0.0; float user_max = 0.0; @@ -594,7 +610,7 @@ PatchLibrarian::parse_node(const CountedPtr<const PatchModel> parent, xmlDocPtr key = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); if ((!xmlStrcmp(child->name, (const xmlChar*)"name"))) { - path = nm->path().base() + Path::nameify((char*)key); + port_name = Path::nameify((char*)key); } else if ((!xmlStrcmp(child->name, (const xmlChar*)"user-min"))) { user_min = atof((char*)key); } else if ((!xmlStrcmp(child->name, (const xmlChar*)"user-max"))) { @@ -607,11 +623,14 @@ PatchLibrarian::parse_node(const CountedPtr<const PatchModel> parent, xmlDocPtr child = child->next; } - // FIXME: nasty assumptions - CountedPtr<PortModel> pm(new PortModel(path, + assert(path.length() > 0); + assert(Path::is_valid(path)); + + // FIXME: /nasty/ assumptions + CountedPtr<PortModel> pm(new PortModel(Path(path).base() + port_name, PortModel::CONTROL, PortModel::INPUT, PortModel::NONE, 0.0, user_min, user_max)); - pm->set_parent(nm); + //pm->set_parent(nm); nm->add_port(pm); // DSSI hacks. Stored in the patch files as special elements, but sent to @@ -637,7 +656,7 @@ PatchLibrarian::parse_node(const CountedPtr<const PatchModel> parent, xmlDocPtr key = NULL; // Avoid a (possible?) double free child = child->next; } - nm->set_metadata("dssi-program", bank +"/"+ program); + nm->set_metadata("dssi-program", Atom(bank.append("/").append(program).c_str())); } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"dssi-configure"))) { xmlNodePtr child = cur->xmlChildrenNode; @@ -659,7 +678,7 @@ PatchLibrarian::parse_node(const CountedPtr<const PatchModel> parent, xmlDocPtr child = child->next; } - nm->set_metadata(string("dssi-configure--").append(dssi_key), dssi_value); + nm->set_metadata(string("dssi-configure--").append(dssi_key), Atom(dssi_value.c_str())); } else { // Don't know what this tag is, add it as metadata if (key != NULL) @@ -729,7 +748,10 @@ PatchLibrarian::parse_node(const CountedPtr<const PatchModel> parent, xmlDocPtr } //nm->plugin(plugin); + return nm; +#endif + return CountedPtr<NodeModel>(); } diff --git a/src/libs/client/PatchModel.cpp b/src/libs/client/PatchModel.cpp index a65f1c49..21e47089 100644 --- a/src/libs/client/PatchModel.cpp +++ b/src/libs/client/PatchModel.cpp @@ -31,13 +31,13 @@ PatchModel::set_path(const Path& new_path) { // FIXME: haack if (new_path == "") { - m_path = ""; + _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->path().name()); + (*i).second->set_path(_path +"/"+ (*i).second->path().name()); #ifdef DEBUG // Be sure connection paths are updated and sane @@ -72,7 +72,7 @@ PatchModel::add_child(CountedPtr<ObjectModel> c) void PatchModel::remove_child(CountedPtr<ObjectModel> c) { - assert(c->path().is_child_of(m_path)); + assert(c->path().is_child_of(_path)); assert(c->parent().get() == this); CountedPtr<PortModel> pm = PtrCast<PortModel>(c); @@ -102,13 +102,13 @@ void PatchModel::add_node(CountedPtr<NodeModel> nm) { assert(nm); - assert(nm->path().is_child_of(m_path)); + assert(nm->path().is_child_of(_path)); assert(nm->parent().get() == this); NodeModelMap::iterator existing = m_nodes.find(nm->path().name()); if (existing != m_nodes.end()) { - cerr << "Warning: node clash, assimilating old node " << m_path << endl; + cerr << "Warning: node clash, assimilating old node " << _path << endl; nm->assimilate((*existing).second); (*existing).second = nm; } else { @@ -121,23 +121,23 @@ PatchModel::add_node(CountedPtr<NodeModel> nm) void PatchModel::remove_node(CountedPtr<NodeModel> nm) { - assert(nm->path().is_child_of(m_path)); + assert(nm->path().is_child_of(_path)); assert(nm->parent().get() == this); NodeModelMap::iterator i = m_nodes.find(nm->path().name()); if (i != m_nodes.end()) { assert(i->second == nm); m_nodes.erase(i); - removed_node_sig.emit(nm->path().name()); + removed_node_sig.emit(nm); i->second->parent().reset(); return; } - cerr << "[PatchModel::remove_node] " << m_path + cerr << "[PatchModel::remove_node] " << _path << ": failed to find node " << nm->path().name() << endl; } - +#if 0 void PatchModel::remove_node(const string& name) { @@ -151,9 +151,9 @@ PatchModel::remove_node(const string& name) return; } - cerr << "[PatchModel::remove_node] " << m_path << ": failed to find node " << name << endl; + cerr << "[PatchModel::remove_node] " << _path << ": failed to find node " << name << endl; } - +#endif void PatchModel::clear() @@ -204,7 +204,7 @@ PatchModel::rename_node(const Path& old_path, const Path& new_path) return; } - cerr << "[PatchModel::rename_node] " << m_path << ": failed to find node " << old_path << endl; + cerr << "[PatchModel::rename_node] " << _path << ": failed to find node " << old_path << endl; } @@ -229,8 +229,8 @@ void PatchModel::add_connection(CountedPtr<ConnectionModel> cm) { assert(cm); - //assert(cm->src_port_path().parent().parent() == m_path); - //assert(cm->dst_port_path().parent().parent() == m_path); + //assert(cm->src_port_path().parent().parent() == _path); + //assert(cm->dst_port_path().parent().parent() == _path); assert(cm->patch_path() == path()); //cerr << "PatchModel::add_connection: " << cm->src_port_path() << " -> " << cm->dst_port_path() << endl; @@ -314,9 +314,9 @@ PatchModel::disable() bool PatchModel::polyphonic() const { - return (!m_parent) + return (!_parent) ? (m_poly > 1) - : (m_poly > 1) && m_poly == ((PatchModel*)m_parent.get())->poly() && m_poly > 1; + : (m_poly > 1) && m_poly == ((PatchModel*)_parent.get())->poly() && m_poly > 1; } diff --git a/src/libs/client/PatchModel.h b/src/libs/client/PatchModel.h index 6ca8ed8f..49a45503 100644 --- a/src/libs/client/PatchModel.h +++ b/src/libs/client/PatchModel.h @@ -39,11 +39,13 @@ namespace Client { class PatchModel : public NodeModel { public: - PatchModel(const string& patch_path, uint poly) - : NodeModel("ingen:patch", patch_path), + PatchModel(const string& patch_path, size_t internal_poly) + : NodeModel("ingen:patch", patch_path, false ), // FIXME m_enabled(false), - m_poly(poly) - {} + m_poly(internal_poly) + { + cerr << "FIXME: patch poly\n"; + } const NodeModelMap& nodes() const { return m_nodes; } const list<CountedPtr<ConnectionModel> >& connections() const { return m_connections; } @@ -55,7 +57,7 @@ public: CountedPtr<NodeModel> get_node(const string& node_name); void add_node(CountedPtr<NodeModel> nm); - void remove_node(const string& name); + //void remove_node(const string& name); void remove_node(CountedPtr<NodeModel> nm); void rename_node(const Path& old_path, const Path& new_path); @@ -77,12 +79,12 @@ public: bool polyphonic() const; // Signals - sigc::signal<void, CountedPtr<NodeModel> > new_node_sig; - sigc::signal<void, const string& > removed_node_sig; - sigc::signal<void, CountedPtr<ConnectionModel> > new_connection_sig; - sigc::signal<void, const string&, const string& > removed_connection_sig; - sigc::signal<void> enabled_sig; - sigc::signal<void> disabled_sig; + sigc::signal<void, CountedPtr<NodeModel> > new_node_sig; + sigc::signal<void, CountedPtr<NodeModel> > removed_node_sig; + sigc::signal<void, CountedPtr<ConnectionModel> > new_connection_sig; + sigc::signal<void, const Path&, const Path& > removed_connection_sig; + sigc::signal<void> enabled_sig; + sigc::signal<void> disabled_sig; private: // Prevent copies (undefined) diff --git a/src/libs/client/PortModel.h b/src/libs/client/PortModel.h index 1f816748..dd0a208b 100644 --- a/src/libs/client/PortModel.h +++ b/src/libs/client/PortModel.h @@ -35,22 +35,17 @@ namespace Client { class PortModel : public ObjectModel { public: + // FIXME: metadataify enum Type { CONTROL, AUDIO, MIDI }; enum Direction { INPUT, OUTPUT }; enum Hint { NONE, INTEGER, TOGGLE, LOGARITHMIC }; - PortModel(const string& path, Type type, Direction dir, Hint hint, - float default_val, float min, float max) + PortModel(const string& path, Type type, Direction dir, Hint hint) : ObjectModel(path), m_type(type), m_direction(dir), m_hint(hint), - m_default_val(default_val), - m_min_val(min), - //m_user_min(min), - m_max_val(max), - //m_user_max(max), - m_current_val(default_val), + m_current_val(0.0f), m_connections(0) { } @@ -60,11 +55,6 @@ public: m_type(type), m_direction(dir), m_hint(NONE), - m_default_val(0.0f), - m_min_val(0.0f), - //m_user_min(0.0f), - m_max_val(0.0f), - //m_user_max(0.0f), m_current_val(0.0f), m_connections(0) { @@ -73,14 +63,6 @@ public: void add_child(CountedPtr<ObjectModel> c) { throw; } void remove_child(CountedPtr<ObjectModel> c) { throw; } - inline float min_val() const { return m_min_val; } - inline float user_min() const { return atof(get_metadata("min").c_str()); } // FIXME: haaack - //inline void user_min(float f) { m_user_min = f; } - inline float default_val() const { return m_default_val; } - inline void default_val(float f) { m_default_val = f; } - inline float max_val() const { return m_max_val; } - inline float user_max() const { return atof(get_metadata("max").c_str()); } - //inline void user_max(float f) { m_user_max = f; } inline float value() const { return m_current_val; } inline void value(float f) { m_current_val = f; control_change_sig.emit(f); } inline bool connected() { return (m_connections > 0); } @@ -96,7 +78,7 @@ public: inline bool is_toggle() const { return (m_hint == TOGGLE); } inline bool operator==(const PortModel& pm) - { return (m_path == pm.m_path); } + { return (_path == pm._path); } void connected_to(CountedPtr<PortModel> p) { ++m_connections; connection_sig.emit(p); } void disconnected_from(CountedPtr<PortModel> p) { --m_connections; disconnection_sig.emit(p); } @@ -114,11 +96,6 @@ private: Type m_type; Direction m_direction; Hint m_hint; - float m_default_val; - float m_min_val; - //float m_user_min; - float m_max_val; - //float m_user_max; float m_current_val; size_t m_connections; }; diff --git a/src/libs/client/SigClientInterface.h b/src/libs/client/SigClientInterface.h index cef7d27d..a28b1a1d 100644 --- a/src/libs/client/SigClientInterface.h +++ b/src/libs/client/SigClientInterface.h @@ -55,7 +55,7 @@ public: sigc::signal<void, string> object_destroyed_sig; sigc::signal<void, string, string> connection_sig; sigc::signal<void, string, string> disconnection_sig; - sigc::signal<void, string, string, string> metadata_update_sig; + sigc::signal<void, string, string, Atom> metadata_update_sig; sigc::signal<void, string, float> control_change_sig; sigc::signal<void, string, uint32_t, uint32_t, string> program_add_sig; sigc::signal<void, string, uint32_t, uint32_t> program_remove_sig; diff --git a/src/libs/client/Store.cpp b/src/libs/client/Store.cpp index df0bdd95..e2637c0f 100644 --- a/src/libs/client/Store.cpp +++ b/src/libs/client/Store.cpp @@ -212,11 +212,11 @@ void Store::destruction_event(const Path& path) { CountedPtr<ObjectModel> removed = remove_object(path); - removed->controller().reset(); - cerr << "Store removed object " << path - << " controller count: " << removed->controller().use_count(); + removed.reset(); - cerr << ", model count: " << removed.use_count() << endl; + + cerr << "Store removed object " << path + << ", count: " << removed.use_count(); } void @@ -244,12 +244,10 @@ Store::new_node_event(const string& plugin_type, const string& plugin_uri, const CountedPtr<PluginModel> plug = plugin(plugin_uri); if (!plug) { - CountedPtr<NodeModel> n(new NodeModel(plugin_uri, node_path)); - n->polyphonic(is_polyphonic); + CountedPtr<NodeModel> n(new NodeModel(plugin_uri, node_path, is_polyphonic)); add_plugin_orphan(n); } else { - CountedPtr<NodeModel> n(new NodeModel(plug, node_path)); - n->polyphonic(is_polyphonic); + CountedPtr<NodeModel> n(new NodeModel(plug, node_path, is_polyphonic)); add_object(n); } } @@ -292,7 +290,7 @@ Store::patch_disabled_event(const Path& path) void -Store::metadata_update_event(const Path& subject_path, const string& predicate, const string& value) +Store::metadata_update_event(const Path& subject_path, const string& predicate, const Atom& value) { CountedPtr<ObjectModel> subject = object(subject_path); if (subject) diff --git a/src/libs/client/Store.h b/src/libs/client/Store.h index e70c5bc0..99466b1d 100644 --- a/src/libs/client/Store.h +++ b/src/libs/client/Store.h @@ -24,6 +24,7 @@ #include "util/CountedPtr.h" #include <sigc++/sigc++.h> #include "util/Path.h" +#include "util/Atom.h" using std::string; using std::map; using std::list; namespace Ingen { @@ -75,7 +76,7 @@ private: void new_port_event(const Path& path, const string& data_type, bool is_output); void patch_enabled_event(const Path& path); void patch_disabled_event(const Path& path); - void metadata_update_event(const Path& subject_path, const string& predicate, const string& value); + void metadata_update_event(const Path& subject_path, const string& predicate, const Atom& value); void control_change_event(const Path& port_path, float value); void connection_event(const Path& src_port_path, const Path& dst_port_path); void disconnection_event(const Path& src_port_path, const Path& dst_port_path); diff --git a/src/libs/client/ThreadedSigClientInterface.h b/src/libs/client/ThreadedSigClientInterface.h index 5a677034..981b038d 100644 --- a/src/libs/client/ThreadedSigClientInterface.h +++ b/src/libs/client/ThreadedSigClientInterface.h @@ -23,6 +23,7 @@ #include "interface/ClientInterface.h" #include "SigClientInterface.h" #include "util/Queue.h" +#include "util/Atom.h" using std::string; /** Returns nothing and takes no parameters (because they have all been bound) */ @@ -114,7 +115,7 @@ public: void disconnection(string src_port_path, string dst_port_path) { push_sig(sigc::bind(disconnection_slot, src_port_path, dst_port_path)); } - void metadata_update(string path, string key, string value) + void metadata_update(string path, string key, Atom value) { push_sig(sigc::bind(metadata_update_slot, path, key, value)); } void control_change(string port_path, float value) @@ -151,7 +152,7 @@ private: sigc::slot<void, string> object_destroyed_slot; sigc::slot<void, string, string> object_renamed_slot; sigc::slot<void, string, string> disconnection_slot; - sigc::slot<void, string, string, string> metadata_update_slot; + sigc::slot<void, string, string, Atom> metadata_update_slot; sigc::slot<void, string, float> control_change_slot; sigc::slot<void, string, uint32_t, uint32_t, string> program_add_slot; sigc::slot<void, string, uint32_t, uint32_t> program_remove_slot; diff --git a/src/libs/engine/ClientBroadcaster.cpp b/src/libs/engine/ClientBroadcaster.cpp index 1b4a2bd2..7a21c38b 100644 --- a/src/libs/engine/ClientBroadcaster.cpp +++ b/src/libs/engine/ClientBroadcaster.cpp @@ -258,7 +258,7 @@ ClientBroadcaster::send_patch_disable(const string& patch_path) * Like control changes, does not send update to client that set the metadata, if applicable. */ void -ClientBroadcaster::send_metadata_update(const string& node_path, const string& key, const string& value) +ClientBroadcaster::send_metadata_update(const string& node_path, const string& key, const Atom& value) { for (ClientList::const_iterator i = _clients.begin(); i != _clients.end(); ++i) (*i).second->metadata_update(node_path, key, value); diff --git a/src/libs/engine/ClientBroadcaster.h b/src/libs/engine/ClientBroadcaster.h index ed4bec4e..47ad75b4 100644 --- a/src/libs/engine/ClientBroadcaster.h +++ b/src/libs/engine/ClientBroadcaster.h @@ -82,7 +82,7 @@ public: void send_all_objects(); void send_patch_enable(const string& patch_path); void send_patch_disable(const string& patch_path); - void send_metadata_update(const string& node_path, const string& key, const string& value); + void send_metadata_update(const string& node_path, const string& key, const Atom& value); void send_control_change(const string& port_path, float value); void send_program_add(const string& node_path, int bank, int program, const string& name); void send_program_remove(const string& node_path, int bank, int program); diff --git a/src/libs/engine/DSSINode.h b/src/libs/engine/DSSINode.h index 3c8dc841..1ef58d58 100644 --- a/src/libs/engine/DSSINode.h +++ b/src/libs/engine/DSSINode.h @@ -37,7 +37,7 @@ class DSSINode : public LADSPANode { public: - typedef map<int, string> Bank; + typedef std::map<int, string> Bank; DSSINode(const Plugin* plugin, const string& name, size_t poly, Patch* parent, DSSI_Descriptor* descriptor, SampleRate srate, size_t buffer_size); ~DSSINode(); @@ -57,7 +57,7 @@ public: bool update_programs(bool send_events); void set_default_program(); - const map<int, Bank>& get_programs() const; + const std::map<int, Bank>& get_programs() const; //void send_creation_messages(ClientInterface* client) const; @@ -90,10 +90,10 @@ private: lo_address _ui_addr; // Current values - int _bank; - int _program; - map<string, string> _configures; - map<int, Bank> _banks; + int _bank; + int _program; + std::map<string, string> _configures; + std::map<int, Bank> _banks; InputPort<MidiMessage>* _midi_in_port; snd_seq_event_t* _alsa_events; diff --git a/src/libs/engine/GraphObject.h b/src/libs/engine/GraphObject.h index 3b0c27b1..4f72a2e6 100644 --- a/src/libs/engine/GraphObject.h +++ b/src/libs/engine/GraphObject.h @@ -23,8 +23,9 @@ #include <cassert> #include "MaidObject.h" #include "util/Path.h" +#include "util/Atom.h" #include "types.h" -using std::string; using std::map; +using std::string; namespace Ingen { @@ -45,6 +46,8 @@ class ObjectStore; class GraphObject : public MaidObject { public: + typedef std::map<string, Atom> MetadataMap; + GraphObject(GraphObject* parent, const string& name) : _parent(parent), _name(name) { @@ -67,16 +70,16 @@ public: assert(_name.find("/") == string::npos); } - void set_metadata(const string& key, const string& value) + void set_metadata(const string& key, const Atom& value) { _metadata[key] = value; } - const string& get_metadata(const string& key) { - static const string empty_string = ""; - map<string, string>::iterator i = _metadata.find(key); - return (i != _metadata.end()) ? (*i).second : empty_string; + const Atom& get_metadata(const string& key) { + static Atom null_atom; + MetadataMap::iterator i = _metadata.find(key); + return (i != _metadata.end()) ? (*i).second : null_atom; } - const map<string, string>& metadata() const { return _metadata; } + const MetadataMap& metadata() const { return _metadata; } /** Patch and Node override this to recursively add their children. */ @@ -104,7 +107,7 @@ private: GraphObject(const GraphObject&); GraphObject& operator=(const GraphObject& copy); - map<string, string> _metadata; + MetadataMap _metadata; }; diff --git a/src/libs/engine/LADSPANode.cpp b/src/libs/engine/LADSPANode.cpp index 76550d0b..00cfd450 100644 --- a/src/libs/engine/LADSPANode.cpp +++ b/src/libs/engine/LADSPANode.cpp @@ -123,11 +123,10 @@ LADSPANode::instantiate() ((TypedPort<Sample>*)port)->set_value(0.0f, 0); } - char tmp_buf[16]; - snprintf(tmp_buf, 16, "%f", min); - port->set_metadata("min", tmp_buf); - snprintf(tmp_buf, 16, "%f", max); - port->set_metadata("max", tmp_buf); + if (port->is_input() && port->buffer_size() == 1) { + port->set_metadata("min", min); + port->set_metadata("max", max); + } } return true; diff --git a/src/libs/engine/OSCClientSender.cpp b/src/libs/engine/OSCClientSender.cpp index 068c461a..538630c0 100644 --- a/src/libs/engine/OSCClientSender.cpp +++ b/src/libs/engine/OSCClientSender.cpp @@ -29,7 +29,7 @@ #include "AudioDriver.h" #include "interface/ClientInterface.h" #include "Responder.h" - +#include "util/LibloAtom.h" using std::cout; using std::cerr; using std::endl; namespace Ingen { @@ -421,9 +421,13 @@ OSCClientSender::disconnection(string src_port_path, string dst_port_path) * \arg \b value (string)</p> \n \n */ void -OSCClientSender::metadata_update(string path, string key, string value) +OSCClientSender::metadata_update(string path, string key, Atom value) { - lo_send(_address, "/om/metadata/update", "sss", path.c_str(), key.c_str(), value.c_str()); + lo_message m = lo_message_new(); + lo_message_add_string(m, path.c_str()); + lo_message_add_string(m, key.c_str()); + LibloAtom::lo_message_add_atom(m, value); + lo_send_message(_address, "/om/metadata/update", m); } diff --git a/src/libs/engine/OSCClientSender.h b/src/libs/engine/OSCClientSender.h index e2404c1a..260dba63 100644 --- a/src/libs/engine/OSCClientSender.h +++ b/src/libs/engine/OSCClientSender.h @@ -107,7 +107,7 @@ public: virtual void metadata_update(string subject_path, string predicate, - string value); + Atom value); virtual void control_change(string port_path, float value); diff --git a/src/libs/engine/OSCEngineReceiver.cpp b/src/libs/engine/OSCEngineReceiver.cpp index 2eb68d70..afed89fd 100644 --- a/src/libs/engine/OSCEngineReceiver.cpp +++ b/src/libs/engine/OSCEngineReceiver.cpp @@ -22,6 +22,7 @@ #include "types.h" #include "util/Queue.h" #include "util/CountedPtr.h" +#include "util/LibloAtom.h" #include "QueuedEventSource.h" #include "interface/ClientKey.h" #include "interface/ClientInterface.h" @@ -106,7 +107,7 @@ OSCEngineReceiver::OSCEngineReceiver(CountedPtr<Engine> engine, size_t queue_siz #endif lo_server_add_method(_server, "/om/metadata/request", "isss", metadata_get_cb, this); - lo_server_add_method(_server, "/om/metadata/set", "isss", metadata_set_cb, this); + lo_server_add_method(_server, "/om/metadata/set", NULL, metadata_set_cb, this); // Queries lo_server_add_method(_server, "/om/request/plugins", "i", request_plugins_cb, this); @@ -758,9 +759,13 @@ OSCEngineReceiver::m_lash_restore_done_cb(const char* path, const char* types, l int OSCEngineReceiver::m_metadata_set_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { + if (argc != 4 || types[0] != 'i' || types[1] != 's' || types[2] != 's') + return 1; + const char* node_path = &argv[1]->s; const char* key = &argv[2]->s; - const char* value = &argv[3]->s; + + Atom value = LibloAtom::lo_arg_to_atom(types[3], argv[3]); set_metadata(node_path, key, value); diff --git a/src/libs/engine/ObjectSender.cpp b/src/libs/engine/ObjectSender.cpp index 063a2d1d..1e6b93c5 100644 --- a/src/libs/engine/ObjectSender.cpp +++ b/src/libs/engine/ObjectSender.cpp @@ -45,8 +45,8 @@ ObjectSender::send_patch(ClientInterface* client, const Patch* patch) send_port(client, port); /* // Send metadata - const map<string, string>& data = port->metadata(); - for (map<string, string>::const_iterator i = data.begin(); i != data.end(); ++i) + const GraphObject::MetadataMap& data = port->metadata(); + for (GraphObject::MetadataMap::const_iterator i = data.begin(); i != data.end(); ++i) client->metadata_update(port->path(), (*i).first, (*i).second); // Control port, send value @@ -64,8 +64,8 @@ ObjectSender::send_patch(ClientInterface* client, const Patch* patch) // Send metadata - const map<string, string>& data = patch->metadata(); - for (map<string, string>::const_iterator j = data.begin(); j != data.end(); ++j) + const GraphObject::MetadataMap& data = patch->metadata(); + for (GraphObject::MetadataMap::const_iterator j = data.begin(); j != data.end(); ++j) client->metadata_update(patch->path(), (*j).first, (*j).second); if (patch->enabled()) @@ -118,8 +118,8 @@ ObjectSender::send_node(ClientInterface* client, const Node* node) client->bundle_end(); // Send metadata - const map<string, string>& data = node->metadata(); - for (map<string, string>::const_iterator j = data.begin(); j != data.end(); ++j) + const GraphObject::MetadataMap& data = node->metadata(); + for (GraphObject::MetadataMap::const_iterator j = data.begin(); j != data.end(); ++j) client->metadata_update(node->path(), (*j).first, (*j).second); } @@ -149,8 +149,8 @@ ObjectSender::send_port(ClientInterface* client, const Port* port) } // Send metadata - const map<string, string>& data = port->metadata(); - for (map<string, string>::const_iterator j = data.begin(); j != data.end(); ++j) + const GraphObject::MetadataMap& data = port->metadata(); + for (GraphObject::MetadataMap::const_iterator j = data.begin(); j != data.end(); ++j) client->metadata_update(port->path(), (*j).first, (*j).second); } diff --git a/src/libs/engine/QueuedEngineInterface.cpp b/src/libs/engine/QueuedEngineInterface.cpp index 35e1c99a..b0903e29 100644 --- a/src/libs/engine/QueuedEngineInterface.cpp +++ b/src/libs/engine/QueuedEngineInterface.cpp @@ -275,7 +275,7 @@ QueuedEngineInterface::midi_learn(const string& node_path) void QueuedEngineInterface::set_metadata(const string& path, const string& predicate, - const string& value) + const Atom& value) { push_queued(new SetMetadataEvent(*_engine.get(), _responder, now(), path, predicate, value)); } diff --git a/src/libs/engine/QueuedEngineInterface.h b/src/libs/engine/QueuedEngineInterface.h index 1e35738f..f9aaa0b4 100644 --- a/src/libs/engine/QueuedEngineInterface.h +++ b/src/libs/engine/QueuedEngineInterface.h @@ -137,7 +137,7 @@ public: virtual void set_metadata(const string& path, const string& predicate, - const string& value); + const Atom& value); // Requests // diff --git a/src/libs/engine/events/DSSIConfigureEvent.cpp b/src/libs/engine/events/DSSIConfigureEvent.cpp index fb9dc727..9a26de0c 100644 --- a/src/libs/engine/events/DSSIConfigureEvent.cpp +++ b/src/libs/engine/events/DSSIConfigureEvent.cpp @@ -64,7 +64,7 @@ DSSIConfigureEvent::post_process() } else { string key = "dssi-configure--"; key += m_key; - _engine.broadcaster()->send_metadata_update(m_node_path, key, m_val); + _engine.broadcaster()->send_metadata_update(m_node_path, key, Atom(m_val.c_str())); } } diff --git a/src/libs/engine/events/RequestMetadataEvent.cpp b/src/libs/engine/events/RequestMetadataEvent.cpp index f6f1bdf9..aaea89c6 100644 --- a/src/libs/engine/events/RequestMetadataEvent.cpp +++ b/src/libs/engine/events/RequestMetadataEvent.cpp @@ -31,7 +31,6 @@ RequestMetadataEvent::RequestMetadataEvent(Engine& engine, CountedPtr<Responder> : QueuedEvent(engine, responder, timestamp), m_path(node_path), m_key(key), - m_value(""), m_object(NULL), m_client(CountedPtr<ClientInterface>()) { @@ -61,8 +60,8 @@ void RequestMetadataEvent::post_process() { if (m_client) { - if (m_value == "") { - string msg = "Unable to find object "; + if (!m_object) { + string msg = "Unable to find metadata subject "; msg += m_path; _responder->respond_error(msg); } else { diff --git a/src/libs/engine/events/RequestMetadataEvent.h b/src/libs/engine/events/RequestMetadataEvent.h index 4f99e023..f4296ac2 100644 --- a/src/libs/engine/events/RequestMetadataEvent.h +++ b/src/libs/engine/events/RequestMetadataEvent.h @@ -19,7 +19,7 @@ #include <string> #include "QueuedEvent.h" - +#include "util/Atom.h" using std::string; namespace Ingen { @@ -45,8 +45,8 @@ public: private: string m_path; string m_key; - string m_value; - GraphObject* m_object; + Atom m_value; + GraphObject* m_object; CountedPtr<ClientInterface> m_client; }; diff --git a/src/libs/engine/events/SetMetadataEvent.cpp b/src/libs/engine/events/SetMetadataEvent.cpp index db8e0118..c4937df5 100644 --- a/src/libs/engine/events/SetMetadataEvent.cpp +++ b/src/libs/engine/events/SetMetadataEvent.cpp @@ -27,7 +27,7 @@ using std::string; namespace Ingen { -SetMetadataEvent::SetMetadataEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, const string& key, const string& value) +SetMetadataEvent::SetMetadataEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, const string& key, const Atom& value) : QueuedEvent(engine, responder, timestamp), m_path(path), m_key(key), diff --git a/src/libs/engine/events/SetMetadataEvent.h b/src/libs/engine/events/SetMetadataEvent.h index 855aeb62..b78f2502 100644 --- a/src/libs/engine/events/SetMetadataEvent.h +++ b/src/libs/engine/events/SetMetadataEvent.h @@ -19,6 +19,7 @@ #include <string> #include "QueuedEvent.h" +#include "util/Atom.h" using std::string; @@ -34,16 +35,16 @@ class GraphObject; class SetMetadataEvent : public QueuedEvent { public: - SetMetadataEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, const string& key, const string& value); + SetMetadataEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, const string& key, const Atom& value); void pre_process(); void execute(SampleCount nframes, FrameTime start, FrameTime end); void post_process(); private: - string m_path; - string m_key; - string m_value; + string m_path; + string m_key; + Atom m_value; GraphObject* m_object; }; diff --git a/src/progs/demolition/demolition.cpp b/src/progs/demolition/demolition.cpp index e5ffded0..27da5dd9 100644 --- a/src/progs/demolition/demolition.cpp +++ b/src/progs/demolition/demolition.cpp @@ -183,11 +183,8 @@ create_patch() engine->create_patch_from_model(pm); // Spread them out a bit for easier monitoring with ingenuity - char tmp_buf[8]; - snprintf(tmp_buf, 8, "%d", 1600 + rand()%800 - 400); - engine->set_metadata(pm->path(), "module-x", string(tmp_buf)); - snprintf(tmp_buf, 8, "%d", 1200 + rand()%700 - 350); - engine->set_metadata(pm->path(), "module-y", string(tmp_buf)); + engine->set_metadata(pm->path(), "module-x", 1600 + rand()%800 - 400); + engine->set_metadata(pm->path(), "module-y", 1200 + rand()%700 - 350); delete pm; } @@ -225,12 +222,10 @@ add_node() NodeModel* nm = new NodeModel(plugin, parent->path() +"/"+ random_name()); cout << "Adding node " << nm->path() << endl; engine->create_node_from_model(nm); + // Spread them out a bit for easier monitoring with ingenuity - char tmp_buf[8]; - snprintf(tmp_buf, 8, "%d", 1600 + rand()%800 - 400); - engine->set_metadata(nm->path(), "module-x", tmp_buf); - snprintf(tmp_buf, 8, "%d", 1200 + rand()%700 - 350); - engine->set_metadata(nm->path(), "module-y", tmp_buf); + engine->set_metadata(pm->path(), "module-x", 1600 + rand()%800 - 400); + engine->set_metadata(pm->path(), "module-y", 1200 + rand()%700 - 350); } } diff --git a/src/progs/ingenuity/App.cpp b/src/progs/ingenuity/App.cpp index ae452f27..60482d77 100644 --- a/src/progs/ingenuity/App.cpp +++ b/src/progs/ingenuity/App.cpp @@ -25,11 +25,6 @@ #include "OmModule.h" #include "ControlPanel.h" #include "SubpatchModule.h" -#include "OmFlowCanvas.h" -#include "GtkObjectController.h" -#include "PatchController.h" -#include "NodeController.h" -#include "PortController.h" #include "LoadPluginWindow.h" #include "PatchWindow.h" #include "MessagesWindow.h" diff --git a/src/progs/ingenuity/App.h b/src/progs/ingenuity/App.h index 25e01ff2..d166c37b 100644 --- a/src/progs/ingenuity/App.h +++ b/src/progs/ingenuity/App.h @@ -45,10 +45,6 @@ using namespace Ingen::Client; namespace Ingenuity { class PatchWindow; -class GtkObjectController; -class PatchController; -class NodeController; -class PortController; class LoadPatchWindow; class MessagesWindow; class ConfigWindow; diff --git a/src/progs/ingenuity/BreadCrumb.h b/src/progs/ingenuity/BreadCrumb.h index 66e6d40a..908e0f80 100644 --- a/src/progs/ingenuity/BreadCrumb.h +++ b/src/progs/ingenuity/BreadCrumb.h @@ -17,31 +17,44 @@ #ifndef BREADCRUMB_H #define BREADCRUMB_H -// FIXME: remove -#include <iostream> -using std::cerr; using std::endl; - #include <gtkmm.h> #include "util/Path.h" +#include "util/CountedPtr.h" +#include "PatchView.h" namespace Ingenuity { /** Breadcrumb button in a PatchWindow. * + * Each Breadcrumb stores a reference to a PatchView for quick switching. + * So, the amount of allocated PatchViews at a given time is equal to the + * number of visible breadcrumbs (which is the perfect cache for GUI + * responsiveness balanced with mem consumption). + * * \ingroup Ingenuity */ class BreadCrumb : public Gtk::ToggleButton { public: - BreadCrumb(const Path& path) - : m_path(path) + BreadCrumb(const Path& path, CountedPtr<PatchView> view = CountedPtr<PatchView>()) + : _path(path) + , _view(view) { + assert( !view || view->patch()->path() == path); set_border_width(0); set_path(path); show_all(); } + void set_view(CountedPtr<PatchView> view) { + assert( !view || view->patch()->path() == _path); + _view = view; + } + + const Path& path() const { return _path; } + CountedPtr<PatchView> view() const { return _view; } + void set_path(const Path& path) { remove(); @@ -50,12 +63,14 @@ public: lab->set_padding(0, 0); lab->show(); add(*lab); + + if (_view && _view->patch()->path() != path) + _view.reset(); } - const Path& path() { return m_path; } - private: - Path m_path; + Path _path; + CountedPtr<PatchView> _view; }; } // namespace Ingenuity diff --git a/src/progs/ingenuity/BreadCrumbBox.cpp b/src/progs/ingenuity/BreadCrumbBox.cpp index aea1cdf0..8dc0b8a0 100644 --- a/src/progs/ingenuity/BreadCrumbBox.cpp +++ b/src/progs/ingenuity/BreadCrumbBox.cpp @@ -34,7 +34,7 @@ BreadCrumbBox::BreadCrumbBox() * children preserved. */ void -BreadCrumbBox::build(Path path) +BreadCrumbBox::build(Path path, CountedPtr<PatchView> view) { bool old_enable_signal = _enable_signal; _enable_signal = false; @@ -42,14 +42,39 @@ BreadCrumbBox::build(Path path) // Moving to a path we already contain, just switch the active button if (_breadcrumbs.size() > 0 && (path.is_parent_of(_full_path) || path == _full_path)) { - for (std::list<BreadCrumb*>::iterator i = _breadcrumbs.begin(); i != _breadcrumbs.end(); ++i) - (*i)->set_active( ((*i)->path() == path) ); + for (std::list<BreadCrumb*>::iterator i = _breadcrumbs.begin(); i != _breadcrumbs.end(); ++i) { + if ((*i)->path() == path) { + (*i)->set_active(true); + (*i)->set_view(view); + } else { + (*i)->set_active(false); + } + } _active_path = path; _enable_signal = old_enable_signal; return; } + // Moving to a child of the full path, just append crumbs (preserve view cache) + if (_breadcrumbs.size() > 0 && (path.is_child_of(_full_path))) { + string postfix = path.substr(_full_path.length()); + while (postfix.length() > 0) { + const string name = postfix.substr(0, postfix.find("/")); + cerr << "NAME: " << name << endl; + _full_path = _full_path.base() + name; + BreadCrumb* but = create_crumb(_full_path, view); + pack_end(*but, false, false, 1); + _breadcrumbs.push_back(but); + if (postfix.find("/") == string::npos) + break; + else + postfix = postfix.substr(postfix.find("/")+1); + } + } + + // Getting here is bad unless absolutely necessary, since the PatchView cache is lost + // Otherwise rebuild from scratch _full_path = path; _active_path = path; @@ -60,18 +85,14 @@ BreadCrumbBox::build(Path path) _breadcrumbs.clear(); // Add root - BreadCrumb* but = manage(new BreadCrumb("/")); - but->signal_toggled().connect(sigc::bind(sigc::mem_fun( - this, &BreadCrumbBox::breadcrumb_clicked), but)); + BreadCrumb* but = create_crumb("/", view); pack_start(*but, false, false, 1); _breadcrumbs.push_front(but); but->set_active(but->path() == _active_path); // Add the others while (path != "/") { - BreadCrumb* but = manage(new BreadCrumb(path)); - but->signal_toggled().connect(sigc::bind(sigc::mem_fun( - this, &BreadCrumbBox::breadcrumb_clicked), but)); + BreadCrumb* but = create_crumb(path, view); pack_start(*but, false, false, 1); _breadcrumbs.push_front(but); but->set_active(but->path() == _active_path); @@ -84,6 +105,23 @@ BreadCrumbBox::build(Path path) } +/** Create a new crumb, assigning it a reference to @a view if their paths + * match, otherwise ignoring @a view. + */ +BreadCrumb* +BreadCrumbBox::create_crumb(const Path& path, + CountedPtr<PatchView> view) +{ + BreadCrumb* but = manage(new BreadCrumb(path, + (view && path == view->patch()->path()) ? view : CountedPtr<PatchView>())); + + but->signal_toggled().connect(sigc::bind(sigc::mem_fun( + this, &BreadCrumbBox::breadcrumb_clicked), but)); + + return but; +} + + void BreadCrumbBox::breadcrumb_clicked(BreadCrumb* crumb) { @@ -95,7 +133,7 @@ BreadCrumbBox::breadcrumb_clicked(BreadCrumb* crumb) // Tried to turn off the current active button, bad user! crumb->set_active(true); } else { - signal_patch_selected.emit(crumb->path()); + signal_patch_selected.emit(crumb->path(), crumb->view()); if (crumb->path() != _active_path) crumb->set_active(false); } diff --git a/src/progs/ingenuity/BreadCrumbBox.h b/src/progs/ingenuity/BreadCrumbBox.h index 35215e43..e38d8e49 100644 --- a/src/progs/ingenuity/BreadCrumbBox.h +++ b/src/progs/ingenuity/BreadCrumbBox.h @@ -22,10 +22,11 @@ #include <libglademm/xml.h> #include <libglademm.h> #include "util/Path.h" +#include "util/CountedPtr.h" +#include "PatchView.h" namespace Ingenuity { -class PatchController; class BreadCrumb; @@ -38,11 +39,14 @@ class BreadCrumbBox : public Gtk::HBox public: BreadCrumbBox(); - void build(Path path); + void build(Path path, CountedPtr<PatchView> view); - sigc::signal<void, const Path&> signal_patch_selected; + sigc::signal<void, const Path&, CountedPtr<PatchView> > signal_patch_selected; private: + BreadCrumb* create_crumb(const Path& path, + CountedPtr<PatchView> view = CountedPtr<PatchView>()); + void breadcrumb_clicked(BreadCrumb* crumb); void object_removed(const Path& path); diff --git a/src/progs/ingenuity/ConfigWindow.cpp b/src/progs/ingenuity/ConfigWindow.cpp index 934dcc6b..a83bfbac 100644 --- a/src/progs/ingenuity/ConfigWindow.cpp +++ b/src/progs/ingenuity/ConfigWindow.cpp @@ -19,9 +19,7 @@ #include <cassert> #include <algorithm> #include <cctype> -#include "PatchController.h" #include "NodeModel.h" -#include "OmFlowCanvas.h" using std::cout; using std::cerr; using std::endl; diff --git a/src/progs/ingenuity/Configuration.cpp b/src/progs/ingenuity/Configuration.cpp index e383cf87..0c985750 100644 --- a/src/progs/ingenuity/Configuration.cpp +++ b/src/progs/ingenuity/Configuration.cpp @@ -22,9 +22,7 @@ #include <map> #include "PortModel.h" #include "PluginModel.h" -#include "PatchController.h" #include "PatchModel.h" -#include "OmFlowCanvas.h" #include "Loader.h" #include "App.h" diff --git a/src/progs/ingenuity/ConnectWindow.cpp b/src/progs/ingenuity/ConnectWindow.cpp index df95f3c3..64d611e2 100644 --- a/src/progs/ingenuity/ConnectWindow.cpp +++ b/src/progs/ingenuity/ConnectWindow.cpp @@ -25,8 +25,6 @@ #include "OSCClientReceiver.h" #include "ThreadedSigClientInterface.h" #include "Store.h" -#include "ControllerFactory.h" -#include "PatchController.h" #include "PatchModel.h" #include "App.h" #include "WindowFactory.h" @@ -353,8 +351,7 @@ ConnectWindow::gtk_callback() if (App::instance().store()->num_objects() > 0) { CountedPtr<PatchModel> root = PtrCast<PatchModel>(App::instance().store()->object("/")); assert(root); - CountedPtr<PatchController> root_c = PtrCast<PatchController>(ControllerFactory::get_controller(root)); - App::instance().window_factory()->present(root_c); + App::instance().window_factory()->present_patch(root); ++stage; } } else if (stage == 8) { diff --git a/src/progs/ingenuity/ControlGroups.cpp b/src/progs/ingenuity/ControlGroups.cpp index 45218bdf..06f49f86 100644 --- a/src/progs/ingenuity/ControlGroups.cpp +++ b/src/progs/ingenuity/ControlGroups.cpp @@ -53,13 +53,12 @@ ControlGroup::ControlGroup(ControlPanel* panel, CountedPtr<PortModel> pm, bool s void -ControlGroup::metadata_update(const string& key, const string& value) +ControlGroup::metadata_update(const string& key, const Atom& value) { - // FIXME: this isn't right - if (key == "user-min" || key == "min") - set_min(atof(value.c_str())); - else if (key == "user-max" || key == "max") - set_max(atof(value.c_str())); + if ( (key == "min") && value.type() == Atom::FLOAT) + set_min(value.get_float()); + else if ( (key == "max") && value.type() == Atom::FLOAT) + set_max(value.get_float()); } @@ -77,17 +76,20 @@ SliderControlGroup::SliderControlGroup(ControlPanel* panel, CountedPtr<PortModel m_max_spinner(1.0, (pm->is_integer() ? 0 : 4)), m_slider_box(false, 0), m_value_spinner(1.0, (pm->is_integer() ? 0 : 4)), - m_slider(pm->user_min(), pm->user_max(), (pm->is_integer() ? 1.0 : 0.0001)) + m_slider(0, 1, (pm->is_integer() ? 1.0 : 0.0001)) { m_slider.set_increments(1.0, 10.0); - // Compensate for crazy plugins - // FIXME - /* - if (m_port_model->user_max() <= m_port_model->user_min()) { - m_port_model->user_max(m_port_model->user_min() + 1.0); - m_slider.set_range(m_port_model->user_min(), m_port_model->user_max()); - }*/ + float min = 0.0f; + float max = 1.0f; + + const Atom& min_atom = pm->get_metadata("min"); + const Atom& max_atom = pm->get_metadata("max"); + if (min_atom.type() == Atom::FLOAT && max_atom.type() == Atom::FLOAT) { + min = min_atom.get_float(); + max = max_atom.get_float(); + } + m_slider.property_draw_value() = false; set_name(pm->path().name()); @@ -103,12 +105,12 @@ SliderControlGroup::SliderControlGroup(ControlPanel* panel, CountedPtr<PortModel m_value_spinner.signal_value_changed().connect( sigc::mem_fun(*this, &SliderControlGroup::update_value_from_spinner)); m_min_spinner.set_range(-99999, 99999); - m_min_spinner.set_value(m_port_model->user_min()); + m_min_spinner.set_value(min); m_min_spinner.set_increments(1.0, 10.0); m_min_spinner.set_digits(5); m_min_spinner.signal_value_changed().connect(sigc::mem_fun(*this, &SliderControlGroup::min_changed)); m_max_spinner.set_range(-99999, 99999); - m_max_spinner.set_value(m_port_model->user_max()); + m_max_spinner.set_value(max); m_max_spinner.set_increments(1.0, 10.0); m_max_spinner.set_digits(5); m_max_spinner.signal_value_changed().connect(sigc::mem_fun(*this, &SliderControlGroup::max_changed)); @@ -135,7 +137,7 @@ SliderControlGroup::SliderControlGroup(ControlPanel* panel, CountedPtr<PortModel pack_start(m_header_box, false, false, 0); pack_start(m_slider_box, false, false, 0); - m_slider.set_range(m_port_model->user_min(), m_port_model->user_max()); + m_slider.set_range(min, max); m_enable_signal = true; @@ -210,7 +212,7 @@ SliderControlGroup::min_changed() if (m_enable_signal) { char temp_buf[16]; snprintf(temp_buf, 16, "%f", min); - App::instance().engine()->set_metadata(m_port_model->path(), "user-min", temp_buf); + App::instance().engine()->set_metadata(m_port_model->path(), "min", temp_buf); } } @@ -231,7 +233,7 @@ SliderControlGroup::max_changed() if (m_enable_signal) { char temp_buf[16]; snprintf(temp_buf, 16, "%f", max); - App::instance().engine()->set_metadata(m_port_model->path(), "user-max", temp_buf); + App::instance().engine()->set_metadata(m_port_model->path(), "max", temp_buf); } } diff --git a/src/progs/ingenuity/ControlGroups.h b/src/progs/ingenuity/ControlGroups.h index a5b3d1f5..3193fa71 100644 --- a/src/progs/ingenuity/ControlGroups.h +++ b/src/progs/ingenuity/ControlGroups.h @@ -58,7 +58,7 @@ protected: virtual void set_min(float val) {} virtual void set_max(float val) {} - virtual void metadata_update(const string& key, const string& value); + virtual void metadata_update(const string& key, const Atom& value); ControlPanel* m_control_panel; CountedPtr<PortModel> m_port_model; diff --git a/src/progs/ingenuity/ControlPanel.cpp b/src/progs/ingenuity/ControlPanel.cpp index 90d17c8a..94945e28 100644 --- a/src/progs/ingenuity/ControlPanel.cpp +++ b/src/progs/ingenuity/ControlPanel.cpp @@ -21,7 +21,6 @@ #include "NodeModel.h" #include "PortModel.h" #include "ControlGroups.h" -#include "PatchController.h" namespace Ingenuity { @@ -52,21 +51,18 @@ ControlPanel::~ControlPanel() void -ControlPanel::init(NodeController* node, size_t poly) +ControlPanel::init(CountedPtr<NodeModel> node, size_t poly) { assert(node != NULL); assert(poly > 0); - const CountedPtr<NodeModel> node_model(node->node_model()); - if (poly > 1) { m_voice_spinbutton->set_range(0, poly - 1); } else { remove(*m_voice_control_box); } - for (PortModelList::const_iterator i = node_model->ports().begin(); - i != node_model->ports().end(); ++i) { + for (PortModelList::const_iterator i = node->ports().begin(); i != node->ports().end(); ++i) { add_port(*i); } diff --git a/src/progs/ingenuity/ControlPanel.h b/src/progs/ingenuity/ControlPanel.h index 025468d5..e1ace50a 100644 --- a/src/progs/ingenuity/ControlPanel.h +++ b/src/progs/ingenuity/ControlPanel.h @@ -27,7 +27,6 @@ #include <utility> // for pair<> #include "ControlGroups.h" #include "util/Path.h" -#include "PortController.h" using std::vector; using std::string; using std::pair; using std::cerr; using std::cout; using std::endl; @@ -40,9 +39,6 @@ using namespace Ingen::Client; namespace Ingenuity { -class NodeController; -class PortController; - /** A group of controls for a node (or patch). * @@ -55,7 +51,7 @@ public: ControlPanel(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& glade_xml); virtual ~ControlPanel(); - void init(NodeController* node, size_t poly); + void init(CountedPtr<NodeModel> node, size_t poly); ControlGroup* find_port(const Path& path) const; diff --git a/src/progs/ingenuity/ControllerFactory.cpp b/src/progs/ingenuity/ControllerFactory.cpp deleted file mode 100644 index b95bef5b..00000000 --- a/src/progs/ingenuity/ControllerFactory.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "ControllerFactory.h" -#include "NodeModel.h" -#include "PatchModel.h" -#include "PortModel.h" -#include "NodeController.h" -#include "PatchController.h" -#include "PortController.h" -#include "DSSIController.h" - -namespace Ingenuity { - - -CountedPtr<GtkObjectController> -ControllerFactory::get_controller(CountedPtr<ObjectModel> model) -{ - CountedPtr<PatchModel> patch_m = PtrCast<PatchModel>(model); - if (patch_m && patch_m->controller()) { - assert(dynamic_cast<PatchController*>(patch_m->controller().get())); - return PtrCast<GtkObjectController>(patch_m->controller()); - } else if (patch_m) { - CountedPtr<PatchController> pc(new PatchController(patch_m)); - patch_m->set_controller(pc); - return pc; - } - - CountedPtr<NodeModel> node_m = PtrCast<NodeModel>(model); - if (node_m && node_m->controller()) { - assert(dynamic_cast<NodeController*>(node_m->controller().get())); - return PtrCast<GtkObjectController>(node_m->controller()); - } else if (node_m) { - if (node_m->plugin()->type() == PluginModel::DSSI) { - CountedPtr<NodeController> nc(new DSSIController(node_m)); - node_m->set_controller(nc); - return nc; - } else { - CountedPtr<NodeController> nc(new NodeController(node_m)); - node_m->set_controller(nc); - return nc; - } - } - - CountedPtr<PortModel> port_m = PtrCast<PortModel>(model); - if (port_m && port_m->controller()) { - assert(dynamic_cast<PortController*>(port_m->controller().get())); - return PtrCast<GtkObjectController>(port_m->controller()); - } else if (port_m) { - CountedPtr<PortController> pc(new PortController(port_m)); - port_m->set_controller(pc); - return pc; - } - - return CountedPtr<GtkObjectController>(); -} - - -} // namespace Ingenuity diff --git a/src/progs/ingenuity/ControllerFactory.h b/src/progs/ingenuity/ControllerFactory.h deleted file mode 100644 index 7f48c262..00000000 --- a/src/progs/ingenuity/ControllerFactory.h +++ /dev/null @@ -1,32 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef CONTROLLER_FACTORY_H -#define CONTROLLER_FACTORY_H - -#include "util/CountedPtr.h" -#include "GtkObjectController.h" - -namespace Ingenuity { - -class ControllerFactory { -public: - static CountedPtr<GtkObjectController> get_controller(CountedPtr<ObjectModel> model); -}; - -} - -#endif // CONTROLLER_FACTORY_H diff --git a/src/progs/ingenuity/DSSIController.cpp b/src/progs/ingenuity/DSSIController.cpp index 6bc75c70..4d5bb2f7 100644 --- a/src/progs/ingenuity/DSSIController.cpp +++ b/src/progs/ingenuity/DSSIController.cpp @@ -29,9 +29,9 @@ namespace Ingenuity { DSSIController::DSSIController(CountedPtr<NodeModel> model) -: NodeController(model), - m_banks_dirty(true) +: m_banks_dirty(true) { +#if 0 assert(model->plugin()->type() == PluginModel::DSSI); Gtk::Menu::MenuList& items = m_menu.items(); items[0].property_sensitive() = true; // "Show Control Window" item @@ -43,21 +43,24 @@ DSSIController::DSSIController(CountedPtr<NodeModel> model) items.push_front(Gtk::Menu_Helpers::MenuElem("Show Plugin GUI", sigc::mem_fun(this, &DSSIController::show_gui))); +#endif } void DSSIController::program_add(int bank, int program, const string& name) { - node_model()->add_program(bank, program, name); - m_banks_dirty = true; + cerr << "FIXME: DSSI add program\n"; + //node_model()->add_program(bank, program, name); + //m_banks_dirty = true; } void DSSIController::program_remove(int bank, int program) { - node_model()->remove_program(bank, program); - m_banks_dirty = true; + cerr << "FIXME: DSSI add program\n"; + //node_model()->remove_program(bank, program); + //m_banks_dirty = true; } /** Trivial wrapper of attempt_to_show_gui for libsigc @@ -120,22 +123,6 @@ DSSIController::send_program_change(int bank, int program) } -void -DSSIController::create_module(OmFlowCanvas* canvas) -{ - //cerr << "Creating DSSI module " << m_model->path() << endl; - - assert(canvas != NULL); - assert(m_module == NULL); - - m_module = new DSSIModule(canvas, this); - create_all_ports(); - - m_module->move_to(node_model()->x(), node_model()->y()); -} - - - /** Attempt to show the DSSI GUI for this plugin. * * Returns whether or not GUI was successfully loaded/shown. @@ -274,9 +261,11 @@ DSSIController::attempt_to_show_gui() void DSSIController::show_menu(GdkEventButton* event) { +#if 0 if (m_banks_dirty) update_program_menu(); NodeController::show_menu(event); +#endif } diff --git a/src/progs/ingenuity/DSSIController.h b/src/progs/ingenuity/DSSIController.h index 0ad26e76..3eaba91a 100644 --- a/src/progs/ingenuity/DSSIController.h +++ b/src/progs/ingenuity/DSSIController.h @@ -20,7 +20,6 @@ #include <string> #include <gtkmm.h> #include "util/Path.h" -#include "NodeController.h" using std::string; using namespace Ingen::Client; @@ -33,19 +32,17 @@ namespace Ingen { namespace Client { namespace Ingenuity { -class Controller; -class OmModule; class NodeControlWindow; class NodePropertiesWindow; -class PortController; -class OmFlowCanvas; -class DSSIModule; /* Controller for a DSSI node. * + * FIXME: legacy cruft. move this code to the appropriate places and nuke + * this class. + * * \ingroup Ingenuity */ -class DSSIController : public NodeController +class DSSIController { public: DSSIController(CountedPtr<NodeModel> model); @@ -59,8 +56,6 @@ public: void send_program_change(int bank, int program); - void create_module(OmFlowCanvas* canvas); - void show_menu(GdkEventButton* event); private: diff --git a/src/progs/ingenuity/DSSIModule.cpp b/src/progs/ingenuity/DSSIModule.cpp index 3d91e69b..5d235be4 100644 --- a/src/progs/ingenuity/DSSIModule.cpp +++ b/src/progs/ingenuity/DSSIModule.cpp @@ -20,8 +20,8 @@ namespace Ingenuity { -DSSIModule::DSSIModule(OmFlowCanvas* canvas, DSSIController* node) -: OmModule(canvas, static_cast<NodeController*>(node)) +DSSIModule::DSSIModule(OmFlowCanvas* canvas, CountedPtr<NodeModel> node) +: OmModule(canvas, node) { } @@ -29,9 +29,11 @@ DSSIModule::DSSIModule(OmFlowCanvas* canvas, DSSIController* node) void DSSIModule::on_double_click(GdkEventButton* ev) { + /* DSSIController* dc = dynamic_cast<DSSIController*>(m_node); if (!dc || ! dc->attempt_to_show_gui()) show_control_window(); + */ } diff --git a/src/progs/ingenuity/DSSIModule.h b/src/progs/ingenuity/DSSIModule.h index 7a1b0035..6cffb891 100644 --- a/src/progs/ingenuity/DSSIModule.h +++ b/src/progs/ingenuity/DSSIModule.h @@ -30,7 +30,7 @@ class DSSIController; class DSSIModule : public OmModule { public: - DSSIModule(OmFlowCanvas* canvas, DSSIController* node); + DSSIModule(OmFlowCanvas* canvas, CountedPtr<NodeModel> node); virtual ~DSSIModule() {} void on_double_click(GdkEventButton* ev); diff --git a/src/progs/ingenuity/GtkObjectController.cpp b/src/progs/ingenuity/GtkObjectController.cpp deleted file mode 100644 index ccaa3ca5..00000000 --- a/src/progs/ingenuity/GtkObjectController.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "GtkObjectController.h" - -namespace Ingenuity { - - -GtkObjectController::GtkObjectController(CountedPtr<ObjectModel> model) -: m_model(model) -{ - assert(m_model); - model->metadata_update_sig.connect(sigc::mem_fun(this, &GtkObjectController::metadata_update)); -} - -GtkObjectController::~GtkObjectController() -{ -} - -} // namespace Ingenuity - diff --git a/src/progs/ingenuity/GtkObjectController.h b/src/progs/ingenuity/GtkObjectController.h deleted file mode 100644 index 6df13d02..00000000 --- a/src/progs/ingenuity/GtkObjectController.h +++ /dev/null @@ -1,83 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef GTKOBJECTCONTROLLER_H -#define GTKOBJECTCONTROLLER_H - -#include <string> -#include <gtkmm.h> - -#include "ObjectModel.h" -#include "ObjectController.h" -#include "util/CountedPtr.h" - -using std::string; - -using namespace Ingen::Client; - -namespace Ingenuity { - -class Controller; - - -/** Controller for an Om object. - * - * Management of the model and view are this object's responsibility. - * The view may not be created (ie in the case of patches which have never - * been shown and all their children). - * - * \ingroup Ingenuity - */ -class GtkObjectController : public ObjectController -{ -public: - GtkObjectController(CountedPtr<ObjectModel> model); - virtual ~GtkObjectController(); - - /** Destroy object. - * - * Object must be safe to delete immediately following the return of - * this call. - */ - virtual void destroy() = 0; - -/* - virtual void add_to_store() = 0; - virtual void remove_from_store() = 0; -*/ - - /** Derived classes should override this to handle special metadata - * keys, then call this to set the model's metadata key. - */ - virtual void metadata_update(const string& key, const string& value) - { assert(m_model->get_metadata(key) != ""); } - - /** Rename object */ - virtual void set_path(const Path& new_path) - { m_model->set_path(new_path); } - - const Path& path() const { return m_model->path(); } - - CountedPtr<ObjectModel> model() const { return m_model; } - -protected: - CountedPtr<ObjectModel> m_model; ///< Model for this object -}; - - -} // namespace Ingenuity - -#endif // GTKOBJECTCONTROLLER_H diff --git a/src/progs/ingenuity/LashController.cpp b/src/progs/ingenuity/LashController.cpp index e5807da7..0fed3cf3 100644 --- a/src/progs/ingenuity/LashController.cpp +++ b/src/progs/ingenuity/LashController.cpp @@ -22,7 +22,6 @@ #include <sys/stat.h> #include <sys/types.h> #include "App.h" -#include "PatchController.h" #include "PatchModel.h" using std::cerr; using std::cout; using std::endl; diff --git a/src/progs/ingenuity/LoadPatchWindow.cpp b/src/progs/ingenuity/LoadPatchWindow.cpp index dcc08fff..5e740aac 100644 --- a/src/progs/ingenuity/LoadPatchWindow.cpp +++ b/src/progs/ingenuity/LoadPatchWindow.cpp @@ -19,7 +19,6 @@ #include <dirent.h> #include "App.h" #include "Configuration.h" -#include "PatchController.h" #include "PatchModel.h" #include "ModelEngineInterface.h" #include "Loader.h" @@ -60,14 +59,23 @@ LoadPatchWindow::LoadPatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gno } +void +LoadPatchWindow::present(CountedPtr<PatchModel> patch, MetadataMap data) +{ + set_patch(patch); + m_initial_data = data; + Gtk::Window::present(); +} + + /** Sets the patch controller for this window and initializes everything. * * This function MUST be called before using the window in any way! */ void -LoadPatchWindow::set_patch(CountedPtr<PatchController> pc) +LoadPatchWindow::set_patch(CountedPtr<PatchModel> patch) { - m_patch_controller = pc; + m_patch = patch; } @@ -108,12 +116,13 @@ LoadPatchWindow::ok_clicked() poly = m_poly_spinbutton->get_value_as_int(); if (m_replace) - App::instance().engine()->clear_patch(m_patch_controller->model()->path()); + App::instance().engine()->clear_patch(m_patch->path()); - CountedPtr<PatchModel> pm(new PatchModel(m_patch_controller->model()->path(), poly)); + CountedPtr<PatchModel> pm(new PatchModel(m_patch->path(), poly)); pm->filename(get_filename()); - pm->set_metadata("filename", get_filename()); - pm->set_parent(m_patch_controller->patch_model()->parent()); + pm->set_metadata("filename", Atom(get_filename().c_str())); + // FIXME: necessary? + //pm->set_parent(m_patch->parent()); //App::instance().engine()->push_added_patch(pm); App::instance().loader()->load_patch(pm, true, true); diff --git a/src/progs/ingenuity/LoadPatchWindow.h b/src/progs/ingenuity/LoadPatchWindow.h index e22b1c1a..2c6035c8 100644 --- a/src/progs/ingenuity/LoadPatchWindow.h +++ b/src/progs/ingenuity/LoadPatchWindow.h @@ -22,12 +22,12 @@ #include <libglademm/xml.h> #include <gtkmm.h> #include "util/CountedPtr.h" -#include "PatchController.h" +#include "PatchModel.h" +using Ingen::Client::PatchModel; +using Ingen::Client::MetadataMap; namespace Ingenuity { -class PatchController; - /** 'Load Patch' window. * @@ -44,11 +44,13 @@ class LoadPatchWindow : public Gtk::FileChooserDialog public: LoadPatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& xml); - void set_patch(CountedPtr<PatchController> pc); + void set_patch(CountedPtr<PatchModel> patch); void set_replace() { m_replace = true; } void set_merge() { m_replace = false; } + void present(CountedPtr<PatchModel> patch, MetadataMap data); + protected: void on_show(); @@ -58,8 +60,10 @@ private: void ok_clicked(); void cancel_clicked(); - CountedPtr<PatchController> m_patch_controller; - bool m_replace; + MetadataMap m_initial_data; + + CountedPtr<PatchModel> m_patch; + bool m_replace; Gtk::RadioButton* m_poly_from_current_radio; Gtk::RadioButton* m_poly_from_file_radio; diff --git a/src/progs/ingenuity/LoadPluginWindow.cpp b/src/progs/ingenuity/LoadPluginWindow.cpp index 2b59efef..9321b12a 100644 --- a/src/progs/ingenuity/LoadPluginWindow.cpp +++ b/src/progs/ingenuity/LoadPluginWindow.cpp @@ -19,11 +19,9 @@ #include <cassert> #include <algorithm> #include <cctype> -#include "PatchController.h" #include "NodeModel.h" #include "App.h" #include "PatchWindow.h" -#include "OmFlowCanvas.h" #include "PatchModel.h" #include "Store.h" #include "ModelEngineInterface.h" @@ -107,6 +105,15 @@ LoadPluginWindow::LoadPluginWindow(BaseObjectType* cobject, const Glib::RefPtr<G } +void +LoadPluginWindow::present(CountedPtr<PatchModel> patch, MetadataMap data) +{ + set_patch(patch); + m_initial_data = data; + Gtk::Window::present(); +} + + /** Called every time the user types into the name input box. * Used to display warning messages, and enable/disable the OK button. */ @@ -117,7 +124,7 @@ LoadPluginWindow::name_changed() if (!Path::is_valid_name(name)) { //m_message_label->set_text("Name contains invalid characters."); m_add_button->property_sensitive() = false; - } else if (m_patch_controller->patch_model()->get_node(name)) { + } else if (m_patch->get_node(name)) { //m_message_label->set_text("An object already exists with that name."); m_add_button->property_sensitive() = false; } else if (name.length() == 0) { @@ -135,11 +142,11 @@ LoadPluginWindow::name_changed() * This function MUST be called before using the window in any way! */ void -LoadPluginWindow::set_patch(CountedPtr<PatchController> pc) +LoadPluginWindow::set_patch(CountedPtr<PatchModel> patch) { - m_patch_controller = pc; + m_patch = patch; - if (pc->patch_model()->poly() <= 1) + if (patch->poly() <= 1) m_polyphonic_checkbutton->property_sensitive() = false; else m_polyphonic_checkbutton->property_sensitive() = true; @@ -161,7 +168,7 @@ LoadPluginWindow::on_show() set_plugin_list(App::instance().store()->plugins()); // Center on patch window - int m_w, m_h; + /*int m_w, m_h; get_size(m_w, m_h); int parent_x, parent_y, parent_w, parent_h; @@ -169,7 +176,7 @@ LoadPluginWindow::on_show() m_patch_controller->window()->get_size(parent_w, parent_h); move(parent_x + parent_w/2 - m_w/2, parent_y + parent_h/2 - m_h/2); - + */ m_has_shown = true; } Gtk::Window::on_show(); @@ -275,7 +282,7 @@ LoadPluginWindow::generate_module_name(int offset) name += "_"; name += num_buf; } - if (!m_patch_controller->patch_model()->get_node(name)) + if (!m_patch->get_node(name)) break; else name = ""; @@ -306,17 +313,10 @@ LoadPluginWindow::add_clicked() dialog.run(); } else { - const string path = m_patch_controller->model()->path().base() + name; - NodeModel* nm = new NodeModel(plugin, path); - nm->polyphonic(polyphonic); + const string path = m_patch->path().base() + name; + NodeModel* nm = new NodeModel(plugin, path, polyphonic); + nm->add_metadata(m_initial_data); - if (m_new_module_x == 0 && m_new_module_y == 0) { - m_patch_controller->get_view()->canvas()->get_new_module_location( - m_new_module_x, m_new_module_y); - } - nm->x(m_new_module_x); - nm->y(m_new_module_y); - App::instance().engine()->create_node_from_model(nm); ++m_plugin_name_offset; m_node_name_entry->set_text(generate_module_name(m_plugin_name_offset)); diff --git a/src/progs/ingenuity/LoadPluginWindow.h b/src/progs/ingenuity/LoadPluginWindow.h index 1654b777..0af40d05 100644 --- a/src/progs/ingenuity/LoadPluginWindow.h +++ b/src/progs/ingenuity/LoadPluginWindow.h @@ -24,12 +24,13 @@ #include <libglademm.h> #include <gtkmm.h> #include "util/CountedPtr.h" - +#include "PatchModel.h" using Ingen::Client::PluginModel; +using Ingen::Client::PatchModel; +using Ingen::Client::MetadataMap; namespace Ingenuity { -class PatchController; // Gtkmm _really_ needs to add some helper to abstract away this stupid nonsense @@ -87,15 +88,14 @@ class LoadPluginWindow : public Gtk::Window public: LoadPluginWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& xml); - void set_patch(CountedPtr<PatchController> pc); + void set_patch(CountedPtr<PatchModel> patch); void set_plugin_list(const std::map<string, CountedPtr<PluginModel> >& m); - void set_next_module_location(double x, double y) - { m_new_module_x = x; m_new_module_y = y; } - void add_plugin(CountedPtr<PluginModel> plugin); bool has_shown() const { return m_has_shown; } + void present(CountedPtr<PatchModel> patch, MetadataMap data); + protected: void on_show(); void on_hide(); @@ -113,7 +113,10 @@ private: void plugin_selection_changed(); string generate_module_name(int offset = 0); - CountedPtr<PatchController> m_patch_controller; + MetadataMap m_initial_data; + + CountedPtr<PatchModel> m_patch; + bool m_has_shown; // plugin list only populated on show to speed patch window creation Glib::RefPtr<Gtk::ListStore> m_plugins_liststore; diff --git a/src/progs/ingenuity/LoadSubpatchWindow.cpp b/src/progs/ingenuity/LoadSubpatchWindow.cpp index 486c92b4..cb7a7ef6 100644 --- a/src/progs/ingenuity/LoadSubpatchWindow.cpp +++ b/src/progs/ingenuity/LoadSubpatchWindow.cpp @@ -19,9 +19,7 @@ #include <dirent.h> #include <cassert> #include "App.h" -#include "PatchController.h" #include "PatchView.h" -#include "OmFlowCanvas.h" #include "NodeModel.h" #include "PatchModel.h" #include "Configuration.h" @@ -68,17 +66,26 @@ LoadSubpatchWindow::LoadSubpatchWindow(BaseObjectType* cobject, const Glib::RefP } +void +LoadSubpatchWindow::present(CountedPtr<PatchModel> patch, MetadataMap data) +{ + set_patch(patch); + m_initial_data = data; + Gtk::Window::present(); +} + + /** Sets the patch controller for this window and initializes everything. * * This function MUST be called before using the window in any way! */ void -LoadSubpatchWindow::set_patch(CountedPtr<PatchController> pc) +LoadSubpatchWindow::set_patch(CountedPtr<PatchModel> patch) { - m_patch_controller = pc; + m_patch = patch; char temp_buf[4]; - snprintf(temp_buf, 4, "%zd", pc->patch_model()->poly()); + snprintf(temp_buf, 4, "%zd", patch->poly()); Glib::ustring txt = "Same as parent ("; txt.append(temp_buf).append(")"); m_poly_from_parent_radio->set_label(txt); @@ -129,8 +136,7 @@ LoadSubpatchWindow::enable_poly_spinner() void LoadSubpatchWindow::ok_clicked() { - assert(m_patch_controller); - assert(m_patch_controller->model()); + assert(m_patch); const string filename = get_filename(); @@ -144,25 +150,22 @@ LoadSubpatchWindow::ok_clicked() if (m_poly_from_user_radio->get_active()) poly = m_poly_spinbutton->get_value_as_int(); else if (m_poly_from_parent_radio->get_active()) - poly = m_patch_controller->patch_model()->poly(); + poly = m_patch->poly(); if (m_new_module_x == 0 && m_new_module_y == 0) { - m_patch_controller->get_view()->canvas()->get_new_module_location( - m_new_module_x, m_new_module_y); + throw; // FIXME + //m_patch_controller->get_view()->canvas()->get_new_module_location( + // m_new_module_x, m_new_module_y); } - CountedPtr<PatchModel> pm(new PatchModel(m_patch_controller->model()->path().base() + name, poly)); + CountedPtr<PatchModel> pm(new PatchModel(m_patch->path().base() + name, poly)); pm->filename(filename); - pm->set_parent(m_patch_controller->model()); - pm->x(m_new_module_x); - pm->y(m_new_module_y); - //if (name == "") - // pm->set_path(""); - char temp_buf[16]; - snprintf(temp_buf, 16, "%16f", m_new_module_x); - pm->set_metadata("module-x", temp_buf); - snprintf(temp_buf, 16, "%16f", m_new_module_y); - pm->set_metadata("module-y", temp_buf); + // FIXME: necessary? + //pm->set_parent(m_patch); + + pm->set_metadata("module-x", Atom((float)m_new_module_x)); + pm->set_metadata("module-y", Atom((float)m_new_module_y)); + App::instance().loader()->load_patch(pm, true, false); App::instance().configuration()->set_patch_folder(pm->filename().substr(0, pm->filename().find_last_of("/"))); diff --git a/src/progs/ingenuity/LoadSubpatchWindow.h b/src/progs/ingenuity/LoadSubpatchWindow.h index e33880e8..ae65a9f4 100644 --- a/src/progs/ingenuity/LoadSubpatchWindow.h +++ b/src/progs/ingenuity/LoadSubpatchWindow.h @@ -14,7 +14,6 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef LOADSUBPATCHWINDOW_H #define LOADSUBPATCHWINDOW_H @@ -22,13 +21,12 @@ #include <libglademm/xml.h> #include <gtkmm.h> #include "util/CountedPtr.h" -#include "PatchController.h" - +#include "PatchModel.h" +using Ingen::Client::PatchModel; +using Ingen::Client::MetadataMap; namespace Ingenuity { -class PatchController; - /** 'Add Subpatch' window. * @@ -41,10 +39,9 @@ class LoadSubpatchWindow : public Gtk::FileChooserDialog public: LoadSubpatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& xml); - void set_patch(CountedPtr<PatchController> pc); + void set_patch(CountedPtr<PatchModel> patch); - void set_next_module_location(double x, double y) - { m_new_module_x = x; m_new_module_y = y; } + void present(CountedPtr<PatchModel> patch, MetadataMap data); protected: void on_show(); @@ -58,7 +55,9 @@ private: void ok_clicked(); void cancel_clicked(); - CountedPtr<PatchController> m_patch_controller; + MetadataMap m_initial_data; + + CountedPtr<PatchModel> m_patch; double m_new_module_x; double m_new_module_y; diff --git a/src/progs/ingenuity/Loader.cpp b/src/progs/ingenuity/Loader.cpp index 0ca6f966..a0f099c2 100644 --- a/src/progs/ingenuity/Loader.cpp +++ b/src/progs/ingenuity/Loader.cpp @@ -20,7 +20,6 @@ #include <string> #include "PatchLibrarian.h" #include "PatchModel.h" -#include "PatchController.h" using std::cout; using std::endl; namespace Ingenuity { diff --git a/src/progs/ingenuity/Makefile.am b/src/progs/ingenuity/Makefile.am index 5c4f5eed..aaa832f3 100644 --- a/src/progs/ingenuity/Makefile.am +++ b/src/progs/ingenuity/Makefile.am @@ -22,6 +22,10 @@ ingenuity_SOURCES = \ cmdline.h \ cmdline.c \ main.cpp \ + NodeMenu.h \ + NodeMenu.cpp \ + OmFlowCanvas.h \ + OmFlowCanvas.cpp \ BreadCrumb.h \ BreadCrumbBox.h \ BreadCrumbBox.cpp \ @@ -33,18 +37,6 @@ ingenuity_SOURCES = \ Configuration.cpp \ GladeFactory.h \ GladeFactory.cpp \ - GtkObjectController.h \ - GtkObjectController.cpp \ - PatchController.h \ - PatchController.cpp \ - NodeController.h \ - NodeController.cpp \ - PortController.h \ - PortController.cpp \ - DSSIController.h \ - DSSIController.cpp \ - ControllerFactory.h \ - ControllerFactory.cpp \ LoadPluginWindow.h \ LoadPluginWindow.cpp \ LoadPatchWindow.h \ @@ -65,8 +57,6 @@ ingenuity_SOURCES = \ PatchWindow.cpp \ WindowFactory.h \ WindowFactory.cpp \ - OmFlowCanvas.h \ - OmFlowCanvas.cpp \ ../../common/types.h \ ../../common/Path.h \ OmModule.h \ diff --git a/src/progs/ingenuity/NewSubpatchWindow.cpp b/src/progs/ingenuity/NewSubpatchWindow.cpp index 7f434445..8d673622 100644 --- a/src/progs/ingenuity/NewSubpatchWindow.cpp +++ b/src/progs/ingenuity/NewSubpatchWindow.cpp @@ -17,11 +17,9 @@ #include "App.h" #include "ModelEngineInterface.h" #include "NewSubpatchWindow.h" -#include "PatchController.h" #include "NodeModel.h" #include "PatchModel.h" #include "PatchView.h" -#include "OmFlowCanvas.h" namespace Ingenuity { @@ -44,15 +42,22 @@ NewSubpatchWindow::NewSubpatchWindow(BaseObjectType* cobject, const Glib::RefPtr m_ok_button->property_sensitive() = false; } +void +NewSubpatchWindow::present(CountedPtr<PatchModel> patch, MetadataMap data) +{ + set_patch(patch); + m_initial_data = data; + Gtk::Window::present(); +} /** Sets the patch controller for this window and initializes everything. * * This function MUST be called before using the window in any way! */ void -NewSubpatchWindow::set_patch(CountedPtr<PatchController> pc) +NewSubpatchWindow::set_patch(CountedPtr<PatchModel> patch) { - m_patch_controller = pc; + m_patch = patch; } @@ -66,7 +71,7 @@ NewSubpatchWindow::name_changed() if (!Path::is_valid_name(name)) { m_message_label->set_text("Name contains invalid characters."); m_ok_button->property_sensitive() = false; - } else if (m_patch_controller->patch_model()->get_node(name)) { + } else if (m_patch->get_node(name)) { m_message_label->set_text("An object already exists with that name."); m_ok_button->property_sensitive() = false; } else if (name.length() == 0) { @@ -83,22 +88,19 @@ void NewSubpatchWindow::ok_clicked() { PatchModel* pm = new PatchModel( - m_patch_controller->model()->path().base() + m_name_entry->get_text(), + m_patch->path().base() + m_name_entry->get_text(), m_poly_spinbutton->get_value_as_int()); if (m_new_module_x == 0 && m_new_module_y == 0) { - m_patch_controller->get_view()->canvas()->get_new_module_location( - m_new_module_x, m_new_module_y); + throw; // FIXME + //m_patch_controller->get_view()->canvas()->get_new_module_location( + // m_new_module_x, m_new_module_y); } - pm->set_parent(m_patch_controller->patch_model()); - pm->x(m_new_module_x); - pm->y(m_new_module_y); - char temp_buf[16]; - snprintf(temp_buf, 16, "%16f", m_new_module_x); - pm->set_metadata("module-x", temp_buf); - snprintf(temp_buf, 16, "%16f", m_new_module_y); - pm->set_metadata("module-y", temp_buf); + // FIXME: necessary? + //pm->set_parent(m_patch); + pm->set_metadata("module-x", (float)m_new_module_x); + pm->set_metadata("module-y", (float)m_new_module_y); App::instance().engine()->create_patch_from_model(pm); hide(); } diff --git a/src/progs/ingenuity/NewSubpatchWindow.h b/src/progs/ingenuity/NewSubpatchWindow.h index 32560dde..420b82c4 100644 --- a/src/progs/ingenuity/NewSubpatchWindow.h +++ b/src/progs/ingenuity/NewSubpatchWindow.h @@ -21,13 +21,12 @@ #include <libglademm/xml.h> #include <gtkmm.h> #include "util/CountedPtr.h" -#include "PatchController.h" - +#include "PatchModel.h" +using Ingen::Client::PatchModel; +using Ingen::Client::MetadataMap; namespace Ingenuity { -class PatchController; - /** 'New Subpatch' window. * @@ -40,17 +39,17 @@ class NewSubpatchWindow : public Gtk::Window public: NewSubpatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& xml); - void set_patch(CountedPtr<PatchController> pc); + void set_patch(CountedPtr<PatchModel> patch); + + void present(CountedPtr<PatchModel> patch, MetadataMap data); - void set_next_module_location(double x, double y) - { m_new_module_x = x; m_new_module_y = y; } - private: void name_changed(); void ok_clicked(); void cancel_clicked(); - CountedPtr<PatchController> m_patch_controller; + MetadataMap m_initial_data; + CountedPtr<PatchModel> m_patch; double m_new_module_x; double m_new_module_y; diff --git a/src/progs/ingenuity/NodeControlWindow.cpp b/src/progs/ingenuity/NodeControlWindow.cpp index 3af8f834..bc362eb5 100644 --- a/src/progs/ingenuity/NodeControlWindow.cpp +++ b/src/progs/ingenuity/NodeControlWindow.cpp @@ -16,7 +16,7 @@ #include "NodeControlWindow.h" #include "GladeFactory.h" -#include "NodeController.h" +#include "NodeModel.h" #include "ControlGroups.h" #include "ControlPanel.h" #include "PatchWindow.h" @@ -29,7 +29,7 @@ namespace Ingenuity { /** Create a node control window and load a new ControlPanel for it. */ -NodeControlWindow::NodeControlWindow(NodeController* node, size_t poly) +NodeControlWindow::NodeControlWindow(CountedPtr<NodeModel> node, size_t poly) : m_node(node), m_position_stored(false), m_x(0), m_y(0) @@ -59,11 +59,11 @@ NodeControlWindow::NodeControlWindow(NodeController* node, size_t poly) /** Create a node control window and with an existing ControlPanel. */ -NodeControlWindow::NodeControlWindow(NodeController* node, ControlPanel* panel) +NodeControlWindow::NodeControlWindow(CountedPtr<NodeModel> node, ControlPanel* panel) : m_node(node), m_control_panel(panel) { - assert(m_node != NULL); + assert(m_node); property_resizable() = true; set_border_width(5); diff --git a/src/progs/ingenuity/NodeControlWindow.h b/src/progs/ingenuity/NodeControlWindow.h index b30223d7..91ccbc49 100644 --- a/src/progs/ingenuity/NodeControlWindow.h +++ b/src/progs/ingenuity/NodeControlWindow.h @@ -14,7 +14,6 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef NODECONTROLWINDOW_H #define NODECONTROLWINDOW_H @@ -23,12 +22,17 @@ #include <gtkmm.h> #include <libglademm.h> #include <sigc++/sigc++.h> +#include "util/CountedPtr.h" using std::string; using std::vector; +namespace Ingen { namespace Client { + class NodeModel; +} } +using Ingen::Client::NodeModel; + namespace Ingenuity { class ControlGroup; -class NodeController; class ControlPanel; @@ -39,10 +43,12 @@ class ControlPanel; class NodeControlWindow : public Gtk::Window { public: - NodeControlWindow(NodeController* node, size_t poly); - NodeControlWindow(NodeController* node, ControlPanel* panel); + NodeControlWindow(CountedPtr<NodeModel> node, size_t poly); + NodeControlWindow(CountedPtr<NodeModel> node, ControlPanel* panel); virtual ~NodeControlWindow(); + CountedPtr<NodeModel> node() { return m_node; } + ControlPanel* control_panel() const { return m_control_panel; } void resize(); @@ -52,9 +58,9 @@ protected: void on_hide(); private: - NodeController* m_node; - ControlPanel* m_control_panel; - bool m_callback_enabled; + CountedPtr<NodeModel> m_node; + ControlPanel* m_control_panel; + bool m_callback_enabled; bool m_position_stored; int m_x; diff --git a/src/progs/ingenuity/NodeController.cpp b/src/progs/ingenuity/NodeController.cpp deleted file mode 100644 index 950f70c9..00000000 --- a/src/progs/ingenuity/NodeController.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "NodeController.h" -#include <iostream> -#include <gtkmm.h> -#include "App.h" -#include "OmModule.h" -#include "NodeModel.h" -#include "PortModel.h" -#include "PortController.h" -#include "GtkObjectController.h" -#include "NodeControlWindow.h" -#include "OmModule.h" -#include "ControllerFactory.h" -#include "PatchController.h" -#include "OmFlowCanvas.h" -#include "RenameWindow.h" -#include "GladeFactory.h" -#include "PatchWindow.h" -#include "PatchModel.h" -#include "NodePropertiesWindow.h" -#include "Store.h" -#include "ModelEngineInterface.h" -using std::cerr; using std::endl; - -namespace Ingenuity { - - -NodeController::NodeController(CountedPtr<NodeModel> model) -: GtkObjectController(model), - m_controls_menuitem(NULL), - m_module(NULL), - m_control_window(NULL), - m_properties_window(NULL), - m_bridge_port(NULL) -{ - // Create port controllers - for (PortModelList::const_iterator i = node_model()->ports().begin(); - i != node_model()->ports().end(); ++i) { - assert(!(*i)->controller()); - assert((*i)->parent()); - assert((*i)->parent().get() == node_model().get()); - CountedPtr<PortController> pc = PtrCast<PortController>(ControllerFactory::get_controller(*i)); - assert((*i)->controller() == pc); // PortController() does this - } - - // Build menu - - Gtk::Menu::MenuList& items = m_menu.items(); - - Gtk::Menu_Helpers::MenuElem controls_elem - = Gtk::Menu_Helpers::MenuElem("Controls", - sigc::mem_fun(this, &NodeController::show_control_window)); - m_controls_menuitem = controls_elem.get_child(); - items.push_back(controls_elem); - items.push_back(Gtk::Menu_Helpers::MenuElem("Properties", - sigc::mem_fun(this, &NodeController::show_properties_window))); - items.push_back(Gtk::Menu_Helpers::SeparatorElem()); - items.push_back(Gtk::Menu_Helpers::MenuElem("Rename...", - sigc::mem_fun(this, &NodeController::show_rename_window))); - items.push_back(Gtk::Menu_Helpers::MenuElem("Clone", - sigc::mem_fun(this, &NodeController::on_menu_clone))); - items.push_back(Gtk::Menu_Helpers::MenuElem("Disconnect All", - sigc::mem_fun(this, &NodeController::on_menu_disconnect_all))); - items.push_back(Gtk::Menu_Helpers::MenuElem("Destroy", - sigc::mem_fun(this, &NodeController::on_menu_destroy))); - - m_controls_menuitem->property_sensitive() = false; - - if (node_model()->plugin() && node_model()->plugin()->type() == PluginModel::Internal - && node_model()->plugin()->plug_label() == "midi_control_in") { - Gtk::Menu::MenuList& items = m_menu.items(); - items.push_back(Gtk::Menu_Helpers::MenuElem("Learn", - sigc::mem_fun(this, &NodeController::on_menu_learn))); - } - - model->new_port_sig.connect(sigc::mem_fun(this, &NodeController::add_port)); - model->destroyed_sig.connect(sigc::mem_fun(this, &NodeController::destroy)); -} - - -NodeController::~NodeController() -{ - cerr << "~NodeController()\n"; - destroy_module(); -} - - -void -NodeController::destroy() -{ - cerr << "FIXME: NODE DESTROYED\n"; - destroy_module(); - CountedPtr<ObjectModel> model = m_model; - m_model->controller().reset(); - m_model.reset(); -} - - -void -NodeController::create_module(OmFlowCanvas* canvas) -{ - if (!m_module || m_module->canvas() != canvas) { - delete m_module; - //cerr << "Creating node module " << m_model->path() << endl; - - // If this is a DSSI plugin, DSSIController should be doing this - /*assert(node_model()->plugin()); - assert(node_model()->plugin()->type() != PluginModel::DSSI); - assert(canvas != NULL); - assert(m_module == NULL);*/ - - assert(canvas); - assert(node_model()); - m_module = new OmModule(canvas, this); - create_all_ports(); - } - - m_module->move_to(node_model()->x(), node_model()->y()); -} - - -void -NodeController::destroy_module() -{ - delete m_module; - m_module = NULL; -} - - -void -NodeController::set_path(const Path& new_path) -{ - cerr << "FIXME: rename\n"; - /* - remove_from_store(); - - // Rename ports - for (list<PortModel*>::const_iterator i = node_model()->ports().begin(); - i != node_model()->ports().end(); ++i) { - GtkObjectController* const pc = (GtkObjectController*)((*i)->controller()); - assert(pc != NULL); - pc->set_path(m_model->path().base() + pc->model()->name()); - } - - // Handle bridge port, if this node represents one - if (m_bridge_port != NULL) - m_bridge_port->set_path(new_path); - - if (m_module != NULL) - m_module->canvas()->rename_module(node_model()->path().name(), new_path.name()); - - GtkObjectController::set_path(new_path); - - add_to_store(); - */ -} - -#if 0 -void -NodeController::destroy() -{ - PatchController* pc = ((PatchController*)m_model->parent()->controller()); - assert(pc != NULL); - - //remove_from_store(); - //pc->remove_node(m_model->path().name()); - cerr << "FIXME: remove node\n"; - - if (m_bridge_port != NULL) - m_bridge_port->destroy(); - m_bridge_port = NULL; - - //if (m_module != NULL) - // delete m_module; -} -#endif - -void -NodeController::metadata_update(const string& key, const string& value) -{ - //cout << "[NodeController] Metadata update: " << m_model->path() << endl; - - if (m_module != NULL) { - if (key == "module-x") { - float x = atof(value.c_str()); - //if (x > 0 && x < m_canvas->width()) - m_module->move_to(x, m_module->property_y().get_value()); - } else if (key == "module-y") { - float y = atof(value.c_str()); - //if (y > 0 && y < m_canvas->height()) - m_module->move_to(m_module->property_x().get_value(), y); - } - } - - //if (m_bridge_port != NULL) - // m_bridge_port->metadata_update(key, value); - - GtkObjectController::metadata_update(key, value); -} - - -void -NodeController::add_port(CountedPtr<PortModel> pm) -{ - assert(pm->parent().get() == node_model().get()); - assert(pm->parent() == node_model()); - assert(node_model()->get_port(pm->path().name()) == pm); - - //cout << "[NodeController] Adding port " << pm->path() << endl; - - CountedPtr<PortController> pc = PtrCast<PortController>(ControllerFactory::get_controller(pm)); - assert(pm->controller() == pc); - - if (m_module != NULL) { - pc->create_port(m_module); - m_module->resize(); - - // Enable "Controls" menu item on module - if (has_control_inputs()) - enable_controls_menuitem(); - } -} - - -void -NodeController::show_control_window() -{ - size_t poly = 1; - if (node_model()->polyphonic()) - poly = ((PatchModel*)node_model()->parent().get())->poly(); - - if (!m_control_window) - m_control_window = new NodeControlWindow(this, poly); - - m_control_window->present(); -} - - -void -NodeController::on_menu_destroy() -{ - App::instance().engine()->destroy(node_model()->path()); -} - - -void -NodeController::show_rename_window() -{ - assert(node_model()->parent()); - - // FIXME: will this be magically cleaned up? - RenameWindow* win = NULL; - Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference("rename_win"); - xml->get_widget_derived("rename_win", win); - - CountedPtr<PatchController> parent = PtrCast<PatchController>(node_model()->parent()->controller()); - assert(parent); - - if (parent->window()) - win->set_transient_for(*parent->window()); - - win->set_object(this); - win->show(); -} - -void -NodeController::on_menu_clone() -{ - cerr << "FIXME: clone broken\n"; - /* - assert(node_model()); - //assert(m_parent != NULL); - //assert(m_parent->model() != NULL); - - string clone_name = node_model()->name(); - int i = 2; // postfix number (ie oldname_2) - - // Check if name already has a number postfix - if (clone_name.find_last_of("_") != string::npos) { - string name_postfix = clone_name.substr(clone_name.find_last_of("_")+1); - clone_name = clone_name.substr(0, clone_name.find_last_of("_")); - if (sscanf(name_postfix.c_str(), "%d", &i)) - ++i; - } - - char clone_postfix[4]; - for ( ; i < 100; ++i) { - snprintf(clone_postfix, 4, "_%d", i); - if (node_model()->parent_patch()->get_node(clone_name + clone_postfix) == NULL) - break; - } - - clone_name = clone_name + clone_postfix; - - const string path = node_model()->parent_patch()->base() + clone_name; - NodeModel* nm = new NodeModel(node_model()->plugin(), path); - nm->polyphonic(node_model()->polyphonic()); - nm->x(node_model()->x() + 20); - nm->y(node_model()->y() + 20); - App::instance().engine()->create_node_from_model(nm); - */ -} - - -void -NodeController::on_menu_learn() -{ - App::instance().engine()->midi_learn(node_model()->path()); -} - -void -NodeController::on_menu_disconnect_all() -{ - App::instance().engine()->disconnect_all(node_model()->path()); -} - - -void -NodeController::show_properties_window() -{ - CountedPtr<PatchController> parent = PtrCast<PatchController>(node_model()->parent()->controller()); - assert(parent); - - if (m_properties_window) { - Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference("node_properties_win"); - xml->get_widget_derived("node_properties_win", m_properties_window); - } - assert(m_properties_window); - assert(parent); - m_properties_window->set_node(node_model()); - if (parent->window()) - m_properties_window->set_transient_for(*parent->window()); - m_properties_window->show(); -} - - -/** Create all (visual) ports and add them to module (and resize it). - * FIXME: this doesn't belong here - */ -void -NodeController::create_all_ports() -{ - assert(m_module); - - for (PortModelList::const_iterator i = node_model()->ports().begin(); - i != node_model()->ports().end(); ++i) { - CountedPtr<PortController> pc = PtrCast<PortController>(ControllerFactory::get_controller(*i)); - pc->create_port(m_module); - } - - m_module->resize(); - - if (has_control_inputs()) - enable_controls_menuitem(); -} - - -bool -NodeController::has_control_inputs() -{ - for (PortModelList::const_iterator i = node_model()->ports().begin(); - i != node_model()->ports().end(); ++i) - if ((*i)->is_input() && (*i)->is_control()) - return true; - - return false; -} - - -void -NodeController::enable_controls_menuitem() -{ - m_controls_menuitem->property_sensitive() = true; -} - - -void -NodeController::disable_controls_menuitem() -{ - m_controls_menuitem->property_sensitive() = false; - - if (m_control_window != NULL) - m_control_window->hide(); -} - - - -} // namespace Ingenuity - diff --git a/src/progs/ingenuity/NodeController.h b/src/progs/ingenuity/NodeController.h deleted file mode 100644 index c0ee6ea9..00000000 --- a/src/progs/ingenuity/NodeController.h +++ /dev/null @@ -1,116 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef NODECONTROLLER_H -#define NODECONTROLLER_H - -#include <string> -#include <gtkmm.h> -#include "util/Path.h" -#include "util/CountedPtr.h" -#include "GtkObjectController.h" -#include "NodeModel.h" - -using std::string; -using namespace Ingen::Client; - -namespace Ingen { namespace Client { - class MetadataModel; - class PortModel; -} } - -namespace Ingenuity { - -class Controller; -class OmModule; -class NodeControlWindow; -class NodePropertiesWindow; -class PortController; -class OmFlowCanvas; - -/** Controller for a Node. - * - * \ingroup Ingenuity - */ -class NodeController : public GtkObjectController -{ -public: - virtual ~NodeController(); - - virtual void metadata_update(const string& key, const string& value); - - virtual void create_module(OmFlowCanvas* canvas); - virtual void destroy_module(); - - void set_path(const Path& new_path); - - virtual void remove_port(const Path& path, bool resize_module) {} - - virtual void program_add(int bank, int program, const string& name) {} - virtual void program_remove(int bank, int program) {} - - OmModule* module() { return m_module; } - - //void bridge_port(PortController* port) { m_bridge_port = port; } - //PortController* as_port() { return m_bridge_port; } - - CountedPtr<NodeModel> node_model() { return PtrCast<NodeModel>(m_model); } - - NodeControlWindow* control_window() { return m_control_window; } - void control_window(NodeControlWindow* cw) { m_control_window = cw; } - - virtual void show_control_window(); - virtual void show_properties_window(); - void show_rename_window(); - - bool has_control_inputs(); - - virtual void show_menu(GdkEventButton* event) - { m_menu.popup(event->button, event->time); } - - virtual void enable_controls_menuitem(); - virtual void disable_controls_menuitem(); - -protected: - friend class ControllerFactory; - - NodeController(CountedPtr<NodeModel> model); - - virtual void destroy(); - - virtual void add_port(CountedPtr<PortModel> pm); - - void create_all_ports(); - - void on_menu_destroy(); - void on_menu_clone(); - void on_menu_learn(); - void on_menu_disconnect_all(); - - Gtk::Menu m_menu; - Glib::RefPtr<Gtk::MenuItem> m_controls_menuitem; - - OmModule* m_module; ///< View (module on a patch canvas) - - NodeControlWindow* m_control_window; - NodePropertiesWindow* m_properties_window; - PortController* m_bridge_port; -}; - - -} // namespace Ingenuity - -#endif // NODECONTROLLER_H diff --git a/src/progs/ingenuity/NodeMenu.cpp b/src/progs/ingenuity/NodeMenu.cpp new file mode 100644 index 00000000..c3ee7a5b --- /dev/null +++ b/src/progs/ingenuity/NodeMenu.cpp @@ -0,0 +1,254 @@ +/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. + * + * Ingen 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. + * + * Ingen 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <iostream> +#include <gtkmm.h> +#include "NodeMenu.h" +#include "NodeModel.h" +#include "App.h" +#include "ModelEngineInterface.h" +#include "WindowFactory.h" + +using std::cerr; using std::endl; + +namespace Ingenuity { + + +NodeMenu::NodeMenu(CountedPtr<NodeModel> node) +: _node(node) +, _controls_menuitem(NULL) +{ + App& app = App::instance(); + + Gtk::Menu_Helpers::MenuElem controls_elem = Gtk::Menu_Helpers::MenuElem("Controls", + sigc::bind( + sigc::mem_fun(app.window_factory(), &WindowFactory::present_controls), + node)); + _controls_menuitem = controls_elem.get_child(); + items().push_back(controls_elem); + + items().push_back(Gtk::Menu_Helpers::MenuElem("Properties", + sigc::bind( + sigc::mem_fun(app.window_factory(), &WindowFactory::present_properties), + node))); + + items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + + /*items().push_back(Gtk::Menu_Helpers::MenuElem("Rename...", + sigc::bind( + sigc::mem_fun(app.window_factory(), &WindowFactory::present_rename), + node)));*/ + /*items().push_back(Gtk::Menu_Helpers::MenuElem("Clone", + sigc::bind( + sigc::mem_fun(app.engine(), &EngineInterface::clone), + node))); + sigc::mem_fun(this, &NodeMenu::on_menu_clone)));*/ + + items().push_back(Gtk::Menu_Helpers::MenuElem("Disconnect All", + sigc::mem_fun(this, &NodeMenu::on_menu_disconnect_all))); + + items().push_back(Gtk::Menu_Helpers::MenuElem("Destroy", + sigc::mem_fun(this, &NodeMenu::on_menu_destroy))); + + //m_controls_menuitem->property_sensitive() = false; + + if (_node->plugin() && _node->plugin()->type() == PluginModel::Internal + && _node->plugin()->plug_label() == "midi_control_in") { + items().push_back(Gtk::Menu_Helpers::MenuElem("Learn", + sigc::mem_fun(this, &NodeMenu::on_menu_learn))); + } + + //model->new_port_sig.connect(sigc::mem_fun(this, &NodeMenu::add_port)); + //model->destroyed_sig.connect(sigc::mem_fun(this, &NodeMenu::destroy)); +} + +#if 0 +NodeMenu::~NodeMenu() +{ + cerr << "~NodeMenu()\n"; +} + +void +NodeMenu::destroy() +{ + cerr << "FIXME: NODE DESTROYED\n"; + //CountedPtr<ObjectModel> model = m_model; + //m_model.reset(); +} +#endif + +void +NodeMenu::set_path(const Path& new_path) +{ + cerr << "FIXME: rename\n"; + /* + remove_from_store(); + + // Rename ports + for (list<PortModel*>::const_iterator i = _node->ports().begin(); + i != _node->ports().end(); ++i) { + ObjectController* const pc = (*i)->controller(); + assert(pc != NULL); + pc->set_path(m_model->path().base() + pc->model()->name()); + } + + // Handle bridge port, if this node represents one + if (m_bridge_port != NULL) + m_bridge_port->set_path(new_path); + + if (m_module != NULL) + m_module->canvas()->rename_module(_node->path().name(), new_path.name()); + + ObjectController::set_path(new_path); + + add_to_store(); + */ +} + +#if 0 +void +NodeMenu::destroy() +{ + PatchController* pc = ((PatchController*)m_model->parent()->controller()); + assert(pc != NULL); + + //remove_from_store(); + //pc->remove_node(m_model->path().name()); + cerr << "FIXME: remove node\n"; + + if (m_bridge_port != NULL) + m_bridge_port->destroy(); + m_bridge_port = NULL; + + //if (m_module != NULL) + // delete m_module; +} +#endif + +#if 0 +void +NodeMenu::add_port(CountedPtr<PortModel> pm) +{ + assert(pm->parent().get() == _node.get()); + assert(pm->parent() == _node); + assert(_node->get_port(pm->path().name()) == pm); + + //cout << "[NodeMenu] Adding port " << pm->path() << endl; + + /* + if (m_module != NULL) { + // (formerly PortController) + pc->create_port(m_module); + m_module->resize(); + + // Enable "Controls" menu item on module + if (has_control_inputs()) + enable_controls_menuitem(); + }*/ +} +#endif + +void +NodeMenu::on_menu_destroy() +{ + App::instance().engine()->destroy(_node->path()); +} + + +void +NodeMenu::on_menu_clone() +{ + cerr << "FIXME: clone broken\n"; + /* + assert(_node); + //assert(m_parent != NULL); + //assert(m_parent->model() != NULL); + + string clone_name = _node->name(); + int i = 2; // postfix number (ie oldname_2) + + // Check if name already has a number postfix + if (clone_name.find_last_of("_") != string::npos) { + string name_postfix = clone_name.substr(clone_name.find_last_of("_")+1); + clone_name = clone_name.substr(0, clone_name.find_last_of("_")); + if (sscanf(name_postfix.c_str(), "%d", &i)) + ++i; + } + + char clone_postfix[4]; + for ( ; i < 100; ++i) { + snprintf(clone_postfix, 4, "_%d", i); + if (_node->parent_patch()->get_node(clone_name + clone_postfix) == NULL) + break; + } + + clone_name = clone_name + clone_postfix; + + const string path = _node->parent_patch()->base() + clone_name; + NodeModel* nm = new NodeModel(_node->plugin(), path); + nm->polyphonic(_node->polyphonic()); + nm->x(_node->x() + 20); + nm->y(_node->y() + 20); + App::instance().engine()->create_node_from_model(nm); + */ +} + + +void +NodeMenu::on_menu_learn() +{ + App::instance().engine()->midi_learn(_node->path()); +} + +void +NodeMenu::on_menu_disconnect_all() +{ + App::instance().engine()->disconnect_all(_node->path()); +} + + +bool +NodeMenu::has_control_inputs() +{ + for (PortModelList::const_iterator i = _node->ports().begin(); + i != _node->ports().end(); ++i) + if ((*i)->is_input() && (*i)->is_control()) + return true; + + return false; +} + + +void +NodeMenu::enable_controls_menuitem() +{ + _controls_menuitem->property_sensitive() = true; +} + + +void +NodeMenu::disable_controls_menuitem() +{ + _controls_menuitem->property_sensitive() = false; + + //if (m_control_window != NULL) + // m_control_window->hide(); +} + + + +} // namespace Ingenuity + diff --git a/src/progs/ingenuity/NodeMenu.h b/src/progs/ingenuity/NodeMenu.h new file mode 100644 index 00000000..a80b7a69 --- /dev/null +++ b/src/progs/ingenuity/NodeMenu.h @@ -0,0 +1,75 @@ +/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. + * + * Ingen 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. + * + * Ingen 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef NODEMENU_H +#define NODEMENU_H + +#include <string> +#include <gtkmm.h> +#include "util/Path.h" +#include "util/CountedPtr.h" +#include "NodeModel.h" +using Ingen::Client::NodeModel; + +using std::string; + +namespace Ingenuity { + +class Controller; +class NodeControlWindow; +class NodePropertiesWindow; +class OmFlowCanvas; + +/** Controller for a Node. + * + * \ingroup Ingenuity + */ +class NodeMenu : public Gtk::Menu +{ +public: + NodeMenu(CountedPtr<NodeModel> node); + + void set_path(const Path& new_path); + + virtual void program_add(int bank, int program, const string& name) {} + virtual void program_remove(int bank, int program) {} + + bool has_control_inputs(); + + //virtual void show_menu(GdkEventButton* event) + //{ m_menu.popup(event->button, event->time); } + +protected: + + virtual void enable_controls_menuitem(); + virtual void disable_controls_menuitem(); + + //virtual void add_port(CountedPtr<PortModel> pm); + + void on_menu_destroy(); + void on_menu_clone(); + void on_menu_learn(); + void on_menu_disconnect_all(); + + //Gtk::Menu m_menu; + CountedPtr<NodeModel> _node; + Glib::RefPtr<Gtk::MenuItem> _controls_menuitem; +}; + + +} // namespace Ingenuity + +#endif // NODEMENU_H diff --git a/src/progs/ingenuity/NodePropertiesWindow.h b/src/progs/ingenuity/NodePropertiesWindow.h index 2c36dc5c..62934f0a 100644 --- a/src/progs/ingenuity/NodePropertiesWindow.h +++ b/src/progs/ingenuity/NodePropertiesWindow.h @@ -20,8 +20,7 @@ #include <gtkmm.h> #include <libglademm.h> #include "util/CountedPtr.h" - -namespace Ingen { namespace Client { class NodeModel; } } +#include "NodeModel.h" using namespace Ingen::Client; namespace Ingenuity { @@ -38,6 +37,7 @@ class NodePropertiesWindow : public Gtk::Window public: NodePropertiesWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& refGlade); + void present(CountedPtr<NodeModel> node_model) { set_node(node_model); Gtk::Window::present(); } void set_node(CountedPtr<NodeModel> node_model); private: diff --git a/src/progs/ingenuity/OmFlowCanvas.cpp b/src/progs/ingenuity/OmFlowCanvas.cpp index d530bca0..0d2e9bb0 100644 --- a/src/progs/ingenuity/OmFlowCanvas.cpp +++ b/src/progs/ingenuity/OmFlowCanvas.cpp @@ -19,7 +19,6 @@ #include <flowcanvas/FlowCanvas.h> #include "App.h" #include "ModelEngineInterface.h" -#include "PatchController.h" #include "PatchModel.h" #include "PatchWindow.h" #include "LoadPluginWindow.h" @@ -28,27 +27,20 @@ #include "OmPort.h" #include "NodeModel.h" #include "OmModule.h" +#include "OmPortModule.h" +#include "SubpatchModule.h" #include "GladeFactory.h" +#include "WindowFactory.h" namespace Ingenuity { -OmFlowCanvas::OmFlowCanvas(PatchController* controller, int width, int height) +OmFlowCanvas::OmFlowCanvas(CountedPtr<PatchModel> patch, int width, int height) : FlowCanvas(width, height), - m_patch_controller(controller), + m_patch(patch), m_last_click_x(0), m_last_click_y(0) { - assert(controller != NULL); - - /*Gtk::Menu::MenuList& items = m_menu.items(); - items.push_back(Gtk::Menu_Helpers::MenuElem("Load Plugin...", - sigc::mem_fun(this, &OmFlowCanvas::menu_load_plugin))); - items.push_back(Gtk::Menu_Helpers::MenuElem("Load Subpatch...", - sigc::mem_fun(this, &OmFlowCanvas::menu_load_subpatch))); - items.push_back(Gtk::Menu_Helpers::MenuElem("New Subpatch...", - sigc::mem_fun(this, &OmFlowCanvas::menu_create_subpatch)));*/ - Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference(); xml->get_widget("canvas_menu", m_menu); @@ -62,6 +54,8 @@ OmFlowCanvas::OmFlowCanvas(PatchController* controller, int width, int height) xml->get_widget("canvas_menu_load_patch", m_menu_load_patch); xml->get_widget("canvas_menu_new_patch", m_menu_new_patch); + build_canvas(); + // Add port menu items m_menu_add_audio_input->signal_activate().connect( sigc::bind(sigc::mem_fun(this, &OmFlowCanvas::menu_add_port), @@ -82,6 +76,13 @@ OmFlowCanvas::OmFlowCanvas(PatchController* controller, int width, int height) sigc::bind(sigc::mem_fun(this, &OmFlowCanvas::menu_add_port), "midi_output", "MIDI", true)); + // Connect to model signals to track state + m_patch->new_node_sig.connect(sigc::mem_fun(this, &OmFlowCanvas::add_node)); + m_patch->removed_node_sig.connect(sigc::mem_fun(this, &OmFlowCanvas::remove_node)); + m_patch->new_connection_sig.connect(sigc::mem_fun(this, &OmFlowCanvas::connection)); + m_patch->removed_connection_sig.connect(sigc::mem_fun(this, &OmFlowCanvas::disconnection)); + + // Connect widget signals to do things m_menu_load_plugin->signal_activate().connect(sigc::mem_fun(this, &OmFlowCanvas::menu_load_plugin)); m_menu_load_patch->signal_activate().connect(sigc::mem_fun(this, &OmFlowCanvas::menu_load_patch)); m_menu_new_patch->signal_activate().connect(sigc::mem_fun(this, &OmFlowCanvas::menu_new_patch)); @@ -89,6 +90,100 @@ OmFlowCanvas::OmFlowCanvas(PatchController* controller, int width, int height) void +OmFlowCanvas::build_canvas() { + + // Create modules for nodes + for (NodeModelMap::const_iterator i = m_patch->nodes().begin(); + i != m_patch->nodes().end(); ++i) { + add_node((*i).second); + } + + // Create pseudo modules for ports (ports on this canvas, not on our module) + for (PortModelList::const_iterator i = m_patch->ports().begin(); + i != m_patch->ports().end(); ++i) { + cerr << "FIXME: PORT MODULE LEAK!" << endl; + new OmPortModule(this, *i); + } + + // Create connections + for (list<CountedPtr<ConnectionModel> >::const_iterator i = m_patch->connections().begin(); + i != m_patch->connections().end(); ++i) { + connection(*i); + } +} + + +void +OmFlowCanvas::add_node(CountedPtr<NodeModel> nm) +{ + cerr << "FIXME: MODULE LEAK!" << endl; + + CountedPtr<PatchModel> pm = PtrCast<PatchModel>(nm); + if (pm) + new SubpatchModule(this, pm); + else + new OmModule(this, nm); +} + + +void +OmFlowCanvas::remove_node(CountedPtr<NodeModel> nm) +{ + LibFlowCanvas::Module* module = get_module(nm->path().name()); + delete module; +} + + +void +OmFlowCanvas::connection(CountedPtr<ConnectionModel> cm) +{ + // Deal with port "anonymous nodes" for this patch's own ports... + const Path& src_parent_path = cm->src_port_path().parent(); + const Path& dst_parent_path = cm->dst_port_path().parent(); + + const string& src_parent_name = + (src_parent_path == m_patch->path()) ? "" : src_parent_path.name(); + const string& dst_parent_name = + (dst_parent_path == m_patch->path()) ? "" : dst_parent_path.name(); + + Port* src_port = get_port(src_parent_name, cm->src_port_path().name()); + Port* dst_port = get_port(dst_parent_name, cm->dst_port_path().name()); + assert(src_port && dst_port); + + add_connection(src_port, dst_port); +} + + +void +OmFlowCanvas::disconnection(const Path& src_port_path, const Path& dst_port_path) +{ + const string& src_node_name = src_port_path.parent().name(); + const string& src_port_name = src_port_path.name(); + const string& dst_node_name = dst_port_path.parent().name(); + const string& dst_port_name = dst_port_path.name(); + + Port* src_port = get_port(src_node_name, src_port_name); + Port* dst_port = get_port(dst_node_name, dst_port_name); + + if (src_port && dst_port) { + remove_connection(src_port, dst_port); + } + + //patch_model()->remove_connection(src_port_path, dst_port_path); + + cerr << "FIXME: disconnection\n"; + /* + // Enable control slider in destination node control window + PortController* p = (PortController)Store::instance().port(dst_port_path)->controller(); + assert(p); + + if (p->control_panel()) + p->control_panel()->enable_port(p->path()); + */ +} + + +void OmFlowCanvas::connect(const Port* src_port, const Port* dst_port) { assert(src_port != NULL); @@ -102,10 +197,12 @@ OmFlowCanvas::connect(const Port* src_port, const Port* dst_port) dst->model()->type() == PortModel::CONTROL) { CountedPtr<PluginModel> pm(new PluginModel(PluginModel::Internal, "", "midi_control_in", "")); - CountedPtr<NodeModel> nm(new NodeModel(pm, m_patch_controller->model()->path().base() - + src->name() + "-" + dst->name())); - nm->x(dst->module()->property_x() - dst->module()->width() - 20); - nm->y(dst->module()->property_y()); + CountedPtr<NodeModel> nm(new NodeModel(pm, m_patch->path().base() + + src->name() + "-" + dst->name(), false)); + nm->set_metadata("module-x", Atom((float) + (dst->module()->property_x() - dst->module()->width() - 20))); + nm->set_metadata("module-y", Atom((float) + (dst->module()->property_y()))); App::instance().engine()->create_node_from_model(nm.get()); App::instance().engine()->connect(src->model()->path(), nm->path() + "/MIDI_In"); App::instance().engine()->connect(nm->path() + "/Out_(CR)", dst->model()->path()); @@ -114,9 +211,9 @@ OmFlowCanvas::connect(const Port* src_port, const Port* dst_port) // Set control node range to port's user range App::instance().engine()->set_port_value_queued(nm->path().base() + "Min", - atof(dst->model()->get_metadata("user-min").c_str())); + dst->model()->get_metadata("user-min").get_float()); App::instance().engine()->set_port_value_queued(nm->path().base() + "Max", - atof(dst->model()->get_metadata("user-max").c_str())); + dst->model()->get_metadata("user-max").get_float()); } else { App::instance().engine()->connect(src->model()->path(), dst->model()->path()); @@ -181,7 +278,7 @@ OmFlowCanvas::generate_port_name(const string& base) { snprintf(num_buf, 5, "%u", i); name = base + "_"; name += num_buf; - if (!m_patch_controller->patch_model()->get_port(name)) + if (!m_patch->get_port(name)) break; } @@ -194,7 +291,7 @@ OmFlowCanvas::generate_port_name(const string& base) { void OmFlowCanvas::menu_add_port(const string& name, const string& type, bool is_output) { - const Path& path = m_patch_controller->path().base() + generate_port_name(name); + const Path& path = m_patch->path().base() + generate_port_name(name); App::instance().engine()->create_port(path, type, is_output); char temp_buf[16]; @@ -267,30 +364,35 @@ OmFlowCanvas::menu_add_midi_output() } */ +MetadataMap +OmFlowCanvas::get_initial_data() +{ + MetadataMap result; + + result["module-x"] = Atom((float)m_last_click_x); + result["module-y"] = Atom((float)m_last_click_y); + + return result; +} + void OmFlowCanvas::menu_load_plugin() { - m_patch_controller->window()->load_plugin_window()->set_next_module_location( - m_last_click_x, m_last_click_y); - m_patch_controller->window()->load_plugin_window()->show(); + App::instance().window_factory()->present_load_plugin(m_patch, get_initial_data()); } void OmFlowCanvas::menu_load_patch() { - m_patch_controller->window()->load_subpatch_window()->set_next_module_location( - m_last_click_x, m_last_click_y); - m_patch_controller->window()->load_subpatch_window()->show(); + App::instance().window_factory()->present_load_subpatch(m_patch, get_initial_data()); } void OmFlowCanvas::menu_new_patch() { - m_patch_controller->window()->new_subpatch_window()->set_next_module_location( - m_last_click_x, m_last_click_y); - m_patch_controller->window()->new_subpatch_window()->show(); + App::instance().window_factory()->present_new_subpatch(m_patch, get_initial_data()); } diff --git a/src/progs/ingenuity/OmFlowCanvas.h b/src/progs/ingenuity/OmFlowCanvas.h index 7db347f7..ae5501c4 100644 --- a/src/progs/ingenuity/OmFlowCanvas.h +++ b/src/progs/ingenuity/OmFlowCanvas.h @@ -19,17 +19,24 @@ #include <string> #include <flowcanvas/FlowCanvas.h> - +#include "util/CountedPtr.h" +#include "util/Path.h" +#include "ConnectionModel.h" +#include "PatchModel.h" using std::string; using namespace LibFlowCanvas; using LibFlowCanvas::Port; +using Ingen::Client::ConnectionModel; +using Ingen::Client::PatchModel; +using Ingen::Client::NodeModel; +using Ingen::Client::MetadataMap; namespace Ingenuity { class OmModule; -class PatchController; + /** Patch canvas widget. * @@ -38,16 +45,18 @@ class PatchController; class OmFlowCanvas : public LibFlowCanvas::FlowCanvas { public: - OmFlowCanvas(PatchController* controller, int width, int height); + OmFlowCanvas(CountedPtr<PatchModel> patch, int width, int height); OmModule* find_module(const string& name) { return (OmModule*)FlowCanvas::get_module(name); } - void connect(const Port* src_port, const Port* dst_port); - void disconnect(const Port* src_port, const Port* dst_port); - + void add_node(CountedPtr<NodeModel> nm); + void remove_node(CountedPtr<NodeModel> nm); + void connection(CountedPtr<ConnectionModel> cm); + void disconnection(const Path& src_port_path, const Path& dst_port_path); + void get_new_module_location(double& x, double& y); - bool canvas_event(GdkEvent* event); + void destroy_selected(); void show_menu(GdkEvent* event) @@ -65,10 +74,20 @@ private: void menu_load_plugin(); void menu_new_patch(); void menu_load_patch(); + + MetadataMap get_initial_data(); + + void build_canvas(); + + bool canvas_event(GdkEvent* event); + + void connect(const Port* src_port, const Port* dst_port); + void disconnect(const Port* src_port, const Port* dst_port); + + CountedPtr<PatchModel> m_patch; - PatchController* m_patch_controller; - int m_last_click_x; - int m_last_click_y; + int m_last_click_x; + int m_last_click_y; Gtk::Menu* m_menu; Gtk::MenuItem* m_menu_add_audio_input; diff --git a/src/progs/ingenuity/OmModule.cpp b/src/progs/ingenuity/OmModule.cpp index dd6f3da5..9e06d910 100644 --- a/src/progs/ingenuity/OmModule.cpp +++ b/src/progs/ingenuity/OmModule.cpp @@ -16,6 +16,7 @@ #include "OmModule.h" #include <cassert> +#include "util/Atom.h" #include "App.h" #include "ModelEngineInterface.h" #include "OmFlowCanvas.h" @@ -24,53 +25,95 @@ #include "OmPort.h" #include "GladeFactory.h" #include "RenameWindow.h" -#include "PatchController.h" #include "PatchWindow.h" +#include "WindowFactory.h" namespace Ingenuity { -OmModule::OmModule(OmFlowCanvas* canvas, NodeController* node) -: LibFlowCanvas::Module(canvas, node->node_model()->path().name(), - node->node_model()->x(), node->node_model()->y()), - m_node(node) +OmModule::OmModule(OmFlowCanvas* canvas, CountedPtr<NodeModel> node) +: LibFlowCanvas::Module(canvas, node->path().name()), + m_node(node), + m_menu(node) { assert(m_node); - /*if (node_model()->polyphonic() && node_model()->parent() != NULL - && node_model()->parent_patch()->poly() > 1) { - border_width(2.0); - }*/ - if (node->node_model()->polyphonic()) { + if (node->polyphonic()) { border_width(2.0); } + + create_all_ports(); + + const Atom& x = node->get_metadata("module-x"); + const Atom& y = node->get_metadata("module-y"); + + if (x.type() == Atom::FLOAT && y.type() == Atom::FLOAT) { + move_to(x.get_float(), y.get_float()); + } else { + double x, y; + ((OmFlowCanvas*)m_canvas)->get_new_module_location(x, y); + } + + node->new_port_sig.connect(sigc::mem_fun(this, &OmModule::add_port)); + node->removed_port_sig.connect(sigc::mem_fun(this, &OmModule::remove_port)); + node->metadata_update_sig.connect(sigc::mem_fun(this, &OmModule::metadata_update)); +} + + +void +OmModule::create_all_ports() +{ + for (PortModelList::const_iterator i = m_node->ports().begin(); + i != m_node->ports().end(); ++i) { + add_port(*i); + } + + resize(); + + // FIXME + //if (has_control_inputs()) + // enable_controls_menuitem(); +} + + +void +OmModule::add_port(CountedPtr<PortModel> port) +{ + new OmPort(this, port); + resize(); +} + + +void +OmModule::remove_port(CountedPtr<PortModel> port) +{ + LibFlowCanvas::Port* canvas_port = get_port(port->path().name()); + delete canvas_port; } void OmModule::show_control_window() { - node()->show_control_window(); + App::instance().window_factory()->present_controls(m_node); } void OmModule::store_location() { - if (m_node->node_model()->x() == 0 || m_node->node_model()->y() == 0) - return; - - char temp_buf[16]; + const float x = static_cast<float>(property_x()); + const float y = static_cast<float>(property_y()); - m_node->node_model()->x(property_x()); - snprintf(temp_buf, 16, "%f", m_node->node_model()->x()); - m_node->node_model()->set_metadata("module-x", temp_buf); // just in case? - App::instance().engine()->set_metadata(m_node->node_model()->path(), "module-x", temp_buf); + const Atom& existing_x = m_node->get_metadata("module-x"); + const Atom& existing_y = m_node->get_metadata("module-y"); - m_node->node_model()->y(property_y()); - snprintf(temp_buf, 16, "%f", m_node->node_model()->y()); - m_node->node_model()->set_metadata("module-y", temp_buf); // just in case? - App::instance().engine()->set_metadata(m_node->node_model()->path(), "module-y", temp_buf); + if (existing_x.type() != Atom::FLOAT || existing_y.type() != Atom::FLOAT + || existing_x.get_float() != x || existing_y.get_float() != y) { + App::instance().engine()->set_metadata(m_node->path(), "module-x", Atom(x)); + App::instance().engine()->set_metadata(m_node->path(), "module-y", Atom(y)); + } + } @@ -78,9 +121,25 @@ void OmModule::move_to(double x, double y) { Module::move_to(x, y); - m_node->node_model()->x(x); - m_node->node_model()->y(y); //store_location(); } + +void +OmModule::on_right_click(GdkEventButton* event) +{ + m_menu.popup(event->button, event->time); +} + + +void +OmModule::metadata_update(const string& key, const Atom& value) +{ + if (key == "module-x" && value.type() == Atom::FLOAT) + move_to(value.get_float(), property_y()); + else if (key == "module-y" && value.type() == Atom::FLOAT) + move_to(property_x(), value.get_float()); +} + + } // namespace Ingenuity diff --git a/src/progs/ingenuity/OmModule.h b/src/progs/ingenuity/OmModule.h index a3d56187..243c31e7 100644 --- a/src/progs/ingenuity/OmModule.h +++ b/src/progs/ingenuity/OmModule.h @@ -14,17 +14,18 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef OMMODULE_H #define OMMODULE_H #include <string> #include <libgnomecanvasmm.h> #include <flowcanvas/Module.h> +#include "NodeMenu.h" #include "util/CountedPtr.h" -#include "NodeController.h" using std::string; +class Atom; + namespace Ingen { namespace Client { class PortModel; class NodeModel; @@ -34,7 +35,6 @@ using namespace Ingen::Client; namespace Ingenuity { -class PatchController; class OmFlowCanvas; class OmPort; @@ -49,7 +49,7 @@ class OmPort; class OmModule : public LibFlowCanvas::Module { public: - OmModule(OmFlowCanvas* canvas, NodeController* node); + OmModule(OmFlowCanvas* canvas, CountedPtr<NodeModel> node); virtual ~OmModule() {} virtual OmPort* port(const string& port_name) { @@ -59,17 +59,24 @@ public: virtual void store_location(); void move_to(double x, double y); - void on_right_click(GdkEventButton* event) { m_node->show_menu(event); } + void on_right_click(GdkEventButton* event); void show_control_window(); - NodeController* node() const { return m_node; } + CountedPtr<NodeModel> node() const { return m_node; } protected: virtual void on_double_click(GdkEventButton* ev) { show_control_window(); } virtual void on_middle_click(GdkEventButton* ev) { show_control_window(); } - NodeController* m_node; + void metadata_update(const string& key, const Atom& value); + + void create_all_ports(); + void add_port(CountedPtr<PortModel> port); + void remove_port(CountedPtr<PortModel> port); + + CountedPtr<NodeModel> m_node; + NodeMenu m_menu; }; diff --git a/src/progs/ingenuity/OmPatchPort.h b/src/progs/ingenuity/OmPatchPort.h index 112fc160..e7d5765f 100644 --- a/src/progs/ingenuity/OmPatchPort.h +++ b/src/progs/ingenuity/OmPatchPort.h @@ -30,7 +30,6 @@ using std::string; using std::list; namespace Ingenuity { class FlowCanvas; -class PatchController; class PatchWindow; class OmPortModule; diff --git a/src/progs/ingenuity/OmPort.h b/src/progs/ingenuity/OmPort.h index 5ffd4e26..cedad156 100644 --- a/src/progs/ingenuity/OmPort.h +++ b/src/progs/ingenuity/OmPort.h @@ -30,7 +30,6 @@ using std::string; using std::list; namespace Ingenuity { class FlowCanvas; -class PatchController; class PatchWindow; class OmModule; diff --git a/src/progs/ingenuity/OmPortModule.cpp b/src/progs/ingenuity/OmPortModule.cpp index e5c5fca6..aaa26205 100644 --- a/src/progs/ingenuity/OmPortModule.cpp +++ b/src/progs/ingenuity/OmPortModule.cpp @@ -24,22 +24,44 @@ #include "OmPort.h" #include "GladeFactory.h" #include "RenameWindow.h" -#include "PatchController.h" #include "PatchWindow.h" +#include "OmPatchPort.h" namespace Ingenuity { -OmPortModule::OmPortModule(OmFlowCanvas* canvas, PortController* port, double x, double y) -: LibFlowCanvas::Module(canvas, "", x, y), +OmPortModule::OmPortModule(OmFlowCanvas* canvas, CountedPtr<PortModel> port) +: LibFlowCanvas::Module(canvas, "", 0, 0), // FIXME: coords? m_port(port) { - assert(m_port != NULL); - /*if (port_model()->polyphonic() && port_model()->parent() != NULL && port_model()->parent_patch()->poly() > 1) { border_width(2.0); }*/ + + assert(canvas); + assert(port); + + if (PtrCast<PatchModel>(port->parent())) { + if (m_patch_port) + delete m_patch_port; + + m_patch_port = new OmPatchPort(this, port); + } + + resize(); + + const Atom& x_atom = port->get_metadata("module-x"); + const Atom& y_atom = port->get_metadata("module-y"); + + if (x_atom && y_atom && x_atom.type() == Atom::FLOAT && y_atom.type() == Atom::FLOAT) { + move_to(x_atom.get_float(), y_atom.get_float()); + } else { + double default_x; + double default_y; + canvas->get_new_module_location(default_x, default_y); + move_to(default_x, default_y); + } } @@ -48,15 +70,15 @@ OmPortModule::store_location() { char temp_buf[16]; - //m_port->port_model()->x(property_x()); + //m_port->x(property_x()); snprintf(temp_buf, 16, "%f", property_x().get_value()); - //m_port->port_model()->set_metadata("module-x", temp_buf); // just in case? - App::instance().engine()->set_metadata(m_port->port_model()->path(), "module-x", temp_buf); + //m_port->set_metadata("module-x", temp_buf); // just in case? + App::instance().engine()->set_metadata(m_port->path(), "module-x", temp_buf); - //m_port->port_model()->y(property_y()); + //m_port->y(property_y()); snprintf(temp_buf, 16, "%f", property_y().get_value()); - //m_port->port_model()->set_metadata("module-y", temp_buf); // just in case? - App::instance().engine()->set_metadata(m_port->port_model()->path(), "module-y", temp_buf); + //m_port->set_metadata("module-y", temp_buf); // just in case? + App::instance().engine()->set_metadata(m_port->path(), "module-y", temp_buf); } @@ -64,8 +86,8 @@ void OmPortModule::move_to(double x, double y) { Module::move_to(x, y); - //m_port->port_model()->x(x); - //m_port->port_model()->y(y); + //m_port->x(x); + //m_port->y(y); //store_location(); } diff --git a/src/progs/ingenuity/OmPortModule.h b/src/progs/ingenuity/OmPortModule.h index 85bd349b..00d20f96 100644 --- a/src/progs/ingenuity/OmPortModule.h +++ b/src/progs/ingenuity/OmPortModule.h @@ -14,14 +14,13 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef OMPORTMODULE_H #define OMPORTMODULE_H #include <string> #include <libgnomecanvasmm.h> #include <flowcanvas/Module.h> -#include "PortController.h" +#include "OmPatchPort.h" using std::string; namespace Ingen { namespace Client { @@ -33,8 +32,6 @@ using namespace Ingen::Client; namespace Ingenuity { -class PatchController; -class PortController; class OmFlowCanvas; class OmPort; @@ -48,7 +45,7 @@ class OmPort; class OmPortModule : public LibFlowCanvas::Module { public: - OmPortModule(OmFlowCanvas* canvas, PortController* port, double x, double y); + OmPortModule(OmFlowCanvas* canvas, CountedPtr<PortModel> port); virtual ~OmPortModule() {} //virtual OmPort* port(const string& port_name) { @@ -60,13 +57,14 @@ public: //void on_right_click(GdkEventButton* event) { m_port->show_menu(event); } - PortController* port() const { return m_port; } + CountedPtr<PortModel> port() const { return m_port; } protected: //virtual void on_double_click(GdkEventButton* ev) { show_control_window(); } //virtual void on_middle_click(GdkEventButton* ev) { show_control_window(); } - PortController* m_port; + CountedPtr<PortModel> m_port; + OmPatchPort* m_patch_port; ///< Port on this 'anonymous' module }; diff --git a/src/progs/ingenuity/PatchController.cpp b/src/progs/ingenuity/PatchController.cpp deleted file mode 100644 index f02aa773..00000000 --- a/src/progs/ingenuity/PatchController.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include "PatchController.h" -#include <cassert> -#include <cstdlib> -#include "GladeFactory.h" -#include "Configuration.h" -#include "util/Path.h" -#include "ControlPanel.h" -#include "ConnectionModel.h" -#include "OmFlowCanvas.h" -#include "PatchView.h" -#include "flowcanvas/Module.h" -#include "PluginModel.h" -#include "SubpatchModule.h" -#include "DSSIModule.h" -#include "PatchWindow.h" -#include "NodeModel.h" -#include "OmModule.h" -#include "OmPortModule.h" -#include "OmPort.h" -#include "ControlModel.h" -#include "NodeControlWindow.h" -#include "NodeController.h" -#include "PortController.h" -#include "App.h" -#include "PatchTreeWindow.h" -#include "PatchPropertiesWindow.h" -#include "DSSIController.h" -#include "PatchModel.h" -#include "Store.h" -#include "ControllerFactory.h" - -using std::cerr; using std::cout; using std::endl; -using namespace Ingen::Client; - -namespace Ingenuity { - - -PatchController::PatchController(CountedPtr<PatchModel> model) -: NodeController(model), - m_properties_window(NULL), - m_window(NULL), - m_patch_model(model), - m_module_x(0), - m_module_y(0) -{ - //model->new_port_sig.connect(sigc::mem_fun(this, &PatchController::add_port)); - model->new_node_sig.connect(sigc::mem_fun(this, &PatchController::add_node)); - model->new_connection_sig.connect(sigc::mem_fun(this, &PatchController::connection)); - model->removed_connection_sig.connect(sigc::mem_fun(this, &PatchController::disconnection)); -} - - -PatchController::~PatchController() -{ - if (m_patch_view) { - claim_patch_view(); - } - - if (m_control_window) { - m_control_window->hide(); - delete m_control_window; - m_control_window = NULL; - } - - if (m_window) { - delete m_window; - m_window = NULL; - } -} - -#if 0 -void -PatchController::clear() -{ - // Destroy model - // Destroying nodes removes models from patch model, which invalidates any - // iterator to nodes, so avoid the iterator problem by doing it this way: - const NodeModelMap& nodes = patch_model()->nodes(); - size_t remaining = nodes.size(); - - while (remaining > 0) { - CountedPtr<NodeController> nc = (*nodes.begin()).second->controller(); - assert(nc); - nc->destroy(); - assert(nodes.size() == remaining - 1); - --remaining; - } - assert(nodes.empty()); - - patch_model()->clear(); - - if (m_patch_view) { - assert(m_patch_view->canvas()); - m_patch_view->canvas()->destroy(); - } -} -#endif - -#if 0 -void -PatchController::destroy() -{ - // Destroying nodes removes models from patch model, which invalidates any - // iterator to nodes, so avoid the iterator problem by doing it this way: - const NodeModelMap& nodes = patch_model()->nodes(); - size_t remaining = nodes.size(); - - while (remaining > 0) { - CountedPtr<NodeController> nc = (*nodes.begin()).second->controller(); - assert(nc); - nc->destroy(); - assert(nodes.size() == remaining - 1); - --remaining; - } - assert(nodes.empty()); - - //App::instance().remove_patch(this); - App::instance().patch_tree()->remove_patch(path()); - - // Delete all children models - //patch_model()->clear(); - - // Remove self from object store - //Store::instance().remove_object(this); - - // Delete self from parent (this will delete model) - /*if (patch_model()->parent()) { - PatchController* const parent = (PatchController*)patch_model()->parent()->controller(); - assert(parent); - parent->remove_node(name()); - } else { - //delete m_model; - }*/ -} -#endif - - -void -PatchController::metadata_update(const string& key, const string& value) -{ - NodeController::metadata_update(key, value); - - if (key == "filename") - patch_model()->filename(value); -} - - -void -PatchController::set_path(const Path& new_path) -{ - assert(m_model); - Path old_path = path(); - - // Rename nodes - for (NodeModelMap::const_iterator i = patch_model()->nodes().begin(); - i != patch_model()->nodes().end(); ++i) { - const NodeModel* const nm = (*i).second.get(); - assert(nm); - CountedPtr<NodeController> nc = PtrCast<NodeController>(nm->controller()); - assert(nc); - nc->set_path(new_path.base() + nc->node_model()->path().name()); - } - -#ifdef DEBUG - // Be sure ports were renamed by their bridge nodes - for (PortModelList::const_iterator i = node_model()->ports().begin(); - i != node_model()->ports().end(); ++i) { - CountedPtr<GtkObjectController> pc = PtrCast<GtkObjectController>((*i)->controller()); - assert(pc); - assert(pc->path().parent()== new_path); - } -#endif - - App::instance().patch_tree()->patch_renamed(old_path, new_path); - - /*if (m_window) - m_window->patch_renamed(new_path);*/ - - if (m_control_window) - m_control_window->set_title(new_path + " Controls"); - - if (m_module) - m_module->name(new_path.name()); - - CountedPtr<PatchController> parent = PtrCast<PatchController>(patch_model()->parent()->controller()); - - //if (parent && parent->window()) - // parent->window()->node_renamed(old_path, new_path); - - //remove_from_store(); - GtkObjectController::set_path(new_path); - //add_to_store(); - - if (old_path.name() != new_path.name()) - parent->patch_model()->rename_node(old_path, new_path); -} - - -void -PatchController::create_module(OmFlowCanvas* canvas) -{ - // Update menu if we didn't used to have a module - if (!m_module) { - /*Gtk::Menu::MenuList& items = m_menu.items(); - m_menu.remove(items[4]); - - items.push_front(Gtk::Menu_Helpers::SeparatorElem()); - items.push_front(Gtk::Menu_Helpers::MenuElem("Browse to Patch", - sigc::mem_fun((SubpatchModule*)m_module, &SubpatchModule::browse_to_patch))); - items.push_front(Gtk::Menu_Helpers::MenuElem("Open Patch in New Window", - sigc::mem_fun(this, &PatchController::show_patch_window)));*/ - } - - if (!m_module || m_module->canvas() != canvas) { - - //cerr << "Creating patch module " << m_model->path() << endl; - - assert(canvas); - assert(m_module == NULL); - assert(!m_patch_view || canvas != m_patch_view->canvas()); - - // FIXME: weirdo using model->controller() to get shared_ptr_from_this.. - m_module = new SubpatchModule(canvas, PtrCast<PatchController>(m_model->controller())); - create_all_ports(); - } - - m_module->move_to(node_model()->x(), node_model()->y()); -} - - -CountedPtr<PatchView> -PatchController::get_view() -{ - if (m_patch_view) - return m_patch_view; - - Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference(); - - PatchView* pv = NULL; - xml->get_widget_derived("patch_view_vbox", pv); - assert(pv); - m_patch_view = CountedPtr<PatchView>(pv); - m_patch_view->patch_controller(this); - assert(m_patch_view->canvas()); - - // Create modules for nodes - for (NodeModelMap::const_iterator i = patch_model()->nodes().begin(); - i != patch_model()->nodes().end(); ++i) { - - const CountedPtr<NodeModel> nm = (*i).second; - - string val = nm->get_metadata("module-x"); - if (val != "") - nm->x(atof(val.c_str())); - val = nm->get_metadata("module-y"); - if (val != "") - nm->y(atof(val.c_str())); - - /* Set sane default coordinates if not set already yet */ - if (nm->x() == 0.0f && nm->y() == 0.0f) { - double x, y; - m_patch_view->canvas()->get_new_module_location(x, y); - nm->x(x); - nm->y(y); - } - - CountedPtr<NodeController> nc = PtrCast<NodeController>(ControllerFactory::get_controller(nm)); - - assert(nc); - assert(nm->controller() == nc); - - nc->create_module(m_patch_view->canvas()); - assert(nc->module()); - } - - // Create pseudo modules for ports (ports on this canvas, not on our module) - for (PortModelList::const_iterator i = patch_model()->ports().begin(); - i != patch_model()->ports().end(); ++i) { - CountedPtr<PortController> pc = PtrCast<PortController>((*i)->controller()); - assert(pc); - pc->create_module(m_patch_view->canvas()); - } - - - // Create connections - for (list<CountedPtr<ConnectionModel> >::const_iterator i = patch_model()->connections().begin(); - i != patch_model()->connections().end(); ++i) { - connection(*i); - } - - // Set run checkbox - if (patch_model()->enabled()) - m_patch_view->enable(); - - return m_patch_view; -} - - -void -PatchController::show_properties_window() -{ - if (!m_properties_window) { - Glib::RefPtr<Gnome::Glade::Xml> glade_xml = GladeFactory::new_glade_reference(); - glade_xml->get_widget_derived("patch_properties_win", m_properties_window); - m_properties_window->patch_model(patch_model()); - } - - m_properties_window->show(); - -} - - -/** Create a connection in the view (canvas). - */ -void -PatchController::connection(CountedPtr<ConnectionModel> cm) -{ - if (m_patch_view) { - - // Deal with port "anonymous nodes" for this patch's own ports... - const Path& src_parent_path = cm->src_port_path().parent(); - const Path& dst_parent_path = cm->dst_port_path().parent(); - - const string& src_parent_name = - (src_parent_path == path()) ? "" : src_parent_path.name(); - const string& dst_parent_name = - (dst_parent_path == path()) ? "" : dst_parent_path.name(); - - Port* src_port = m_patch_view->canvas()->get_port(src_parent_name, cm->src_port_path().name()); - Port* dst_port = m_patch_view->canvas()->get_port(dst_parent_name, cm->dst_port_path().name()); - assert(src_port && dst_port); - - m_patch_view->canvas()->add_connection(src_port, dst_port); - } -} - - -/** Add a child node to this patch. - * - * This is for plugin nodes and patches, and is responsible for creating the - * GtkObjectController for @a node (and through that the View if necessary) - */ -void -PatchController::add_node(CountedPtr<NodeModel> node) -{ - assert(node); - assert(node->parent().get() == m_patch_model.get()); - assert(node->parent() == m_patch_model); - assert(patch_model()->get_node(node->path().name())); - - assert(node->parent() == m_patch_model); - - CountedPtr<NodeController> nc = PtrCast<NodeController>(ControllerFactory::get_controller(node)); - assert(nc); - assert(node->controller() == nc); // lifeline reference - - if (m_patch_view) { - double x, y; - m_patch_view->canvas()->get_new_module_location(x, y); - node->x(x); - node->y(y); - - // Set zoom to 1.0 so module isn't messed up (Death to GnomeCanvas) - float old_zoom = m_patch_view->canvas()->get_zoom(); - if (old_zoom != 1.0) - m_patch_view->canvas()->set_zoom(1.0); - - nc->create_module(m_patch_view->canvas()); - assert(nc->module()); - nc->module()->resize(); - - // Reset zoom - if (old_zoom != 1.0) { - m_patch_view->canvas()->set_zoom(old_zoom); - nc->module()->zoom(old_zoom); - } - } - -} - -#if 0 -/** Add a port to this patch. - * - * Will add a port to the subpatch module and the control window, if they - * exist. - */ -void -PatchController::add_port(CountedPtr<PortModel> pm) -{ - assert(pm); - assert(pm->parent() == m_patch_model); - assert(patch_model()->get_port(pm->path().name())); - - //cerr << "[PatchController] Adding port " << pm->path() << endl; - - /*if (patch_model()->get_port(pm->path().name())) { - cerr << "[PatchController] Ignoring duplicate port " - << pm->path() << endl; - return; - }*/ - - //node_model()->add_port(pm); - CountedPtr<PortController> pc = ControllerFactory::get_controller(pm); - - // Handle bridge ports/nodes (this is uglier than it should be) - /*NodeController* nc = (NodeController*)Store::instance().node(pm->path())->controller(); - if (nc) - nc->bridge_port(pc); - */ - - // Create port on this patch's module (if there is one) - if (m_module) { - pc->create_port(m_module); - m_module->resize(); - } - - // Create port's (pseudo) module on this patch's canvas (if there is one) - if (m_patch_view) { - - // Set zoom to 1.0 so module isn't messed up (Death to GnomeCanvas) - float old_zoom = m_patch_view->canvas()->get_zoom(); - m_patch_view->canvas()->set_zoom(1.0); - - pc->create_module(m_patch_view->canvas()); - - // Reset zoom - pc->module()->zoom(old_zoom); - } - - if (m_control_window) { - assert(m_control_window->control_panel()); - m_control_window->control_panel()->add_port(pm); - m_control_window->resize(); - } - - // Enable "Controls" menuitem on module and patch window, if necessary - if (has_control_inputs()) - enable_controls_menuitem(); -} - - -/** Removes a port from this patch - */ -void -PatchController::remove_port(const Path& path, bool resize_module) -{ - assert(path.parent() == m_model->path()); - assert( ! patch_model()->get_port(path.name())); - - //cerr << "[PatchController] Removing port " << path << endl; - - /* FIXME - if (m_control_panel) { - m_control_panel->remove_port(path); - if (m_control_window) { - assert(m_control_window->control_panel() == m_control_panel); - m_control_window->resize(); - } - }*/ - - if (m_module) { - delete m_module->port(path.name()); - if (resize_module) - m_module->resize(); - } - - // Disable "Controls" menuitem on module and patch window, if necessary - if (!has_control_inputs()) - disable_controls_menuitem(); -} -#endif - -void -PatchController::disconnection(const Path& src_port_path, const Path& dst_port_path) -{ - const string& src_node_name = src_port_path.parent().name(); - const string& src_port_name = src_port_path.name(); - const string& dst_node_name = dst_port_path.parent().name(); - const string& dst_port_name = dst_port_path.name(); - - if (m_patch_view) { - Port* src_port = m_patch_view->canvas()->get_port(src_node_name, src_port_name); - Port* dst_port = m_patch_view->canvas()->get_port(dst_node_name, dst_port_name); - - if (src_port && dst_port) { - m_patch_view->canvas()->remove_connection(src_port, dst_port); - } - } - - //patch_model()->remove_connection(src_port_path, dst_port_path); - - cerr << "FIXME: disconnection\n"; - /* - // Enable control slider in destination node control window - PortController* p = (PortController)Store::instance().port(dst_port_path)->controller(); - assert(p); - - if (p->control_panel()) - p->control_panel()->enable_port(p->path()); - */ -} - - -/** Become the parent of the patch view. - * - * Steals the view away from whatever window is currently showing it. - */ -void -PatchController::claim_patch_view() -{ - assert(m_patch_view); - - m_patch_view->hide(); - m_patch_view->reparent(m_patch_view_bin); -} - - -void -PatchController::show_control_window() -{ - assert(patch_model()); - - if (m_control_window == NULL) - m_control_window = new NodeControlWindow(this, patch_model()->poly()); - - if (m_control_window->control_panel()->num_controls() > 0) - m_control_window->present(); -} - - -} // namespace Ingenuity diff --git a/src/progs/ingenuity/PatchController.h b/src/progs/ingenuity/PatchController.h deleted file mode 100644 index e9c0d0b6..00000000 --- a/src/progs/ingenuity/PatchController.h +++ /dev/null @@ -1,124 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef PATCHCONTROLLER_H -#define PATCHCONTROLLER_H - -#include <string> -#include <gtkmm.h> -#include "util/CountedPtr.h" -#include "NodeController.h" -#include "PatchModel.h" - -namespace Ingen { namespace Client { - class PatchModel; - class NodeModel; - class PortModel; - class ControlModel; - class ConnectionModel; -} } - -using std::string; -using namespace Ingen::Client; - -namespace Ingenuity { - -class PatchWindow; -class SubpatchModule; -class Controller; -class OmFlowCanvas; -class NodeControlWindow; -class PatchPropertiesWindow; -class ControlPanel; -class PatchView; -class NodeController; - - -/** Controller for a patch. - * - * A patch is different from a port or node because there are two - * representations in the Gtk client - the window and the module in the parent - * patch (if applicable). So, this is a master class that contains both of - * those representations, and acts as the recipient of all patch related - * events (being the controller). - * - * \ingroup Ingenuity - */ -class PatchController : public NodeController -{ -public: - virtual ~PatchController(); - - /* - virtual void add_to_store(); - virtual void remove_from_store(); - */ - - virtual void metadata_update(const string& key, const string& value); - - //virtual void add_port(CountedPtr<PortModel> pm); - //virtual void remove_port(const Path& path, bool resize_module); - - void connection(CountedPtr<ConnectionModel> cm); - void disconnection(const Path& src_port_path, const Path& dst_port_path); - //void clear(); - - void show_control_window(); - void show_properties_window(); - void show_patch_window(); - - void claim_patch_view(); - - void create_module(OmFlowCanvas* canvas); - - CountedPtr<PatchView> get_view(); - PatchWindow* window() const { return m_window; } - void window(PatchWindow* pw) { m_window = pw; } - - void set_path(const Path& new_path); - - //void enable(); - //void disable(); - - const CountedPtr<PatchModel> patch_model() const { return m_patch_model; } - -private: - friend class ControllerFactory; - PatchController(CountedPtr<PatchModel> model); - - void add_node(CountedPtr<NodeModel> object); - - PatchPropertiesWindow* m_properties_window; - - // FIXME: remove these - PatchWindow* m_window; ///< Patch Window currently showing m_patch_view - CountedPtr<PatchView> m_patch_view; ///< View (canvas) of this patch - - CountedPtr<PatchModel> m_patch_model; - - /** Invisible bin used to store patch view when not shown by a patch window */ - Gtk::Alignment m_patch_view_bin; - - // Coordinates for next added plugin (used by canvas menu) - // 0 means "not set", ie guess at the best location - int m_module_x; - int m_module_y; -}; - - -} // namespace Ingenuity - -#endif // PATCHCONTROLLER_H diff --git a/src/progs/ingenuity/PatchPropertiesWindow.cpp b/src/progs/ingenuity/PatchPropertiesWindow.cpp index 2271cc21..b6dd5e7f 100644 --- a/src/progs/ingenuity/PatchPropertiesWindow.cpp +++ b/src/progs/ingenuity/PatchPropertiesWindow.cpp @@ -41,20 +41,32 @@ PatchPropertiesWindow::PatchPropertiesWindow(BaseObjectType* cobject, const Glib * the window in any way. */ void -PatchPropertiesWindow::patch_model(CountedPtr<PatchModel> patch_model) +PatchPropertiesWindow::set_patch(CountedPtr<PatchModel> patch_model) { property_title() = patch_model->path() + " Properties"; m_patch_model = patch_model; - m_author_entry->set_text(m_patch_model->get_metadata("author")); - m_textview->get_buffer()->set_text(m_patch_model->get_metadata("description")); + + const Atom& author_atom = m_patch_model->get_metadata("author"); + m_author_entry->set_text( + (author_atom.type() == Atom::STRING) ? author_atom.get_string() : "" ); + + const Atom& desc_atom = m_patch_model->get_metadata("description"); + m_textview->get_buffer()->set_text( + (desc_atom.type() == Atom::STRING) ? desc_atom.get_string() : "" ); } void PatchPropertiesWindow::cancel_clicked() { - m_author_entry->set_text(m_patch_model->get_metadata("author")); - m_textview->get_buffer()->set_text(m_patch_model->get_metadata("description")); + const Atom& author_atom = m_patch_model->get_metadata("author"); + m_author_entry->set_text( + (author_atom.type() == Atom::STRING) ? author_atom.get_string() : "" ); + + const Atom& desc_atom = m_patch_model->get_metadata("description"); + m_textview->get_buffer()->set_text( + (desc_atom.type() == Atom::STRING) ? desc_atom.get_string() : "" ); + hide(); } @@ -62,8 +74,8 @@ PatchPropertiesWindow::cancel_clicked() void PatchPropertiesWindow::ok_clicked() { - m_patch_model->set_metadata("author", m_author_entry->get_text()); - m_patch_model->set_metadata("description", m_textview->get_buffer()->get_text()); + m_patch_model->set_metadata("author", Atom(m_author_entry->get_text().c_str())); + m_patch_model->set_metadata("description", Atom(m_textview->get_buffer()->get_text().c_str())); hide(); } diff --git a/src/progs/ingenuity/PatchPropertiesWindow.h b/src/progs/ingenuity/PatchPropertiesWindow.h index 76f12061..4f5da674 100644 --- a/src/progs/ingenuity/PatchPropertiesWindow.h +++ b/src/progs/ingenuity/PatchPropertiesWindow.h @@ -40,7 +40,8 @@ class PatchPropertiesWindow : public Gtk::Window public: PatchPropertiesWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& refGlade); - void patch_model(CountedPtr<PatchModel> patch_model); + void present(CountedPtr<PatchModel> patch_model) { set_patch(patch_model); Gtk::Window::present(); } + void set_patch(CountedPtr<PatchModel> patch_model); void cancel_clicked(); void ok_clicked(); diff --git a/src/progs/ingenuity/PatchTreeWindow.cpp b/src/progs/ingenuity/PatchTreeWindow.cpp index 090aba18..40ce5baf 100644 --- a/src/progs/ingenuity/PatchTreeWindow.cpp +++ b/src/progs/ingenuity/PatchTreeWindow.cpp @@ -18,7 +18,6 @@ #include "ModelEngineInterface.h" #include "OSCEngineSender.h" #include "PatchTreeWindow.h" -#include "PatchController.h" #include "PatchWindow.h" #include "Store.h" #include "SubpatchModule.h" @@ -77,15 +76,13 @@ PatchTreeWindow::new_object(CountedPtr<ObjectModel> object) { CountedPtr<PatchModel> patch = PtrCast<PatchModel>(object); if (patch) - add_patch(PtrCast<PatchController>(patch->controller())); + add_patch(patch); } void -PatchTreeWindow::add_patch(CountedPtr<PatchController> pc) +PatchTreeWindow::add_patch(CountedPtr<PatchModel> pm) { - const CountedPtr<PatchModel> pm = pc->patch_model(); - if (!pm->parent()) { Gtk::TreeModel::iterator iter = m_patch_treestore->append(); Gtk::TreeModel::Row row = *iter; @@ -101,7 +98,7 @@ PatchTreeWindow::add_patch(CountedPtr<PatchController> pc) row[m_patch_tree_columns.name_col] = pm->path().name(); } row[m_patch_tree_columns.enabled_col] = false; - row[m_patch_tree_columns.patch_controller_col] = pc; + row[m_patch_tree_columns.patch_model_col] = pm; m_patches_treeview->expand_row(m_patch_treestore->get_path(iter), true); } else { Gtk::TreeModel::Children children = m_patch_treestore->children(); @@ -112,7 +109,7 @@ PatchTreeWindow::add_patch(CountedPtr<PatchController> pc) Gtk::TreeModel::Row row = *iter; row[m_patch_tree_columns.name_col] = pm->path().name(); row[m_patch_tree_columns.enabled_col] = false; - row[m_patch_tree_columns.patch_controller_col] = pc; + row[m_patch_tree_columns.patch_model_col] = pm; m_patches_treeview->expand_row(m_patch_treestore->get_path(iter), true); } } @@ -132,8 +129,8 @@ Gtk::TreeModel::iterator PatchTreeWindow::find_patch(Gtk::TreeModel::Children root, const Path& path) { for (Gtk::TreeModel::iterator c = root.begin(); c != root.end(); ++c) { - CountedPtr<PatchController> pc = (*c)[m_patch_tree_columns.patch_controller_col]; - if (pc->model()->path() == path) { + CountedPtr<PatchModel> pm = (*c)[m_patch_tree_columns.patch_model_col]; + if (pm->path() == path) { return c; } else if ((*c)->children().size() > 0) { Gtk::TreeModel::iterator ret = find_patch(c->children(), path); @@ -151,7 +148,7 @@ PatchTreeWindow::event_patch_selected() Gtk::TreeModel::iterator active = m_patch_tree_selection->get_selected(); if (active) { Gtk::TreeModel::Row row = *active; - CountedPtr<PatchController> pc = row[m_patch_tree_columns.patch_controller_col]; + CountedPtr<PatchModel> pm = row[m_patch_tree_columns.patch_model_col]; } } */ @@ -165,9 +162,10 @@ PatchTreeWindow::show_patch_menu(GdkEventButton* ev) Gtk::TreeModel::iterator active = m_patch_tree_selection->get_selected(); if (active) { Gtk::TreeModel::Row row = *active; - CountedPtr<PatchController> pc = row[m_patch_tree_columns.patch_controller_col]; - if (pc) - pc->show_menu(ev); + CountedPtr<PatchModel> pm = row[m_patch_tree_columns.patch_model_col]; + if (pm) + cerr << "FIXME: patch menu\n"; + //pm->show_menu(ev); } } @@ -177,9 +175,10 @@ PatchTreeWindow::event_patch_activated(const Gtk::TreeModel::Path& path, Gtk::Tr { Gtk::TreeModel::iterator active = m_patch_treestore->get_iter(path); Gtk::TreeModel::Row row = *active; - CountedPtr<PatchController> pc = row[m_patch_tree_columns.patch_controller_col]; + CountedPtr<PatchModel> pm = row[m_patch_tree_columns.patch_model_col]; - App::instance().window_factory()->present(pc); + cerr << "FIXME: tree win show\n"; + //App::instance().window_factory()->present(pc); } @@ -190,12 +189,12 @@ PatchTreeWindow::event_patch_enabled_toggled(const Glib::ustring& path_str) Gtk::TreeModel::iterator active = m_patch_treestore->get_iter(path); Gtk::TreeModel::Row row = *active; - CountedPtr<PatchController> pc = row[m_patch_tree_columns.patch_controller_col]; - Glib::ustring patch_path = pc->model()->path(); + CountedPtr<PatchModel> pm = row[m_patch_tree_columns.patch_model_col]; + Glib::ustring patch_path = pm->path(); - assert(pc); + assert(pm); - if ( ! pc->patch_model()->enabled()) { + if ( ! pm->enabled()) { if (m_enable_signal) App::instance().engine()->enable_patch(patch_path); //pc->enable(); diff --git a/src/progs/ingenuity/PatchTreeWindow.h b/src/progs/ingenuity/PatchTreeWindow.h index d23c4e54..91e68bf1 100644 --- a/src/progs/ingenuity/PatchTreeWindow.h +++ b/src/progs/ingenuity/PatchTreeWindow.h @@ -29,7 +29,6 @@ using Ingen::Client::Store; namespace Ingenuity { class PatchWindow; -class PatchController; class PatchTreeView; @@ -50,7 +49,7 @@ public: void patch_disabled(const Path& path); void patch_renamed(const Path& old_path, const Path& new_path); - void add_patch(CountedPtr<PatchController> pc); + void add_patch(CountedPtr<PatchModel> pm); void remove_patch(const Path& path); void show_patch_menu(GdkEventButton* ev); @@ -66,11 +65,11 @@ protected: struct PatchTreeModelColumns : public Gtk::TreeModel::ColumnRecord { PatchTreeModelColumns() - { add(name_col); add(enabled_col); add(patch_controller_col); } + { add(name_col); add(enabled_col); add(patch_model_col); } Gtk::TreeModelColumn<Glib::ustring> name_col; Gtk::TreeModelColumn<bool> enabled_col; - Gtk::TreeModelColumn<CountedPtr<PatchController> > patch_controller_col; + Gtk::TreeModelColumn<CountedPtr<PatchModel> > patch_model_col; }; bool m_enable_signal; diff --git a/src/progs/ingenuity/PatchView.cpp b/src/progs/ingenuity/PatchView.cpp index 90c0083e..0ae82f45 100644 --- a/src/progs/ingenuity/PatchView.cpp +++ b/src/progs/ingenuity/PatchView.cpp @@ -21,7 +21,6 @@ #include "App.h" #include "ModelEngineInterface.h" #include "OmFlowCanvas.h" -#include "PatchController.h" #include "LoadPluginWindow.h" #include "PatchModel.h" #include "NewSubpatchWindow.h" @@ -29,13 +28,13 @@ #include "NodeControlWindow.h" #include "PatchPropertiesWindow.h" #include "PatchTreeWindow.h" +#include "GladeFactory.h" namespace Ingenuity { PatchView::PatchView(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& xml) : Gtk::Box(cobject), - _patch(NULL), _canvas(NULL), _breadcrumb_container(NULL), _enable_signal(true) @@ -56,23 +55,27 @@ PatchView::PatchView(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::X void -PatchView::patch_controller(PatchController* pc) +PatchView::set_patch(CountedPtr<PatchModel> patch) { - _patch = pc; - _canvas = new OmFlowCanvas(pc, 1600*2, 1200*2); + cerr << "Creating view for " << patch->path() << endl; + + assert(_breadcrumb_container); // ensure created + + _patch = patch; + _canvas = new OmFlowCanvas(patch, 1600*2, 1200*2); _canvas_scrolledwindow->add(*_canvas); - _poly_spin->set_value(pc->patch_model()->poly()); - _destroy_but->set_sensitive(pc->path() != "/"); - //_description_window->patch_model(pc->model()); - + _poly_spin->set_value(patch->poly()); + _destroy_but->set_sensitive(patch->path() != "/"); + patch->enabled() ? enable() : disable(); + + // Connect model signals to track state + patch->enabled_sig.connect(sigc::mem_fun(this, &PatchView::enable)); + patch->disabled_sig.connect(sigc::mem_fun(this, &PatchView::disable)); - pc->patch_model()->enabled_sig.connect(sigc::mem_fun(this, &PatchView::enable)); - pc->patch_model()->disabled_sig.connect(sigc::mem_fun(this, &PatchView::disable)); - + // Connect widget signals to do things _process_but->signal_toggled().connect(sigc::mem_fun(this, &PatchView::process_toggled)); - _clear_but->signal_clicked().connect(sigc::mem_fun(this, &PatchView::clear_clicked)); _zoom_normal_but->signal_clicked().connect(sigc::bind(sigc::mem_fun( @@ -83,11 +86,22 @@ PatchView::patch_controller(PatchController* pc) } -void -PatchView::show_control_window() +PatchView::~PatchView() +{ + cerr << "Destroying view for " << _patch->path() << endl; +} + + +CountedPtr<PatchView> +PatchView::create(CountedPtr<PatchModel> patch) + { - if (_patch != NULL) - _patch->show_control_window(); + const Glib::RefPtr<Gnome::Glade::Xml>& xml = GladeFactory::new_glade_reference("patch_view_box"); + PatchView* result = NULL; + xml->get_widget_derived("patch_view_box", result); + assert(result); + result->set_patch(patch); + return CountedPtr<PatchView>(result); } @@ -98,11 +112,11 @@ PatchView::process_toggled() return; if (_process_but->get_active()) { - App::instance().engine()->enable_patch(_patch->model()->path()); - App::instance().patch_tree()->patch_enabled(_patch->model()->path()); + App::instance().engine()->enable_patch(_patch->path()); + App::instance().patch_tree()->patch_enabled(_patch->path()); } else { - App::instance().engine()->disable_patch(_patch->model()->path()); - App::instance().patch_tree()->patch_disabled(_patch->model()->path()); + App::instance().engine()->disable_patch(_patch->path()); + App::instance().patch_tree()->patch_disabled(_patch->path()); } } diff --git a/src/progs/ingenuity/PatchView.h b/src/progs/ingenuity/PatchView.h index 59e16aad..a6484b97 100644 --- a/src/progs/ingenuity/PatchView.h +++ b/src/progs/ingenuity/PatchView.h @@ -21,12 +21,12 @@ #include <gtkmm.h> #include <libglademm/xml.h> #include <libglademm.h> +#include "util/CountedPtr.h" +#include "PatchModel.h" using std::string; namespace Ingen { namespace Client { - class PatchModel; - class NodeModel; class PortModel; class ControlModel; class MetadataModel; @@ -36,7 +36,6 @@ using namespace Ingen::Client; namespace Ingenuity { -class PatchController; class OmFlowCanvas; class LoadPluginWindow; class NewSubpatchWindow; @@ -56,28 +55,29 @@ class PatchView : public Gtk::Box { public: PatchView(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& glade_xml); - - void patch_controller(PatchController* pc); + ~PatchView(); + + OmFlowCanvas* canvas() const { return _canvas; } + CountedPtr<PatchModel> patch() const { return _patch; } + Gtk::Viewport* breadcrumb_container() const { return _breadcrumb_container; } - OmFlowCanvas* canvas() const { return _canvas; } - PatchController* patch_controller() const { return _patch; } - Gtk::Viewport* breadcrumb_container() const { return _breadcrumb_container; } - void show_control_window(); + static CountedPtr<PatchView> create(CountedPtr<PatchModel> patch); +private: + void set_patch(CountedPtr<PatchModel> patch); + void process_toggled(); + void clear_clicked(); + void enable(); void disable(); void zoom_full(); -private: - void process_toggled(); - void clear_clicked(); - - PatchController* _patch; - OmFlowCanvas* _canvas; + CountedPtr<PatchModel> _patch; + OmFlowCanvas* _canvas; - Gtk::ScrolledWindow* _canvas_scrolledwindow; + Gtk::ScrolledWindow* _canvas_scrolledwindow; Gtk::ToggleToolButton* _process_but; Gtk::SpinButton* _poly_spin; diff --git a/src/progs/ingenuity/PatchWindow.cpp b/src/progs/ingenuity/PatchWindow.cpp index c395c265..1aec1977 100644 --- a/src/progs/ingenuity/PatchWindow.cpp +++ b/src/progs/ingenuity/PatchWindow.cpp @@ -21,7 +21,6 @@ #include "App.h" #include "ModelEngineInterface.h" #include "OmFlowCanvas.h" -#include "PatchController.h" #include "LoadPluginWindow.h" #include "PatchModel.h" #include "NewSubpatchWindow.h" @@ -36,7 +35,6 @@ #include "Store.h" #include "ConnectWindow.h" #include "Loader.h" -#include "ControllerFactory.h" #include "WindowFactory.h" #include "PatchView.h" @@ -45,8 +43,6 @@ namespace Ingenuity { PatchWindow::PatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& xml) : Gtk::Window(cobject), - m_load_plugin_window(NULL), - m_new_subpatch_window(NULL), m_enable_signal(true), m_position_stored(false), m_x(0), @@ -75,17 +71,7 @@ PatchWindow::PatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glad xml->get_widget("patch_view_messages_window_menuitem", m_menu_view_messages_window); xml->get_widget("patch_view_patch_tree_window_menuitem", m_menu_view_patch_tree_window); xml->get_widget("patch_help_about_menuitem", m_menu_help_about); - - // FIXME: these shouldn't be loaded here - xml->get_widget_derived("load_plugin_win", m_load_plugin_window); - xml->get_widget_derived("new_subpatch_win", m_new_subpatch_window); - xml->get_widget_derived("load_patch_win", m_load_patch_window); - xml->get_widget_derived("load_subpatch_win", m_load_subpatch_window); - - m_new_subpatch_window->set_transient_for(*this); - m_load_patch_window->set_transient_for(*this); - m_load_subpatch_window->set_transient_for(*this); - + m_menu_view_control_window->property_sensitive() = false; //m_status_bar->push(App::instance().engine()->engine_url()); //m_status_bar->pack_start(*Gtk::manage(new Gtk::Image(Gtk::Stock::CONNECT, Gtk::ICON_SIZE_MENU)), false, false); @@ -134,14 +120,10 @@ PatchWindow::PatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glad PatchWindow::~PatchWindow() { // Prevents deletion - m_patch->claim_patch_view(); + //m_patch->claim_patch_view(); App::instance().remove_patch_window(this); - hide(); - - delete m_new_subpatch_window; - delete m_load_subpatch_window; delete m_breadcrumb_box; } @@ -149,84 +131,63 @@ PatchWindow::~PatchWindow() /** Set the patch controller from a Path (for use by eg. BreadCrumbBox) */ void -PatchWindow::set_patch_from_path(const Path& path) +PatchWindow::set_patch_from_path(const Path& path, CountedPtr<PatchView> view) { - CountedPtr<PatchModel> model = PtrCast<PatchModel>(App::instance().store()->object(path)); - if (!model) - return; // can't really do anything useful.. - - CountedPtr<PatchController> pc = PtrCast<PatchController>(ControllerFactory::get_controller(model)); - assert(pc); - - App::instance().window_factory()->present(pc, this); + if (view) { + assert(view->patch()->path() == path); + App::instance().window_factory()->present_patch(view->patch(), this, view); + } else { + CountedPtr<PatchModel> model = PtrCast<PatchModel>(App::instance().store()->object(path)); + if (model) + App::instance().window_factory()->present_patch(model, this); + } } /** Sets the patch controller for this window and initializes everything. * - * This function MUST be called before using the window in any way! + * If @a view is NULL, a new view will be created. */ void -PatchWindow::set_patch(CountedPtr<PatchController> pc) +PatchWindow::set_patch(CountedPtr<PatchModel> patch, CountedPtr<PatchView> view) { - if (!pc || pc == m_patch) + if (!patch || patch == m_patch) return; m_enable_signal = false; - if (m_patch) { - CountedPtr<PatchController> old_pc = m_patch; - assert(old_pc->window() == NULL || old_pc->window() == this); - old_pc->claim_patch_view(); - old_pc->window(NULL); - } - - m_patch = pc; + m_patch = patch; - CountedPtr<PatchView> patch_view = pc->get_view(); - assert(patch_view); - patch_view->reparent(*m_viewport); + m_view = view ? view : PatchView::create(patch); + assert(m_view); + + m_viewport->remove(); + m_viewport->add(*m_view.get()); - if (m_breadcrumb_box->get_parent()) - m_breadcrumb_box->reparent(*patch_view->breadcrumb_container()); - else - patch_view->breadcrumb_container()->add(*m_breadcrumb_box); + m_view->breadcrumb_container()->remove(); + m_view->breadcrumb_container()->add(*m_breadcrumb_box); - m_breadcrumb_box->build(pc->model()->path()); + m_breadcrumb_box->build(patch->path(), m_view); m_breadcrumb_box->show(); - pc->window(this); - show_all(); - - assert(m_load_plugin_window != NULL); - assert(m_new_subpatch_window != NULL); - assert(m_load_patch_window != NULL); - assert(m_load_subpatch_window != NULL); - - m_load_patch_window->set_patch(m_patch); - m_load_plugin_window->set_patch(m_patch); - m_new_subpatch_window->set_patch(m_patch); - m_load_subpatch_window->set_patch(m_patch); - - m_menu_view_control_window->property_sensitive() = pc->has_control_inputs(); + show_all(); + + //m_menu_view_control_window->property_sensitive() = patch->has_control_inputs(); int width, height; get_size(width, height); - patch_view->canvas()->scroll_to( - ((int)patch_view->canvas()->width() - width)/2, - ((int)patch_view->canvas()->height() - height)/2); + m_view->canvas()->scroll_to( + ((int)m_view->canvas()->width() - width)/2, + ((int)m_view->canvas()->height() - height)/2); - set_title(m_patch->model()->path()); + set_title(m_patch->path()); //m_properties_window->patch_model(pc->patch_model()); - if (pc->model()->path() == "/") + if (patch->path() == "/") m_menu_destroy_patch->set_sensitive(false); else m_menu_destroy_patch->set_sensitive(true); - assert(m_patch == pc); - assert(m_patch->window() == this); - m_enable_signal = true; } @@ -242,45 +203,31 @@ PatchWindow::event_show_engine() void PatchWindow::event_show_controls() { - if (m_patch) - m_patch->show_control_window(); + App::instance().window_factory()->present_controls(m_patch); } void PatchWindow::event_show_properties() { - if (m_patch) - m_patch->show_properties_window(); + App::instance().window_factory()->present_properties(m_patch); } -/* -void -PatchWindow::event_open() -{ - m_load_patch_window->set_replace(); - m_load_patch_window->present(); -} -*/ - void PatchWindow::event_import() { - m_load_patch_window->set_merge(); - m_load_patch_window->present(); + App::instance().window_factory()->present_load_patch(m_patch); } void PatchWindow::event_save() { - CountedPtr<PatchModel> model(m_patch->patch_model().get()); - - if (model->filename() == "") + if (m_patch->filename() == "") event_save_as(); else - App::instance().loader()->save_patch(model, model->filename(), false); + App::instance().loader()->save_patch(m_patch, m_patch->filename(), false); } @@ -301,7 +248,7 @@ PatchWindow::event_save_as() dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); // Set current folder to most sensible default - const string& current_filename = m_patch->patch_model()->filename(); + const string& current_filename = m_patch->filename(); if (current_filename.length() > 0) dialog.set_filename(current_filename); else if (App::instance().configuration()->patch_folder().length() > 0) @@ -335,8 +282,8 @@ PatchWindow::event_save_as() fin.close(); if (confirm) { - App::instance().loader()->save_patch(m_patch->patch_model(), filename, recursive); - m_patch->patch_model()->filename(filename); + App::instance().loader()->save_patch(m_patch, filename, recursive); + m_patch->filename(filename); } } App::instance().configuration()->set_patch_folder(dialog.get_current_folder()); @@ -367,10 +314,12 @@ bool PatchWindow::on_key_press_event(GdkEventKey* event) { if (event->keyval == GDK_Delete) { + cerr << "FIXME: delete key\n"; + /* if (m_patch && m_patch->get_view()) { assert(m_patch->get_view()->canvas()); m_patch->get_view()->canvas()->destroy_selected(); - } + }*/ return true; } else { return Gtk::Window::on_key_press_event(event); @@ -409,14 +358,14 @@ PatchWindow::event_quit() void PatchWindow::event_destroy() { - App::instance().engine()->destroy(m_patch->model()->path()); + App::instance().engine()->destroy(m_patch->path()); } void PatchWindow::event_clear() { - App::instance().engine()->clear_patch(m_patch->model()->path()); + App::instance().engine()->clear_patch(m_patch->path()); } void diff --git a/src/progs/ingenuity/PatchWindow.h b/src/progs/ingenuity/PatchWindow.h index d538db78..2e0a388b 100644 --- a/src/progs/ingenuity/PatchWindow.h +++ b/src/progs/ingenuity/PatchWindow.h @@ -24,13 +24,15 @@ #include <libglademm.h> #include "util/Path.h" #include "util/CountedPtr.h" -#include "PatchController.h" +#include "PatchModel.h" +#include "PatchView.h" +using Ingen::Client::PatchModel; + using std::string; using std::list; namespace Ingen { namespace Client { class PatchModel; - class NodeModel; class PortModel; class ControlModel; class MetadataModel; @@ -40,7 +42,6 @@ using namespace Ingen::Client; namespace Ingenuity { -class PatchController; class OmFlowCanvas; class LoadPluginWindow; class LoadPatchWindow; @@ -64,13 +65,10 @@ public: PatchWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& glade_xml); ~PatchWindow(); - void set_patch_from_path(const Path& path); - void set_patch(CountedPtr<PatchController> pc); + void set_patch_from_path(const Path& path, CountedPtr<PatchView> view); + void set_patch(CountedPtr<PatchModel> pc, CountedPtr<PatchView> view); - CountedPtr<PatchController> patch_controller() const { return m_patch; } - LoadPluginWindow* load_plugin_window() const { return m_load_plugin_window; } - LoadSubpatchWindow* load_subpatch_window() const { return m_load_subpatch_window; } - NewSubpatchWindow* new_subpatch_window() const { return m_new_subpatch_window; } + CountedPtr<PatchModel> patch() const { return m_patch; } Gtk::MenuItem* menu_view_control_window() { return m_menu_view_control_window; } @@ -93,12 +91,8 @@ private: void event_show_controls(); void event_show_engine(); - CountedPtr<PatchController> m_patch; - - LoadPluginWindow* m_load_plugin_window; - LoadPatchWindow* m_load_patch_window; - NewSubpatchWindow* m_new_subpatch_window; - LoadSubpatchWindow* m_load_subpatch_window; + CountedPtr<PatchModel> m_patch; + CountedPtr<PatchView> m_view; bool m_enable_signal; bool m_position_stored; diff --git a/src/progs/ingenuity/PortController.cpp b/src/progs/ingenuity/PortController.cpp deleted file mode 100644 index 167cb594..00000000 --- a/src/progs/ingenuity/PortController.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "PortController.h" -#include "OmFlowCanvas.h" -#include "OmModule.h" -#include "PortModel.h" -#include "PatchModel.h" -#include "OmPort.h" -#include "OmPatchPort.h" -#include "Store.h" - -namespace Ingenuity { - - -PortController::PortController(CountedPtr<PortModel> model) -: GtkObjectController(model), - m_patch_port(NULL), - m_module(NULL), - m_port(NULL) -{ - assert(model); - assert(model->parent()); -} - - -void -PortController::destroy() -{ - assert(m_model->parent()); - CountedPtr<NodeController> parent = PtrCast<NodeController>(m_model->parent()->controller()); - assert(parent); - - parent->remove_port(path(), false); -} - - -void -PortController::create_module(OmFlowCanvas* canvas) -{ - //cerr << "Creating port module " << m_model->path() << endl; - - const string x_str = m_model->get_metadata("module-x"); - const string y_str = m_model->get_metadata("module-y"); - - double default_x; - double default_y; - canvas->get_new_module_location(default_x, default_y); - const double x = (x_str == "") ? default_x : atof(x_str.c_str()); - const double y = (y_str == "") ? default_y : atof(y_str.c_str()); - - assert(canvas); - assert(port_model()); - - if (m_module) - delete m_module; - - m_module = new OmPortModule(canvas, this, x, y); - - if (PtrCast<PatchModel>(port_model()->parent())) { - if (m_patch_port) - delete m_patch_port; - - m_patch_port = new OmPatchPort(m_module, port_model()); - } - - m_module->resize(); - - m_module->move_to(x, y); // FIXME: redundant (?) -} - - -void -PortController::destroy_module() -{ - delete m_module; - m_module = NULL; -} - - -void -PortController::metadata_update(const string& key, const string& value) -{ - //cerr << "Metadata " << path() << ": " << key << " = " << value << endl; - - if (m_module != NULL) { - if (key == "module-x") { - float x = atof(value.c_str()); - //if (x > 0 && x < m_canvas->width()) - m_module->move_to(x, m_module->property_y().get_value()); - } else if (key == "module-y") { - float y = atof(value.c_str()); - //if (y > 0 && y < m_canvas->height()) - m_module->move_to(m_module->property_x().get_value(), y); - } - } - - GtkObjectController::metadata_update(key, value); -} - -void -PortController::set_path(const Path& new_path) -{ - // Change port name on module, if view exists - if (m_port != NULL) - m_port->set_name(new_path.name()); - - m_model->set_path(new_path); -} - - -/** Create the visible port on a canvas module. - * - * Does not resize the module, caller's responsibility to do so if necessary. - */ -void -PortController::create_port(OmModule* module) -{ - assert(module != NULL); - - new OmPort(module, port_model()); -} - - -} // namespace Ingenuity - diff --git a/src/progs/ingenuity/PortController.h b/src/progs/ingenuity/PortController.h deleted file mode 100644 index e28cd21d..00000000 --- a/src/progs/ingenuity/PortController.h +++ /dev/null @@ -1,79 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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. - * - * Ingen 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., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef PORTCONTROLLER_H -#define PORTCONTROLLER_H - -#include <string> -#include <gtkmm.h> -#include "GtkObjectController.h" -#include "OmPortModule.h" - -using std::string; -using namespace Ingen::Client; - -namespace Ingen { namespace Client { - class MetadataModel; - class PortModel; -} } - -namespace Ingenuity { - -class Controller; -class OmPort; -class OmPatchPort; -class OmModule; -class OmPortModule; -class OmFlowCanvas; - - -/** Controller for a port on a (non-patch) node. - * - * \ingroup Ingenuity - */ -class PortController : public GtkObjectController -{ -public: - virtual ~PortController() {} - - virtual void destroy(); - - virtual void create_module(OmFlowCanvas* canvas); - virtual void destroy_module(); - OmPortModule* module() { return m_module; } - - virtual void metadata_update(const string& key, const string& value); - - void create_port(OmModule* module); - void destroy_port(); - - void set_path(const Path& new_path); - - CountedPtr<PortModel> port_model() const { return PtrCast<PortModel>(m_model); } - -private: - friend class ControllerFactory; - PortController(CountedPtr<PortModel> model); - - OmPatchPort* m_patch_port; ///< Port on m_module - OmPortModule* m_module; ///< Port pseudo-module (for patch ports only) - OmPort* m_port; ///< Port on some other canvas module -}; - - -} // namespace Ingenuity - -#endif // PORTCONTROLLER_H diff --git a/src/progs/ingenuity/RenameWindow.cpp b/src/progs/ingenuity/RenameWindow.cpp index 7a458e31..37d4fc39 100644 --- a/src/progs/ingenuity/RenameWindow.cpp +++ b/src/progs/ingenuity/RenameWindow.cpp @@ -18,7 +18,6 @@ #include <cassert> #include <string> #include "ObjectModel.h" -#include "GtkObjectController.h" #include "Store.h" #include "App.h" #include "ModelEngineInterface.h" @@ -47,7 +46,7 @@ RenameWindow::RenameWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Gl * This function MUST be called before using this object in any way. */ void -RenameWindow::set_object(GtkObjectController* object) +RenameWindow::set_object(CountedPtr<ObjectModel> object) { m_object = object; m_name_entry->set_text(object->path().name()); @@ -62,15 +61,15 @@ RenameWindow::name_changed() { assert(m_name_entry); assert(m_message_label); - assert(m_object->model()); - assert(m_object->model()->parent()); + assert(m_object); + assert(m_object->parent()); string name = m_name_entry->get_text(); if (name.find("/") != string::npos) { m_message_label->set_text("Name may not contain '/'"); m_ok_button->property_sensitive() = false; //} else if (m_object->parent()->patch_model()->get_node(name) != NULL) { - } else if (App::instance().store()->object(m_object->model()->parent()->path().base() + name)) { + } else if (App::instance().store()->object(m_object->parent()->path().base() + name)) { m_message_label->set_text("An object already exists with that name."); m_ok_button->property_sensitive() = false; } else if (name.length() == 0) { @@ -105,7 +104,7 @@ RenameWindow::ok_clicked() assert(name.length() > 0); assert(name.find("/") == string::npos); - App::instance().engine()->rename(m_object->model()->path(), name); + App::instance().engine()->rename(m_object->path(), name); hide(); } diff --git a/src/progs/ingenuity/RenameWindow.h b/src/progs/ingenuity/RenameWindow.h index af826f15..fe342100 100644 --- a/src/progs/ingenuity/RenameWindow.h +++ b/src/progs/ingenuity/RenameWindow.h @@ -19,16 +19,14 @@ #include <gtkmm.h> #include <libglademm.h> - +#include "util/CountedPtr.h" +#include "ObjectModel.h" +using Ingen::Client::ObjectModel; namespace Ingenuity { -class GtkObjectController; - -/** 'New Patch' Window. - * - * Loaded by libglade as a derived object. +/** Rename window. Handles renaming of any (Ingen) object. * * \ingroup Ingenuity */ @@ -37,14 +35,16 @@ class RenameWindow : public Gtk::Window public: RenameWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& refGlade); - void set_object(GtkObjectController* object); + void present(CountedPtr<ObjectModel> object) { set_object(object); Gtk::Window::present(); } private: + void set_object(CountedPtr<ObjectModel> object); + void name_changed(); void cancel_clicked(); void ok_clicked(); - GtkObjectController* m_object; + CountedPtr<ObjectModel> m_object; Gtk::Entry* m_name_entry; Gtk::Label* m_message_label; diff --git a/src/progs/ingenuity/SubpatchModule.cpp b/src/progs/ingenuity/SubpatchModule.cpp index 598cc9db..47465b09 100644 --- a/src/progs/ingenuity/SubpatchModule.cpp +++ b/src/progs/ingenuity/SubpatchModule.cpp @@ -24,7 +24,6 @@ #include "PatchModel.h" #include "PatchWindow.h" #include "OmFlowCanvas.h" -#include "PatchController.h" #include "OmPort.h" #include "WindowFactory.h" using std::cerr; using std::cout; using std::endl; @@ -32,8 +31,8 @@ using std::cerr; using std::cout; using std::endl; namespace Ingenuity { -SubpatchModule::SubpatchModule(OmFlowCanvas* canvas, CountedPtr<PatchController> patch) -: OmModule(canvas, patch.get()), +SubpatchModule::SubpatchModule(OmFlowCanvas* canvas, CountedPtr<PatchModel> patch) +: OmModule(canvas, patch), m_patch(patch) { assert(canvas); @@ -46,12 +45,13 @@ SubpatchModule::on_double_click(GdkEventButton* event) { assert(m_patch); - CountedPtr<PatchController> parent = PtrCast<PatchController>(m_patch->model()->parent()->controller()); + CountedPtr<PatchModel> parent = PtrCast<PatchModel>(m_patch->parent()); - PatchWindow* const preferred - = (event->state & GDK_SHIFT_MASK) ? NULL : parent->window(); + PatchWindow* const preferred = ( (parent && (event->state & GDK_SHIFT_MASK)) + ? NULL + : App::instance().window_factory()->patch_window(parent) ); - App::instance().window_factory()->present(m_patch, preferred); + App::instance().window_factory()->present_patch(m_patch, preferred); } @@ -62,10 +62,15 @@ SubpatchModule::on_double_click(GdkEventButton* event) void SubpatchModule::browse_to_patch() { - assert(m_patch->model()->parent()); - CountedPtr<PatchController> pc = PtrCast<PatchController>(m_patch->model()->parent()->controller()); + assert(m_patch->parent()); - App::instance().window_factory()->present(m_patch, pc->window()); + CountedPtr<PatchModel> parent = PtrCast<PatchModel>(m_patch->parent()); + + PatchWindow* const preferred = ( (parent) + ? App::instance().window_factory()->patch_window(parent) + : NULL ); + + App::instance().window_factory()->present_patch(m_patch, preferred); } @@ -73,14 +78,15 @@ SubpatchModule::browse_to_patch() void SubpatchModule::show_dialog() { - m_patch->show_control_window(); + cerr << "FIXME: dialog\n"; + //m_patch->show_control_window(); } void SubpatchModule::menu_remove() { - App::instance().engine()->destroy(m_patch->model()->path()); + App::instance().engine()->destroy(m_patch->path()); } } // namespace Ingenuity diff --git a/src/progs/ingenuity/SubpatchModule.h b/src/progs/ingenuity/SubpatchModule.h index a8e6e971..0f52ae2b 100644 --- a/src/progs/ingenuity/SubpatchModule.h +++ b/src/progs/ingenuity/SubpatchModule.h @@ -22,7 +22,7 @@ #include <libgnomecanvasmm.h> #include "OmModule.h" #include "util/CountedPtr.h" -#include "PatchController.h" +#include "PatchModel.h" using std::string; using std::list; namespace Ingen { namespace Client { @@ -46,7 +46,7 @@ class NodeControlWindow; class SubpatchModule : public OmModule { public: - SubpatchModule(OmFlowCanvas* canvas, CountedPtr<PatchController> controller); + SubpatchModule(OmFlowCanvas* canvas, CountedPtr<PatchModel> controller); virtual ~SubpatchModule() {} void on_double_click(GdkEventButton* ev); @@ -55,10 +55,10 @@ public: void browse_to_patch(); void menu_remove(); - CountedPtr<PatchController> patch() { return m_patch; } + CountedPtr<PatchModel> patch() { return m_patch; } protected: - CountedPtr<PatchController> m_patch; + CountedPtr<PatchModel> m_patch; }; diff --git a/src/progs/ingenuity/WindowFactory.cpp b/src/progs/ingenuity/WindowFactory.cpp index c7d79aca..3edbf568 100644 --- a/src/progs/ingenuity/WindowFactory.cpp +++ b/src/progs/ingenuity/WindowFactory.cpp @@ -15,13 +15,70 @@ */ #include "WindowFactory.h" +#include "App.h" #include "PatchWindow.h" #include "GladeFactory.h" -#include "App.h" +#include "NodePropertiesWindow.h" +#include "PatchPropertiesWindow.h" +#include "NodeControlWindow.h" +#include "LoadPluginWindow.h" +#include "LoadPatchWindow.h" +#include "LoadSubpatchWindow.h" +#include "RenameWindow.h" +#include "NewSubpatchWindow.h" namespace Ingenuity { +WindowFactory::WindowFactory() +: _load_plugin_win(NULL) +, _load_patch_win(NULL) +, _new_subpatch_win(NULL) +, _load_subpatch_win(NULL) +, _node_properties_win(NULL) +, _patch_properties_win(NULL) +{ + Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference(); + + xml->get_widget_derived("load_plugin_win", _load_plugin_win); + xml->get_widget_derived("load_patch_win", _load_patch_win); + xml->get_widget_derived("new_subpatch_win", _new_subpatch_win); + xml->get_widget_derived("load_subpatch_win", _load_subpatch_win); + xml->get_widget_derived("node_properties_win", _node_properties_win); + xml->get_widget_derived("patch_properties_win", _patch_properties_win); + +} + + +WindowFactory::~WindowFactory() +{ + for (PatchWindowMap::iterator i = _patch_windows.begin(); i != _patch_windows.end(); ++i) + delete i->second; + + for (ControlWindowMap::iterator i = _control_windows.begin(); i != _control_windows.end(); ++i) + delete i->second; + +} + + +PatchWindow* +WindowFactory::patch_window(CountedPtr<PatchModel> patch) +{ + PatchWindowMap::iterator w = _patch_windows.find(patch->path()); + + return (w == _patch_windows.end()) ? NULL : w->second; +} + + +NodeControlWindow* +WindowFactory::control_window(CountedPtr<NodeModel> node) +{ + ControlWindowMap::iterator w = _control_windows.find(node->path()); + + return (w == _control_windows.end()) ? NULL : w->second; +} + + /** Present a PatchWindow for a Patch. * * If @a preferred is not NULL, it will be set to display @a patch if the patch @@ -29,54 +86,55 @@ namespace Ingenuity { * @a preferred left unmodified. */ void -WindowFactory::present(CountedPtr<PatchController> patch, PatchWindow* preferred) +WindowFactory::present_patch(CountedPtr<PatchModel> patch, PatchWindow* preferred, CountedPtr<PatchView> view) { - std::map<Path, PatchWindow*>::iterator w = _windows.find(patch->model()->path()); + assert( !view || view->patch() == patch); + + PatchWindowMap::iterator w = _patch_windows.find(patch->path()); - if (w != _windows.end()) { + if (w != _patch_windows.end()) { (*w).second->present(); } else if (preferred) { - w = _windows.find(preferred->patch_controller()->model()->path()); + w = _patch_windows.find(preferred->patch()->path()); assert((*w).second == preferred); - preferred->set_patch(patch); - _windows.erase(w); - _windows[patch->model()->path()] = preferred; + preferred->set_patch(patch, view); + _patch_windows.erase(w); + _patch_windows[patch->path()] = preferred; preferred->present(); } else { - PatchWindow* win = create_new(patch); + PatchWindow* win = new_patch_window(patch, view); win->present(); } } PatchWindow* -WindowFactory::create_new(CountedPtr<PatchController> patch) +WindowFactory::new_patch_window(CountedPtr<PatchModel> patch, CountedPtr<PatchView> view) { - // FIXME: can't just load "patch_win" and children because PatchWindow - // loads things it really shouldn't. - //Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference("patch_win"); - Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference(); + assert( !view || view->patch() == patch); + + Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference("patch_win"); PatchWindow* win = NULL; xml->get_widget_derived("patch_win", win); assert(win); - win->set_patch(patch); - _windows[patch->model()->path()] = win; + win->set_patch(patch, view); + _patch_windows[patch->path()] = win; win->signal_delete_event().connect(sigc::bind<0>( - sigc::mem_fun(this, &WindowFactory::remove), win)); + sigc::mem_fun(this, &WindowFactory::remove_patch_window), win)); return win; } bool -WindowFactory::remove(PatchWindow* win, GdkEventAny* ignored) +WindowFactory::remove_patch_window(PatchWindow* win, GdkEventAny* ignored) { - if (_windows.size() <= 1) { + if (_patch_windows.size() <= 1) { Gtk::MessageDialog d(*win, "This is the last remaining open patch " "window. Closing this window will exit Ingenuity (the engine will " "remain running).\n\nAre you sure you want to quit?", @@ -90,15 +148,145 @@ WindowFactory::remove(PatchWindow* win, GdkEventAny* ignored) return false; } - std::map<Path, PatchWindow*>::iterator w - = _windows.find(win->patch_controller()->model()->path()); + PatchWindowMap::iterator w = _patch_windows.find(win->patch()->path()); + + assert((*w).second == win); + _patch_windows.erase(w); + + delete win; + + return true; +} + + +void +WindowFactory::present_controls(CountedPtr<NodeModel> node) +{ + NodeControlWindow* win = control_window(node); + + if (win) { + win->present(); + } else { + win = new_control_window(node); + win->present(); + } +} + + +NodeControlWindow* +WindowFactory::new_control_window(CountedPtr<NodeModel> node) +{ + size_t poly = 1; + if (node->polyphonic()) + poly = ((PatchModel*)node->parent().get())->poly(); + + NodeControlWindow* win = new NodeControlWindow(node, poly); + + _control_windows[node->path()] = win; + + win->signal_delete_event().connect(sigc::bind<0>( + sigc::mem_fun(this, &WindowFactory::remove_control_window), win)); + + return win; +} + + +bool +WindowFactory::remove_control_window(NodeControlWindow* win, GdkEventAny* ignored) +{ + ControlWindowMap::iterator w = _control_windows.find(win->node()->path()); assert((*w).second == win); - _windows.erase(w); + _control_windows.erase(w); delete win; return true; } +void +WindowFactory::present_load_plugin(CountedPtr<PatchModel> patch, MetadataMap data) +{ + PatchWindowMap::iterator w = _patch_windows.find(patch->path()); + + if (w != _patch_windows.end()) + _load_plugin_win->set_transient_for(*w->second); + + _load_plugin_win->present(patch, data); +} + + +void +WindowFactory::present_load_patch(CountedPtr<PatchModel> patch, MetadataMap data) +{ + PatchWindowMap::iterator w = _patch_windows.find(patch->path()); + + if (w != _patch_windows.end()) + _load_patch_win->set_transient_for(*w->second); + + _load_patch_win->set_merge(); // Import is the only choice + + _load_patch_win->present(patch, data); +} + + +void +WindowFactory::present_new_subpatch(CountedPtr<PatchModel> patch, MetadataMap data) +{ + PatchWindowMap::iterator w = _patch_windows.find(patch->path()); + + if (w != _patch_windows.end()) + _new_subpatch_win->set_transient_for(*w->second); + + _new_subpatch_win->present(patch, data); +} + + +void +WindowFactory::present_load_subpatch(CountedPtr<PatchModel> patch, MetadataMap data) +{ + PatchWindowMap::iterator w = _patch_windows.find(patch->path()); + + if (w != _patch_windows.end()) + _load_subpatch_win->set_transient_for(*w->second); + + _load_subpatch_win->present(patch, data); +} + + +void +WindowFactory::present_rename(CountedPtr<ObjectModel> object) +{ + PatchWindowMap::iterator w = _patch_windows.find(object->path()); + + if (w != _patch_windows.end()) + _rename_win->set_transient_for(*w->second); + + _rename_win->present(object); +} + + +void +WindowFactory::present_properties(CountedPtr<NodeModel> node) +{ + CountedPtr<PatchModel> patch = PtrCast<PatchModel>(node); + if (patch) { + + PatchWindowMap::iterator w = _patch_windows.find(patch->path()); + if (w != _patch_windows.end()) + _patch_properties_win->set_transient_for(*w->second); + + _patch_properties_win->present(patch); + + } else { + + PatchWindowMap::iterator w = _patch_windows.find(node->parent()->path()); + if (w != _patch_windows.end()) + _node_properties_win->set_transient_for(*w->second); + + _node_properties_win->present(node); + } +} + + } // namespace Ingenuity diff --git a/src/progs/ingenuity/WindowFactory.h b/src/progs/ingenuity/WindowFactory.h index add2d97b..831ab646 100644 --- a/src/progs/ingenuity/WindowFactory.h +++ b/src/progs/ingenuity/WindowFactory.h @@ -18,23 +18,69 @@ #define WINDOW_FACTORY_H #include <map> +#include <gtkmm.h> #include "util/CountedPtr.h" -#include "PatchController.h" +#include "PatchView.h" +#include "PatchModel.h" +using Ingen::Client::PatchModel; namespace Ingenuity { class PatchWindow; +class NodeControlWindow; +class NodePropertiesWindow; +class PatchPropertiesWindow; +class LoadPatchWindow; +class RenameWindow; +/** Manager/Factory for all windows. + * + * This serves as a nice centralized spot for all window management issues, + * as well as an enumeration of all the windows in Ingenuity (the goal being + * to reduce that number as much as possible). + */ class WindowFactory { public: - void present(CountedPtr<PatchController> patch, PatchWindow* preferred = NULL); + WindowFactory(); + ~WindowFactory(); + + PatchWindow* patch_window(CountedPtr<PatchModel> patch); + NodeControlWindow* control_window(CountedPtr<NodeModel> node); + + void present_patch(CountedPtr<PatchModel> patch, + PatchWindow* preferred = NULL, + CountedPtr<PatchView> patch = CountedPtr<PatchView>()); + + void present_controls(CountedPtr<NodeModel> node); + + void present_load_plugin(CountedPtr<PatchModel> patch, MetadataMap data = MetadataMap()); + void present_load_patch(CountedPtr<PatchModel> patch, MetadataMap data = MetadataMap()); + void present_new_subpatch(CountedPtr<PatchModel> patch, MetadataMap data = MetadataMap()); + void present_load_subpatch(CountedPtr<PatchModel> patch, MetadataMap data = MetadataMap()); + void present_rename(CountedPtr<ObjectModel> object); + void present_properties(CountedPtr<NodeModel> node); private: - PatchWindow* create_new(CountedPtr<PatchController> patch); - bool remove(PatchWindow* win, GdkEventAny* ignored); + typedef std::map<Path, PatchWindow*> PatchWindowMap; + typedef std::map<Path, NodeControlWindow*> ControlWindowMap; + + PatchWindow* new_patch_window(CountedPtr<PatchModel> patch, CountedPtr<PatchView> view); + bool remove_patch_window(PatchWindow* win, GdkEventAny* ignored); + + NodeControlWindow* new_control_window(CountedPtr<NodeModel> node); + bool remove_control_window(NodeControlWindow* win, GdkEventAny* ignored); + + PatchWindowMap _patch_windows; + ControlWindowMap _control_windows; - std::map<Path, PatchWindow*> _windows; + LoadPluginWindow* _load_plugin_win; + LoadPatchWindow* _load_patch_win; + NewSubpatchWindow* _new_subpatch_win; + LoadSubpatchWindow* _load_subpatch_win; + NodePropertiesWindow* _node_properties_win; + PatchPropertiesWindow* _patch_properties_win; + RenameWindow* _rename_win; }; } diff --git a/src/progs/ingenuity/ingenuity.glade b/src/progs/ingenuity/ingenuity.glade index 2221a805..7f18f954 100644 --- a/src/progs/ingenuity/ingenuity.glade +++ b/src/progs/ingenuity/ingenuity.glade @@ -1758,7 +1758,7 @@ </child> <child> - <widget class="GtkVBox" id="patch_view_vbox"> + <widget class="GtkVBox" id="patch_view_box"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> |