From 6f93b3d7c80f9dee2d95fac1bbc4f781a6f45979 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 18 Sep 2006 06:24:53 +0000 Subject: Work on loading old (deprecated) patches. More error tolerance in Store, related bugfixes. Patch port adding (threading) bug fixed (made event blocking). Better PatchView cacheing. Moved generic things from engine to util (shared) Bug fixes, features, etc. git-svn-id: http://svn.drobilla.net/lad/ingen@142 a436a847-0d15-0410-975c-d299462d15a1 --- src/progs/ingenuity/App.cpp | 2 +- src/progs/ingenuity/BreadCrumbBox.cpp | 18 ++- src/progs/ingenuity/BreadCrumbBox.h | 4 + src/progs/ingenuity/LoadPluginWindow.cpp | 4 +- src/progs/ingenuity/LoadSubpatchWindow.cpp | 15 +- src/progs/ingenuity/Loader.cpp | 216 ++++------------------------- src/progs/ingenuity/Loader.h | 120 +++------------- src/progs/ingenuity/NodeMenu.cpp | 3 + src/progs/ingenuity/NodeModule.cpp | 22 ++- src/progs/ingenuity/NodeModule.h | 1 + src/progs/ingenuity/PatchCanvas.cpp | 13 +- src/progs/ingenuity/PatchView.cpp | 10 ++ src/progs/ingenuity/PatchView.h | 1 + src/progs/ingenuity/PatchWindow.cpp | 19 ++- src/progs/ingenuity/PatchWindow.h | 4 +- 15 files changed, 115 insertions(+), 337 deletions(-) (limited to 'src/progs/ingenuity') diff --git a/src/progs/ingenuity/App.cpp b/src/progs/ingenuity/App.cpp index a4b820d1..55cab815 100644 --- a/src/progs/ingenuity/App.cpp +++ b/src/progs/ingenuity/App.cpp @@ -99,7 +99,7 @@ App::attach(const CountedPtr& engine, const CountedPtrinit(*_store); diff --git a/src/progs/ingenuity/BreadCrumbBox.cpp b/src/progs/ingenuity/BreadCrumbBox.cpp index c4234e8a..5fa5eb6e 100644 --- a/src/progs/ingenuity/BreadCrumbBox.cpp +++ b/src/progs/ingenuity/BreadCrumbBox.cpp @@ -28,6 +28,17 @@ BreadCrumbBox::BreadCrumbBox() } +CountedPtr +BreadCrumbBox::view(const Path& path) +{ + for (std::list::const_iterator i = _breadcrumbs.begin(); i != _breadcrumbs.end(); ++i) + if ((*i)->path() == path) + return (*i)->view(); + + return CountedPtr(); +} + + /** Sets up the crumbs to display a @a path. * * If @a path is already part of the shown path, it will be selected and the @@ -45,7 +56,12 @@ BreadCrumbBox::build(Path path, CountedPtr view) for (std::list::iterator i = _breadcrumbs.begin(); i != _breadcrumbs.end(); ++i) { if ((*i)->path() == path) { (*i)->set_active(true); - (*i)->set_view(view); + if (!(*i)->view()) + (*i)->set_view(view); + + // views are expensive, having two around for the same patch is a bug + assert((*i)->view() == view); + } else { (*i)->set_active(false); } diff --git a/src/progs/ingenuity/BreadCrumbBox.h b/src/progs/ingenuity/BreadCrumbBox.h index e38d8e49..93af05a3 100644 --- a/src/progs/ingenuity/BreadCrumbBox.h +++ b/src/progs/ingenuity/BreadCrumbBox.h @@ -31,6 +31,8 @@ class BreadCrumb; /** Collection of breadcrumb buttons forming a path. + * + * This doubles as a cache for PatchViews. * * \ingroup Ingenuity */ @@ -39,6 +41,8 @@ class BreadCrumbBox : public Gtk::HBox public: BreadCrumbBox(); + CountedPtr view(const Path& path); + void build(Path path, CountedPtr view); sigc::signal > signal_patch_selected; diff --git a/src/progs/ingenuity/LoadPluginWindow.cpp b/src/progs/ingenuity/LoadPluginWindow.cpp index e99550e5..01a2accd 100644 --- a/src/progs/ingenuity/LoadPluginWindow.cpp +++ b/src/progs/ingenuity/LoadPluginWindow.cpp @@ -263,7 +263,7 @@ LoadPluginWindow::generate_module_name(int offset) CountedPtr plugin = row.get_value(m_plugins_columns.m_col_plugin_model); char num_buf[3]; for (uint i=0; i < 99; ++i) { - name = plugin->plug_label(); + name = plugin->default_node_name(); if (name == "") name = plugin->name().substr(0, plugin->name().find(' ')); if (i+offset != 0) { @@ -381,8 +381,6 @@ LoadPluginWindow::filter_changed() //model_row[m_plugins_columns.m_col_label] = plugin->plug_label(); model_row[m_plugins_columns.m_col_type] = plugin->type_string(); model_row[m_plugins_columns.m_col_uri] = plugin->uri(); - model_row[m_plugins_columns.m_col_label] = plugin->plug_label(); - //model_row[m_plugins_columns.m_col_library] = plugin->lib_name(); model_row[m_plugins_columns.m_col_plugin_model] = plugin; ++num_visible; diff --git a/src/progs/ingenuity/LoadSubpatchWindow.cpp b/src/progs/ingenuity/LoadSubpatchWindow.cpp index 07b51716..453d874e 100644 --- a/src/progs/ingenuity/LoadSubpatchWindow.cpp +++ b/src/progs/ingenuity/LoadSubpatchWindow.cpp @@ -138,8 +138,7 @@ LoadSubpatchWindow::ok_clicked() const string filename = get_filename(); - // FIXME - string name = filename.substr(filename.find_last_of("/")+1); + string name = ""; int poly = 1; if (m_name_from_user_radio->get_active()) @@ -150,17 +149,7 @@ LoadSubpatchWindow::ok_clicked() else if (m_poly_from_parent_radio->get_active()) poly = m_patch->poly(); - /*CountedPtr pm(new PatchModel(m_patch->path().base() + name, poly)); - pm->filename(filename); - - 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("/"))); - */ - cerr << "FIXME: load subpatch" << endl; + App::instance().loader()->load_patch(filename, m_patch->path(), name, poly, m_initial_data); hide(); } diff --git a/src/progs/ingenuity/Loader.cpp b/src/progs/ingenuity/Loader.cpp index a0f099c2..59d718c7 100644 --- a/src/progs/ingenuity/Loader.cpp +++ b/src/progs/ingenuity/Loader.cpp @@ -25,219 +25,63 @@ using std::cout; using std::endl; namespace Ingenuity { -// LoadPatchEvent // - -void -LoadPatchEvent::execute() -{ - assert(m_patch_librarian != NULL); - m_patch_librarian->load_patch(m_patch_model, m_wait, m_merge); -} - - - -// SavePatchEvent // - -void -SavePatchEvent::execute() -{ - assert(m_patch_librarian != NULL); - m_patch_librarian->save_patch(m_patch_model, m_filename, m_recursive); -} - -/* -void -LoadSessionEvent::execute() -{ - std::ifstream is; - is.open(m_filename.c_str(), std::ios::in); - - if ( ! is.good()) { - cout << "[Loader] Unable to open session file " << m_filename << endl; - return; - } else { - cout << "[Loader] Loading session from " << m_filename << endl; - } - string s; - - is >> s; - if (s != "version") { - cout << "[Loader] Corrupt session file." << endl; - is.close(); - return; - } - - is >> s; - if (s != "1") { - cout << "[Loader] Unrecognised session file version." << endl; - is.close(); - return; - } - - while (!is.eof()) { - is >> s; - if (s == "") continue; - - if (s != "patch") { - //cerr << "[Loader] Corrupt session file, aborting session load." << endl; - break; - } else { - is >> s; - PatchModel* pm = new PatchModel("", 0); - if (s.substr(0, 1) != "/") - s = m_filename.substr(0, m_filename.find_last_of("/")+1) + s; - pm->filename(s); - pm->parent(NULL); - m_patch_librarian->load_patch(pm); - } - } - - is.close(); -} - - -void -SaveSessionEvent::execute() -{ - assert(m_filename != ""); - string dir = m_filename.substr(0, m_filename.find_last_of("/")); - - string patch_filename; - - std::ofstream os; - os.open(m_filename.c_str(), std::ios::out); - - if ( ! os.good()) { - cout << "[Loader] Unable to write to session file " << m_filename << endl; - return; - } else { - cout << "[Loader] Saving session to " << m_filename << endl; - } - - os << "version 1" << endl; - - for (map::iterator i = app->patches().begin(); - i != app->patches().end(); ++i) - { - if ((*i).second->model()->parent() == NULL) { - patch_filename = (*i).second->model()->filename(); - - // Make path relative if possible - if (patch_filename.length() > dir.length() && - patch_filename.substr(0, dir.length()) == dir) - patch_filename = patch_filename.substr(dir.length()+1); - - os << "patch " << patch_filename << endl; - } - } - - os.close(); -} -*/ - - -//////// Loader ////////// - - Loader::Loader(CountedPtr engine) -: m_patch_librarian(new PatchLibrarian(engine)), - m_event(NULL), - m_thread_exit_flag(false) +: _patch_librarian(new PatchLibrarian(engine)) { - assert(m_patch_librarian != NULL); - pthread_mutex_init(&m_mutex, NULL); - pthread_cond_init(&m_cond, NULL); - + assert(_patch_librarian != NULL); + // FIXME: rework this so the thread is only present when it's doing something (save mem) - launch(); + start(); } Loader::~Loader() { - m_thread_exit_flag = true; - pthread_join(m_thread, NULL); - delete m_patch_librarian; -} - - -void -Loader::set_event(LoaderEvent* ev) -{ - assert(ev != NULL); - - pthread_mutex_lock(&m_mutex); - assert(m_event == NULL); - m_event = ev; - pthread_cond_signal(&m_cond); - pthread_mutex_unlock(&m_mutex); + delete _patch_librarian; } void -Loader::launch() +Loader::_whipped() { - pthread_create(&m_thread, NULL, Loader::thread_function, this); -} + _mutex.lock(); + Closure& ev = _event; + ev(); + ev.disconnect(); -void* -Loader::thread_function(void* me) -{ - Loader* ct = static_cast(me); - return ct->m_thread_function(NULL); -} - - -void* -Loader::m_thread_function(void *) -{ - while ( ! m_thread_exit_flag) { - pthread_mutex_lock(&m_mutex); - pthread_cond_wait(&m_cond, &m_mutex); - - LoaderEvent* ev = m_event; - ev->execute(); - delete ev; - m_event = NULL; - - pthread_mutex_unlock(&m_mutex); - } - - pthread_exit(NULL); - return NULL; + _cond.signal(); + _mutex.unlock(); } void -Loader::load_patch(CountedPtr model, bool wait, bool merge) +Loader::load_patch(const string& filename, + const string& parent_path, + const string& name, + size_t poly, + const MetadataMap& initial_data, + bool existing) { - set_event(new LoadPatchEvent(m_patch_librarian, model, wait, merge)); -} - - -void -Loader::save_patch(CountedPtr model, const string& filename, bool recursive) -{ - cout << "[Loader] Saving patch " << filename << endl; - set_event(new SavePatchEvent(m_patch_librarian, model, filename, recursive)); -} + _mutex.lock(); + _event = sigc::hide_return(sigc::bind( + sigc::mem_fun(_patch_librarian, &PatchLibrarian::load_patch), + filename, parent_path, name, poly, initial_data, existing)); + + whip(); -/* -void -Loader::load_session(const string& filename) -{ - set_event(new LoadSessionEvent(m_patch_librarian, filename)); + _cond.wait(_mutex); + _mutex.unlock(); } void -Loader::save_session(const string& filename) +Loader::save_patch(CountedPtr model, const string& filename, bool recursive) { - cout << "Saving session..." << endl; - set_event(new SaveSessionEvent(m_patch_librarian, filename)); + cerr << "FIXME: (loader) save patch\n"; + //cout << "[Loader] Saving patch " << filename << endl; + //set_event(new SavePatchEvent(m_patch_librarian, model, filename, recursive)); } -*/ } // namespace Ingenuity diff --git a/src/progs/ingenuity/Loader.h b/src/progs/ingenuity/Loader.h index 58c301af..a33945a1 100644 --- a/src/progs/ingenuity/Loader.h +++ b/src/progs/ingenuity/Loader.h @@ -19,97 +19,23 @@ #include #include +#include "util/Thread.h" +#include "util/Slave.h" +#include "util/Mutex.h" +#include "util/Condition.h" #include "ModelEngineInterface.h" +#include "ObjectModel.h" using std::string; namespace Ingen { namespace Client { class PatchLibrarian; class PatchModel; - class ModelEngineInterface; } } using namespace Ingen::Client; namespace Ingenuity { -/** Event to run in the Loader thread. - * - * \ingroup Ingenuity - */ -class LoaderEvent -{ -public: - virtual void execute() = 0; - virtual ~LoaderEvent() {} -protected: - LoaderEvent() {} -}; - - -/** Loader thread patch loading event. - * - * \ingroup Ingenuity - */ -class LoadPatchEvent : public LoaderEvent -{ -public: - LoadPatchEvent(PatchLibrarian* pl, CountedPtr model, bool wait, bool merge) - : m_patch_librarian(pl), m_patch_model(model), m_wait(wait), m_merge(merge) {} - virtual ~LoadPatchEvent() {} - void execute(); -private: - PatchLibrarian* m_patch_librarian; - CountedPtr m_patch_model; - bool m_wait; - bool m_merge; -}; - - -/** Loader thread patch loading event. - * - * \ingroup Ingenuity - */ -class SavePatchEvent : public LoaderEvent -{ -public: - SavePatchEvent(PatchLibrarian* pl, CountedPtr pm, const string& filename, bool recursive) - : m_patch_librarian(pl), m_patch_model(pm), m_filename(filename), m_recursive(recursive) {} - virtual ~SavePatchEvent() {} - void execute(); -private: - PatchLibrarian* m_patch_librarian; - CountedPtr m_patch_model; - string m_filename; - bool m_recursive; -}; - -/* -class LoadSessionEvent : public LoaderEvent -{ -public: - LoadSessionEvent(PatchLibrarian* pl, const string& filename) - : m_patch_librarian(pl), m_filename(filename) {} - virtual ~LoadSessionEvent() {} - void execute(); -private: - PatchLibrarian* m_patch_librarian; - string m_filename; -}; - - -class SaveSessionEvent : public LoaderEvent -{ -public: - SaveSessionEvent(PatchLibrarian* pl, const string& filename) - : m_patch_librarian(pl), m_filename(filename) {} - virtual ~SaveSessionEvent() {} - void execute(); -private: - PatchLibrarian* m_patch_librarian; - string m_filename; -}; -*/ - /** Thread for loading patch files. * * This is a seperate thread so it can send all the loading message without @@ -118,37 +44,35 @@ private: * * \ingroup Ingenuity */ -class Loader +class Loader : public Slave { public: Loader(CountedPtr engine); ~Loader(); - PatchLibrarian& librarian() { return *m_patch_librarian; } + PatchLibrarian& librarian() { return *_patch_librarian; } - void launch(); - void exit() { m_thread_exit_flag = true; } + void load_patch(const string& filename, + const string& parent_path, + const string& name, + size_t poly, + const MetadataMap& initial_data, + bool merge = false); - void load_patch(CountedPtr model, bool wait, bool merge); void save_patch(CountedPtr model, const string& filename, bool recursive); - - //void load_session(const string& filename); - //void save_session(const string& filename); - - static void* thread_function(void* me); + private: - void* m_thread_function(void*); - - void set_event(LoaderEvent* ev); - PatchLibrarian* const m_patch_librarian; - LoaderEvent* m_event; - bool m_thread_exit_flag; - pthread_t m_thread; - pthread_mutex_t m_mutex; - pthread_cond_t m_cond; + /** Returns nothing and takes no parameters (because they have all been bound) */ + typedef sigc::slot Closure; + + void _whipped(); + PatchLibrarian* const _patch_librarian; + Mutex _mutex; + Condition _cond; + Closure _event; }; diff --git a/src/progs/ingenuity/NodeMenu.cpp b/src/progs/ingenuity/NodeMenu.cpp index c3ee7a5b..9f2a9ea5 100644 --- a/src/progs/ingenuity/NodeMenu.cpp +++ b/src/progs/ingenuity/NodeMenu.cpp @@ -65,11 +65,14 @@ NodeMenu::NodeMenu(CountedPtr node) //m_controls_menuitem->property_sensitive() = false; + cerr << "FIXME: MIDI learn menu\n"; + /* 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)); diff --git a/src/progs/ingenuity/NodeModule.cpp b/src/progs/ingenuity/NodeModule.cpp index 9384917b..8545e493 100644 --- a/src/progs/ingenuity/NodeModule.cpp +++ b/src/progs/ingenuity/NodeModule.cpp @@ -43,16 +43,7 @@ NodeModule::NodeModule(PatchCanvas* canvas, CountedPtr node) } 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; - ((PatchCanvas*)m_canvas)->get_new_module_location(x, y); - } + set_all_metadata(); node->new_port_sig.connect(sigc::mem_fun(this, &NodeModule::add_port)); node->removed_port_sig.connect(sigc::mem_fun(this, &NodeModule::remove_port)); @@ -76,11 +67,18 @@ NodeModule::create_all_ports() } +void +NodeModule::set_all_metadata() +{ + for (MetadataMap::const_iterator i = m_node->metadata().begin(); i != m_node->metadata().end(); ++i) + metadata_update(i->first, i->second); +} + + void NodeModule::add_port(CountedPtr port) { - cerr << "FIXME: port leak\n"; - new Port(this, port); + manage(new Port(this, port)); resize(); } diff --git a/src/progs/ingenuity/NodeModule.h b/src/progs/ingenuity/NodeModule.h index 5b4ec922..6f7460bf 100644 --- a/src/progs/ingenuity/NodeModule.h +++ b/src/progs/ingenuity/NodeModule.h @@ -68,6 +68,7 @@ protected: virtual void on_double_click(GdkEventButton* ev) { show_control_window(); } virtual void on_middle_click(GdkEventButton* ev) { show_control_window(); } + void set_all_metadata(); void metadata_update(const string& key, const Atom& value); void create_all_ports(); diff --git a/src/progs/ingenuity/PatchCanvas.cpp b/src/progs/ingenuity/PatchCanvas.cpp index 5dc39a2b..9419b252 100644 --- a/src/progs/ingenuity/PatchCanvas.cpp +++ b/src/progs/ingenuity/PatchCanvas.cpp @@ -103,8 +103,7 @@ PatchCanvas::build_canvas() { // 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 PatchPortModule(this, *i); + manage(new PatchPortModule(this, *i)); } // Create connections @@ -118,13 +117,11 @@ PatchCanvas::build_canvas() { void PatchCanvas::add_node(CountedPtr nm) { - cerr << "FIXME: MODULE LEAK!" << endl; - CountedPtr pm = PtrCast(nm); if (pm) - new SubpatchModule(this, pm); + manage(new SubpatchModule(this, pm)); else - new NodeModule(this, nm); + manage(new NodeModule(this, nm)); } @@ -139,9 +136,7 @@ PatchCanvas::remove_node(CountedPtr nm) void PatchCanvas::add_port(CountedPtr pm) { - cerr << "FIXME: PORT MODULE LEAK!" << endl; - - new PatchPortModule(this, pm); + manage(new PatchPortModule(this, pm)); } diff --git a/src/progs/ingenuity/PatchView.cpp b/src/progs/ingenuity/PatchView.cpp index e8cf9e5f..fbebd886 100644 --- a/src/progs/ingenuity/PatchView.cpp +++ b/src/progs/ingenuity/PatchView.cpp @@ -77,6 +77,7 @@ PatchView::set_patch(CountedPtr patch) // 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)); + _refresh_but->signal_clicked().connect(sigc::mem_fun(this, &PatchView::refresh_clicked)); _zoom_normal_but->signal_clicked().connect(sigc::bind(sigc::mem_fun( static_cast(_canvas), &FlowCanvas::set_zoom), 1.0)); @@ -120,12 +121,21 @@ PatchView::process_toggled() } } + void PatchView::clear_clicked() { App::instance().engine()->clear_patch(_patch->path()); } + +void +PatchView::refresh_clicked() +{ + App::instance().engine()->request_object(_patch->path()); +} + + void PatchView::enable() { diff --git a/src/progs/ingenuity/PatchView.h b/src/progs/ingenuity/PatchView.h index d0c9c4c4..a0225bda 100644 --- a/src/progs/ingenuity/PatchView.h +++ b/src/progs/ingenuity/PatchView.h @@ -68,6 +68,7 @@ private: void process_toggled(); void clear_clicked(); + void refresh_clicked(); void enable(); void disable(); diff --git a/src/progs/ingenuity/PatchWindow.cpp b/src/progs/ingenuity/PatchWindow.cpp index edf2e9d0..e429d136 100644 --- a/src/progs/ingenuity/PatchWindow.cpp +++ b/src/progs/ingenuity/PatchWindow.cpp @@ -158,9 +158,15 @@ PatchWindow::set_patch(CountedPtr patch, CountedPtr view) m_patch = patch; - m_view = view ? view : PatchView::create(patch); - assert(m_view); + m_view = m_breadcrumb_box->view(patch->path()); + + if (!m_view) + m_view = PatchView::create(patch); + else + assert(!view || m_view == view); + assert(m_view); + // Add view to ourself if (m_view->get_parent()) m_view->get_parent()->remove(*m_view); @@ -196,21 +202,12 @@ PatchWindow::set_patch(CountedPtr patch, CountedPtr view) else m_menu_destroy_patch->set_sensitive(true); - m_patch->destroyed_sig.connect(sigc::mem_fun(this, &PatchWindow::patch_destroyed)); - show_all(); m_enable_signal = true; } -void -PatchWindow::patch_destroyed() -{ - App::instance().window_factory()->remove_patch_window(this); -} - - void PatchWindow::event_show_engine() { diff --git a/src/progs/ingenuity/PatchWindow.h b/src/progs/ingenuity/PatchWindow.h index 0ab5fe48..b957c420 100644 --- a/src/progs/ingenuity/PatchWindow.h +++ b/src/progs/ingenuity/PatchWindow.h @@ -68,7 +68,7 @@ public: void set_patch_from_path(const Path& path, CountedPtr view); void set_patch(CountedPtr pc, CountedPtr view); - CountedPtr patch() const { return m_patch; } + CountedPtr patch() const { return m_patch; } Gtk::MenuItem* menu_view_control_window() { return m_menu_view_control_window; } @@ -89,8 +89,6 @@ private: void event_show_controls(); void event_show_engine(); - void patch_destroyed(); - CountedPtr m_patch; CountedPtr m_view; -- cgit v1.2.1