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/libs/engine/events/AddNodeEvent.cpp | 31 +++++--- src/libs/engine/events/AddNodeEvent.h | 18 ++++- src/libs/engine/events/AddPortEvent.cpp | 31 +++++++- src/libs/engine/events/AddPortEvent.h | 2 +- src/libs/engine/events/CreatePatchEvent.cpp | 8 +- src/libs/engine/events/Makefile.am | 4 + src/libs/engine/events/RequestAllObjectsEvent.cpp | 2 +- src/libs/engine/events/RequestObjectEvent.cpp | 97 +++++++++++++++++++++++ src/libs/engine/events/RequestObjectEvent.h | 55 +++++++++++++ src/libs/engine/events/RequestPluginEvent.cpp | 78 ++++++++++++++++++ src/libs/engine/events/RequestPluginEvent.h | 55 +++++++++++++ 11 files changed, 353 insertions(+), 28 deletions(-) create mode 100644 src/libs/engine/events/RequestObjectEvent.cpp create mode 100644 src/libs/engine/events/RequestObjectEvent.h create mode 100644 src/libs/engine/events/RequestPluginEvent.cpp create mode 100644 src/libs/engine/events/RequestPluginEvent.h (limited to 'src/libs/engine/events') diff --git a/src/libs/engine/events/AddNodeEvent.cpp b/src/libs/engine/events/AddNodeEvent.cpp index 6e42ef82..1a317e39 100644 --- a/src/libs/engine/events/AddNodeEvent.cpp +++ b/src/libs/engine/events/AddNodeEvent.cpp @@ -33,23 +33,31 @@ namespace Ingen { -/*AddNodeEvent::AddNodeEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& path, Plugin* plugin, bool poly) +AddNodeEvent::AddNodeEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& path, + const string& plugin_uri, bool poly) : QueuedEvent(engine, responder, timestamp), m_path(path), - m_plugin(plugin), + m_plugin_uri(plugin_uri), m_poly(poly), m_patch(NULL), m_node(NULL), m_process_order(NULL), m_node_already_exists(false) { -}*/ +} + +/** DEPRECATED: Construct from type, library name, and plugin label. + * + * Do not use. + */ AddNodeEvent::AddNodeEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& path, - const string& plugin_uri, bool poly) + const string& plugin_type, const string& plugin_lib, const string& plugin_label, bool poly) : QueuedEvent(engine, responder, timestamp), m_path(path), - m_plugin_uri(plugin_uri), + m_plugin_type(plugin_type), + m_plugin_lib(plugin_lib), + m_plugin_label(plugin_label), m_poly(poly), m_patch(NULL), m_node(NULL), @@ -59,11 +67,6 @@ AddNodeEvent::AddNodeEvent(Engine& engine, CountedPtr responder, Samp } -AddNodeEvent::~AddNodeEvent() -{ -} - - void AddNodeEvent::pre_process() { @@ -74,7 +77,10 @@ AddNodeEvent::pre_process() } m_patch = _engine.object_store()->find_patch(m_path.parent()); - const Plugin* plugin = _engine.node_factory()->plugin(m_plugin_uri); + + const Plugin* plugin = (m_plugin_uri != "") + ? _engine.node_factory()->plugin(m_plugin_uri) + : _engine.node_factory()->plugin(m_plugin_type, m_plugin_lib, m_plugin_label); if (m_patch && plugin) { if (m_poly) @@ -130,8 +136,7 @@ AddNodeEvent::post_process() _responder->respond_error(msg); } else { _responder->respond_ok(); - //_engine.broadcaster()->send_node_creation_messages(m_node); - _engine.broadcaster()->send_node(m_node); + _engine.broadcaster()->send_node(m_node, true); // yes, send ports } } diff --git a/src/libs/engine/events/AddNodeEvent.h b/src/libs/engine/events/AddNodeEvent.h index b4345f90..22e164ea 100644 --- a/src/libs/engine/events/AddNodeEvent.h +++ b/src/libs/engine/events/AddNodeEvent.h @@ -39,15 +39,22 @@ class Plugin; class AddNodeEvent : public QueuedEvent { public: - //AddNodeEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& path, Plugin* plugin, bool poly); AddNodeEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& node_path, const string& plugin_uri, bool poly); - - ~AddNodeEvent(); + + // DEPRECATED + AddNodeEvent(Engine& engine, + CountedPtr responder, + SampleCount timestamp, + const string& node_path, + const string& plugin_type, + const string& lib_name, + const string& plugin_label, + bool poly); void pre_process(); void execute(SampleCount nframes, FrameTime start, FrameTime end); @@ -56,7 +63,10 @@ public: private: string m_patch_name; Path m_path; - string m_plugin_uri; + string m_plugin_uri; ///< If nonempty then type, library, label, are ignored + string m_plugin_type; + string m_plugin_lib; + string m_plugin_label; bool m_poly; Patch* m_patch; Node* m_node; diff --git a/src/libs/engine/events/AddPortEvent.cpp b/src/libs/engine/events/AddPortEvent.cpp index 06ddae94..ae692b1b 100644 --- a/src/libs/engine/events/AddPortEvent.cpp +++ b/src/libs/engine/events/AddPortEvent.cpp @@ -23,6 +23,7 @@ #include "Patch.h" #include "Maid.h" #include "util/Path.h" +#include "QueuedEventSource.h" #include "ObjectStore.h" #include "ClientBroadcaster.h" #include "util/Path.h" @@ -32,12 +33,13 @@ #include "List.h" #include "Driver.h" #include "DuplexPort.h" +#include "Array.h" namespace Ingen { -AddPortEvent::AddPortEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& path, const string& type, bool is_output) -: QueuedEvent(engine, responder, timestamp), +AddPortEvent::AddPortEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& path, const string& type, bool is_output, QueuedEventSource* source) +: QueuedEvent(engine, responder, timestamp, true, source), _path(path), _type(type), _is_output(is_output), @@ -46,6 +48,14 @@ AddPortEvent::AddPortEvent(Engine& engine, CountedPtr responder, Samp _patch_port(NULL), _driver_port(NULL) { + /* This is blocking because of the two different sets of Patch ports, the array used in the + * audio thread (inherited from NodeBase), and the arrays used in the pre processor thread. + * If two add port events arrive in the same cycle and the second pre processes before the + * first executes, bad things happen (ports are lost). + * + * FIXME: fix this using RCU + */ + string type_str; if (type == "CONTROL" || type == "AUDIO") _data_type = DataType::FLOAT; @@ -73,17 +83,22 @@ AddPortEvent::pre_process() if (_type == "AUDIO" || _type == "MIDI") buffer_size = _engine.audio_driver()->buffer_size(); + const size_t old_num_ports = _patch->num_ports(); + _patch_port = _patch->create_port(_path.name(), _data_type, buffer_size, _is_output); + if (_patch_port) { + if (_is_output) _patch->add_output(new ListNode(_patch_port)); else _patch->add_input(new ListNode(_patch_port)); if (_patch->external_ports()) - _ports_array = new Array(_patch->num_ports() + 1, *_patch->external_ports()); + _ports_array = new Array(old_num_ports + 1, *_patch->external_ports()); else - _ports_array = new Array(_patch->num_ports() + 1, NULL); + _ports_array = new Array(old_num_ports + 1, NULL); + _ports_array->at(_patch->num_ports()) = _patch_port; _engine.object_store()->add(_patch_port); @@ -96,6 +111,9 @@ AddPortEvent::pre_process() _driver_port = _engine.midi_driver()->create_port( dynamic_cast*>(_patch_port)); } + + assert(_patch->num_ports() == old_num_ports); + assert(_ports_array->size() == _patch->num_ports() + 1); } } QueuedEvent::pre_process(); @@ -108,8 +126,10 @@ AddPortEvent::execute(SampleCount nframes, FrameTime start, FrameTime end) QueuedEvent::execute(nframes, start, end); if (_patch_port) { + _engine.maid()->push(_patch->external_ports()); //_patch->add_port(_port); + _patch->external_ports(_ports_array); } @@ -121,6 +141,9 @@ AddPortEvent::execute(SampleCount nframes, FrameTime start, FrameTime end) void AddPortEvent::post_process() { + if (_source) + _source->unblock(); + if (!_patch_port) { const string msg = string("Could not create port - ").append(_path); _responder->respond_error(msg); diff --git a/src/libs/engine/events/AddPortEvent.h b/src/libs/engine/events/AddPortEvent.h index 070d07df..0ef33515 100644 --- a/src/libs/engine/events/AddPortEvent.h +++ b/src/libs/engine/events/AddPortEvent.h @@ -41,7 +41,7 @@ class DriverPort; class AddPortEvent : public QueuedEvent { public: - AddPortEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& path, const string& type, bool is_output); + AddPortEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& path, const string& type, bool is_output, QueuedEventSource* source); void pre_process(); void execute(SampleCount nframes, FrameTime start, FrameTime end); diff --git a/src/libs/engine/events/CreatePatchEvent.cpp b/src/libs/engine/events/CreatePatchEvent.cpp index 7532291b..97be5557 100644 --- a/src/libs/engine/events/CreatePatchEvent.cpp +++ b/src/libs/engine/events/CreatePatchEvent.cpp @@ -120,11 +120,9 @@ CreatePatchEvent::post_process() _responder->respond_ok(); - // Don't want to send nodes that have been added since prepare() - //_engine.broadcaster()->send_node_creation_messages(m_patch); - - // Patches are always empty on creation, so this is fine - _engine.broadcaster()->send_patch(m_patch); + // Don't send ports/nodes that have been added since prepare() + // (otherwise they would be sent twice) + _engine.broadcaster()->send_patch(m_patch, false); } else if (m_error == OBJECT_EXISTS) { string msg = "Unable to create patch: "; diff --git a/src/libs/engine/events/Makefile.am b/src/libs/engine/events/Makefile.am index 5b29e12b..a1760738 100644 --- a/src/libs/engine/events/Makefile.am +++ b/src/libs/engine/events/Makefile.am @@ -36,6 +36,10 @@ EXTRA_DIST = \ events/SetMetadataEvent.cpp \ events/RequestMetadataEvent.h \ events/RequestMetadataEvent.cpp \ + events/RequestPluginEvent.h \ + events/RequestPluginEvent.cpp \ + events/RequestObjectEvent.h \ + events/RequestObjectEvent.cpp \ events/RequestPortValueEvent.h \ events/RequestPortValueEvent.cpp \ events/RequestAllObjectsEvent.h \ diff --git a/src/libs/engine/events/RequestAllObjectsEvent.cpp b/src/libs/engine/events/RequestAllObjectsEvent.cpp index f51a514e..893aa5df 100644 --- a/src/libs/engine/events/RequestAllObjectsEvent.cpp +++ b/src/libs/engine/events/RequestAllObjectsEvent.cpp @@ -48,7 +48,7 @@ RequestAllObjectsEvent::post_process() // Everything is a child of the root patch, so this sends it all Patch* root = _engine.object_store()->find_patch("/"); if (root) - ObjectSender::send_patch(m_client.get(), root); + ObjectSender::send_patch(m_client.get(), root, true); } else { _responder->respond_error("Unable to find client to send all objects"); diff --git a/src/libs/engine/events/RequestObjectEvent.cpp b/src/libs/engine/events/RequestObjectEvent.cpp new file mode 100644 index 00000000..3b0dc6fd --- /dev/null +++ b/src/libs/engine/events/RequestObjectEvent.cpp @@ -0,0 +1,97 @@ +/* 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 "RequestObjectEvent.h" +#include +#include "Responder.h" +#include "Engine.h" +#include "interface/ClientInterface.h" +#include "TypedPort.h" +#include "ObjectStore.h" +#include "ClientBroadcaster.h" +#include "Patch.h" +#include "Node.h" +#include "ObjectSender.h" + +using std::string; + +namespace Ingen { + + +RequestObjectEvent::RequestObjectEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& path) +: QueuedEvent(engine, responder, timestamp), + m_path(path), + m_object(NULL) +{ +} + + +void +RequestObjectEvent::pre_process() +{ + m_client = _engine.broadcaster()->client(_responder->client_key()); + m_object = _engine.object_store()->find(m_path); + + QueuedEvent::pre_process(); +} + + +void +RequestObjectEvent::execute(SampleCount nframes, FrameTime start, FrameTime end) +{ + QueuedEvent::execute(nframes, start, end); + assert(_time >= start && _time <= end); +} + + +void +RequestObjectEvent::post_process() +{ + if (!m_object) { + _responder->respond_error("Unable to find object requested."); + + } else if (m_client) { + Patch* const patch = dynamic_cast(m_object); + if (patch) { + _responder->respond_ok(); + ObjectSender::send_patch(m_client.get(), patch, true); + return; + } + + Node* const node = dynamic_cast(m_object); + if (node) { + _responder->respond_ok(); + ObjectSender::send_node(m_client.get(), node, true); + return; + } + + Port* const port = dynamic_cast(m_object); + if (port) { + _responder->respond_ok(); + ObjectSender::send_port(m_client.get(), port); + return; + } + + _responder->respond_error("Object of unknown type requested."); + + } else { + _responder->respond_error("Unable to find client to send object."); + } +} + + +} // namespace Ingen + diff --git a/src/libs/engine/events/RequestObjectEvent.h b/src/libs/engine/events/RequestObjectEvent.h new file mode 100644 index 00000000..276b60fa --- /dev/null +++ b/src/libs/engine/events/RequestObjectEvent.h @@ -0,0 +1,55 @@ +/* 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 REQUESTOBJECTEVENT_H +#define REQUESTOBJECTEVENT_H + +#include +#include "QueuedEvent.h" +#include "types.h" + +using std::string; + +namespace Ingen { + +class GraphObject; +namespace Shared { class ClientInterface; } +using Shared::ClientInterface; + + +/** A request from a client to send the value of a port. + * + * \ingroup engine + */ +class RequestObjectEvent : public QueuedEvent +{ +public: + RequestObjectEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& port_path); + + void pre_process(); + void execute(SampleCount nframes, FrameTime start, FrameTime end); + void post_process(); + +private: + string m_path; + GraphObject* m_object; + CountedPtr m_client; +}; + + +} // namespace Ingen + +#endif // REQUESTOBJECTEVENT_H diff --git a/src/libs/engine/events/RequestPluginEvent.cpp b/src/libs/engine/events/RequestPluginEvent.cpp new file mode 100644 index 00000000..95141226 --- /dev/null +++ b/src/libs/engine/events/RequestPluginEvent.cpp @@ -0,0 +1,78 @@ +/* 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 "RequestPluginEvent.h" +#include +#include "Responder.h" +#include "Engine.h" +#include "interface/ClientInterface.h" +#include "TypedPort.h" +#include "ObjectStore.h" +#include "ClientBroadcaster.h" +#include "NodeFactory.h" +#include "Plugin.h" + +using std::string; + +namespace Ingen { + + +RequestPluginEvent::RequestPluginEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& uri) +: QueuedEvent(engine, responder, timestamp), + m_uri(uri), + m_plugin(NULL) +{ +} + + +void +RequestPluginEvent::pre_process() +{ + m_client = _engine.broadcaster()->client(_responder->client_key()); + m_plugin = _engine.node_factory()->plugin(m_uri); + + QueuedEvent::pre_process(); +} + + +void +RequestPluginEvent::execute(SampleCount nframes, FrameTime start, FrameTime end) +{ + QueuedEvent::execute(nframes, start, end); + assert(_time >= start && _time <= end); +} + + +void +RequestPluginEvent::post_process() +{ + if (!m_plugin) { + _responder->respond_error("Unable to find plugin requested."); + + } else if (m_client) { + + _responder->respond_ok(); + assert(m_plugin->uri() == m_uri); + m_client->new_plugin(m_uri, m_plugin->name()); + + } else { + _responder->respond_error("Unable to find client to send plugin."); + } +} + + +} // namespace Ingen + diff --git a/src/libs/engine/events/RequestPluginEvent.h b/src/libs/engine/events/RequestPluginEvent.h new file mode 100644 index 00000000..1c12c78e --- /dev/null +++ b/src/libs/engine/events/RequestPluginEvent.h @@ -0,0 +1,55 @@ +/* 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 REQUESTPLUGINEVENT_H +#define REQUESTPLUGINEVENT_H + +#include +#include "QueuedEvent.h" +#include "types.h" + +using std::string; + +namespace Ingen { + +class Plugin; +namespace Shared { class ClientInterface; } +using Shared::ClientInterface; + + +/** A request from a client to send the value of a port. + * + * \ingroup engine + */ +class RequestPluginEvent : public QueuedEvent +{ +public: + RequestPluginEvent(Engine& engine, CountedPtr responder, SampleCount timestamp, const string& uri); + + void pre_process(); + void execute(SampleCount nframes, FrameTime start, FrameTime end); + void post_process(); + +private: + string m_uri; + const Plugin* m_plugin; + CountedPtr m_client; +}; + + +} // namespace Ingen + +#endif // REQUESTPLUGINEVENT_H -- cgit v1.2.1