summaryrefslogtreecommitdiffstats
path: root/src/engine/events
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2006-06-10 01:02:08 +0000
committerDavid Robillard <d@drobilla.net>2006-06-10 01:02:08 +0000
commit6f78a755b0f8c59f85cdc02e9eeca8db860a2ed2 (patch)
treedbb7c668101a811e8b5e10f42f19991edb129674 /src/engine/events
parentc2fbab4c27df8b9346bb68e30fddd7f94540dee1 (diff)
downloadingen-6f78a755b0f8c59f85cdc02e9eeca8db860a2ed2.tar.gz
ingen-6f78a755b0f8c59f85cdc02e9eeca8db860a2ed2.tar.bz2
ingen-6f78a755b0f8c59f85cdc02e9eeca8db860a2ed2.zip
Juggling things around...
git-svn-id: http://svn.drobilla.net/lad/grauph@13 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine/events')
-rw-r--r--src/engine/events/ActivateEvent.cpp52
-rw-r--r--src/engine/events/ActivateEvent.h41
-rw-r--r--src/engine/events/AddNodeEvent.cpp128
-rw-r--r--src/engine/events/AddNodeEvent.h63
-rw-r--r--src/engine/events/AllNotesOffEvent.cpp67
-rw-r--r--src/engine/events/AllNotesOffEvent.h50
-rw-r--r--src/engine/events/ClearPatchEvent.cpp114
-rw-r--r--src/engine/events/ClearPatchEvent.h54
-rw-r--r--src/engine/events/ConnectionEvent.cpp240
-rw-r--r--src/engine/events/ConnectionEvent.h107
-rw-r--r--src/engine/events/CreatePatchEvent.cpp150
-rw-r--r--src/engine/events/CreatePatchEvent.h64
-rw-r--r--src/engine/events/DSSIConfigureEvent.cpp73
-rw-r--r--src/engine/events/DSSIConfigureEvent.h49
-rw-r--r--src/engine/events/DSSIControlEvent.cpp68
-rw-r--r--src/engine/events/DSSIControlEvent.h51
-rw-r--r--src/engine/events/DSSIProgramEvent.cpp77
-rw-r--r--src/engine/events/DSSIProgramEvent.h49
-rw-r--r--src/engine/events/DSSIUpdateEvent.cpp80
-rw-r--r--src/engine/events/DSSIUpdateEvent.h54
-rw-r--r--src/engine/events/DeactivateEvent.cpp54
-rw-r--r--src/engine/events/DeactivateEvent.h42
-rw-r--r--src/engine/events/DestroyEvent.cpp168
-rw-r--r--src/engine/events/DestroyEvent.h68
-rw-r--r--src/engine/events/DisablePatchEvent.cpp70
-rw-r--r--src/engine/events/DisablePatchEvent.h52
-rw-r--r--src/engine/events/DisconnectNodeEvent.cpp140
-rw-r--r--src/engine/events/DisconnectNodeEvent.h68
-rw-r--r--src/engine/events/DisconnectPortEvent.cpp145
-rw-r--r--src/engine/events/DisconnectPortEvent.h70
-rw-r--r--src/engine/events/DisconnectionEvent.cpp295
-rw-r--r--src/engine/events/DisconnectionEvent.h106
-rw-r--r--src/engine/events/EnablePatchEvent.cpp82
-rw-r--r--src/engine/events/EnablePatchEvent.h56
-rw-r--r--src/engine/events/Event.cpp48
-rw-r--r--src/engine/events/Event.h71
-rw-r--r--src/engine/events/LashRestoreDoneEvent.h54
-rw-r--r--src/engine/events/LoadPluginsEvent.cpp44
-rw-r--r--src/engine/events/LoadPluginsEvent.h40
-rw-r--r--src/engine/events/Makefile.am65
-rw-r--r--src/engine/events/MidiLearnEvent.cpp88
-rw-r--r--src/engine/events/MidiLearnEvent.h84
-rw-r--r--src/engine/events/NoteOffEvent.cpp78
-rw-r--r--src/engine/events/NoteOffEvent.h52
-rw-r--r--src/engine/events/NoteOnEvent.cpp89
-rw-r--r--src/engine/events/NoteOnEvent.h54
-rw-r--r--src/engine/events/PingQueuedEvent.h44
-rw-r--r--src/engine/events/QueuedEvent.h86
-rw-r--r--src/engine/events/RegisterClientEvent.cpp53
-rw-r--r--src/engine/events/RegisterClientEvent.h53
-rw-r--r--src/engine/events/RenameEvent.cpp123
-rw-r--r--src/engine/events/RenameEvent.h66
-rw-r--r--src/engine/events/RequestAllObjectsEvent.cpp55
-rw-r--r--src/engine/events/RequestAllObjectsEvent.h50
-rw-r--r--src/engine/events/RequestMetadataEvent.cpp80
-rw-r--r--src/engine/events/RequestMetadataEvent.h56
-rw-r--r--src/engine/events/RequestPluginsEvent.cpp55
-rw-r--r--src/engine/events/RequestPluginsEvent.h51
-rw-r--r--src/engine/events/RequestPortValueEvent.cpp81
-rw-r--r--src/engine/events/RequestPortValueEvent.h56
-rw-r--r--src/engine/events/SetMetadataEvent.cpp79
-rw-r--r--src/engine/events/SetMetadataEvent.h53
-rw-r--r--src/engine/events/SetPortValueEvent.cpp104
-rw-r--r--src/engine/events/SetPortValueEvent.h56
-rw-r--r--src/engine/events/SetPortValueQueuedEvent.cpp116
-rw-r--r--src/engine/events/SetPortValueQueuedEvent.h57
-rw-r--r--src/engine/events/UnregisterClientEvent.cpp45
-rw-r--r--src/engine/events/UnregisterClientEvent.h53
68 files changed, 5286 insertions, 0 deletions
diff --git a/src/engine/events/ActivateEvent.cpp b/src/engine/events/ActivateEvent.cpp
new file mode 100644
index 00000000..671b26d5
--- /dev/null
+++ b/src/engine/events/ActivateEvent.cpp
@@ -0,0 +1,52 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ActivateEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+
+namespace Om {
+
+
+ActivateEvent::ActivateEvent(CountedPtr<Responder> responder)
+: QueuedEvent(responder)
+{
+}
+
+
+void
+ActivateEvent::pre_process()
+{
+ QueuedEvent::pre_process();
+
+ if (om != NULL)
+ om->activate();
+}
+
+
+void
+ActivateEvent::post_process()
+{
+ if (om != NULL)
+ m_responder->respond_ok();
+ else
+ m_responder->respond_error("Not ready to activate yet.");
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/ActivateEvent.h b/src/engine/events/ActivateEvent.h
new file mode 100644
index 00000000..280b5523
--- /dev/null
+++ b/src/engine/events/ActivateEvent.h
@@ -0,0 +1,41 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ACTIVATEEVENT_H
+#define ACTIVATEEVENT_H
+
+#include "QueuedEvent.h"
+
+namespace Om {
+
+
+/** Activates the engine.
+ *
+ * \ingroup engine
+ */
+class ActivateEvent : public QueuedEvent
+{
+public:
+ ActivateEvent(CountedPtr<Responder> responder);
+
+ void pre_process();
+ void post_process();
+};
+
+
+} // namespace Om
+
+#endif // ACTIVATEEVENT_H
diff --git a/src/engine/events/AddNodeEvent.cpp b/src/engine/events/AddNodeEvent.cpp
new file mode 100644
index 00000000..2b31ef4a
--- /dev/null
+++ b/src/engine/events/AddNodeEvent.cpp
@@ -0,0 +1,128 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "AddNodeEvent.h"
+#include "Responder.h"
+#include "Patch.h"
+#include "Node.h"
+#include "Tree.h"
+#include "Plugin.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Patch.h"
+#include "NodeFactory.h"
+#include "ClientBroadcaster.h"
+#include "Maid.h"
+#include "util/Path.h"
+#include "ObjectStore.h"
+#include "util/Path.h"
+#include "Port.h"
+
+namespace Om {
+
+
+AddNodeEvent::AddNodeEvent(CountedPtr<Responder> responder, const string& path, Plugin* plugin, bool poly)
+: QueuedEvent(responder),
+ m_path(path),
+ m_plugin(plugin),
+ m_poly(poly),
+ m_patch(NULL),
+ m_node(NULL),
+ m_process_order(NULL),
+ m_node_already_exists(false)
+{
+}
+
+
+AddNodeEvent::~AddNodeEvent()
+{
+ delete m_plugin;
+}
+
+
+void
+AddNodeEvent::pre_process()
+{
+ if (om->object_store()->find(m_path) != NULL) {
+ m_node_already_exists = true;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ m_patch = om->object_store()->find_patch(m_path.parent());
+
+ if (m_patch != NULL) {
+ if (m_poly)
+ m_node = om->node_factory()->load_plugin(m_plugin, m_path.name(), m_patch->internal_poly(), m_patch);
+ else
+ m_node = om->node_factory()->load_plugin(m_plugin, m_path.name(), 1, m_patch);
+
+ if (m_node != NULL) {
+ m_node->activate();
+
+ // This can be done here because the audio thread doesn't touch the
+ // node tree - just the process order array
+ m_patch->add_node(new ListNode<Node*>(m_node));
+ m_node->add_to_store();
+
+ if (m_patch->process())
+ m_process_order = m_patch->build_process_order();
+ }
+ }
+ QueuedEvent::pre_process();
+}
+
+
+void
+AddNodeEvent::execute(samplecount offset)
+{
+ QueuedEvent::execute(offset);
+
+ if (m_node != NULL) {
+ m_node->add_to_patch();
+
+ if (m_patch->process_order() != NULL)
+ om->maid()->push(m_patch->process_order());
+ m_patch->process_order(m_process_order);
+ }
+}
+
+
+void
+AddNodeEvent::post_process()
+{
+ string msg;
+ if (m_node_already_exists) {
+ msg = string("Could not create node - ").append(m_path);// + " already exists.";
+ m_responder->respond_error(msg);
+ } else if (m_patch == NULL) {
+ msg = "Could not find patch '" + m_path.parent() +"' for add_node.";
+ m_responder->respond_error(msg);
+ } else if (m_node == NULL) {
+ msg = "Unable to load node ";
+ msg.append(m_path).append(" (you're missing the plugin \"").append(
+ m_plugin->lib_name()).append(":").append(m_plugin->plug_label()).append("\")");;
+ m_responder->respond_error(msg);
+ } else {
+ m_responder->respond_ok();
+ //om->client_broadcaster()->send_node_creation_messages(m_node);
+ om->client_broadcaster()->send_node(m_node);
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/AddNodeEvent.h b/src/engine/events/AddNodeEvent.h
new file mode 100644
index 00000000..fe0236ba
--- /dev/null
+++ b/src/engine/events/AddNodeEvent.h
@@ -0,0 +1,63 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ADDNODEEVENT_H
+#define ADDNODEEVENT_H
+
+#include "QueuedEvent.h"
+#include "util/Path.h"
+#include <string>
+using std::string;
+
+template <typename T> class Array;
+template<typename T> class TreeNode;
+
+namespace Om {
+
+class Patch;
+class Node;
+class Plugin;
+
+
+/** An event to load a Node and insert it into a Patch.
+ *
+ * \ingroup engine
+ */
+class AddNodeEvent : public QueuedEvent
+{
+public:
+ AddNodeEvent(CountedPtr<Responder> responder, const string& path, Plugin* plugin, bool poly);
+ ~AddNodeEvent();
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_patch_name;
+ Path m_path;
+ Plugin* m_plugin;
+ bool m_poly;
+ Patch* m_patch;
+ Node* m_node;
+ Array<Node*>* m_process_order; // Patch's new process order
+ bool m_node_already_exists;
+};
+
+
+} // namespace Om
+
+#endif // ADDNODEEVENT_H
diff --git a/src/engine/events/AllNotesOffEvent.cpp b/src/engine/events/AllNotesOffEvent.cpp
new file mode 100644
index 00000000..aa3a00f1
--- /dev/null
+++ b/src/engine/events/AllNotesOffEvent.cpp
@@ -0,0 +1,67 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "AllNotesOffEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ObjectStore.h"
+
+namespace Om {
+
+
+/** Note off with patch explicitly passed - triggered by MIDI.
+ */
+AllNotesOffEvent::AllNotesOffEvent(CountedPtr<Responder> responder, Patch* patch)
+: Event(responder),
+ m_patch(patch)
+{
+}
+
+
+/** Note off event with lookup - triggered by OSC.
+ */
+AllNotesOffEvent::AllNotesOffEvent(CountedPtr<Responder> responder, const string& patch_path)
+: Event(responder),
+ m_patch(NULL),
+ m_patch_path(patch_path)
+{
+}
+
+
+void
+AllNotesOffEvent::execute(samplecount offset)
+{
+ if (m_patch == NULL && m_patch_path != "")
+ m_patch = om->object_store()->find_patch(m_patch_path);
+
+ //if (m_patch != NULL)
+ // for (List<MidiInNode*>::iterator j = m_patch->midi_in_nodes().begin(); j != m_patch->midi_in_nodes().end(); ++j)
+ // (*j)->all_notes_off(offset);
+}
+
+
+void
+AllNotesOffEvent::post_process()
+{
+ if (m_patch != NULL)
+ m_responder->respond_ok();
+}
+
+
+} // namespace Om
+
+
diff --git a/src/engine/events/AllNotesOffEvent.h b/src/engine/events/AllNotesOffEvent.h
new file mode 100644
index 00000000..ea23301b
--- /dev/null
+++ b/src/engine/events/AllNotesOffEvent.h
@@ -0,0 +1,50 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ALLNOTESOFFEVENT_H
+#define ALLNOTESOFFEVENT_H
+
+#include "Event.h"
+#include <string>
+using std::string;
+
+namespace Om {
+
+class Patch;
+
+
+/** A note off event for all active voices.
+ *
+ * \ingroup engine
+ */
+class AllNotesOffEvent : public Event
+{
+public:
+ AllNotesOffEvent(CountedPtr<Responder> responder, Patch* patch);
+ AllNotesOffEvent(CountedPtr<Responder> responder, const string& patch_path);
+
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ Patch* m_patch;
+ string m_patch_path;
+};
+
+
+} // namespace Om
+
+#endif // ALLNOTESOFFEVENT_H
diff --git a/src/engine/events/ClearPatchEvent.cpp b/src/engine/events/ClearPatchEvent.cpp
new file mode 100644
index 00000000..8b8fc223
--- /dev/null
+++ b/src/engine/events/ClearPatchEvent.cpp
@@ -0,0 +1,114 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ClearPatchEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Patch.h"
+#include "ClientBroadcaster.h"
+#include "util.h"
+#include "ObjectStore.h"
+#include "Port.h"
+#include "Maid.h"
+#include "Node.h"
+#include "Connection.h"
+#include "QueuedEventSource.h"
+
+namespace Om {
+
+
+ClearPatchEvent::ClearPatchEvent(CountedPtr<Responder> responder, const string& patch_path)
+: QueuedEvent(responder, true),
+ m_patch_path(patch_path),
+ m_patch(NULL),
+ m_process(false)
+{
+}
+
+
+void
+ClearPatchEvent::pre_process()
+{
+ m_patch = om->object_store()->find_patch(m_patch_path);
+
+ if (m_patch != NULL) {
+
+ m_process = m_patch->process();
+
+ for (List<Node*>::const_iterator i = m_patch->nodes().begin(); i != m_patch->nodes().end(); ++i)
+ (*i)->remove_from_store();
+ }
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+ClearPatchEvent::execute(samplecount offset)
+{
+ if (m_patch != NULL) {
+ m_patch->process(false);
+
+ for (List<Node*>::const_iterator i = m_patch->nodes().begin(); i != m_patch->nodes().end(); ++i)
+ (*i)->remove_from_patch();
+
+ if (m_patch->process_order() != NULL) {
+ om->maid()->push(m_patch->process_order());
+ m_patch->process_order(NULL);
+ }
+ }
+
+ QueuedEvent::execute(offset);
+}
+
+
+void
+ClearPatchEvent::post_process()
+{
+ if (m_patch != NULL) {
+ // Delete all nodes
+ for (List<Node*>::iterator i = m_patch->nodes().begin(); i != m_patch->nodes().end(); ++i) {
+ (*i)->deactivate();
+ delete *i;
+ }
+ m_patch->nodes().clear();
+
+ // Delete all connections
+ for (List<Connection*>::iterator i = m_patch->connections().begin(); i != m_patch->connections().end(); ++i)
+ delete *i;
+ m_patch->connections().clear();
+
+ // Restore patch's run state
+ m_patch->process(m_process);
+
+ // Make sure everything's sane
+ assert(m_patch->nodes().size() == 0);
+ assert(m_patch->connections().size() == 0);
+
+ // Reply
+ m_responder->respond_ok();
+ om->client_broadcaster()->send_patch_cleared(m_patch_path);
+ } else {
+ m_responder->respond_error(string("Patch ") + m_patch_path + " not found");
+ }
+
+ m_source->unblock();
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/ClearPatchEvent.h b/src/engine/events/ClearPatchEvent.h
new file mode 100644
index 00000000..c6e531a8
--- /dev/null
+++ b/src/engine/events/ClearPatchEvent.h
@@ -0,0 +1,54 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef CLEARPATCHEVENT_H
+#define CLEARPATCHEVENT_H
+
+#include <string>
+#include "QueuedEvent.h"
+#include "Array.h"
+
+using std::string;
+
+namespace Om {
+
+class Patch;
+
+
+/** Delete all nodes from a patch.
+ *
+ * \ingroup engine
+ */
+class ClearPatchEvent : public QueuedEvent
+{
+public:
+ ClearPatchEvent(CountedPtr<Responder> responder, const string& patch_path);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_patch_path;
+ Patch* m_patch;
+ bool m_process;
+};
+
+
+} // namespace Om
+
+
+#endif // CLEARPATCHEVENT_H
diff --git a/src/engine/events/ConnectionEvent.cpp b/src/engine/events/ConnectionEvent.cpp
new file mode 100644
index 00000000..fe3b991e
--- /dev/null
+++ b/src/engine/events/ConnectionEvent.cpp
@@ -0,0 +1,240 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ConnectionEvent.h"
+#include <string>
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ConnectionBase.h"
+#include "InputPort.h"
+#include "OutputPort.h"
+#include "Patch.h"
+#include "ClientBroadcaster.h"
+#include "Port.h"
+#include "PortInfo.h"
+#include "Maid.h"
+#include "ObjectStore.h"
+#include "util/Path.h"
+
+using std::string;
+namespace Om {
+
+
+//// ConnectionEvent ////
+
+
+ConnectionEvent::ConnectionEvent(CountedPtr<Responder> responder, const string& src_port_path, const string& dst_port_path)
+: QueuedEvent(responder),
+ m_src_port_path(src_port_path),
+ m_dst_port_path(dst_port_path),
+ m_patch(NULL),
+ m_src_port(NULL),
+ m_dst_port(NULL),
+ m_typed_event(NULL),
+ m_error(NO_ERROR)
+{
+}
+
+
+ConnectionEvent::~ConnectionEvent()
+{
+ delete m_typed_event;
+}
+
+
+void
+ConnectionEvent::pre_process()
+{
+ if (m_src_port_path.parent().parent() != m_dst_port_path.parent().parent()) {
+ m_error = PARENT_PATCH_DIFFERENT;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ /*m_patch = om->object_store()->find_patch(m_src_port_path.parent().parent());
+
+ if (m_patch == NULL) {
+ m_error = PORT_NOT_FOUND;
+ QueuedEvent::pre_process();
+ return;
+ }*/
+
+ Port* port1 = om->object_store()->find_port(m_src_port_path);
+ Port* port2 = om->object_store()->find_port(m_dst_port_path);
+
+ if (port1 == NULL || port2 == NULL) {
+ m_error = PORT_NOT_FOUND;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (port1->port_info()->type() != port2->port_info()->type()) {
+ m_error = TYPE_MISMATCH;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (port1->port_info()->is_output() && port2->port_info()->is_input()) {
+ m_src_port = port1;
+ m_dst_port = port2;
+ } else if (port2->port_info()->is_output() && port1->port_info()->is_input()) {
+ m_src_port = port2;
+ m_dst_port = port1;
+ } else {
+ m_error = TYPE_MISMATCH;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ // Create the typed event to actually do the work
+ const PortType type = port1->port_info()->type();
+ if (type == AUDIO || type == CONTROL) {
+ m_typed_event = new TypedConnectionEvent<sample>(m_responder,
+ (OutputPort<sample>*)m_src_port, (InputPort<sample>*)m_dst_port);
+ } else if (type == MIDI) {
+ m_typed_event = new TypedConnectionEvent<MidiMessage>(m_responder,
+ (OutputPort<MidiMessage>*)m_src_port, (InputPort<MidiMessage>*)m_dst_port);
+ } else {
+ m_error = TYPE_MISMATCH;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ m_typed_event->pre_process();
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+ConnectionEvent::execute(samplecount offset)
+{
+ QueuedEvent::execute(offset);
+
+ if (m_error == NO_ERROR)
+ m_typed_event->execute(offset);
+}
+
+
+void
+ConnectionEvent::post_process()
+{
+ if (m_error == NO_ERROR) {
+ m_typed_event->post_process();
+ } else {
+ // FIXME: better error messages
+ string msg = "Unable to make connection ";
+ msg.append(m_src_port_path + " -> " + m_dst_port_path);
+ m_responder->respond_error(msg);
+ }
+}
+
+
+
+//// TypedConnectionEvent ////
+
+
+template <typename T>
+TypedConnectionEvent<T>::TypedConnectionEvent(CountedPtr<Responder> responder, OutputPort<T>* src_port, InputPort<T>* dst_port)
+: QueuedEvent(responder),
+ m_src_port(src_port),
+ m_dst_port(dst_port),
+ m_patch(NULL),
+ m_process_order(NULL),
+ m_connection(NULL),
+ m_port_listnode(NULL),
+ m_succeeded(true)
+{
+ assert(src_port != NULL);
+ assert(dst_port != NULL);
+}
+
+template <typename T>
+TypedConnectionEvent<T>::~TypedConnectionEvent()
+{
+ // FIXME: haaaack, prevent a double delete
+ // this class is unusable by anything other than ConnectionEvent because of this
+ //m_responder = NULL;
+}
+
+
+template <typename T>
+void
+TypedConnectionEvent<T>::pre_process()
+{
+ Node* const src_node = m_src_port->parent_node();
+ Node* const dst_node = m_dst_port->parent_node();
+
+ m_patch = src_node->parent_patch();
+
+ if (src_node == NULL || dst_node == NULL) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (src_node->parent() != m_patch || dst_node->parent() != m_patch) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ m_connection = new ConnectionBase<T>(m_src_port, m_dst_port);
+ m_port_listnode = new ListNode<ConnectionBase<T>*>(m_connection);
+ m_patch_listnode = new ListNode<Connection*>(m_connection);
+
+ dst_node->providers()->push_back(new ListNode<Node*>(src_node));
+ src_node->dependants()->push_back(new ListNode<Node*>(dst_node));
+
+ if (m_patch->process())
+ m_process_order = m_patch->build_process_order();
+}
+
+
+template <typename T>
+void
+TypedConnectionEvent<T>::execute(samplecount offset)
+{
+ if (m_succeeded) {
+ // These must be inserted here, since they're actually used by the audio thread
+ m_dst_port->add_connection(m_port_listnode);
+ m_patch->add_connection(m_patch_listnode);
+ if (m_patch->process_order() != NULL)
+ om->maid()->push(m_patch->process_order());
+ m_patch->process_order(m_process_order);
+ }
+}
+
+
+template <typename T>
+void
+TypedConnectionEvent<T>::post_process()
+{
+ if (m_succeeded) {
+ assert(m_connection != NULL);
+
+ m_responder->respond_ok();
+
+ om->client_broadcaster()->send_connection(m_connection);
+ } else {
+ m_responder->respond_error("Unable to make connection.");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/ConnectionEvent.h b/src/engine/events/ConnectionEvent.h
new file mode 100644
index 00000000..8aaf2292
--- /dev/null
+++ b/src/engine/events/ConnectionEvent.h
@@ -0,0 +1,107 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef CONNECTIONEVENT_H
+#define CONNECTIONEVENT_H
+
+#include <string>
+#include "QueuedEvent.h"
+#include "util/Path.h"
+#include "util/types.h"
+using std::string;
+
+template <typename T> class ListNode;
+template <typename T> class Array;
+
+namespace Om {
+
+class Patch;
+class Node;
+class Connection;
+class MidiMessage;
+class Port;
+template <typename T> class ConnectionBase;
+template <typename T> class InputPort;
+template <typename T> class OutputPort;
+template <typename T> class TypedConnectionEvent; // helper, defined below
+
+
+/** Make a Connection between two Ports.
+ *
+ * \ingroup engine
+ */
+class ConnectionEvent : public QueuedEvent
+{
+public:
+ ConnectionEvent(CountedPtr<Responder> responder, const string& src_port_path, const string& dst_port_path);
+ ~ConnectionEvent();
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+
+ enum ErrorType { NO_ERROR, PARENT_PATCH_DIFFERENT, PORT_NOT_FOUND, TYPE_MISMATCH };
+
+ Path m_src_port_path;
+ Path m_dst_port_path;
+
+ Patch* m_patch;
+ Port* m_src_port;
+ Port* m_dst_port;
+
+ QueuedEvent* m_typed_event;
+
+ ErrorType m_error;
+};
+
+
+/** Templated ConnectionEvent.
+ *
+ * Intended to be called from ConnectionEvent so callers (ie OSCReceiver)
+ * can use ConnectionEvent without knowing anything about types (which
+ * they can't, since all they have is Port paths).
+ */
+template <typename T>
+class TypedConnectionEvent : public QueuedEvent
+{
+public:
+ TypedConnectionEvent(CountedPtr<Responder> responder, OutputPort<T>* src_port, InputPort<T>* dst_port);
+ ~TypedConnectionEvent();
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ OutputPort<T>* m_src_port;
+ InputPort<T>* m_dst_port;
+
+ Patch* m_patch;
+ Array<Node*>* m_process_order; ///< New process order for Patch
+ ConnectionBase<T>* m_connection;
+ ListNode<Connection*>* m_patch_listnode;
+ ListNode<ConnectionBase<T>*>* m_port_listnode;
+
+ bool m_succeeded;
+};
+
+
+
+} // namespace Om
+
+#endif // CONNECTIONEVENT_H
diff --git a/src/engine/events/CreatePatchEvent.cpp b/src/engine/events/CreatePatchEvent.cpp
new file mode 100644
index 00000000..9f0ae7f2
--- /dev/null
+++ b/src/engine/events/CreatePatchEvent.cpp
@@ -0,0 +1,150 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "CreatePatchEvent.h"
+#include "Responder.h"
+#include "Patch.h"
+#include "Node.h"
+#include "Tree.h"
+#include "Plugin.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Maid.h"
+#include "ClientBroadcaster.h"
+#include "AudioDriver.h"
+#include "util/Path.h"
+#include "ObjectStore.h"
+
+namespace Om {
+
+
+CreatePatchEvent::CreatePatchEvent(CountedPtr<Responder> responder, const string& path, int poly)
+: QueuedEvent(responder),
+ m_path(path),
+ m_patch(NULL),
+ m_parent(NULL),
+ m_process_order(NULL),
+ m_poly(poly),
+ m_error(NO_ERROR)
+{
+}
+
+
+void
+CreatePatchEvent::pre_process()
+{
+ if (om->object_store()->find(m_path) != NULL) {
+ m_error = OBJECT_EXISTS;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (m_poly < 1) {
+ m_error = INVALID_POLY;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (m_path != "/") {
+ m_parent = om->object_store()->find_patch(m_path.parent());
+ if (m_parent == NULL) {
+ m_error = PARENT_NOT_FOUND;
+ QueuedEvent::pre_process();
+ return;
+ }
+ }
+
+ size_t poly = 1;
+ if (m_parent != NULL && m_poly > 1 && m_poly == static_cast<int>(m_parent->internal_poly()))
+ poly = m_poly;
+
+ m_patch = new Patch(m_path.name(), poly, m_parent, om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size(), m_poly);
+
+ if (m_parent != NULL) {
+ m_parent->add_node(new ListNode<Node*>(m_patch->as_node()));
+
+ if (m_parent->process())
+ m_process_order = m_parent->build_process_order();
+ }
+
+ m_patch->activate();
+
+ // Insert into ObjectStore
+ m_patch->add_to_store();
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+CreatePatchEvent::execute(samplecount offset)
+{
+ QueuedEvent::execute(offset);
+
+ if (m_patch != NULL) {
+ if (m_parent == NULL) {
+ assert(m_path == "/");
+ assert(m_patch->parent_patch() == NULL);
+ om->audio_driver()->set_root_patch(m_patch);
+ } else {
+ assert(m_parent != NULL);
+ assert(m_path != "/");
+
+ m_patch->add_to_patch();
+
+ if (m_parent->process_order() != NULL)
+ om->maid()->push(m_parent->process_order());
+ m_parent->process_order(m_process_order);
+ }
+ }
+}
+
+
+void
+CreatePatchEvent::post_process()
+{
+ if (m_responder.get()) {
+ if (m_error == NO_ERROR) {
+
+ m_responder->respond_ok();
+
+ // Don't want to send nodes that have been added since prepare()
+ //om->client_broadcaster()->send_node_creation_messages(m_patch);
+
+ // Patches are always empty on creation, so this is fine
+ om->client_broadcaster()->send_patch(m_patch);
+
+ } else if (m_error == OBJECT_EXISTS) {
+ string msg = "Unable to create patch: ";
+ msg += m_path += " already exists.";
+ m_responder->respond_error(msg);
+ } else if (m_error == PARENT_NOT_FOUND) {
+ string msg = "Unable to create patch: Parent ";
+ msg += m_path.parent() += " not found.";
+ m_responder->respond_error(msg);
+ } else if (m_error == INVALID_POLY) {
+ string msg = "Unable to create patch ";
+ msg.append(m_path).append(": ").append("Invalid polyphony respondered.");
+ m_responder->respond_error(msg);
+ } else {
+ m_responder->respond_error("Unable to load patch.");
+ }
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/CreatePatchEvent.h b/src/engine/events/CreatePatchEvent.h
new file mode 100644
index 00000000..507d03c7
--- /dev/null
+++ b/src/engine/events/CreatePatchEvent.h
@@ -0,0 +1,64 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef CREATEPATCHEVENT_H
+#define CREATEPATCHEVENT_H
+
+#include "util/Path.h"
+#include "QueuedEvent.h"
+#include <string>
+using std::string;
+
+template<typename T> class Array;
+template<typename T> class TreeNode;
+
+namespace Om {
+
+class Patch;
+class Node;
+class Plugin;
+
+
+/** Creates a new Patch.
+ *
+ * \ingroup engine
+ */
+class CreatePatchEvent : public QueuedEvent
+{
+public:
+ CreatePatchEvent(CountedPtr<Responder> responder, const string& path, int poly);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ enum ErrorType { NO_ERROR, OBJECT_EXISTS, PARENT_NOT_FOUND, INVALID_POLY };
+
+ Path m_path;
+ Patch* m_patch;
+ Patch* m_parent;
+ Array<Node*>* m_process_order;
+ TreeNode<Node*>* m_patch_treenode;
+ int m_poly;
+ ErrorType m_error;
+};
+
+
+} // namespace Om
+
+
+#endif // CREATEPATCHEVENT_H
diff --git a/src/engine/events/DSSIConfigureEvent.cpp b/src/engine/events/DSSIConfigureEvent.cpp
new file mode 100644
index 00000000..2ade4671
--- /dev/null
+++ b/src/engine/events/DSSIConfigureEvent.cpp
@@ -0,0 +1,73 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DSSIConfigureEvent.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Node.h"
+#include "ClientBroadcaster.h"
+#include "Plugin.h"
+#include "ObjectStore.h"
+
+namespace Om {
+
+
+DSSIConfigureEvent::DSSIConfigureEvent(CountedPtr<Responder> responder, const string& node_path, const string& key, const string& val)
+: QueuedEvent(responder),
+ m_node_path(node_path),
+ m_key(key),
+ m_val(val),
+ m_node(NULL)
+{
+}
+
+
+void
+DSSIConfigureEvent::pre_process()
+{
+ Node* node = om->object_store()->find_node(m_node_path);
+
+ if (node != NULL && node->plugin()->type() == Plugin::DSSI) {
+ m_node = (DSSIPlugin*)node;
+ m_node->configure(m_key, m_val);
+ }
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+DSSIConfigureEvent::execute(samplecount offset)
+{
+ // Nothing.
+}
+
+
+void
+DSSIConfigureEvent::post_process()
+{
+ if (m_node == NULL) {
+ cerr << "Unable to find DSSI node " << m_node_path << endl;
+ } else {
+ string key = "dssi-configure--";
+ key += m_key;
+ om->client_broadcaster()->send_metadata_update(m_node_path, key, m_val);
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/DSSIConfigureEvent.h b/src/engine/events/DSSIConfigureEvent.h
new file mode 100644
index 00000000..00b4a134
--- /dev/null
+++ b/src/engine/events/DSSIConfigureEvent.h
@@ -0,0 +1,49 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DSSICONFIGUREEVENT_H
+#define DSSICONFIGUREEVENT_H
+
+#include "QueuedEvent.h"
+#include "DSSIPlugin.h"
+
+namespace Om {
+
+
+/** Change of a 'configure' key/value pair for a DSSI plugin.
+ *
+ * \ingroup engine
+ */
+class DSSIConfigureEvent : public QueuedEvent
+{
+public:
+ DSSIConfigureEvent(CountedPtr<Responder> responder, const string& node_path, const string& key, const string& val);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_node_path;
+ string m_key;
+ string m_val;
+ DSSIPlugin* m_node;
+};
+
+
+} // namespace Om
+
+#endif // DSSICONFIGUREEVENT_H
diff --git a/src/engine/events/DSSIControlEvent.cpp b/src/engine/events/DSSIControlEvent.cpp
new file mode 100644
index 00000000..ea3e70ac
--- /dev/null
+++ b/src/engine/events/DSSIControlEvent.cpp
@@ -0,0 +1,68 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DSSIControlEvent.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Node.h"
+#include "Plugin.h"
+#include "ObjectStore.h"
+
+namespace Om {
+
+
+DSSIControlEvent::DSSIControlEvent(CountedPtr<Responder> responder, const string& node_path, int port_num, sample val)
+: QueuedEvent(responder),
+ m_node_path(node_path),
+ m_port_num(port_num),
+ m_val(val),
+ m_node(NULL)
+{
+}
+
+
+void
+DSSIControlEvent::pre_process()
+{
+ Node* node = om->object_store()->find_node(m_node_path);
+
+ if (node->plugin()->type() != Plugin::DSSI)
+ m_node = NULL;
+ else
+ m_node = (DSSIPlugin*)node;
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+DSSIControlEvent::execute(samplecount offset)
+{
+ if (m_node != NULL)
+ m_node->set_control(m_port_num, m_val);
+}
+
+
+void
+DSSIControlEvent::post_process()
+{
+ if (m_node == NULL)
+ std::cerr << "Unable to find DSSI node " << m_node_path << std::endl;
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/DSSIControlEvent.h b/src/engine/events/DSSIControlEvent.h
new file mode 100644
index 00000000..30a5279e
--- /dev/null
+++ b/src/engine/events/DSSIControlEvent.h
@@ -0,0 +1,51 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DSSICONTROLEVENT_H
+#define DSSICONTROLEVENT_H
+
+#include "QueuedEvent.h"
+#include "DSSIPlugin.h"
+
+namespace Om {
+
+
+/** A control change event for a DSSI plugin.
+ *
+ * This does essentially the same thing as a SetPortValueEvent.
+ *
+ * \ingroup engine
+ */
+class DSSIControlEvent : public QueuedEvent
+{
+public:
+ DSSIControlEvent(CountedPtr<Responder> responder, const string& node_path, int port_num, sample val);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_node_path;
+ int m_port_num;
+ float m_val;
+ DSSIPlugin* m_node;
+};
+
+
+} // namespace Om
+
+#endif // DSSICONTROLEVENT_H
diff --git a/src/engine/events/DSSIProgramEvent.cpp b/src/engine/events/DSSIProgramEvent.cpp
new file mode 100644
index 00000000..eb68ef77
--- /dev/null
+++ b/src/engine/events/DSSIProgramEvent.cpp
@@ -0,0 +1,77 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DSSIProgramEvent.h"
+#include <cstdio>
+#include <iostream>
+#include "Om.h"
+#include "OmApp.h"
+#include "Node.h"
+#include "ClientBroadcaster.h"
+#include "Plugin.h"
+#include "ObjectStore.h"
+using std::cout; using std::cerr; using std::endl;
+
+
+namespace Om {
+
+
+DSSIProgramEvent::DSSIProgramEvent(CountedPtr<Responder> responder, const string& node_path, int bank, int program)
+: QueuedEvent(responder),
+ m_node_path(node_path),
+ m_bank(bank),
+ m_program(program),
+ m_node(NULL)
+{
+}
+
+
+void
+DSSIProgramEvent::pre_process()
+{
+ Node* node = om->object_store()->find_node(m_node_path);
+
+ if (node != NULL && node->plugin()->type() == Plugin::DSSI)
+ m_node = (DSSIPlugin*)node;
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+DSSIProgramEvent::execute(samplecount offset)
+{
+ if (m_node != NULL)
+ m_node->program(m_bank, m_program);
+}
+
+
+void
+DSSIProgramEvent::post_process()
+{
+ if (m_node == NULL) {
+ cerr << "Unable to find DSSI node " << m_node_path << endl;
+ } else {
+ // sends program as metadata in the form bank/program
+ char* temp_buf = new char[16];
+ snprintf(temp_buf, 16, "%d/%d", m_bank, m_program);
+ om->client_broadcaster()->send_metadata_update(m_node_path, "dssi-program", temp_buf);
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/DSSIProgramEvent.h b/src/engine/events/DSSIProgramEvent.h
new file mode 100644
index 00000000..152f3cb1
--- /dev/null
+++ b/src/engine/events/DSSIProgramEvent.h
@@ -0,0 +1,49 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DSSIPROGRAMEVENT_H
+#define DSSIPROGRAMEVENT_H
+
+#include "QueuedEvent.h"
+#include "DSSIPlugin.h"
+
+namespace Om {
+
+
+/** A program change for a DSSI plugin.
+ *
+ * \ingroup engine
+ */
+class DSSIProgramEvent : public QueuedEvent
+{
+public:
+ DSSIProgramEvent(CountedPtr<Responder> responder, const string& node_path, int bank, int program);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_node_path;
+ int m_bank;
+ int m_program;
+ DSSIPlugin* m_node;
+};
+
+
+} // namespace Om
+
+#endif // DSSIPROGRAMEVENT_H
diff --git a/src/engine/events/DSSIUpdateEvent.cpp b/src/engine/events/DSSIUpdateEvent.cpp
new file mode 100644
index 00000000..5650dd63
--- /dev/null
+++ b/src/engine/events/DSSIUpdateEvent.cpp
@@ -0,0 +1,80 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DSSIUpdateEvent.h"
+#include <iostream>
+#include "Node.h"
+#include "ObjectStore.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "DSSIPlugin.h"
+#include "Plugin.h"
+
+using std::cerr; using std::endl;
+
+namespace Om {
+
+
+DSSIUpdateEvent::DSSIUpdateEvent(CountedPtr<Responder> responder, const string& path, const string& url)
+: QueuedEvent(responder),
+ m_path(path),
+ m_url(url),
+ m_node(NULL)
+{
+}
+
+
+void
+DSSIUpdateEvent::pre_process()
+{
+ Node* node = om->object_store()->find_node(m_path);
+
+ if (node == NULL || node->plugin()->type() != Plugin::DSSI) {
+ m_node = NULL;
+ QueuedEvent::pre_process();
+ return;
+ } else {
+ m_node = (DSSIPlugin*)node;
+ }
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+DSSIUpdateEvent::execute(samplecount offset)
+{
+ if (m_node != NULL) {
+ m_node->set_ui_url(m_url);
+ }
+
+ QueuedEvent::execute(offset);
+}
+
+
+void
+DSSIUpdateEvent::post_process()
+{
+ cerr << "DSSI update event: " << m_url << endl;
+
+ if (m_node != NULL) {
+ m_node->send_update();
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/DSSIUpdateEvent.h b/src/engine/events/DSSIUpdateEvent.h
new file mode 100644
index 00000000..cdd8851e
--- /dev/null
+++ b/src/engine/events/DSSIUpdateEvent.h
@@ -0,0 +1,54 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DSSIUPDATEEVENT_H
+#define DSSIUPDATEEVENT_H
+
+#include "QueuedEvent.h"
+#include <string>
+
+using std::string;
+
+namespace Om {
+
+class DSSIPlugin;
+
+
+/** A DSSI "update" responder for a DSSI plugin/node.
+ *
+ * This sends all information about the plugin to the UI (over OSC).
+ *
+ * \ingroup engine
+ */
+class DSSIUpdateEvent : public QueuedEvent
+{
+public:
+ DSSIUpdateEvent(CountedPtr<Responder> responder, const string& path, const string& url);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_path;
+ string m_url;
+ DSSIPlugin* m_node;
+};
+
+
+} // namespace Om
+
+#endif // DSSIUPDATEEVENT_H
diff --git a/src/engine/events/DeactivateEvent.cpp b/src/engine/events/DeactivateEvent.cpp
new file mode 100644
index 00000000..48bff55a
--- /dev/null
+++ b/src/engine/events/DeactivateEvent.cpp
@@ -0,0 +1,54 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DeactivateEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+
+namespace Om {
+
+
+DeactivateEvent::DeactivateEvent(CountedPtr<Responder> responder)
+: QueuedEvent(responder)
+{
+}
+
+
+void
+DeactivateEvent::pre_process()
+{
+ QueuedEvent::pre_process();
+}
+
+
+void
+DeactivateEvent::execute(samplecount offset)
+{
+ QueuedEvent::execute(offset);
+}
+
+
+void
+DeactivateEvent::post_process()
+{
+ m_responder->respond_ok();
+ om->deactivate();
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/DeactivateEvent.h b/src/engine/events/DeactivateEvent.h
new file mode 100644
index 00000000..8401f332
--- /dev/null
+++ b/src/engine/events/DeactivateEvent.h
@@ -0,0 +1,42 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DEACTIVATEEVENT_H
+#define DEACTIVATEEVENT_H
+
+#include "QueuedEvent.h"
+
+namespace Om {
+
+
+/** Deactivates the engine.
+ *
+ * \ingroup engine
+ */
+class DeactivateEvent : public QueuedEvent
+{
+public:
+ DeactivateEvent(CountedPtr<Responder> responder);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+};
+
+
+} // namespace Om
+
+#endif // DEACTIVATEEVENT_H
diff --git a/src/engine/events/DestroyEvent.cpp b/src/engine/events/DestroyEvent.cpp
new file mode 100644
index 00000000..3988195a
--- /dev/null
+++ b/src/engine/events/DestroyEvent.cpp
@@ -0,0 +1,168 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DestroyEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Patch.h"
+#include "Tree.h"
+#include "Node.h"
+#include "Plugin.h"
+#include "InternalNode.h"
+#include "DisconnectNodeEvent.h"
+#include "DisconnectPortEvent.h"
+#include "ClientBroadcaster.h"
+#include "Maid.h"
+#include "ObjectStore.h"
+#include "util/Path.h"
+#include "QueuedEventSource.h"
+#include "Port.h"
+
+namespace Om {
+
+
+DestroyEvent::DestroyEvent(CountedPtr<Responder> responder, const string& path, bool lock_mutex)
+: QueuedEvent(responder, true),
+ m_path(path),
+ m_node(NULL),
+ m_patch_listnode(NULL),
+ m_store_treenode(NULL),
+ m_process_order(NULL),
+ m_disconnect_event(NULL),
+ m_parent_disconnect_event(NULL)
+{
+}
+
+
+DestroyEvent::DestroyEvent(CountedPtr<Responder> responder, Node* node, bool lock_mutex)
+: QueuedEvent(responder, true),
+ m_path(node->path()),
+ m_node(node),
+ m_patch_listnode(NULL),
+ m_store_treenode(NULL),
+ m_process_order(NULL),
+ m_disconnect_event(NULL),
+ m_parent_disconnect_event(NULL)
+{
+}
+
+
+DestroyEvent::~DestroyEvent()
+{
+ delete m_disconnect_event;
+ delete m_parent_disconnect_event;
+}
+
+
+void
+DestroyEvent::pre_process()
+{
+ if (m_node == NULL) {
+ OmObject* const obj = om->object_store()->find_node(m_path);
+
+ if (obj != NULL && obj->as_node() != NULL)
+ m_node = obj->as_node();
+ }
+
+ if (m_node != NULL && m_path != "/") {
+ assert(m_node->parent_patch() != NULL);
+ m_patch_listnode = m_node->parent_patch()->remove_node(m_path.name());
+ if (m_patch_listnode != NULL) {
+ assert(m_patch_listnode->elem() == m_node);
+
+ m_node->remove_from_store();
+
+ if (m_node->providers()->size() != 0 || m_node->dependants()->size() != 0) {
+ m_disconnect_event = new DisconnectNodeEvent(m_node);
+ m_disconnect_event->pre_process();
+ }
+
+ // Create a recursive disconnect event for the parent port, if a bridge node
+ Port* parent_port = m_patch_listnode->elem()->as_port();
+ if (parent_port != NULL) { // Bridge node
+ m_parent_disconnect_event = new DisconnectPortEvent(parent_port);
+ m_parent_disconnect_event->pre_process();
+ }
+
+ if (m_node->parent_patch()->process()) {
+ m_process_order = m_node->parent_patch()->build_process_order();
+ // Remove node to be removed from the process order so it isn't executed by
+ // Patch::run and can safely be destroyed
+ //for (size_t i=0; i < m_process_order->size(); ++i)
+ // if (m_process_order->at(i) == m_node)
+ // m_process_order->at(i) = NULL; // ew, gap
+
+#ifdef DEBUG
+ // Be sure node is removed from process order, so it can be destroyed
+ for (size_t i=0; i < m_process_order->size(); ++i)
+ assert(m_process_order->at(i) != m_node);
+#endif
+ }
+ }
+ }
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+DestroyEvent::execute(samplecount offset)
+{
+ QueuedEvent::execute(offset);
+
+ if (m_patch_listnode != NULL) {
+ m_node->remove_from_patch();
+
+ if (m_disconnect_event != NULL)
+ m_disconnect_event->execute(offset);
+ if (m_parent_disconnect_event != NULL)
+ m_parent_disconnect_event->execute(offset);
+
+ if (m_node->parent_patch()->process_order() != NULL)
+ om->maid()->push(m_node->parent_patch()->process_order());
+ m_node->parent_patch()->process_order(m_process_order);
+ }
+}
+
+
+void
+DestroyEvent::post_process()
+{
+ m_source->unblock();
+
+ if (m_node == NULL) {
+ if (m_path == "/")
+ m_responder->respond_error("You can not destroy the root patch (/)");
+ else
+ m_responder->respond_error("Could not find node to destroy");
+ } else if (m_patch_listnode != NULL) {
+ m_node->deactivate();
+ m_responder->respond_ok();
+ if (m_disconnect_event != NULL)
+ m_disconnect_event->post_process();
+ if (m_parent_disconnect_event != NULL)
+ m_parent_disconnect_event->post_process();
+ om->client_broadcaster()->send_destroyed(m_path);
+ om->maid()->push(m_patch_listnode);
+ om->maid()->push(m_node);
+ } else {
+ m_responder->respond_error("Unable to destroy object");
+ }
+}
+
+
+} // namespace Om
diff --git a/src/engine/events/DestroyEvent.h b/src/engine/events/DestroyEvent.h
new file mode 100644
index 00000000..fc579bf4
--- /dev/null
+++ b/src/engine/events/DestroyEvent.h
@@ -0,0 +1,68 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DESTROYEVENT_H
+#define DESTROYEVENT_H
+
+#include "util/Path.h"
+#include "QueuedEvent.h"
+#include <string>
+
+using std::string;
+
+template<typename T> class Array;
+template<typename T> class ListNode;
+template<typename T> class TreeNode;
+
+namespace Om {
+
+class OmObject;
+class Patch;
+class Node;
+class Plugin;
+class DisconnectNodeEvent;
+class DisconnectPortEvent;
+
+
+/** An event to remove and delete a Node.
+ *
+ * \ingroup engine
+ */
+class DestroyEvent : public QueuedEvent
+{
+public:
+ DestroyEvent(CountedPtr<Responder> responder, const string& path, bool lock_mutex = true);
+ DestroyEvent(CountedPtr<Responder> responder, Node* node, bool lock_mutex = true);
+ ~DestroyEvent();
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ Path m_path;
+ Node* m_node;
+ ListNode<Node*>* m_patch_listnode;
+ TreeNode<OmObject*>* m_store_treenode;
+ Array<Node*>* m_process_order; // Patch's new process order
+ DisconnectNodeEvent* m_disconnect_event;
+ DisconnectPortEvent* m_parent_disconnect_event; // used for input/output nodes
+};
+
+
+} // namespace Om
+
+#endif // DESTROYEVENT_H
diff --git a/src/engine/events/DisablePatchEvent.cpp b/src/engine/events/DisablePatchEvent.cpp
new file mode 100644
index 00000000..a772e6e9
--- /dev/null
+++ b/src/engine/events/DisablePatchEvent.cpp
@@ -0,0 +1,70 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DisablePatchEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Patch.h"
+#include "ClientBroadcaster.h"
+#include "util.h"
+#include "ObjectStore.h"
+#include "Port.h"
+
+namespace Om {
+
+
+DisablePatchEvent::DisablePatchEvent(CountedPtr<Responder> responder, const string& patch_path)
+: QueuedEvent(responder),
+ m_patch_path(patch_path),
+ m_patch(NULL)
+{
+}
+
+
+void
+DisablePatchEvent::pre_process()
+{
+ m_patch = om->object_store()->find_patch(m_patch_path);
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+DisablePatchEvent::execute(samplecount offset)
+{
+ if (m_patch != NULL)
+ m_patch->process(false);
+
+ QueuedEvent::execute(offset);
+}
+
+
+void
+DisablePatchEvent::post_process()
+{
+ if (m_patch != NULL) {
+ m_responder->respond_ok();
+ om->client_broadcaster()->send_patch_disable(m_patch_path);
+ } else {
+ m_responder->respond_error(string("Patch ") + m_patch_path + " not found");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/DisablePatchEvent.h b/src/engine/events/DisablePatchEvent.h
new file mode 100644
index 00000000..f38f14af
--- /dev/null
+++ b/src/engine/events/DisablePatchEvent.h
@@ -0,0 +1,52 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DISABLEPATCHEVENT_H
+#define DISABLEPATCHEVENT_H
+
+#include <string>
+#include "QueuedEvent.h"
+
+using std::string;
+
+namespace Om {
+
+class Patch;
+
+
+/** Disables a Patch's DSP processing.
+ *
+ * \ingroup engine
+ */
+class DisablePatchEvent : public QueuedEvent
+{
+public:
+ DisablePatchEvent(CountedPtr<Responder> responder, const string& patch_path);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_patch_path;
+ Patch* m_patch;
+};
+
+
+} // namespace Om
+
+
+#endif // DISABLEPATCHEVENT_H
diff --git a/src/engine/events/DisconnectNodeEvent.cpp b/src/engine/events/DisconnectNodeEvent.cpp
new file mode 100644
index 00000000..17367dd4
--- /dev/null
+++ b/src/engine/events/DisconnectNodeEvent.cpp
@@ -0,0 +1,140 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DisconnectNodeEvent.h"
+#include <iostream>
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Maid.h"
+#include "List.h"
+#include "Node.h"
+#include "ConnectionBase.h"
+#include "DisconnectionEvent.h"
+#include "Port.h"
+#include "Array.h"
+#include "InputPort.h"
+#include "OutputPort.h"
+#include "Patch.h"
+#include "ClientBroadcaster.h"
+#include "util.h"
+#include "ObjectStore.h"
+#include "util/Path.h"
+
+using std::cerr; using std::endl;
+
+namespace Om {
+
+
+DisconnectNodeEvent::DisconnectNodeEvent(CountedPtr<Responder> responder, const string& node_path)
+: QueuedEvent(responder),
+ m_node_path(node_path),
+ m_patch(NULL),
+ m_node(NULL),
+ m_succeeded(true),
+ m_lookup(true)
+{
+}
+
+
+/** Internal version, disconnects parent port as well (in the case of InputNode, etc).
+ */
+DisconnectNodeEvent::DisconnectNodeEvent(Node* node)
+: QueuedEvent(),
+ m_node_path(""),
+ m_patch(node->parent_patch()),
+ m_node(node),
+ m_succeeded(true),
+ m_lookup(false)
+{
+}
+
+
+DisconnectNodeEvent::~DisconnectNodeEvent()
+{
+ for (List<DisconnectionEvent*>::iterator i = m_disconnection_events.begin(); i != m_disconnection_events.end(); ++i)
+ delete (*i);
+}
+
+
+void
+DisconnectNodeEvent::pre_process()
+{
+ typedef List<Connection*>::const_iterator ConnectionListIterator;
+
+ // cerr << "Preparing disconnection event...\n";
+
+ if (m_lookup) {
+ m_patch = om->object_store()->find_patch(m_node_path.parent());
+
+ if (m_patch == NULL) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ m_node = om->object_store()->find_node(m_node_path);
+
+ if (m_node == NULL) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+ }
+
+ Connection* c = NULL;
+ for (ConnectionListIterator i = m_patch->connections().begin(); i != m_patch->connections().end(); ++i) {
+ c = (*i);
+ if ((c->src_port()->parent_node() == m_node || c->dst_port()->parent_node() == m_node) && !c->pending_disconnection()) {
+ DisconnectionEvent* ev = new DisconnectionEvent(CountedPtr<Responder>(new Responder()), c->src_port(), c->dst_port());
+ ev->pre_process();
+ m_disconnection_events.push_back(new ListNode<DisconnectionEvent*>(ev));
+ c->pending_disconnection(true);
+ }
+ }
+
+ m_succeeded = true;
+ QueuedEvent::pre_process();
+}
+
+
+void
+DisconnectNodeEvent::execute(samplecount offset)
+{
+ if (m_succeeded) {
+ for (List<DisconnectionEvent*>::iterator i = m_disconnection_events.begin(); i != m_disconnection_events.end(); ++i)
+ (*i)->execute(offset);
+ }
+
+ QueuedEvent::execute(offset);
+}
+
+
+void
+DisconnectNodeEvent::post_process()
+{
+ if (m_succeeded) {
+ m_responder->respond_ok();
+ for (List<DisconnectionEvent*>::iterator i = m_disconnection_events.begin(); i != m_disconnection_events.end(); ++i)
+ (*i)->post_process();
+ } else {
+ m_responder->respond_error("Unable to disconnect all ports.");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/DisconnectNodeEvent.h b/src/engine/events/DisconnectNodeEvent.h
new file mode 100644
index 00000000..a82fbaec
--- /dev/null
+++ b/src/engine/events/DisconnectNodeEvent.h
@@ -0,0 +1,68 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DISCONNECTNODEEVENT_H
+#define DISCONNECTNODEEVENT_H
+
+#include <string>
+#include "util/Path.h"
+#include "QueuedEvent.h"
+#include "List.h"
+using std::string;
+
+namespace Om {
+
+class DisconnectionEvent;
+class Patch;
+class Node;
+class Connection;
+template <typename T> class ConnectionBase;
+class Port;
+template <typename T> class InputPort;
+template <typename T> class OutputPort;
+
+
+/** An event to disconnect all connections to a Node.
+ *
+ * \ingroup engine
+ */
+class DisconnectNodeEvent : public QueuedEvent
+{
+public:
+ DisconnectNodeEvent(CountedPtr<Responder> responder, const string& node_path);
+ DisconnectNodeEvent(Node* node);
+ ~DisconnectNodeEvent();
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ Path m_node_path;
+ Patch* m_patch;
+ Node* m_node;
+ List<DisconnectionEvent*> m_disconnection_events;
+
+ bool m_succeeded;
+ bool m_lookup;
+ bool m_disconnect_parent;
+};
+
+
+} // namespace Om
+
+
+#endif // DISCONNECTNODEEVENT_H
diff --git a/src/engine/events/DisconnectPortEvent.cpp b/src/engine/events/DisconnectPortEvent.cpp
new file mode 100644
index 00000000..a4c213d5
--- /dev/null
+++ b/src/engine/events/DisconnectPortEvent.cpp
@@ -0,0 +1,145 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DisconnectPortEvent.h"
+#include <iostream>
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Maid.h"
+#include "List.h"
+#include "Node.h"
+#include "Connection.h"
+#include "DisconnectionEvent.h"
+#include "Port.h"
+#include "Array.h"
+#include "InputPort.h"
+#include "OutputPort.h"
+#include "Patch.h"
+#include "ClientBroadcaster.h"
+#include "util.h"
+#include "ObjectStore.h"
+#include "util/Path.h"
+
+using std::cerr; using std::endl;
+
+namespace Om {
+
+
+DisconnectPortEvent::DisconnectPortEvent(CountedPtr<Responder> responder, const string& port_path)
+: QueuedEvent(responder),
+ m_port_path(port_path),
+ m_patch(NULL),
+ m_port(NULL),
+ m_process_order(NULL),
+ m_succeeded(true),
+ m_lookup(true)
+{
+}
+
+
+DisconnectPortEvent::DisconnectPortEvent(Port* port)
+: QueuedEvent(),
+ m_port_path(""),
+ m_patch((port->parent_node() == NULL) ? NULL : port->parent_node()->parent_patch()),
+ m_port(port),
+ m_process_order(NULL),
+ m_succeeded(true),
+ m_lookup(false)
+{
+ //cerr << "DisconnectPortEvent()\n";
+}
+
+
+DisconnectPortEvent::~DisconnectPortEvent()
+{
+ for (List<DisconnectionEvent*>::iterator i = m_disconnection_events.begin(); i != m_disconnection_events.end(); ++i)
+ delete (*i);
+}
+
+
+void
+DisconnectPortEvent::pre_process()
+{
+ // cerr << "Preparing disconnection event...\n";
+
+ if (m_lookup) {
+ m_patch = om->object_store()->find_patch(m_port_path.parent().parent());
+
+ if (m_patch == NULL) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ m_port = om->object_store()->find_port(m_port_path);
+
+ if (m_port == NULL) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+ }
+
+ if (m_patch == NULL) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ Connection* c = NULL;
+ for (List<Connection*>::const_iterator i = m_patch->connections().begin(); i != m_patch->connections().end(); ++i) {
+ c = (*i);
+ if ((c->src_port() == m_port || c->dst_port() == m_port) && !c->pending_disconnection()) {
+ DisconnectionEvent* ev = new DisconnectionEvent(CountedPtr<Responder>(new Responder()), c->src_port(), c->dst_port());
+ ev->pre_process();
+ m_disconnection_events.push_back(new ListNode<DisconnectionEvent*>(ev));
+ c->pending_disconnection(true);
+ }
+ }
+
+ m_succeeded = true;
+ QueuedEvent::pre_process();
+}
+
+
+void
+DisconnectPortEvent::execute(samplecount offset)
+{
+ if (m_succeeded) {
+ for (List<DisconnectionEvent*>::iterator i = m_disconnection_events.begin(); i != m_disconnection_events.end(); ++i)
+ (*i)->execute(offset);
+ }
+
+ QueuedEvent::execute(offset);
+}
+
+
+void
+DisconnectPortEvent::post_process()
+{
+ if (m_succeeded) {
+ m_responder->respond_ok();
+ for (List<DisconnectionEvent*>::iterator i = m_disconnection_events.begin(); i != m_disconnection_events.end(); ++i)
+ (*i)->post_process();
+ } else {
+ m_responder->respond_error("Unable to disconnect port.");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/DisconnectPortEvent.h b/src/engine/events/DisconnectPortEvent.h
new file mode 100644
index 00000000..e8de4120
--- /dev/null
+++ b/src/engine/events/DisconnectPortEvent.h
@@ -0,0 +1,70 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DISCONNECTPORTEVENT_H
+#define DISCONNECTPORTEVENT_H
+
+#include <string>
+#include "util/Path.h"
+#include "QueuedEvent.h"
+#include "List.h"
+
+template <typename T> class Array;
+
+namespace Om {
+
+
+class Patch;
+class Node;
+class Connection;
+class Port;
+class DisconnectionEvent;
+
+using std::string;
+
+
+/** An event to disconnect all connections to a Port.
+ *
+ * \ingroup engine
+ */
+class DisconnectPortEvent : public QueuedEvent
+{
+public:
+ DisconnectPortEvent(CountedPtr<Responder> responder, const string& port_path);
+ DisconnectPortEvent(Port* port);
+ ~DisconnectPortEvent();
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ Path m_port_path;
+ Patch* m_patch;
+ Port* m_port;
+ List<DisconnectionEvent*> m_disconnection_events;
+
+ Array<Node*>* m_process_order; // Patch's new process order
+
+ bool m_succeeded;
+ bool m_lookup;
+};
+
+
+} // namespace Om
+
+
+#endif // DISCONNECTPORTEVENT_H
diff --git a/src/engine/events/DisconnectionEvent.cpp b/src/engine/events/DisconnectionEvent.cpp
new file mode 100644
index 00000000..e7d06eab
--- /dev/null
+++ b/src/engine/events/DisconnectionEvent.cpp
@@ -0,0 +1,295 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DisconnectionEvent.h"
+#include <string>
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ConnectionBase.h"
+#include "InputPort.h"
+#include "OutputPort.h"
+#include "Patch.h"
+#include "ClientBroadcaster.h"
+#include "Port.h"
+#include "PortInfo.h"
+#include "Maid.h"
+#include "ObjectStore.h"
+#include "util/Path.h"
+
+using std::string;
+namespace Om {
+
+
+//// DisconnectionEvent ////
+
+
+DisconnectionEvent::DisconnectionEvent(CountedPtr<Responder> responder, const string& src_port_path, const string& dst_port_path)
+: QueuedEvent(responder),
+ m_src_port_path(src_port_path),
+ m_dst_port_path(dst_port_path),
+ m_patch(NULL),
+ m_src_port(NULL),
+ m_dst_port(NULL),
+ m_lookup(true),
+ m_typed_event(NULL),
+ m_error(NO_ERROR)
+{
+}
+
+
+DisconnectionEvent::DisconnectionEvent(CountedPtr<Responder> responder, Port* const src_port, Port* const dst_port)
+: QueuedEvent(responder),
+ m_src_port_path(src_port->path()),
+ m_dst_port_path(dst_port->path()),
+ m_patch(src_port->parent_node()->parent_patch()),
+ m_src_port(src_port),
+ m_dst_port(dst_port),
+ m_lookup(false),
+ m_typed_event(NULL),
+ m_error(NO_ERROR)
+{
+ assert(src_port->port_info()->is_output());
+ assert(dst_port->port_info()->is_input());
+ assert(src_port->port_info()->type() == dst_port->port_info()->type());
+ assert(src_port->parent_node()->parent_patch()
+ == dst_port->parent_node()->parent_patch());
+}
+
+DisconnectionEvent::~DisconnectionEvent()
+{
+ delete m_typed_event;
+}
+
+
+void
+DisconnectionEvent::pre_process()
+{
+ if (m_lookup) {
+ if (m_src_port_path.parent().parent() != m_dst_port_path.parent().parent()) {
+ m_error = PARENT_PATCH_DIFFERENT;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ /*m_patch = om->object_store()->find_patch(m_src_port_path.parent().parent());
+
+ if (m_patch == NULL) {
+ m_error = PORT_NOT_FOUND;
+ QueuedEvent::pre_process();
+ return;
+ }*/
+
+ Port* port1 = om->object_store()->find_port(m_src_port_path);
+ Port* port2 = om->object_store()->find_port(m_dst_port_path);
+
+ if (port1 == NULL || port2 == NULL) {
+ m_error = PORT_NOT_FOUND;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (port1->port_info()->type() != port2->port_info()->type()) {
+ m_error = TYPE_MISMATCH;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (port1->port_info()->is_output() && port2->port_info()->is_input()) {
+ m_src_port = port1;
+ m_dst_port = port2;
+ } else if (port2->port_info()->is_output() && port1->port_info()->is_input()) {
+ m_src_port = port2;
+ m_dst_port = port1;
+ } else {
+ m_error = TYPE_MISMATCH;
+ QueuedEvent::pre_process();
+ return;
+ }
+ }
+
+ // Create the typed event to actually do the work
+ const PortType type = m_src_port->port_info()->type();
+ if (type == AUDIO || type == CONTROL) {
+ m_typed_event = new TypedDisconnectionEvent<sample>(m_responder,
+ (OutputPort<sample>*)m_src_port, (InputPort<sample>*)m_dst_port);
+ } else if (type == MIDI) {
+ m_typed_event = new TypedDisconnectionEvent<MidiMessage>(m_responder,
+ (OutputPort<MidiMessage>*)m_src_port, (InputPort<MidiMessage>*)m_dst_port);
+ } else {
+ m_error = TYPE_MISMATCH;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ m_typed_event->pre_process();
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+DisconnectionEvent::execute(samplecount offset)
+{
+ QueuedEvent::execute(offset);
+
+ if (m_error == NO_ERROR)
+ m_typed_event->execute(offset);
+}
+
+
+void
+DisconnectionEvent::post_process()
+{
+ if (m_error == NO_ERROR) {
+ m_typed_event->post_process();
+ } else {
+ // FIXME: better error messages
+ string msg = "Unable to make connection ";
+ msg.append(m_src_port_path + " -> " + m_dst_port_path);
+ m_responder->respond_error(msg);
+ }
+}
+
+
+
+//// TypedDisconnectionEvent ////
+
+
+template <typename T>
+TypedDisconnectionEvent<T>::TypedDisconnectionEvent(CountedPtr<Responder> responder, OutputPort<T>* src_port, InputPort<T>* dst_port)
+: QueuedEvent(responder),
+ m_src_port(src_port),
+ m_dst_port(dst_port),
+ m_patch(NULL),
+ m_process_order(NULL),
+ m_succeeded(true)
+{
+ assert(src_port != NULL);
+ assert(dst_port != NULL);
+}
+
+template <typename T>
+TypedDisconnectionEvent<T>::~TypedDisconnectionEvent()
+{
+ // FIXME: haaaack, prevent a double delete
+ // this class is unusable by anything other than DisconnectionEvent because of this
+ //m_responder = NULL;
+}
+
+
+template <typename T>
+void
+TypedDisconnectionEvent<T>::pre_process()
+{
+ if (!m_dst_port->is_connected_to(m_src_port)) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ Node* const src_node = m_src_port->parent_node();
+ Node* const dst_node = m_dst_port->parent_node();
+
+ m_patch = src_node->parent_patch();
+
+ if (src_node == NULL || dst_node == NULL) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (src_node->parent() != m_patch || dst_node->parent() != m_patch) {
+ m_succeeded = false;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ bool removed = false;
+
+ for (List<Node*>::iterator i = dst_node->providers()->begin(); i != dst_node->providers()->end(); ++i)
+ if ((*i) == src_node) {
+ delete dst_node->providers()->remove(i);
+ removed = true;
+ break;
+ }
+ assert(removed);
+ removed = false;
+
+ for (List<Node*>::iterator i = src_node->dependants()->begin(); i != src_node->dependants()->end(); ++i)
+ if ((*i) == dst_node) {
+ delete src_node->dependants()->remove(i);
+ removed = true;
+ break;
+ }
+ assert(removed);
+
+ if (m_patch->process())
+ m_process_order = m_patch->build_process_order();
+
+ m_succeeded = true;
+ QueuedEvent::pre_process();
+}
+
+
+template <typename T>
+void
+TypedDisconnectionEvent<T>::execute(samplecount offset)
+{
+ if (m_succeeded) {
+
+ ListNode<ConnectionBase<T>*>* const port_connection
+ = m_dst_port->remove_connection(m_src_port);
+
+ if (port_connection != NULL) {
+ ListNode<Connection*>* const patch_connection
+ = m_patch->remove_connection(m_src_port, m_dst_port);
+
+ assert((Connection*)port_connection->elem() == patch_connection->elem());
+
+ // Clean up both the list node and the connection itself...
+ om->maid()->push(port_connection);
+ om->maid()->push(patch_connection);
+ om->maid()->push(port_connection->elem());
+
+ if (m_patch->process_order() != NULL)
+ om->maid()->push(m_patch->process_order());
+ m_patch->process_order(m_process_order);
+ } else {
+ m_succeeded = false; // Ports weren't connected
+ }
+ }
+ QueuedEvent::execute(offset);
+}
+
+
+template <typename T>
+void
+TypedDisconnectionEvent<T>::post_process()
+{
+ if (m_succeeded) {
+
+ m_responder->respond_ok();
+
+ om->client_broadcaster()->send_disconnection(m_src_port->path(), m_dst_port->path());
+ } else {
+ m_responder->respond_error("Unable to disconnect ports.");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/DisconnectionEvent.h b/src/engine/events/DisconnectionEvent.h
new file mode 100644
index 00000000..bbb70f3c
--- /dev/null
+++ b/src/engine/events/DisconnectionEvent.h
@@ -0,0 +1,106 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DISCONNECTIONEVENT_H
+#define DISCONNECTIONEVENT_H
+
+#include <string>
+#include "util/Path.h"
+#include "QueuedEvent.h"
+#include "util/types.h"
+using std::string;
+
+template <typename T> class ListNode;
+template <typename T> class Array;
+
+namespace Om {
+
+class Patch;
+class Node;
+class Connection;
+class MidiMessage;
+class Port;
+template <typename T> class ConnectionBase;
+template <typename T> class InputPort;
+template <typename T> class OutputPort;
+template <typename T> class TypedDisconnectionEvent; // helper, defined below
+
+
+/** Make a Connection between two Ports.
+ *
+ * \ingroup engine
+ */
+class DisconnectionEvent : public QueuedEvent
+{
+public:
+ DisconnectionEvent(CountedPtr<Responder> responder, const string& src_port_path, const string& dst_port_path);
+ DisconnectionEvent(CountedPtr<Responder> responder, Port* const src_port, Port* const dst_port);
+ ~DisconnectionEvent();
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+
+ enum ErrorType { NO_ERROR, PARENT_PATCH_DIFFERENT, PORT_NOT_FOUND, TYPE_MISMATCH };
+
+ Path m_src_port_path;
+ Path m_dst_port_path;
+
+ Patch* m_patch;
+ Port* m_src_port;
+ Port* m_dst_port;
+
+ bool m_lookup;
+ QueuedEvent* m_typed_event;
+
+ ErrorType m_error;
+};
+
+
+/** Templated DisconnectionEvent.
+ *
+ * Intended to be called from DisconnectionEvent so callers (ie OSCReceiver)
+ * can use DisconnectionEvent without knowing anything about types (which
+ * they can't, since all they have is Port paths).
+ */
+template <typename T>
+class TypedDisconnectionEvent : public QueuedEvent
+{
+public:
+ TypedDisconnectionEvent(CountedPtr<Responder> responder, OutputPort<T>* src_port, InputPort<T>* dst_port);
+ ~TypedDisconnectionEvent();
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ OutputPort<T>* m_src_port;
+ InputPort<T>* m_dst_port;
+
+ Patch* m_patch;
+ Array<Node*>* m_process_order; ///< New process order for Patch
+
+ bool m_succeeded;
+};
+
+
+
+} // namespace Om
+
+#endif // DISCONNECTIONEVENT_H
diff --git a/src/engine/events/EnablePatchEvent.cpp b/src/engine/events/EnablePatchEvent.cpp
new file mode 100644
index 00000000..6af3b844
--- /dev/null
+++ b/src/engine/events/EnablePatchEvent.cpp
@@ -0,0 +1,82 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "EnablePatchEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "Patch.h"
+#include "util.h"
+#include "ClientBroadcaster.h"
+#include "ObjectStore.h"
+
+namespace Om {
+
+
+EnablePatchEvent::EnablePatchEvent(CountedPtr<Responder> responder, const string& patch_path)
+: QueuedEvent(responder),
+ m_patch_path(patch_path),
+ m_patch(NULL),
+ m_process_order(NULL)
+{
+}
+
+
+void
+EnablePatchEvent::pre_process()
+{
+ m_patch = om->object_store()->find_patch(m_patch_path);
+
+ if (m_patch != NULL) {
+ /* Any event that requires a new process order will set the patch's
+ * process order to NULL if it is executed when the patch is not
+ * active. So, if the PO is NULL, calculate it here */
+ if (m_patch->process_order() == NULL)
+ m_process_order = m_patch->build_process_order();
+ }
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+EnablePatchEvent::execute(samplecount offset)
+{
+ if (m_patch != NULL) {
+ m_patch->process(true);
+
+ if (m_patch->process_order() == NULL)
+ m_patch->process_order(m_process_order);
+ }
+
+ QueuedEvent::execute(offset);
+}
+
+
+void
+EnablePatchEvent::post_process()
+{
+ if (m_patch != NULL) {
+ m_responder->respond_ok();
+ om->client_broadcaster()->send_patch_enable(m_patch_path);
+ } else {
+ m_responder->respond_error(string("Patch ") + m_patch_path + " not found");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/EnablePatchEvent.h b/src/engine/events/EnablePatchEvent.h
new file mode 100644
index 00000000..f3d22e69
--- /dev/null
+++ b/src/engine/events/EnablePatchEvent.h
@@ -0,0 +1,56 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ENABLEPATCHEVENT_H
+#define ENABLEPATCHEVENT_H
+
+#include <string>
+#include "QueuedEvent.h"
+
+using std::string;
+
+template <typename T> class Array;
+
+namespace Om {
+
+class Patch;
+class Node;
+
+
+/** Enables a patch's DSP processing.
+ *
+ * \ingroup engine
+ */
+class EnablePatchEvent : public QueuedEvent
+{
+public:
+ EnablePatchEvent(CountedPtr<Responder> responder, const string& patch_path);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_patch_path;
+ Patch* m_patch;
+ Array<Node*>* m_process_order; // Patch's new process order
+};
+
+
+} // namespace Om
+
+
+#endif // ENABLEPATCHEVENT_H
diff --git a/src/engine/events/Event.cpp b/src/engine/events/Event.cpp
new file mode 100644
index 00000000..7d590e76
--- /dev/null
+++ b/src/engine/events/Event.cpp
@@ -0,0 +1,48 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Event.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "AudioDriver.h"
+
+namespace Om {
+
+// It'd be nice if this was inlined..
+Event::Event(CountedPtr<Responder> responder)
+: m_responder(responder),
+ m_executed(false)
+{
+ m_time_stamp = om->audio_driver()->time_stamp();
+}
+
+
+/** Construct an event with no responder.
+ *
+ * For internal events only, attempting to access the responder will
+ * cause a NULL pointer dereference.
+ */
+Event::Event()
+: m_responder(NULL),
+ m_executed(false)
+{
+ m_time_stamp = om->audio_driver()->time_stamp();
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/Event.h b/src/engine/events/Event.h
new file mode 100644
index 00000000..a6d06f83
--- /dev/null
+++ b/src/engine/events/Event.h
@@ -0,0 +1,71 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EVENT_H
+#define EVENT_H
+
+#include <cassert>
+#include "util/CountedPtr.h"
+#include "util/types.h"
+#include "MaidObject.h"
+#include "Responder.h"
+
+namespace Om {
+
+
+
+/** Base class for all events (both realtime and QueuedEvent).
+ *
+ * This is for time-critical events like note ons. There is no non-realtime
+ * pre-execute method as in QueuedEvent's, any lookups etc need to be done in the
+ * realtime execute() method.
+ *
+ * QueuedEvent extends this class with a pre_process() method for any work that needs
+ * to be done before processing in the realtime audio thread.
+ *
+ * \ingroup engine
+ */
+class Event : public MaidObject
+{
+public:
+ virtual ~Event() {}
+
+ /** Execute event, MUST be realtime safe */
+ virtual void execute(samplecount offset) { assert(!m_executed); m_executed = true; }
+
+ /** Perform any actions after execution (ie send OSC response to client).
+ * No realtime requirement. */
+ virtual void post_process() {}
+
+ inline samplecount time_stamp() { return m_time_stamp; }
+
+protected:
+ Event(CountedPtr<Responder> responder);
+ Event();
+
+ // Prevent copies
+ Event(const Event&);
+ Event& operator=(const Event&);
+
+ CountedPtr<Responder> m_responder;
+ samplecount m_time_stamp;
+ bool m_executed;
+};
+
+
+} // namespace Om
+
+#endif // EVENT_H
diff --git a/src/engine/events/LashRestoreDoneEvent.h b/src/engine/events/LashRestoreDoneEvent.h
new file mode 100644
index 00000000..dfc5b120
--- /dev/null
+++ b/src/engine/events/LashRestoreDoneEvent.h
@@ -0,0 +1,54 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LASHRESTOREDONEEVENT_H
+#define LASHRESTOREDONEEVENT_H
+
+#include "QueuedEvent.h"
+#include "LashDriver.h"
+#include "util/types.h"
+
+#include <iostream>
+using std::cerr;
+
+namespace Om {
+
+class Port;
+
+
+/** Notification from a client that the LASH session is finished restoring.
+ *
+ * This is a bit of a hack, but needed to defer notifying LASH of our
+ * existance until all ports are created.
+ *
+ * \ingroup engine
+ */
+class LashRestoreDoneEvent : public QueuedEvent
+{
+public:
+ LashRestoreDoneEvent(CountedPtr<Responder> responder) : QueuedEvent(responder) {}
+
+ void post_process()
+ {
+ m_responder->respond_ok();
+ lash_driver->restore_finished();
+ }
+};
+
+
+} // namespace Om
+
+#endif // LASHRESTOREDONEEVENT_H
diff --git a/src/engine/events/LoadPluginsEvent.cpp b/src/engine/events/LoadPluginsEvent.cpp
new file mode 100644
index 00000000..656e9010
--- /dev/null
+++ b/src/engine/events/LoadPluginsEvent.cpp
@@ -0,0 +1,44 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "LoadPluginsEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "NodeFactory.h"
+
+namespace Om {
+
+
+LoadPluginsEvent::LoadPluginsEvent(CountedPtr<Responder> responder)
+: QueuedEvent(responder)
+{
+}
+
+
+void
+LoadPluginsEvent::post_process()
+{
+ // Why is this done here and not in pre_process()???
+ om->node_factory()->load_plugins();
+ m_responder->respond_ok();
+
+ //cerr << "Load plugins post finished\n";
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/LoadPluginsEvent.h b/src/engine/events/LoadPluginsEvent.h
new file mode 100644
index 00000000..b69dbb38
--- /dev/null
+++ b/src/engine/events/LoadPluginsEvent.h
@@ -0,0 +1,40 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LOADPLUGINSEVENT_H
+#define LOADPLUGINSEVENT_H
+
+#include "QueuedEvent.h"
+
+namespace Om {
+
+
+/** Loads all plugins into the internal plugin database (in NodeFactory).
+ *
+ * \ingroup engine
+ */
+class LoadPluginsEvent : public QueuedEvent
+{
+public:
+ LoadPluginsEvent(CountedPtr<Responder> responder);
+
+ void post_process();
+};
+
+
+} // namespace Om
+
+#endif // LOADPLUGINSEVENT_H
diff --git a/src/engine/events/Makefile.am b/src/engine/events/Makefile.am
new file mode 100644
index 00000000..9a882a4f
--- /dev/null
+++ b/src/engine/events/Makefile.am
@@ -0,0 +1,65 @@
+EXTRA_DIST = \
+ events/RegisterClientEvent.h \
+ events/RegisterClientEvent.cpp \
+ events/UnregisterClientEvent.h \
+ events/UnregisterClientEvent.cpp \
+ events/PingQueuedEvent.h \
+ events/ActivateEvent.h \
+ events/ActivateEvent.cpp \
+ events/DeactivateEvent.h \
+ events/DeactivateEvent.cpp \
+ events/SetPortValueEvent.h \
+ events/SetPortValueEvent.cpp \
+ events/SetPortValueQueuedEvent.h \
+ events/SetPortValueQueuedEvent.cpp \
+ events/NoteOnEvent.h \
+ events/NoteOnEvent.cpp \
+ events/NoteOffEvent.h \
+ events/NoteOffEvent.cpp \
+ events/AllNotesOffEvent.h \
+ events/AllNotesOffEvent.cpp \
+ events/ConnectionEvent.h \
+ events/ConnectionEvent.cpp \
+ events/DisconnectionEvent.h \
+ events/DisconnectionEvent.cpp \
+ events/DisconnectNodeEvent.h \
+ events/DisconnectNodeEvent.cpp \
+ events/DisconnectPortEvent.h \
+ events/DisconnectPortEvent.cpp \
+ events/DestroyEvent.h \
+ events/DestroyEvent.cpp \
+ events/AddNodeEvent.h \
+ events/AddNodeEvent.cpp \
+ events/SetMetadataEvent.h \
+ events/SetMetadataEvent.cpp \
+ events/RequestMetadataEvent.h \
+ events/RequestMetadataEvent.cpp \
+ events/RequestPortValueEvent.h \
+ events/RequestPortValueEvent.cpp \
+ events/RequestAllObjectsEvent.h \
+ events/RequestAllObjectsEvent.cpp \
+ events/RequestPluginsEvent.h \
+ events/RequestPluginsEvent.cpp \
+ events/CreatePatchEvent.h \
+ events/CreatePatchEvent.cpp \
+ events/LoadPluginsEvent.h \
+ events/LoadPluginsEvent.cpp \
+ events/EnablePatchEvent.h \
+ events/EnablePatchEvent.cpp \
+ events/DisablePatchEvent.h \
+ events/DisablePatchEvent.cpp \
+ events/ClearPatchEvent.h \
+ events/ClearPatchEvent.cpp \
+ events/RenameEvent.h \
+ events/RenameEvent.cpp \
+ events/MidiLearnEvent.h \
+ events/MidiLearnEvent.cpp \
+ DSSIConfigureEvent.cpp \
+ DSSIConfigureEvent.h \
+ DSSIControlEvent.cpp \
+ DSSIControlEvent.h \
+ DSSIProgramEvent.cpp \
+ DSSIProgramEvent.h \
+ DSSIUpdateEvent.cpp \
+ DSSIUpdateEvent.h
+
diff --git a/src/engine/events/MidiLearnEvent.cpp b/src/engine/events/MidiLearnEvent.cpp
new file mode 100644
index 00000000..63ad82fc
--- /dev/null
+++ b/src/engine/events/MidiLearnEvent.cpp
@@ -0,0 +1,88 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "MidiLearnEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ObjectStore.h"
+#include "Node.h"
+#include "MidiControlNode.h"
+#include "ClientBroadcaster.h"
+
+namespace Om {
+
+
+// MidiLearnResponseEvent
+
+void
+MidiLearnResponseEvent::post_process()
+{
+ om->client_broadcaster()->send_control_change(m_port_path, m_value);
+}
+
+
+
+// MidiLearnEvent
+
+MidiLearnEvent::MidiLearnEvent(CountedPtr<Responder> responder, const string& node_path)
+: QueuedEvent(responder),
+ m_node_path(node_path),
+ m_node(NULL),
+ m_response_event(NULL)
+{
+}
+
+
+void
+MidiLearnEvent::pre_process()
+{
+ m_node = om->object_store()->find_node(m_node_path);
+ m_response_event = new MidiLearnResponseEvent(m_node_path + "/Controller Number");
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+MidiLearnEvent::execute(samplecount offset)
+{
+ QueuedEvent::execute(offset);
+
+ // FIXME: this isn't very good at all.
+ if (m_node != NULL && m_node->plugin()->type() == Plugin::Internal
+ && m_node->plugin()->plug_label() == "midi_control_in") {
+ ((MidiControlNode*)m_node)->learn(m_response_event);
+ }
+}
+
+
+void
+MidiLearnEvent::post_process()
+{
+ if (m_node != NULL) {
+ m_responder->respond_ok();
+ } else {
+ string msg = "Did not find node '";
+ msg.append(m_node_path).append("' for MIDI learn.");
+ m_responder->respond_error(msg);
+ }
+}
+
+
+} // namespace Om
+
+
diff --git a/src/engine/events/MidiLearnEvent.h b/src/engine/events/MidiLearnEvent.h
new file mode 100644
index 00000000..793e675a
--- /dev/null
+++ b/src/engine/events/MidiLearnEvent.h
@@ -0,0 +1,84 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MIDILEARNEVENT_H
+#define MIDILEARNEVENT_H
+
+#include "QueuedEvent.h"
+#include "MidiControlNode.h"
+#include "util/types.h"
+#include <string>
+using std::string;
+
+namespace Om {
+
+class Node;
+class ControlChangeEvent;
+
+
+/** Response event for a MIDI learn.
+ *
+ * This is a trivial event that sends a control change in it's post_process
+ * method (used by MidiLearnEvent to notify clients when the learn happens)
+ */
+class MidiLearnResponseEvent : public Event
+{
+public:
+ MidiLearnResponseEvent(const string& port_path)
+ : Event(CountedPtr<Responder>(NULL)),
+ m_port_path(port_path),
+ m_value(0.0f)
+ {}
+
+ void set_value(sample val) { m_value = val; }
+ void post_process();
+
+private:
+ string m_port_path;
+ sample m_value;
+};
+
+
+
+/** A MIDI learn event.
+ *
+ * This creates a MidiLearnResponseEvent and passes it to the learning node, which
+ * will push it to the post-processor once the learn happens in order to reply
+ * to the client with the new port (learned controller) value.
+ *
+ * \ingroup engine
+ */
+class MidiLearnEvent : public QueuedEvent
+{
+public:
+ MidiLearnEvent(CountedPtr<Responder> responder, const string& node_path);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_node_path;
+ Node* m_node;
+
+ /// Event to respond with when learned
+ MidiLearnResponseEvent* m_response_event;
+};
+
+
+} // namespace Om
+
+#endif // MIDILEARNEVENT_H
diff --git a/src/engine/events/NoteOffEvent.cpp b/src/engine/events/NoteOffEvent.cpp
new file mode 100644
index 00000000..fde2e520
--- /dev/null
+++ b/src/engine/events/NoteOffEvent.cpp
@@ -0,0 +1,78 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "NoteOffEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ObjectStore.h"
+#include "Node.h"
+#include "MidiNoteNode.h"
+#include "MidiTriggerNode.h"
+
+namespace Om {
+
+
+/** Note off with patch explicitly passed - triggered by MIDI.
+ */
+NoteOffEvent::NoteOffEvent(CountedPtr<Responder> responder, Node* node, uchar note_num)
+: Event(responder),
+ m_node(node),
+ m_note_num(note_num)
+{
+}
+
+
+/** Note off event with lookup - triggered by OSC.
+ */
+NoteOffEvent::NoteOffEvent(CountedPtr<Responder> responder, const string& node_path, uchar note_num)
+: Event(responder),
+ m_node(NULL),
+ m_node_path(node_path),
+ m_note_num(note_num)
+{
+}
+
+
+void
+NoteOffEvent::execute(samplecount offset)
+{
+ if (m_node == NULL && m_node_path != "")
+ m_node = om->object_store()->find_node(m_node_path);
+
+ // FIXME: this isn't very good at all.
+ if (m_node != NULL && m_node->plugin()->type() == Plugin::Internal) {
+ if (m_node->plugin()->plug_label() == "note_in")
+ ((MidiNoteNode*)m_node)->note_off(m_note_num, offset);
+ else if (m_node->plugin()->plug_label() == "trigger_in")
+ ((MidiTriggerNode*)m_node)->note_off(m_note_num, offset);
+ }
+}
+
+
+void
+NoteOffEvent::post_process()
+{
+ if (m_node != NULL)
+ m_responder->respond_ok();
+ else
+ m_responder->respond_error("Did not find node for note_off");
+}
+
+
+} // namespace Om
+
+
diff --git a/src/engine/events/NoteOffEvent.h b/src/engine/events/NoteOffEvent.h
new file mode 100644
index 00000000..edd0b373
--- /dev/null
+++ b/src/engine/events/NoteOffEvent.h
@@ -0,0 +1,52 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NOTEOFFEVENT_H
+#define NOTEOFFEVENT_H
+
+#include "Event.h"
+#include "util/types.h"
+#include <string>
+using std::string;
+
+namespace Om {
+
+class Node;
+
+
+/** A note off event.
+ *
+ * \ingroup engine
+ */
+class NoteOffEvent : public Event
+{
+public:
+ NoteOffEvent(CountedPtr<Responder> responder, Node* node, uchar note_num);
+ NoteOffEvent(CountedPtr<Responder> responder, const string& node_path, uchar note_num);
+
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ Node* m_node;
+ string m_node_path;
+ uchar m_note_num;
+};
+
+
+} // namespace Om
+
+#endif // NOTEOFFEVENT_H
diff --git a/src/engine/events/NoteOnEvent.cpp b/src/engine/events/NoteOnEvent.cpp
new file mode 100644
index 00000000..9688af79
--- /dev/null
+++ b/src/engine/events/NoteOnEvent.cpp
@@ -0,0 +1,89 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "NoteOnEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ObjectStore.h"
+#include "Node.h"
+#include "MidiNoteNode.h"
+#include "MidiTriggerNode.h"
+#include "Plugin.h"
+
+namespace Om {
+
+
+/** Note on with Patch explicitly passed.
+ *
+ * Used to be triggered by MIDI. Not used anymore.
+ */
+NoteOnEvent::NoteOnEvent(CountedPtr<Responder> responder, Node* patch, uchar note_num, uchar velocity)
+: Event(responder),
+ m_node(patch),
+ m_note_num(note_num),
+ m_velocity(velocity),
+ m_is_osc_triggered(false)
+{
+}
+
+
+/** Note on with Node lookup.
+ *
+ * Triggered by OSC.
+ */
+NoteOnEvent::NoteOnEvent(CountedPtr<Responder> responder, const string& node_path, uchar note_num, uchar velocity)
+: Event(responder),
+ m_node(NULL),
+ m_node_path(node_path),
+ m_note_num(note_num),
+ m_velocity(velocity),
+ m_is_osc_triggered(true)
+{
+}
+
+
+void
+NoteOnEvent::execute(samplecount offset)
+{
+ // Lookup if neccessary
+ if (m_is_osc_triggered)
+ m_node = om->object_store()->find_node(m_node_path);
+
+ // FIXME: this isn't very good at all.
+ if (m_node != NULL && m_node->plugin()->type() == Plugin::Internal) {
+ if (m_node->plugin()->plug_label() == "note_in")
+ ((MidiNoteNode*)m_node)->note_on(m_note_num, m_velocity, offset);
+ else if (m_node->plugin()->plug_label() == "trigger_in")
+ ((MidiTriggerNode*)m_node)->note_on(m_note_num, m_velocity, offset);
+ }
+}
+
+
+void
+NoteOnEvent::post_process()
+{
+ if (m_is_osc_triggered) {
+ if (m_node != NULL)
+ m_responder->respond_ok();
+ else
+ m_responder->respond_error("Did not find node for note_on");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/NoteOnEvent.h b/src/engine/events/NoteOnEvent.h
new file mode 100644
index 00000000..1e09e450
--- /dev/null
+++ b/src/engine/events/NoteOnEvent.h
@@ -0,0 +1,54 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NOTEONEVENT_H
+#define NOTEONEVENT_H
+
+#include "Event.h"
+#include "util/types.h"
+#include <string>
+using std::string;
+
+namespace Om {
+
+class Node;
+
+
+/** A note on event.
+ *
+ * \ingroup engine
+ */
+class NoteOnEvent : public Event
+{
+public:
+ NoteOnEvent(CountedPtr<Responder> responder, Node* patch, uchar note_num, uchar velocity);
+ NoteOnEvent(CountedPtr<Responder> responder, const string& node_path, uchar note_num, uchar velocity);
+
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ Node* m_node;
+ string m_node_path;
+ uchar m_note_num;
+ uchar m_velocity;
+ bool m_is_osc_triggered;
+};
+
+
+} // namespace Om
+
+#endif // NOTEONEVENT_H
diff --git a/src/engine/events/PingQueuedEvent.h b/src/engine/events/PingQueuedEvent.h
new file mode 100644
index 00000000..cfba7058
--- /dev/null
+++ b/src/engine/events/PingQueuedEvent.h
@@ -0,0 +1,44 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PINGQUEUEDEVENT_H
+#define PINGQUEUEDEVENT_H
+
+#include "QueuedEvent.h"
+#include "util/types.h"
+#include "Responder.h"
+
+namespace Om {
+
+class Port;
+
+
+/** A "blocking" ping that travels through the event queue before responding.
+ *
+ * \ingroup engine
+ */
+class PingQueuedEvent : public QueuedEvent
+{
+public:
+ PingQueuedEvent(CountedPtr<Responder> responder) : QueuedEvent(responder) {}
+
+ void post_process() { m_responder->respond_ok(); }
+};
+
+
+} // namespace Om
+
+#endif // PINGQUEUEDEVENT_H
diff --git a/src/engine/events/QueuedEvent.h b/src/engine/events/QueuedEvent.h
new file mode 100644
index 00000000..16560aaa
--- /dev/null
+++ b/src/engine/events/QueuedEvent.h
@@ -0,0 +1,86 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef QUEUEDEVENT_H
+#define QUEUEDEVENT_H
+
+#include "Event.h"
+
+namespace Om {
+
+class Responder;
+class QueuedEventSource;
+
+
+/** An Event with a not-time-critical preprocessing stage.
+ *
+ * These events are events that aren't able to be executed immediately by the
+ * Jack thread (because they allocate memory or whatever). They are pushed
+ * on to the QueuedEventQueue where they are preprocessed then pushed on
+ * to the realtime Event Queue when they are ready.
+ *
+ * Lookups for these events should go in the pre_process() method, since they are
+ * not time critical and shouldn't waste time in the audio thread doing
+ * lookups they can do beforehand. (This applies for any expensive operation that
+ * could be done before the execute() method).
+ *
+ * \ingroup engine
+ */
+class QueuedEvent : public Event
+{
+public:
+ /** Process this event into a realtime-suitable event.
+ */
+ virtual void pre_process() {
+ assert(m_pre_processed == false);
+ m_pre_processed = true;
+ }
+
+ virtual void execute(samplecount offset) {
+ assert(m_pre_processed);
+ Event::execute(offset);
+ }
+
+ virtual void post_process() {}
+
+ /** If this event blocks the prepare phase of other slow events */
+ bool is_blocking() { return m_blocking; }
+
+ bool is_prepared() { return m_pre_processed; }
+
+protected:
+ // Prevent copies
+ QueuedEvent(const QueuedEvent& copy);
+ QueuedEvent& operator=(const QueuedEvent&);
+
+ QueuedEvent(CountedPtr<Responder> responder, bool blocking = false, QueuedEventSource* source=NULL)
+ : Event(responder), m_pre_processed(false), m_blocking(blocking), m_source(source)
+ {}
+
+ // NULL event base (for internal events)
+ QueuedEvent()
+ : Event(), m_pre_processed(false), m_blocking(false), m_source(NULL)
+ {}
+
+ bool m_pre_processed;
+ bool m_blocking;
+ QueuedEventSource* m_source;
+};
+
+
+} // namespace Om
+
+#endif // QUEUEDEVENT_H
diff --git a/src/engine/events/RegisterClientEvent.cpp b/src/engine/events/RegisterClientEvent.cpp
new file mode 100644
index 00000000..ca7dd1f6
--- /dev/null
+++ b/src/engine/events/RegisterClientEvent.cpp
@@ -0,0 +1,53 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "RegisterClientEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ClientBroadcaster.h"
+
+namespace Om {
+
+
+RegisterClientEvent::RegisterClientEvent(CountedPtr<Responder> responder,
+ ClientKey key,
+ CountedPtr<ClientInterface> client)
+: QueuedEvent(responder)
+, _key(key)
+, _client(client)
+{
+}
+
+
+void
+RegisterClientEvent::pre_process()
+{
+ om->client_broadcaster()->register_client(_key, _client);
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+RegisterClientEvent::post_process()
+{
+ m_responder->respond_ok();
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/RegisterClientEvent.h b/src/engine/events/RegisterClientEvent.h
new file mode 100644
index 00000000..f4b6b60f
--- /dev/null
+++ b/src/engine/events/RegisterClientEvent.h
@@ -0,0 +1,53 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef REGISTERCLIENTEVENT_H
+#define REGISTERCLIENTEVENT_H
+
+#include "QueuedEvent.h"
+#include "interface/ClientKey.h"
+#include "interface/ClientInterface.h"
+#include <string>
+using std::string;
+using Om::Shared::ClientInterface;
+using Om::Shared::ClientKey;
+
+namespace Om {
+
+
+/** Registers a new client with the OSC system, so it can receive updates.
+ *
+ * \ingroup engine
+ */
+class RegisterClientEvent : public QueuedEvent
+{
+public:
+ RegisterClientEvent(CountedPtr<Responder> responder,
+ ClientKey key,
+ CountedPtr<ClientInterface> client);
+
+ void pre_process();
+ void post_process();
+
+private:
+ ClientKey _key;
+ CountedPtr<ClientInterface> _client;
+};
+
+
+} // namespace Om
+
+#endif // REGISTERCLIENTEVENT_H
diff --git a/src/engine/events/RenameEvent.cpp b/src/engine/events/RenameEvent.cpp
new file mode 100644
index 00000000..e2e98dd0
--- /dev/null
+++ b/src/engine/events/RenameEvent.cpp
@@ -0,0 +1,123 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "RenameEvent.h"
+#include "Responder.h"
+#include "Patch.h"
+#include "Node.h"
+#include "Tree.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ClientBroadcaster.h"
+#include "util/Path.h"
+#include "ObjectStore.h"
+
+namespace Om {
+
+
+RenameEvent::RenameEvent(CountedPtr<Responder> responder, const string& path, const string& name)
+: QueuedEvent(responder),
+ m_old_path(path),
+ m_name(name),
+ m_new_path(m_old_path.parent().base_path() + name),
+ m_parent_patch(NULL),
+ m_store_treenode(NULL),
+ m_error(NO_ERROR)
+{
+ /*
+ if (m_old_path.parent() == "/")
+ m_new_path = string("/") + m_name;
+ else
+ m_new_path = m_old_path.parent() +"/"+ m_name;*/
+}
+
+
+RenameEvent::~RenameEvent()
+{
+}
+
+
+void
+RenameEvent::pre_process()
+{
+ if (m_name.find("/") != string::npos) {
+ m_error = INVALID_NAME;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (om->object_store()->find(m_new_path)) {
+ m_error = OBJECT_EXISTS;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ OmObject* obj = om->object_store()->find(m_old_path);
+
+ if (obj == NULL) {
+ m_error = OBJECT_NOT_FOUND;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ // Renaming only works for Nodes and Patches (which are Nodes)
+ if (obj->as_node() == NULL) {
+ m_error = OBJECT_NOT_RENAMABLE;
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ if (obj != NULL) {
+ obj->set_path(m_new_path);
+ assert(obj->path() == m_new_path);
+ }
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+RenameEvent::execute(samplecount offset)
+{
+ //cout << "Executing rename event...";
+ QueuedEvent::execute(offset);
+}
+
+
+void
+RenameEvent::post_process()
+{
+ string msg = "Unable to rename object - ";
+
+ if (m_error == NO_ERROR) {
+ m_responder->respond_ok();
+ om->client_broadcaster()->send_rename(m_old_path, m_new_path);
+ } else {
+ if (m_error == OBJECT_EXISTS)
+ msg.append("Object already exists at ").append(m_new_path);
+ else if (m_error == OBJECT_NOT_FOUND)
+ msg.append("Could not find object ").append(m_old_path);
+ else if (m_error == OBJECT_NOT_RENAMABLE)
+ msg.append(m_old_path).append(" is not renamable");
+ else if (m_error == INVALID_NAME)
+ msg.append(m_name).append(" is not a valid name");
+
+ m_responder->respond_error(msg);
+ }
+}
+
+
+} // namespace Om
diff --git a/src/engine/events/RenameEvent.h b/src/engine/events/RenameEvent.h
new file mode 100644
index 00000000..c1c9fe91
--- /dev/null
+++ b/src/engine/events/RenameEvent.h
@@ -0,0 +1,66 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef RENAMEEVENT_H
+#define RENAMEEVENT_H
+
+#include "QueuedEvent.h"
+#include "util/Path.h"
+#include <string>
+using std::string;
+
+template<typename T> class TreeNode;
+template<typename T> class ListNode;
+
+namespace Om {
+
+class OmObject;
+class Patch;
+class Node;
+class Plugin;
+class DisconnectNodeEvent;
+class DisconnectPortEvent;
+
+
+/** An event to change the name of an OmObject.
+ *
+ * \ingroup engine
+ */
+class RenameEvent : public QueuedEvent
+{
+public:
+ RenameEvent(CountedPtr<Responder> responder, const string& path, const string& name);
+ ~RenameEvent();
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ enum ErrorType { NO_ERROR, OBJECT_NOT_FOUND, OBJECT_EXISTS, OBJECT_NOT_RENAMABLE, INVALID_NAME };
+
+ Path m_old_path;
+ string m_name;
+ Path m_new_path;
+ Patch* m_parent_patch;
+ TreeNode<OmObject*>* m_store_treenode;
+ ErrorType m_error;
+};
+
+
+} // namespace Om
+
+#endif // RENAMEEVENT_H
diff --git a/src/engine/events/RequestAllObjectsEvent.cpp b/src/engine/events/RequestAllObjectsEvent.cpp
new file mode 100644
index 00000000..ef40a0de
--- /dev/null
+++ b/src/engine/events/RequestAllObjectsEvent.cpp
@@ -0,0 +1,55 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "RequestAllObjectsEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ObjectSender.h"
+
+namespace Om {
+
+
+RequestAllObjectsEvent::RequestAllObjectsEvent(CountedPtr<Responder> responder)
+: QueuedEvent(responder),
+ m_client(CountedPtr<ClientInterface>(NULL))
+{
+}
+
+
+void
+RequestAllObjectsEvent::pre_process()
+{
+ m_client = m_responder->find_client();
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+RequestAllObjectsEvent::post_process()
+{
+ if (m_client) {
+ m_responder->respond_ok();
+ ObjectSender::send_all(m_client.get());
+ } else {
+ m_responder->respond_error("Invalid URL");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/RequestAllObjectsEvent.h b/src/engine/events/RequestAllObjectsEvent.h
new file mode 100644
index 00000000..df63a577
--- /dev/null
+++ b/src/engine/events/RequestAllObjectsEvent.h
@@ -0,0 +1,50 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef REQUESTALLOBJECTSEVENT_H
+#define REQUESTALLOBJECTSEVENT_H
+
+#include <string>
+#include "QueuedEvent.h"
+using std::string;
+
+namespace Om {
+
+namespace Shared {
+ class ClientInterface;
+} using Shared::ClientInterface;
+
+
+/** A request from a client to send notification of all objects (ie refresh).
+ *
+ * \ingroup engine
+ */
+class RequestAllObjectsEvent : public QueuedEvent
+{
+public:
+ RequestAllObjectsEvent(CountedPtr<Responder> responder);
+
+ void pre_process();
+ void post_process();
+
+private:
+ CountedPtr<ClientInterface> m_client;
+};
+
+
+} // namespace Om
+
+#endif // REQUESTALLOBJECTSEVENT_H
diff --git a/src/engine/events/RequestMetadataEvent.cpp b/src/engine/events/RequestMetadataEvent.cpp
new file mode 100644
index 00000000..10e1007c
--- /dev/null
+++ b/src/engine/events/RequestMetadataEvent.cpp
@@ -0,0 +1,80 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "RequestMetadataEvent.h"
+#include <string>
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "OmObject.h"
+#include "ObjectStore.h"
+#include "interface/ClientInterface.h"
+#include "ClientBroadcaster.h"
+using std::string;
+
+namespace Om {
+
+
+RequestMetadataEvent::RequestMetadataEvent(CountedPtr<Responder> responder, const string& node_path, const string& key)
+: QueuedEvent(responder),
+ m_path(node_path),
+ m_key(key),
+ m_value(""),
+ m_object(NULL),
+ m_client(CountedPtr<ClientInterface>(NULL))
+{
+}
+
+
+void
+RequestMetadataEvent::pre_process()
+{
+ m_client = m_responder->find_client();
+
+ if (m_client) {
+ m_object = om->object_store()->find(m_path);
+ if (m_object == NULL) {
+ QueuedEvent::pre_process();
+ return;
+ }
+ }
+
+ m_value = m_object->get_metadata(m_key);
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+RequestMetadataEvent::post_process()
+{
+ if (m_client) {
+ if (m_value == "") {
+ string msg = "Unable to find object ";
+ msg += m_path;
+ m_responder->respond_error(msg);
+ } else {
+ m_responder->respond_ok();
+ m_client->metadata_update(m_path, m_key, m_value);
+ }
+ } else {
+ m_responder->respond_error("Unknown client");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/RequestMetadataEvent.h b/src/engine/events/RequestMetadataEvent.h
new file mode 100644
index 00000000..e4243eb3
--- /dev/null
+++ b/src/engine/events/RequestMetadataEvent.h
@@ -0,0 +1,56 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef REQUESTMETADATAEVENT_H
+#define REQUESTMETADATAEVENT_H
+
+#include <string>
+#include "QueuedEvent.h"
+
+using std::string;
+
+namespace Om {
+
+class OmObject;
+namespace Shared {
+ class ClientInterface;
+} using Shared::ClientInterface;
+
+
+/** A request from a client for a piece of metadata.
+ *
+ * \ingroup engine
+ */
+class RequestMetadataEvent : public QueuedEvent
+{
+public:
+ RequestMetadataEvent(CountedPtr<Responder> responder, const string& path, const string& key);
+
+ void pre_process();
+ void post_process();
+
+private:
+ string m_path;
+ string m_key;
+ string m_value;
+ OmObject* m_object;
+ CountedPtr<ClientInterface> m_client;
+};
+
+
+} // namespace Om
+
+#endif // REQUESTMETADATAEVENT_H
diff --git a/src/engine/events/RequestPluginsEvent.cpp b/src/engine/events/RequestPluginsEvent.cpp
new file mode 100644
index 00000000..89dbefd5
--- /dev/null
+++ b/src/engine/events/RequestPluginsEvent.cpp
@@ -0,0 +1,55 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "RequestPluginsEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ClientBroadcaster.h"
+
+namespace Om {
+
+
+RequestPluginsEvent::RequestPluginsEvent(CountedPtr<Responder> responder)
+: QueuedEvent(responder),
+ m_client(CountedPtr<ClientInterface>(NULL))
+{
+}
+
+
+void
+RequestPluginsEvent::pre_process()
+{
+ m_client = m_responder->find_client();
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+RequestPluginsEvent::post_process()
+{
+ if (m_client) {
+ om->client_broadcaster()->send_plugins_to(m_client.get());
+ m_responder->respond_ok();
+ } else {
+ m_responder->respond_error("Invalid URL");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/RequestPluginsEvent.h b/src/engine/events/RequestPluginsEvent.h
new file mode 100644
index 00000000..83447fb3
--- /dev/null
+++ b/src/engine/events/RequestPluginsEvent.h
@@ -0,0 +1,51 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef REQUESTPLUGINSEVENT_H
+#define REQUESTPLUGINSEVENT_H
+
+#include <string>
+#include "QueuedEvent.h"
+using std::string;
+
+namespace Om {
+
+class Responder;
+namespace Shared {
+ class ClientInterface;
+} using Shared::ClientInterface;
+
+
+/** A request from a client to send notification of all objects (ie refresh).
+ *
+ * \ingroup engine
+ */
+class RequestPluginsEvent : public QueuedEvent
+{
+public:
+ RequestPluginsEvent(CountedPtr<Responder> responder);
+
+ void pre_process();
+ void post_process();
+
+private:
+ CountedPtr<ClientInterface> m_client;
+};
+
+
+} // namespace Om
+
+#endif // REQUESTPLUGINSEVENT_H
diff --git a/src/engine/events/RequestPortValueEvent.cpp b/src/engine/events/RequestPortValueEvent.cpp
new file mode 100644
index 00000000..e4d3985e
--- /dev/null
+++ b/src/engine/events/RequestPortValueEvent.cpp
@@ -0,0 +1,81 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "RequestPortValueEvent.h"
+#include <string>
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "interface/ClientInterface.h"
+#include "PortBase.h"
+#include "PortInfo.h"
+#include "ObjectStore.h"
+#include "ClientBroadcaster.h"
+
+using std::string;
+
+namespace Om {
+
+
+RequestPortValueEvent::RequestPortValueEvent(CountedPtr<Responder> responder, const string& port_path)
+: QueuedEvent(responder),
+ m_port_path(port_path),
+ m_port(NULL),
+ m_value(0.0),
+ m_client(CountedPtr<ClientInterface>(NULL))
+{
+}
+
+
+void
+RequestPortValueEvent::pre_process()
+{
+ m_client = m_responder->find_client();
+ m_port = om->object_store()->find_port(m_port_path);
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+RequestPortValueEvent::execute(samplecount offset)
+{
+ if (m_port != NULL && m_port->port_info()->is_audio() || m_port->port_info()->is_control())
+ m_value = ((PortBase<sample>*)m_port)->buffer(0)->value_at(offset);
+ else
+ m_port = NULL; // triggers error response
+
+ QueuedEvent::execute(offset);
+}
+
+
+void
+RequestPortValueEvent::post_process()
+{
+ string msg;
+ if (m_port) {
+ m_responder->respond_error("Unable to find port for get_value responder.");
+ } else if (m_client) {
+ m_responder->respond_ok();
+ m_client->control_change(m_port_path, m_value);
+ } else {
+ m_responder->respond_error("Invalid URL");
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/RequestPortValueEvent.h b/src/engine/events/RequestPortValueEvent.h
new file mode 100644
index 00000000..d970ee9c
--- /dev/null
+++ b/src/engine/events/RequestPortValueEvent.h
@@ -0,0 +1,56 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef REQUESTPORTVALUEEVENT_H
+#define REQUESTPORTVALUEEVENT_H
+
+#include <string>
+#include "QueuedEvent.h"
+#include "util/types.h"
+
+using std::string;
+
+namespace Om {
+
+class Port;
+namespace Shared { class ClientInterface; }
+using Shared::ClientInterface;
+
+
+/** A request from a client to send the value of a port.
+ *
+ * \ingroup engine
+ */
+class RequestPortValueEvent : public QueuedEvent
+{
+public:
+ RequestPortValueEvent(CountedPtr<Responder> responder, const string& port_path);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_port_path;
+ Port* m_port;
+ sample m_value;
+ CountedPtr<ClientInterface> m_client;
+};
+
+
+} // namespace Om
+
+#endif // REQUESTPORTVALUEEVENT_H
diff --git a/src/engine/events/SetMetadataEvent.cpp b/src/engine/events/SetMetadataEvent.cpp
new file mode 100644
index 00000000..614f7ca9
--- /dev/null
+++ b/src/engine/events/SetMetadataEvent.cpp
@@ -0,0 +1,79 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "SetMetadataEvent.h"
+#include <string>
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ClientBroadcaster.h"
+#include "OmObject.h"
+#include "ObjectStore.h"
+
+using std::string;
+
+namespace Om {
+
+
+SetMetadataEvent::SetMetadataEvent(CountedPtr<Responder> responder, const string& path, const string& key, const string& value)
+: QueuedEvent(responder),
+ m_path(path),
+ m_key(key),
+ m_value(value),
+ m_object(NULL)
+{
+}
+
+
+void
+SetMetadataEvent::pre_process()
+{
+ m_object = om->object_store()->find(m_path);
+ if (m_object == NULL) {
+ QueuedEvent::pre_process();
+ return;
+ }
+
+ m_object->set_metadata(m_key, m_value);
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+SetMetadataEvent::execute(samplecount offset)
+{
+ // Do nothing
+
+ QueuedEvent::execute(offset);
+}
+
+
+void
+SetMetadataEvent::post_process()
+{
+ if (m_object == NULL) {
+ string msg = "Unable to find object ";
+ msg += m_path;
+ m_responder->respond_error(msg);
+ } else {
+ m_responder->respond_ok();
+ om->client_broadcaster()->send_metadata_update(m_path, m_key, m_value);
+ }
+}
+
+
+} // namespace Om
diff --git a/src/engine/events/SetMetadataEvent.h b/src/engine/events/SetMetadataEvent.h
new file mode 100644
index 00000000..ef471033
--- /dev/null
+++ b/src/engine/events/SetMetadataEvent.h
@@ -0,0 +1,53 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SETMETADATAEVENT_H
+#define SETMETADATAEVENT_H
+
+#include <string>
+#include "QueuedEvent.h"
+
+using std::string;
+
+namespace Om {
+
+class OmObject;
+
+
+/** An event to set a piece of metadata for an OmObject.
+ *
+ * \ingroup engine
+ */
+class SetMetadataEvent : public QueuedEvent
+{
+public:
+ SetMetadataEvent(CountedPtr<Responder> responder, const string& path, const string& key, const string& value);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ string m_path;
+ string m_key;
+ string m_value;
+ OmObject* m_object;
+};
+
+
+} // namespace Om
+
+#endif // SETMETADATAEVENT_H
diff --git a/src/engine/events/SetPortValueEvent.cpp b/src/engine/events/SetPortValueEvent.cpp
new file mode 100644
index 00000000..964cd9ca
--- /dev/null
+++ b/src/engine/events/SetPortValueEvent.cpp
@@ -0,0 +1,104 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "SetPortValueEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "PortBase.h"
+#include "PortInfo.h"
+#include "ClientBroadcaster.h"
+#include "Node.h"
+#include "ObjectStore.h"
+
+namespace Om {
+
+
+/** Voice-specific control setting
+ */
+SetPortValueEvent::SetPortValueEvent(CountedPtr<Responder> responder, size_t voice_num, const string& port_path, sample val)
+: Event(responder),
+ m_voice_num(voice_num),
+ m_port_path(port_path),
+ m_val(val),
+ m_port(NULL),
+ m_error(NO_ERROR)
+{
+}
+
+
+SetPortValueEvent::SetPortValueEvent(CountedPtr<Responder> responder, const string& port_path, sample val)
+: Event(responder),
+ m_voice_num(-1),
+ m_port_path(port_path),
+ m_val(val),
+ m_port(NULL),
+ m_error(NO_ERROR)
+{
+}
+
+
+void
+SetPortValueEvent::execute(samplecount offset)
+{
+ if (m_port == NULL)
+ m_port = om->object_store()->find_port(m_port_path);
+
+ if (m_port == NULL) {
+ m_error = PORT_NOT_FOUND;
+ } else if (!m_port->port_info()->is_audio() && !m_port->port_info()->is_control()) {
+ m_error = TYPE_MISMATCH;
+ } else {
+ if (m_voice_num == -1)
+ ((PortBase<sample>*)m_port)->set_value(m_val, offset);
+ else
+ ((PortBase<sample>*)m_port)->set_value(m_voice_num, m_val, offset);
+ //((PortBase<sample>*)m_port)->buffer(m_voice_num)->set(m_val, offset); // FIXME: check range
+ }
+}
+
+
+void
+SetPortValueEvent::post_process()
+{
+ if (m_error == NO_ERROR) {
+ assert(m_port != NULL);
+
+ m_responder->respond_ok();
+ om->client_broadcaster()->send_control_change(m_port_path, m_val);
+
+ // Send patch port control change, if this is a bridge port
+ Port* parent_port = m_port->parent_node()->as_port();
+ if (parent_port != NULL) {
+ assert(parent_port->port_info()->is_control() || parent_port->port_info()->is_audio());
+ om->client_broadcaster()->send_control_change(parent_port->path(), m_val);
+ }
+
+ } else if (m_error == PORT_NOT_FOUND) {
+ string msg = "Unable to find port ";
+ msg.append(m_port_path).append(" for set_port_value");
+ m_responder->respond_error(msg);
+
+ } else if (m_error == TYPE_MISMATCH) {
+ string msg = "Attempt to set ";
+ msg.append(m_port_path).append(" to incompatible type");
+ m_responder->respond_error(msg);
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/SetPortValueEvent.h b/src/engine/events/SetPortValueEvent.h
new file mode 100644
index 00000000..0a9614b9
--- /dev/null
+++ b/src/engine/events/SetPortValueEvent.h
@@ -0,0 +1,56 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SETPORTVALUEEVENT_H
+#define SETPORTVALUEEVENT_H
+
+#include <string>
+#include "Event.h"
+#include "util/types.h"
+using std::string;
+
+namespace Om {
+
+class Port;
+
+
+/** An event to change the value of a port.
+ *
+ * \ingroup engine
+ */
+class SetPortValueEvent : public Event
+{
+public:
+ SetPortValueEvent(CountedPtr<Responder> responder, const string& port_path, sample val);
+ SetPortValueEvent(CountedPtr<Responder> responder, size_t voice_num, const string& port_path, sample val);
+
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ enum ErrorType { NO_ERROR, PORT_NOT_FOUND, TYPE_MISMATCH };
+
+ int m_voice_num;
+ string m_port_path;
+ float m_val;
+ Port* m_port;
+ ErrorType m_error;
+};
+
+
+} // namespace Om
+
+#endif // SETPORTVALUEEVENT_H
diff --git a/src/engine/events/SetPortValueQueuedEvent.cpp b/src/engine/events/SetPortValueQueuedEvent.cpp
new file mode 100644
index 00000000..e73c0486
--- /dev/null
+++ b/src/engine/events/SetPortValueQueuedEvent.cpp
@@ -0,0 +1,116 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "SetPortValueQueuedEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "PortBase.h"
+#include "PortInfo.h"
+#include "ClientBroadcaster.h"
+#include "Plugin.h"
+#include "Node.h"
+#include "ObjectStore.h"
+
+namespace Om {
+
+
+/** Voice-specific control setting
+ */
+SetPortValueQueuedEvent::SetPortValueQueuedEvent(CountedPtr<Responder> responder, size_t voice_num, const string& port_path, sample val)
+: QueuedEvent(responder),
+ m_voice_num(voice_num),
+ m_port_path(port_path),
+ m_val(val),
+ m_port(NULL),
+ m_error(NO_ERROR)
+{
+}
+
+
+SetPortValueQueuedEvent::SetPortValueQueuedEvent(CountedPtr<Responder> responder, const string& port_path, sample val)
+: QueuedEvent(responder),
+ m_voice_num(-1),
+ m_port_path(port_path),
+ m_val(val),
+ m_port(NULL),
+ m_error(NO_ERROR)
+{
+}
+
+
+void
+SetPortValueQueuedEvent::pre_process()
+{
+ if (m_port == NULL)
+ m_port = om->object_store()->find_port(m_port_path);
+
+ if (m_port == NULL) {
+ m_error = PORT_NOT_FOUND;
+ } else if (!m_port->port_info()->is_audio() && !m_port->port_info()->is_control()) {
+ m_error = TYPE_MISMATCH;
+ }
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+SetPortValueQueuedEvent::execute(samplecount offset)
+{
+ QueuedEvent::execute(offset);
+
+ if (m_error == NO_ERROR) {
+ assert(m_port != NULL);
+ if (m_voice_num == -1)
+ ((PortBase<sample>*)m_port)->set_value(m_val, offset);
+ else
+ ((PortBase<sample>*)m_port)->buffer(m_voice_num)->set(m_val, offset); // FIXME: check range
+ }
+}
+
+
+void
+SetPortValueQueuedEvent::post_process()
+{
+ if (m_error == NO_ERROR) {
+ assert(m_port != NULL);
+
+ m_responder->respond_ok();
+ om->client_broadcaster()->send_control_change(m_port_path, m_val);
+
+ // Send patch port control change, if this is a bridge port
+ Port* parent_port = m_port->parent_node()->as_port();
+ if (parent_port != NULL) {
+ assert(parent_port->port_info()->is_control() || parent_port->port_info()->is_audio());
+ om->client_broadcaster()->send_control_change(parent_port->path(), m_val);
+ }
+
+ } else if (m_error == PORT_NOT_FOUND) {
+ string msg = "Unable to find port ";
+ msg.append(m_port_path).append(" for set_port_value_slow");
+ m_responder->respond_error(msg);
+
+ } else if (m_error == TYPE_MISMATCH) {
+ string msg = "Attempt to set ";
+ msg.append(m_port_path).append(" to incompatible type");
+ m_responder->respond_error(msg);
+ }
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/SetPortValueQueuedEvent.h b/src/engine/events/SetPortValueQueuedEvent.h
new file mode 100644
index 00000000..b92beacf
--- /dev/null
+++ b/src/engine/events/SetPortValueQueuedEvent.h
@@ -0,0 +1,57 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SETPORTVALUEQUEUEDEVENT_H
+#define SETPORTVALUEQUEUEDEVENT_H
+
+#include "QueuedEvent.h"
+#include "util/types.h"
+#include <string>
+using std::string;
+
+namespace Om {
+
+class Port;
+
+
+/** An event to change the value of a port.
+ *
+ * \ingroup engine
+ */
+class SetPortValueQueuedEvent : public QueuedEvent
+{
+public:
+ SetPortValueQueuedEvent(CountedPtr<Responder> responder, const string& port_path, sample val);
+ SetPortValueQueuedEvent(CountedPtr<Responder> responder, size_t voice_num, const string& port_path, sample val);
+
+ void pre_process();
+ void execute(samplecount offset);
+ void post_process();
+
+private:
+ enum ErrorType { NO_ERROR, PORT_NOT_FOUND, TYPE_MISMATCH };
+
+ int m_voice_num;
+ string m_port_path;
+ float m_val;
+ Port* m_port;
+ ErrorType m_error;
+};
+
+
+} // namespace Om
+
+#endif // SETPORTVALUEQUEUEDEVENT_H
diff --git a/src/engine/events/UnregisterClientEvent.cpp b/src/engine/events/UnregisterClientEvent.cpp
new file mode 100644
index 00000000..ef5a9979
--- /dev/null
+++ b/src/engine/events/UnregisterClientEvent.cpp
@@ -0,0 +1,45 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "UnregisterClientEvent.h"
+#include "Responder.h"
+#include "Om.h"
+#include "OmApp.h"
+#include "ClientBroadcaster.h"
+#include "interface/ClientInterface.h"
+
+namespace Om {
+
+
+UnregisterClientEvent::UnregisterClientEvent(CountedPtr<Responder> responder, ClientKey key)
+: QueuedEvent(responder)
+, _key(key)
+{
+}
+
+
+void
+UnregisterClientEvent::post_process()
+{
+ if (om->client_broadcaster()->unregister_client(_key))
+ m_responder->respond_ok();
+ else
+ m_responder->respond_error("Unable to unregister client");
+}
+
+
+} // namespace Om
+
diff --git a/src/engine/events/UnregisterClientEvent.h b/src/engine/events/UnregisterClientEvent.h
new file mode 100644
index 00000000..fdbdb314
--- /dev/null
+++ b/src/engine/events/UnregisterClientEvent.h
@@ -0,0 +1,53 @@
+/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
+ *
+ * Om 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.
+ *
+ * Om 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef UNREGISTERCLIENTEVENT_H
+#define UNREGISTERCLIENTEVENT_H
+
+#include "QueuedEvent.h"
+#include "interface/ClientKey.h"
+#include <string>
+using std::string;
+
+namespace Om {
+
+namespace Shared {
+ class ClientInterface;
+ class ClientKey;
+}
+using Shared::ClientInterface;
+using Shared::ClientKey;
+
+
+/** Unregisters an OSC client so it no longer receives notifications.
+ *
+ * \ingroup engine
+ */
+class UnregisterClientEvent : public QueuedEvent
+{
+public:
+ UnregisterClientEvent(CountedPtr<Responder> responder, ClientKey key);
+
+ void post_process();
+
+private:
+ ClientKey _key;
+};
+
+
+} // namespace Om
+
+#endif // UNREGISTERCLIENTEVENT_H