From e5675ebfeb93175e16762d0a078bd51d15d05f63 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 13 Sep 2006 06:11:25 +0000 Subject: Heavy-duty redesign of client library and GUI (now fully signal driven with clean Model/View separation). Smarter, centralized window creation/management (should make window unification easy (panes?)). Typed metadata system, no more fugly string conversion of floats. Supports OSC fundamental types string, int, float, blob for now (though blob isn't working over the wire yet). git-svn-id: http://svn.drobilla.net/lad/ingen@131 a436a847-0d15-0410-975c-d299462d15a1 --- src/common/interface/ClientInterface.h | 3 +- src/common/interface/EngineInterface.h | 2 +- src/common/util/Path.h | 4 + src/libs/client/ModelClientInterface.cpp | 12 +- src/libs/client/ModelEngineInterface.cpp | 4 +- src/libs/client/NodeModel.cpp | 58 +-- src/libs/client/NodeModel.h | 67 ++- src/libs/client/OSCClientReceiver.cpp | 11 +- src/libs/client/OSCEngineSender.cpp | 15 +- src/libs/client/OSCEngineSender.h | 2 +- src/libs/client/ObjectController.h | 45 -- src/libs/client/ObjectModel.cpp | 32 +- src/libs/client/ObjectModel.h | 61 +-- src/libs/client/PatchLibrarian.cpp | 76 ++-- src/libs/client/PatchModel.cpp | 32 +- src/libs/client/PatchModel.h | 24 +- src/libs/client/PortModel.h | 31 +- src/libs/client/SigClientInterface.h | 2 +- src/libs/client/Store.cpp | 16 +- src/libs/client/Store.h | 3 +- src/libs/client/ThreadedSigClientInterface.h | 5 +- src/libs/engine/ClientBroadcaster.cpp | 2 +- src/libs/engine/ClientBroadcaster.h | 2 +- src/libs/engine/DSSINode.h | 12 +- src/libs/engine/GraphObject.h | 19 +- src/libs/engine/LADSPANode.cpp | 9 +- src/libs/engine/OSCClientSender.cpp | 10 +- src/libs/engine/OSCClientSender.h | 2 +- src/libs/engine/OSCEngineReceiver.cpp | 9 +- src/libs/engine/ObjectSender.cpp | 16 +- src/libs/engine/QueuedEngineInterface.cpp | 2 +- src/libs/engine/QueuedEngineInterface.h | 2 +- src/libs/engine/events/DSSIConfigureEvent.cpp | 2 +- src/libs/engine/events/RequestMetadataEvent.cpp | 5 +- src/libs/engine/events/RequestMetadataEvent.h | 6 +- src/libs/engine/events/SetMetadataEvent.cpp | 2 +- src/libs/engine/events/SetMetadataEvent.h | 9 +- src/progs/demolition/demolition.cpp | 15 +- src/progs/ingenuity/App.cpp | 5 - src/progs/ingenuity/App.h | 4 - src/progs/ingenuity/BreadCrumb.h | 33 +- src/progs/ingenuity/BreadCrumbBox.cpp | 58 ++- src/progs/ingenuity/BreadCrumbBox.h | 10 +- src/progs/ingenuity/ConfigWindow.cpp | 2 - src/progs/ingenuity/Configuration.cpp | 2 - src/progs/ingenuity/ConnectWindow.cpp | 5 +- src/progs/ingenuity/ControlGroups.cpp | 40 +- src/progs/ingenuity/ControlGroups.h | 2 +- src/progs/ingenuity/ControlPanel.cpp | 8 +- src/progs/ingenuity/ControlPanel.h | 6 +- src/progs/ingenuity/ControllerFactory.cpp | 72 ---- src/progs/ingenuity/ControllerFactory.h | 32 -- src/progs/ingenuity/DSSIController.cpp | 33 +- src/progs/ingenuity/DSSIController.h | 13 +- src/progs/ingenuity/DSSIModule.cpp | 6 +- src/progs/ingenuity/DSSIModule.h | 2 +- src/progs/ingenuity/GtkObjectController.cpp | 34 -- src/progs/ingenuity/GtkObjectController.h | 83 ---- src/progs/ingenuity/LashController.cpp | 1 - src/progs/ingenuity/LoadPatchWindow.cpp | 23 +- src/progs/ingenuity/LoadPatchWindow.h | 16 +- src/progs/ingenuity/LoadPluginWindow.cpp | 38 +- src/progs/ingenuity/LoadPluginWindow.h | 17 +- src/progs/ingenuity/LoadSubpatchWindow.cpp | 45 +- src/progs/ingenuity/LoadSubpatchWindow.h | 17 +- src/progs/ingenuity/Loader.cpp | 1 - src/progs/ingenuity/Makefile.am | 18 +- src/progs/ingenuity/NewSubpatchWindow.cpp | 34 +- src/progs/ingenuity/NewSubpatchWindow.h | 17 +- src/progs/ingenuity/NodeControlWindow.cpp | 8 +- src/progs/ingenuity/NodeControlWindow.h | 20 +- src/progs/ingenuity/NodeController.cpp | 404 ----------------- src/progs/ingenuity/NodeController.h | 116 ----- src/progs/ingenuity/NodeMenu.cpp | 254 +++++++++++ src/progs/ingenuity/NodeMenu.h | 75 ++++ src/progs/ingenuity/NodePropertiesWindow.h | 4 +- src/progs/ingenuity/OmFlowCanvas.cpp | 162 +++++-- src/progs/ingenuity/OmFlowCanvas.h | 39 +- src/progs/ingenuity/OmModule.cpp | 109 +++-- src/progs/ingenuity/OmModule.h | 21 +- src/progs/ingenuity/OmPatchPort.h | 1 - src/progs/ingenuity/OmPort.h | 1 - src/progs/ingenuity/OmPortModule.cpp | 48 ++- src/progs/ingenuity/OmPortModule.h | 12 +- src/progs/ingenuity/PatchController.cpp | 548 ------------------------ src/progs/ingenuity/PatchController.h | 124 ------ src/progs/ingenuity/PatchPropertiesWindow.cpp | 26 +- src/progs/ingenuity/PatchPropertiesWindow.h | 3 +- src/progs/ingenuity/PatchTreeWindow.cpp | 37 +- src/progs/ingenuity/PatchTreeWindow.h | 7 +- src/progs/ingenuity/PatchView.cpp | 56 ++- src/progs/ingenuity/PatchView.h | 32 +- src/progs/ingenuity/PatchWindow.cpp | 139 ++---- src/progs/ingenuity/PatchWindow.h | 24 +- src/progs/ingenuity/PortController.cpp | 139 ------ src/progs/ingenuity/PortController.h | 79 ---- src/progs/ingenuity/RenameWindow.cpp | 11 +- src/progs/ingenuity/RenameWindow.h | 16 +- src/progs/ingenuity/SubpatchModule.cpp | 30 +- src/progs/ingenuity/SubpatchModule.h | 8 +- src/progs/ingenuity/WindowFactory.cpp | 232 +++++++++- src/progs/ingenuity/WindowFactory.h | 56 ++- src/progs/ingenuity/ingenuity.glade | 2 +- 103 files changed, 1623 insertions(+), 2526 deletions(-) delete mode 100644 src/libs/client/ObjectController.h delete mode 100644 src/progs/ingenuity/ControllerFactory.cpp delete mode 100644 src/progs/ingenuity/ControllerFactory.h delete mode 100644 src/progs/ingenuity/GtkObjectController.cpp delete mode 100644 src/progs/ingenuity/GtkObjectController.h delete mode 100644 src/progs/ingenuity/NodeController.cpp delete mode 100644 src/progs/ingenuity/NodeController.h create mode 100644 src/progs/ingenuity/NodeMenu.cpp create mode 100644 src/progs/ingenuity/NodeMenu.h delete mode 100644 src/progs/ingenuity/PatchController.cpp delete mode 100644 src/progs/ingenuity/PatchController.h delete mode 100644 src/progs/ingenuity/PortController.cpp delete mode 100644 src/progs/ingenuity/PortController.h (limited to 'src') 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 +#include "util/Atom.h" #include 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 plugin(new PluginModel(plugin_type, plugin_uri)); - CountedPtr nm(new NodeModel(plugin, node_path)); + CountedPtr 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::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 plugin, const Path& path) +NodeModel::NodeModel(CountedPtr 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 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 c) void NodeModel::remove_child(CountedPtr c) { - assert(c->path().is_child_of(m_path)); + assert(c->path().is_child_of(_path)); assert(c->parent().get() == this); CountedPtr pm = PtrCast(c); @@ -117,7 +115,7 @@ void NodeModel::add_port(CountedPtr 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 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 pm) CountedPtr -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(); @@ -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 plugin, const Path& path); + NodeModel(const string& plugin_uri, const Path& path, bool polyphonic); + NodeModel(CountedPtr plugin, const Path& path, bool polyphonic); virtual ~NodeModel(); - - void add_child(CountedPtr c); - void remove_child(CountedPtr c); - - CountedPtr get_port(const string& port_name); - void add_port(CountedPtr pm); - void remove_port(CountedPtr pm); - void remove_port(const string& port_path); - - virtual void clear(); - - const map >& 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 plugin() const { return m_plugin; } - //void plugin(CountedPtr p) { m_plugin = p; } + CountedPtr 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 >& get_programs() const { return m_banks; } + const string& plugin_uri() const { return m_plugin_uri; } + CountedPtr 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 > new_port_sig; + sigc::signal > removed_port_sig; protected: + friend class Store; NodeModel(const Path& path); + void add_child(CountedPtr c); + void remove_child(CountedPtr c); + void add_port(CountedPtr pm); + void remove_port(CountedPtr 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 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 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 > 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 m_plugin; ///< The plugin this node is an instance of + map > 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 #include #include @@ -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 #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::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 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 c) void ObjectModel::assimilate(CountedPtr model) { - assert(m_path == model->path()); + assert(_path == model->path()); - for (map::const_iterator i = model->metadata().begin(); + for (MetadataMap::const_iterator i = model->metadata().begin(); i != model->metadata().end(); ++i) { - map::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,19 +24,26 @@ #include #include #include +#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 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 */ @@ -44,39 +51,39 @@ class ObjectModel { public: ObjectModel(const Path& path); - ObjectModel() : m_path("/UNINITIALIZED") {} // FIXME: remove virtual ~ObjectModel(); - - const map& 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 parent() const { return m_parent; } - virtual void set_parent(CountedPtr p) { m_parent = p; } - - virtual void add_child(CountedPtr c) = 0; - virtual void remove_child(CountedPtr c) = 0; - CountedPtr controller() const { return m_controller; } - - void set_controller(CountedPtr 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 parent() const { return _parent; } void assimilate(CountedPtr model); // Signals - sigc::signal metadata_update_sig; - sigc::signal destroyed_sig; + sigc::signal metadata_update_sig; + sigc::signal 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 m_parent; - CountedPtr m_controller; + friend class Store; + friend class PatchLibrarian; // FIXME: remove + virtual void set_path(const Path& p) { _path = p; } + virtual void set_parent(CountedPtr p) { _parent = p; } + virtual void add_child(CountedPtr c) = 0; + virtual void remove_child(CountedPtr c) = 0; + + Path _path; + CountedPtr _parent; - map 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 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 patch_model, const string& fil xml_node = xmlNewChild(xml_root_node, NULL, (xmlChar*)"polyphony", (xmlChar*)temp_buf); // Write metadata - for (map::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 patch_model, const string& fil xml_child_node = xmlNewChild(xml_node, NULL, (xmlChar*)"polyphony", (xmlChar*)temp_buf); // Write metadata - for (map::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 patch_model, const string& fil (xmlChar*)(nm->plugin()->uri().c_str())); // Write metadata - for (map::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 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 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 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 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 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 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 pm, bool wait, bool existing) CountedPtr PatchLibrarian::parse_node(const CountedPtr parent, xmlDocPtr doc, const xmlNodePtr node) { +cerr << "FIXME: load node\n"; +#if 0 CountedPtr plugin(new PluginModel()); - CountedPtr 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 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 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 parent, xmlDocPtr child = child->next; } - // FIXME: nasty assumptions - CountedPtr pm(new PortModel(path, + assert(path.length() > 0); + assert(Path::is_valid(path)); + + // FIXME: /nasty/ assumptions + CountedPtr 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 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 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 parent, xmlDocPtr } //nm->plugin(plugin); + return nm; +#endif + return CountedPtr(); } 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 c) void PatchModel::remove_child(CountedPtr c) { - assert(c->path().is_child_of(m_path)); + assert(c->path().is_child_of(_path)); assert(c->parent().get() == this); CountedPtr pm = PtrCast(c); @@ -102,13 +102,13 @@ void PatchModel::add_node(CountedPtr 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 nm) void PatchModel::remove_node(CountedPtr 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 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 >& connections() const { return m_connections; } @@ -55,7 +57,7 @@ public: CountedPtr get_node(const string& node_name); void add_node(CountedPtr nm); - void remove_node(const string& name); + //void remove_node(const string& name); void remove_node(CountedPtr nm); void rename_node(const Path& old_path, const Path& new_path); @@ -77,12 +79,12 @@ public: bool polyphonic() const; // Signals - sigc::signal > new_node_sig; - sigc::signal removed_node_sig; - sigc::signal > new_connection_sig; - sigc::signal removed_connection_sig; - sigc::signal enabled_sig; - sigc::signal disabled_sig; + sigc::signal > new_node_sig; + sigc::signal > removed_node_sig; + sigc::signal > new_connection_sig; + sigc::signal removed_connection_sig; + sigc::signal enabled_sig; + sigc::signal 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 c) { throw; } void remove_child(CountedPtr 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 p) { ++m_connections; connection_sig.emit(p); } void disconnected_from(CountedPtr 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 object_destroyed_sig; sigc::signal connection_sig; sigc::signal disconnection_sig; - sigc::signal metadata_update_sig; + sigc::signal metadata_update_sig; sigc::signal control_change_sig; sigc::signal program_add_sig; sigc::signal 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 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 plug = plugin(plugin_uri); if (!plug) { - CountedPtr n(new NodeModel(plugin_uri, node_path)); - n->polyphonic(is_polyphonic); + CountedPtr n(new NodeModel(plugin_uri, node_path, is_polyphonic)); add_plugin_orphan(n); } else { - CountedPtr n(new NodeModel(plug, node_path)); - n->polyphonic(is_polyphonic); + CountedPtr 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 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 #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 object_destroyed_slot; sigc::slot object_renamed_slot; sigc::slot disconnection_slot; - sigc::slot metadata_update_slot; + sigc::slot metadata_update_slot; sigc::slot control_change_slot; sigc::slot program_add_slot; sigc::slot 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 Bank; + typedef std::map 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& get_programs() const; + const std::map& 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 _configures; - map _banks; + int _bank; + int _program; + std::map _configures; + std::map _banks; InputPort* _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 #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 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::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& 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 _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*)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)

\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, 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& data = port->metadata(); - for (map::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& data = patch->metadata(); - for (map::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& data = node->metadata(); - for (map::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& data = port->metadata(); - for (map::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 : QueuedEvent(engine, responder, timestamp), m_path(node_path), m_key(key), - m_value(""), m_object(NULL), m_client(CountedPtr()) { @@ -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 #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 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, SampleCount timestamp, const string& path, const string& key, const string& value) +SetMetadataEvent::SetMetadataEvent(Engine& engine, CountedPtr 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 #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, SampleCount timestamp, const string& path, const string& key, const string& value); + SetMetadataEvent(Engine& engine, CountedPtr 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 -using std::cerr; using std::endl; - #include #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 view = CountedPtr()) + : _path(path) + , _view(view) { + assert( !view || view->patch()->path() == path); set_border_width(0); set_path(path); show_all(); } + void set_view(CountedPtr view) { + assert( !view || view->patch()->path() == _path); + _view = view; + } + + const Path& path() const { return _path; } + CountedPtr 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 _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 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::iterator i = _breadcrumbs.begin(); i != _breadcrumbs.end(); ++i) - (*i)->set_active( ((*i)->path() == path) ); + for (std::list::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 view) +{ + BreadCrumb* but = manage(new BreadCrumb(path, + (view && path == view->patch()->path()) ? view : CountedPtr())); + + 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 #include #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 view); - sigc::signal signal_patch_selected; + sigc::signal > signal_patch_selected; private: + BreadCrumb* create_crumb(const Path& path, + CountedPtr view = CountedPtr()); + 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 #include #include -#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 #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 root = PtrCast(App::instance().store()->object("/")); assert(root); - CountedPtr root_c = PtrCast(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 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, CountedPtris_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, CountedPtruser_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, CountedPtruser_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 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 node, size_t poly) { assert(node != NULL); assert(poly > 0); - const CountedPtr 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 // 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& glade_xml); virtual ~ControlPanel(); - void init(NodeController* node, size_t poly); + void init(CountedPtr 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 -ControllerFactory::get_controller(CountedPtr model) -{ - CountedPtr patch_m = PtrCast(model); - if (patch_m && patch_m->controller()) { - assert(dynamic_cast(patch_m->controller().get())); - return PtrCast(patch_m->controller()); - } else if (patch_m) { - CountedPtr pc(new PatchController(patch_m)); - patch_m->set_controller(pc); - return pc; - } - - CountedPtr node_m = PtrCast(model); - if (node_m && node_m->controller()) { - assert(dynamic_cast(node_m->controller().get())); - return PtrCast(node_m->controller()); - } else if (node_m) { - if (node_m->plugin()->type() == PluginModel::DSSI) { - CountedPtr nc(new DSSIController(node_m)); - node_m->set_controller(nc); - return nc; - } else { - CountedPtr nc(new NodeController(node_m)); - node_m->set_controller(nc); - return nc; - } - } - - CountedPtr port_m = PtrCast(model); - if (port_m && port_m->controller()) { - assert(dynamic_cast(port_m->controller().get())); - return PtrCast(port_m->controller()); - } else if (port_m) { - CountedPtr pc(new PortController(port_m)); - port_m->set_controller(pc); - return pc; - } - - return CountedPtr(); -} - - -} // 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 get_controller(CountedPtr 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 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 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 #include #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 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(node)) +DSSIModule::DSSIModule(OmFlowCanvas* canvas, CountedPtr 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(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 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 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 -#include - -#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 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 model() const { return m_model; } - -protected: - CountedPtr 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 #include #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 #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 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 pc) +LoadPatchWindow::set_patch(CountedPtr 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 pm(new PatchModel(m_patch_controller->model()->path(), poly)); + CountedPtr 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 #include #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& xml); - void set_patch(CountedPtr pc); + void set_patch(CountedPtr patch); void set_replace() { m_replace = true; } void set_merge() { m_replace = false; } + void present(CountedPtr patch, MetadataMap data); + protected: void on_show(); @@ -58,8 +60,10 @@ private: void ok_clicked(); void cancel_clicked(); - CountedPtr m_patch_controller; - bool m_replace; + MetadataMap m_initial_data; + + CountedPtr 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 #include #include -#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 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 pc) +LoadPluginWindow::set_patch(CountedPtr 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 #include #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& xml); - void set_patch(CountedPtr pc); + void set_patch(CountedPtr patch); void set_plugin_list(const std::map >& m); - void set_next_module_location(double x, double y) - { m_new_module_x = x; m_new_module_y = y; } - void add_plugin(CountedPtr plugin); bool has_shown() const { return m_has_shown; } + void present(CountedPtr 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 m_patch_controller; + MetadataMap m_initial_data; + + CountedPtr m_patch; + bool m_has_shown; // plugin list only populated on show to speed patch window creation Glib::RefPtr 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 #include #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 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 pc) +LoadSubpatchWindow::set_patch(CountedPtr 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 pm(new PatchModel(m_patch_controller->model()->path().base() + name, poly)); + CountedPtr 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 #include #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& xml); - void set_patch(CountedPtr pc); + void set_patch(CountedPtr patch); - void set_next_module_location(double x, double y) - { m_new_module_x = x; m_new_module_y = y; } + void present(CountedPtr patch, MetadataMap data); protected: void on_show(); @@ -58,7 +55,9 @@ private: void ok_clicked(); void cancel_clicked(); - CountedPtr m_patch_controller; + MetadataMap m_initial_data; + + CountedPtr 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 #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 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 pc) +NewSubpatchWindow::set_patch(CountedPtr 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 #include #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& xml); - void set_patch(CountedPtr pc); + void set_patch(CountedPtr patch); + + void present(CountedPtr 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 m_patch_controller; + MetadataMap m_initial_data; + CountedPtr 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 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 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 #include #include +#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 node, size_t poly); + NodeControlWindow(CountedPtr node, ControlPanel* panel); virtual ~NodeControlWindow(); + CountedPtr 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 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 -#include -#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 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 pc = PtrCast(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 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::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 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 pc = PtrCast(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 xml = GladeFactory::new_glade_reference("rename_win"); - xml->get_widget_derived("rename_win", win); - - CountedPtr parent = PtrCast(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 parent = PtrCast(node_model()->parent()->controller()); - assert(parent); - - if (m_properties_window) { - Glib::RefPtr 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 pc = PtrCast(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 -#include -#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 node_model() { return PtrCast(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 model); - - virtual void destroy(); - - virtual void add_port(CountedPtr 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 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 +#include +#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 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 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::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 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 +#include +#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 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 pm); + + void on_menu_destroy(); + void on_menu_clone(); + void on_menu_learn(); + void on_menu_disconnect_all(); + + //Gtk::Menu m_menu; + CountedPtr _node; + Glib::RefPtr _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 #include #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& refGlade); + void present(CountedPtr node_model) { set_node(node_model); Gtk::Window::present(); } void set_node(CountedPtr 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 #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 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 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,12 +76,113 @@ 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)); } +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 >::const_iterator i = m_patch->connections().begin(); + i != m_patch->connections().end(); ++i) { + connection(*i); + } +} + + +void +OmFlowCanvas::add_node(CountedPtr nm) +{ + cerr << "FIXME: MODULE LEAK!" << endl; + + CountedPtr pm = PtrCast(nm); + if (pm) + new SubpatchModule(this, pm); + else + new OmModule(this, nm); +} + + +void +OmFlowCanvas::remove_node(CountedPtr nm) +{ + LibFlowCanvas::Module* module = get_module(nm->path().name()); + delete module; +} + + +void +OmFlowCanvas::connection(CountedPtr 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) { @@ -102,10 +197,12 @@ OmFlowCanvas::connect(const Port* src_port, const Port* dst_port) dst->model()->type() == PortModel::CONTROL) { CountedPtr pm(new PluginModel(PluginModel::Internal, "", "midi_control_in", "")); - CountedPtr 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 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 #include - +#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 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 nm); + void remove_node(CountedPtr nm); + void connection(CountedPtr 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 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 +#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 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 port) +{ + new OmPort(this, port); + resize(); +} + + +void +OmModule::remove_port(CountedPtr 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(property_x()); + const float y = static_cast(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 #include #include +#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 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 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 port); + void remove_port(CountedPtr port); + + CountedPtr 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 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(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 #include #include -#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 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 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 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 -#include -#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 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 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 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 nc = PtrCast(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 pc = PtrCast((*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 parent = PtrCast(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(m_model->controller())); - create_all_ports(); - } - - m_module->move_to(node_model()->x(), node_model()->y()); -} - - -CountedPtr -PatchController::get_view() -{ - if (m_patch_view) - return m_patch_view; - - Glib::RefPtr xml = GladeFactory::new_glade_reference(); - - PatchView* pv = NULL; - xml->get_widget_derived("patch_view_vbox", pv); - assert(pv); - m_patch_view = CountedPtr(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 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 nc = PtrCast(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 pc = PtrCast((*i)->controller()); - assert(pc); - pc->create_module(m_patch_view->canvas()); - } - - - // Create connections - for (list >::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 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 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 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 nc = PtrCast(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 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 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 -#include -#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 pm); - //virtual void remove_port(const Path& path, bool resize_module); - - void connection(CountedPtr 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 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 patch_model() const { return m_patch_model; } - -private: - friend class ControllerFactory; - PatchController(CountedPtr model); - - void add_node(CountedPtr object); - - PatchPropertiesWindow* m_properties_window; - - // FIXME: remove these - PatchWindow* m_window; ///< Patch Window currently showing m_patch_view - CountedPtr m_patch_view; ///< View (canvas) of this patch - - CountedPtr 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 patch_model) +PatchPropertiesWindow::set_patch(CountedPtr 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& refGlade); - void patch_model(CountedPtr patch_model); + void present(CountedPtr patch_model) { set_patch(patch_model); Gtk::Window::present(); } + void set_patch(CountedPtr 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 object) { CountedPtr patch = PtrCast(object); if (patch) - add_patch(PtrCast(patch->controller())); + add_patch(patch); } void -PatchTreeWindow::add_patch(CountedPtr pc) +PatchTreeWindow::add_patch(CountedPtr pm) { - const CountedPtr 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 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 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 pc = (*c)[m_patch_tree_columns.patch_controller_col]; - if (pc->model()->path() == path) { + CountedPtr 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 pc = row[m_patch_tree_columns.patch_controller_col]; + CountedPtr 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 pc = row[m_patch_tree_columns.patch_controller_col]; - if (pc) - pc->show_menu(ev); + CountedPtr 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 pc = row[m_patch_tree_columns.patch_controller_col]; + CountedPtr 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 pc = row[m_patch_tree_columns.patch_controller_col]; - Glib::ustring patch_path = pc->model()->path(); + CountedPtr 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 pc); + void add_patch(CountedPtr 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 name_col; Gtk::TreeModelColumn enabled_col; - Gtk::TreeModelColumn > patch_controller_col; + Gtk::TreeModelColumn > 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& 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 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::create(CountedPtr patch) + { - if (_patch != NULL) - _patch->show_control_window(); + const Glib::RefPtr& 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(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 #include #include +#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& glade_xml); - - void patch_controller(PatchController* pc); + ~PatchView(); + + OmFlowCanvas* canvas() const { return _canvas; } + CountedPtr 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 create(CountedPtr patch); +private: + void set_patch(CountedPtr 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 _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& 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::RefPtrget_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::RefPtrclaim_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 view) { - CountedPtr model = PtrCast(App::instance().store()->object(path)); - if (!model) - return; // can't really do anything useful.. - - CountedPtr pc = PtrCast(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 model = PtrCast(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 pc) +PatchWindow::set_patch(CountedPtr patch, CountedPtr view) { - if (!pc || pc == m_patch) + if (!patch || patch == m_patch) return; m_enable_signal = false; - if (m_patch) { - CountedPtr 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 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 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 #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& glade_xml); ~PatchWindow(); - void set_patch_from_path(const Path& path); - void set_patch(CountedPtr pc); + void set_patch_from_path(const Path& path, CountedPtr view); + void set_patch(CountedPtr pc, CountedPtr view); - CountedPtr 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 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 m_patch; - - LoadPluginWindow* m_load_plugin_window; - LoadPatchWindow* m_load_patch_window; - NewSubpatchWindow* m_new_subpatch_window; - LoadSubpatchWindow* m_load_subpatch_window; + CountedPtr m_patch; + CountedPtr 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 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 parent = PtrCast(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(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 -#include -#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 port_model() const { return PtrCast(m_model); } - -private: - friend class ControllerFactory; - PortController(CountedPtr 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 #include #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 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 #include - +#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& refGlade); - void set_object(GtkObjectController* object); + void present(CountedPtr object) { set_object(object); Gtk::Window::present(); } private: + void set_object(CountedPtr object); + void name_changed(); void cancel_clicked(); void ok_clicked(); - GtkObjectController* m_object; + CountedPtr 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 patch) -: OmModule(canvas, patch.get()), +SubpatchModule::SubpatchModule(OmFlowCanvas* canvas, CountedPtr patch) +: OmModule(canvas, patch), m_patch(patch) { assert(canvas); @@ -46,12 +45,13 @@ SubpatchModule::on_double_click(GdkEventButton* event) { assert(m_patch); - CountedPtr parent = PtrCast(m_patch->model()->parent()->controller()); + CountedPtr parent = PtrCast(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 pc = PtrCast(m_patch->model()->parent()->controller()); + assert(m_patch->parent()); - App::instance().window_factory()->present(m_patch, pc->window()); + CountedPtr parent = PtrCast(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 #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 controller); + SubpatchModule(OmFlowCanvas* canvas, CountedPtr controller); virtual ~SubpatchModule() {} void on_double_click(GdkEventButton* ev); @@ -55,10 +55,10 @@ public: void browse_to_patch(); void menu_remove(); - CountedPtr patch() { return m_patch; } + CountedPtr patch() { return m_patch; } protected: - CountedPtr m_patch; + CountedPtr 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 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 patch) +{ + PatchWindowMap::iterator w = _patch_windows.find(patch->path()); + + return (w == _patch_windows.end()) ? NULL : w->second; +} + + +NodeControlWindow* +WindowFactory::control_window(CountedPtr 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 patch, PatchWindow* preferred) +WindowFactory::present_patch(CountedPtr patch, PatchWindow* preferred, CountedPtr view) { - std::map::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 patch) +WindowFactory::new_patch_window(CountedPtr patch, CountedPtr view) { - // FIXME: can't just load "patch_win" and children because PatchWindow - // loads things it really shouldn't. - //Glib::RefPtr xml = GladeFactory::new_glade_reference("patch_win"); - Glib::RefPtr xml = GladeFactory::new_glade_reference(); + assert( !view || view->patch() == patch); + + Glib::RefPtr 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::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 node) +{ + NodeControlWindow* win = control_window(node); + + if (win) { + win->present(); + } else { + win = new_control_window(node); + win->present(); + } +} + + +NodeControlWindow* +WindowFactory::new_control_window(CountedPtr 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 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 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 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 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 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 node) +{ + CountedPtr patch = PtrCast(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 +#include #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 patch, PatchWindow* preferred = NULL); + WindowFactory(); + ~WindowFactory(); + + PatchWindow* patch_window(CountedPtr patch); + NodeControlWindow* control_window(CountedPtr node); + + void present_patch(CountedPtr patch, + PatchWindow* preferred = NULL, + CountedPtr patch = CountedPtr()); + + void present_controls(CountedPtr node); + + void present_load_plugin(CountedPtr patch, MetadataMap data = MetadataMap()); + void present_load_patch(CountedPtr patch, MetadataMap data = MetadataMap()); + void present_new_subpatch(CountedPtr patch, MetadataMap data = MetadataMap()); + void present_load_subpatch(CountedPtr patch, MetadataMap data = MetadataMap()); + void present_rename(CountedPtr object); + void present_properties(CountedPtr node); private: - PatchWindow* create_new(CountedPtr patch); - bool remove(PatchWindow* win, GdkEventAny* ignored); + typedef std::map PatchWindowMap; + typedef std::map ControlWindowMap; + + PatchWindow* new_patch_window(CountedPtr patch, CountedPtr view); + bool remove_patch_window(PatchWindow* win, GdkEventAny* ignored); + + NodeControlWindow* new_control_window(CountedPtr node); + bool remove_control_window(NodeControlWindow* win, GdkEventAny* ignored); + + PatchWindowMap _patch_windows; + ControlWindowMap _control_windows; - std::map _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 @@ - + True False 0 -- cgit v1.2.1