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