summaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-08-19 18:51:06 +0000
committerDavid Robillard <d@drobilla.net>2008-08-19 18:51:06 +0000
commite16206982d074e62956de00eeef611478f01c430 (patch)
tree388bc6e5ad9220cf9cdedf865a2d45856f418ae4 /src/libs
parent14764da12f3808da0c40b643ac8224716f060729 (diff)
downloadingen-e16206982d074e62956de00eeef611478f01c430.tar.gz
ingen-e16206982d074e62956de00eeef611478f01c430.tar.bz2
ingen-e16206982d074e62956de00eeef611478f01c430.zip
Preliminary connecting via HTTP in Gtk client.
Better handling of overflowed client event receive buffer. Store fixes, complain only once about orphans, don't request an orphan parent over and over. git-svn-id: http://svn.drobilla.net/lad/ingen@1447 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/client/ClientStore.cpp10
-rw-r--r--src/libs/client/HTTPClientReceiver.cpp97
-rw-r--r--src/libs/client/HTTPClientReceiver.hpp62
-rw-r--r--src/libs/client/HTTPEngineSender.cpp300
-rw-r--r--src/libs/client/HTTPEngineSender.hpp162
-rw-r--r--src/libs/client/Makefile.am16
-rw-r--r--src/libs/client/NodeModel.cpp12
-rw-r--r--src/libs/client/NodeModel.hpp9
-rw-r--r--src/libs/client/OSCClientReceiver.hpp14
-rw-r--r--src/libs/client/OSCEngineSender.hpp8
-rw-r--r--src/libs/client/ObjectModel.cpp33
-rw-r--r--src/libs/client/PortModel.cpp4
-rw-r--r--src/libs/client/PortModel.hpp2
-rw-r--r--src/libs/client/SigClientInterface.hpp2
-rw-r--r--src/libs/client/ThreadedSigClientInterface.cpp32
-rw-r--r--src/libs/client/ThreadedSigClientInterface.hpp13
-rw-r--r--src/libs/client/client.cpp24
-rw-r--r--src/libs/client/client.hpp2
-rw-r--r--src/libs/engine/OSCClientSender.hpp2
-rw-r--r--src/libs/engine/OSCEngineReceiver.cpp2
-rw-r--r--src/libs/engine/QueuedEngineInterface.hpp3
-rw-r--r--src/libs/gui/ConnectWindow.cpp26
-rw-r--r--src/libs/gui/ConnectWindow.hpp2
-rw-r--r--src/libs/gui/ControlPanel.cpp2
-rw-r--r--src/libs/gui/Makefile.am6
-rw-r--r--src/libs/gui/NodeControlWindow.cpp2
-rw-r--r--src/libs/gui/NodeMenu.cpp2
-rw-r--r--src/libs/gui/NodeModule.cpp8
-rw-r--r--src/libs/gui/NodePropertiesWindow.cpp2
-rw-r--r--src/libs/gui/PatchCanvas.cpp5
-rw-r--r--src/libs/gui/PatchTreeWindow.cpp2
-rw-r--r--src/libs/gui/PatchWindow.cpp4
-rw-r--r--src/libs/serialisation/Parser.cpp49
-rw-r--r--src/libs/serialisation/Parser.hpp8
-rw-r--r--src/libs/shared/OSCSender.cpp4
-rw-r--r--src/libs/shared/OSCSender.hpp2
36 files changed, 808 insertions, 125 deletions
diff --git a/src/libs/client/ClientStore.cpp b/src/libs/client/ClientStore.cpp
index 0597aa21..18582046 100644
--- a/src/libs/client/ClientStore.cpp
+++ b/src/libs/client/ClientStore.cpp
@@ -72,17 +72,15 @@ ClientStore::add_plugin_orphan(SharedPtr<NodeModel> node)
{
if (!_handle_orphans)
return;
- cerr << "WARNING: Node " << node->path() << " received, but plugin "
- << node->plugin_uri() << " unknown." << endl;
Raul::Table<string, list<SharedPtr<NodeModel> > >::iterator spawn
= _plugin_orphans.find(node->plugin_uri());
- _engine->request_plugin(node->plugin_uri());
-
if (spawn != _plugin_orphans.end()) {
spawn->second.push_back(node);
} else {
+ cerr << "WARNING: Orphans of plugin " << node->plugin_uri() << " received" << endl;
+ _engine->request_plugin(node->plugin_uri());
list<SharedPtr<NodeModel> > l;
l.push_back(node);
_plugin_orphans[node->plugin_uri()] = l;
@@ -108,7 +106,7 @@ ClientStore::resolve_plugin_orphans(SharedPtr<PluginModel> plugin)
for (list<SharedPtr<NodeModel> >::iterator i = spawn.begin();
i != spawn.end(); ++i) {
(*i)->_plugin = plugin;
- add_object(*i);
+ //add_object(*i);
}
}
}
@@ -248,7 +246,6 @@ ClientStore::add_object(SharedPtr<ObjectModel> object)
// one (with precedence to the new values).
iterator existing = find(object->path());
if (existing != end()) {
- cout << "WARNING: Object " << object->path() << " already exists in store" << endl;
PtrCast<ObjectModel>(existing->second)->set(object);
} else {
@@ -444,6 +441,7 @@ ClientStore::new_node(const string& path, const string& plugin_uri)
if (!plug) {
SharedPtr<NodeModel> n(new NodeModel(plugin_uri, path));
add_plugin_orphan(n);
+ add_object(n);
} else {
SharedPtr<NodeModel> n(new NodeModel(plug, path));
add_object(n);
diff --git a/src/libs/client/HTTPClientReceiver.cpp b/src/libs/client/HTTPClientReceiver.cpp
new file mode 100644
index 00000000..ece55ab2
--- /dev/null
+++ b/src/libs/client/HTTPClientReceiver.cpp
@@ -0,0 +1,97 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <list>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <sstream>
+#include <raul/AtomLiblo.hpp>
+#include "module/Module.hpp"
+#include "HTTPClientReceiver.hpp"
+
+using namespace std;
+using namespace Raul;
+
+namespace Ingen {
+namespace Client {
+
+
+HTTPClientReceiver::HTTPClientReceiver(
+ Shared::World* world,
+ const std::string& url,
+ SharedPtr<Shared::ClientInterface> target)
+ : _target(target)
+ , _world(world)
+ , _url(url)
+ , _session(NULL)
+{
+ start(false);
+}
+
+
+HTTPClientReceiver::~HTTPClientReceiver()
+{
+ stop();
+}
+
+
+void
+HTTPClientReceiver::message_callback(SoupSession* session, SoupMessage* msg, void* ptr)
+{
+ HTTPClientReceiver* me = (HTTPClientReceiver*)ptr;
+ cout << "RECEIVED ASYNC MESSAGE: " << msg->response_body->data << endl;
+ me->_target->response_ok(0);
+ me->_target->enable();
+ me->_parser->parse_string(me->_world, me->_target.get(), Glib::ustring(msg->response_body->data),
+ Glib::ustring("/"), Glib::ustring(""));
+}
+
+
+void
+HTTPClientReceiver::start(bool dump)
+{
+ Glib::Mutex::Lock lock(_world->rdf_world->mutex());
+ if (!_parser) {
+ if (!_world->serialisation_module)
+ _world->serialisation_module = Ingen::Shared::load_module("ingen_serialisation");
+
+ if (_world->serialisation_module) {
+ Parser* (*new_parser)() = NULL;
+ if (_world->serialisation_module->get_symbol("new_parser", (void*&)new_parser))
+ _parser = SharedPtr<Parser>(new_parser());
+ }
+ }
+ _session = soup_session_async_new();
+ SoupMessage* msg = soup_message_new("GET", _url.c_str());
+ soup_session_queue_message (_session, msg, message_callback, this);
+}
+
+
+void
+HTTPClientReceiver::stop()
+{
+ if (_session != NULL) {
+ //unregister_client();
+ soup_session_abort(_session);
+ _session = NULL;
+ }
+}
+
+
+} // namespace Client
+} // namespace Ingen
diff --git a/src/libs/client/HTTPClientReceiver.hpp b/src/libs/client/HTTPClientReceiver.hpp
new file mode 100644
index 00000000..bab55578
--- /dev/null
+++ b/src/libs/client/HTTPClientReceiver.hpp
@@ -0,0 +1,62 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef HTTPCLIENTRECEIVER_H
+#define HTTPCLIENTRECEIVER_H
+
+#include <cstdlib>
+#include <boost/utility.hpp>
+#include <libsoup/soup.h>
+#include "interface/ClientInterface.hpp"
+#include "serialisation/Parser.hpp"
+#include "redlandmm/World.hpp"
+#include "raul/Deletable.hpp"
+
+namespace Ingen {
+namespace Client {
+
+
+class HTTPClientReceiver : public boost::noncopyable, public Raul::Deletable
+{
+public:
+ HTTPClientReceiver(Shared::World* world,
+ const std::string& url,
+ SharedPtr<Shared::ClientInterface> target);
+
+ ~HTTPClientReceiver();
+
+ std::string uri() const { return _url; }
+
+ void start(bool dump);
+ void stop();
+
+private:
+ static void message_callback(SoupSession* session, SoupMessage* msg, void* ptr);
+
+ SharedPtr<Shared::ClientInterface> _target;
+
+ Shared::World* _world;
+ const std::string _url;
+ SoupSession* _session;
+ SharedPtr<Parser> _parser;
+};
+
+
+} // namespace Client
+} // namespace Ingen
+
+#endif // HTTPCLIENTRECEIVER_H
diff --git a/src/libs/client/HTTPEngineSender.cpp b/src/libs/client/HTTPEngineSender.cpp
new file mode 100644
index 00000000..882a4bc4
--- /dev/null
+++ b/src/libs/client/HTTPEngineSender.cpp
@@ -0,0 +1,300 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <iostream>
+#include <libsoup/soup.h>
+#include "HTTPEngineSender.hpp"
+
+using namespace std;
+
+namespace Ingen {
+namespace Client {
+
+
+HTTPEngineSender::HTTPEngineSender(const string& engine_url)
+ : _engine_url(engine_url)
+ , _id(0)
+ , _enabled(true)
+{
+ _session = soup_session_sync_new();
+}
+
+
+HTTPEngineSender::~HTTPEngineSender()
+{
+ soup_session_abort(_session);
+}
+
+
+void
+HTTPEngineSender::attach(int32_t ping_id, bool block)
+{
+ /*SoupMessage *msg;
+ msg = soup_message_new ("GET", _engine_url.c_str());
+ int status = soup_session_send_message (_session, msg);
+ cout << "STATUS: " << status << endl;
+ cout << "RESPONSE: " << msg->response_body->data << endl;*/
+}
+
+
+/* *** EngineInterface implementation below here *** */
+
+
+/** Register with the engine via HTTP.
+ *
+ * Note that this does not actually use 'key', since the engine creates
+ * it's own key for HTTP clients (namely the incoming URL), for NAT
+ * traversal. It is a parameter to remain compatible with EngineInterface.
+ */
+void
+HTTPEngineSender::register_client(ClientInterface* client)
+{
+
+}
+
+
+void
+HTTPEngineSender::unregister_client(const string& uri)
+{
+
+}
+
+
+// Engine commands
+void
+HTTPEngineSender::load_plugins()
+{
+
+}
+
+
+void
+HTTPEngineSender::activate()
+{
+
+}
+
+
+void
+HTTPEngineSender::deactivate()
+{
+
+}
+
+
+void
+HTTPEngineSender::quit()
+{
+
+}
+
+
+
+// Object commands
+
+void
+HTTPEngineSender::new_patch(const string& path,
+ uint32_t poly)
+{
+}
+
+
+void
+HTTPEngineSender::new_port(const string& path,
+ uint32_t index,
+ const string& data_type,
+ bool is_output)
+{
+}
+
+
+void
+HTTPEngineSender::new_node(const string& path,
+ const string& plugin_uri)
+{
+}
+
+
+/** Create a node using library name and plugin label (DEPRECATED).
+ *
+ * DO NOT USE THIS.
+ */
+void
+HTTPEngineSender::new_node_deprecated(const string& path,
+ const string& plugin_type,
+ const string& library_name,
+ const string& plugin_label)
+{
+}
+
+
+void
+HTTPEngineSender::rename(const string& old_path,
+ const string& new_name)
+{
+}
+
+
+void
+HTTPEngineSender::destroy(const string& path)
+{
+}
+
+
+void
+HTTPEngineSender::clear_patch(const string& patch_path)
+{
+}
+
+
+void
+HTTPEngineSender::connect(const string& src_port_path,
+ const string& dst_port_path)
+{
+}
+
+
+void
+HTTPEngineSender::disconnect(const string& src_port_path,
+ const string& dst_port_path)
+{
+}
+
+
+void
+HTTPEngineSender::disconnect_all(const string& parent_patch_path,
+ const string& node_path)
+{
+}
+
+
+void
+HTTPEngineSender::set_port_value(const string& port_path,
+ const Raul::Atom& value)
+{
+}
+
+
+void
+HTTPEngineSender::set_voice_value(const string& port_path,
+ uint32_t voice,
+ const Raul::Atom& value)
+{
+}
+
+
+void
+HTTPEngineSender::set_port_value_immediate(const string& port_path,
+ const Raul::Atom& value)
+{
+}
+
+
+void
+HTTPEngineSender::set_voice_value_immediate(const string& port_path,
+ uint32_t voice,
+ const Raul::Atom& value)
+{
+}
+
+
+void
+HTTPEngineSender::set_program(const string& node_path,
+ uint32_t bank,
+ uint32_t program)
+{
+}
+
+
+void
+HTTPEngineSender::midi_learn(const string& node_path)
+{
+}
+
+
+void
+HTTPEngineSender::set_variable(const string& obj_path,
+ const string& predicate,
+ const Raul::Atom& value)
+{
+}
+
+
+void
+HTTPEngineSender::set_property(const string& obj_path,
+ const string& predicate,
+ const Raul::Atom& value)
+{
+}
+
+
+
+// Requests //
+
+void
+HTTPEngineSender::ping()
+{
+}
+
+
+void
+HTTPEngineSender::request_plugin(const string& uri)
+{
+}
+
+
+void
+HTTPEngineSender::request_object(const string& path)
+{
+}
+
+
+void
+HTTPEngineSender::request_port_value(const string& port_path)
+{
+}
+
+
+void
+HTTPEngineSender::request_variable(const string& object_path, const string& key)
+{
+}
+
+
+void
+HTTPEngineSender::request_property(const string& object_path, const string& key)
+{
+}
+
+
+void
+HTTPEngineSender::request_plugins()
+{
+}
+
+
+void
+HTTPEngineSender::request_all_objects()
+{
+}
+
+
+
+} // namespace Client
+} // namespace Ingen
+
+
diff --git a/src/libs/client/HTTPEngineSender.hpp b/src/libs/client/HTTPEngineSender.hpp
new file mode 100644
index 00000000..f753eea3
--- /dev/null
+++ b/src/libs/client/HTTPEngineSender.hpp
@@ -0,0 +1,162 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef HTTPENGINESENDER_H
+#define HTTPENGINESENDER_H
+
+#include <inttypes.h>
+#include <string>
+#include <libsoup/soup.h>
+#include "interface/EngineInterface.hpp"
+using std::string;
+using Ingen::Shared::EngineInterface;
+using Ingen::Shared::ClientInterface;
+
+namespace Ingen {
+namespace Client {
+
+
+/* HTTP (via libsoup) interface to the engine.
+ *
+ * Clients can use this opaquely as an EngineInterface to control the engine
+ * over HTTP (whether over a network or not).
+ *
+ * \ingroup IngenClient
+ */
+class HTTPEngineSender : public EngineInterface {
+public:
+ HTTPEngineSender(const string& engine_url);
+ ~HTTPEngineSender();
+
+ string uri() const { return _engine_url; }
+
+ inline int32_t next_id()
+ { int32_t ret = (_id == -1) ? -1 : _id++; return ret; }
+
+ void set_next_response_id(int32_t id) { _id = id; }
+ void disable_responses() { _id = -1; }
+
+ void attach(int32_t ping_id, bool block);
+
+
+ /* *** EngineInterface implementation below here *** */
+
+ void enable() { _enabled = true; }
+ void disable() { _enabled = false; }
+
+ void bundle_begin() { transfer_begin(); }
+ void bundle_end() { transfer_end(); }
+
+ void transfer_begin();
+ void transfer_end();
+
+ // Client registration
+ void register_client(ClientInterface* client);
+ void unregister_client(const string& uri);
+
+ // Engine commands
+ void load_plugins();
+ void activate();
+ void deactivate();
+ void quit();
+
+ // Object commands
+
+ void new_patch(const string& path,
+ uint32_t poly);
+
+ void new_port(const string& path,
+ uint32_t index,
+ const string& data_type,
+ bool is_output);
+
+ void new_node(const string& path,
+ const string& plugin_uri);
+
+ void new_node_deprecated(const string& path,
+ const string& plugin_type,
+ const string& library_name,
+ const string& plugin_label);
+
+ void rename(const string& old_path,
+ const string& new_name);
+
+ void destroy(const string& path);
+
+ void clear_patch(const string& patch_path);
+
+ void connect(const string& src_port_path,
+ const string& dst_port_path);
+
+ void disconnect(const string& src_port_path,
+ const string& dst_port_path);
+
+ void disconnect_all(const string& parent_patch_path,
+ const string& node_path);
+
+ void set_port_value(const string& port_path,
+ const Raul::Atom& value);
+
+ void set_voice_value(const string& port_path,
+ uint32_t voice,
+ const Raul::Atom& value);
+
+ void set_port_value_immediate(const string& port_path,
+ const Raul::Atom& value);
+
+ void set_voice_value_immediate(const string& port_path,
+ uint32_t voice,
+ const Raul::Atom& value);
+
+ void set_program(const string& node_path,
+ uint32_t bank,
+ uint32_t program);
+
+ void midi_learn(const string& node_path);
+
+ void set_variable(const string& obj_path,
+ const string& predicate,
+ const Raul::Atom& value);
+
+ void set_property(const string& obj_path,
+ const string& predicate,
+ const Raul::Atom& value);
+
+ // Requests //
+ void ping();
+ void request_plugin(const string& uri);
+ void request_object(const string& path);
+ void request_port_value(const string& port_path);
+ void request_variable(const string& path, const string& key);
+ void request_property(const string& path, const string& key);
+ void request_plugins();
+ void request_all_objects();
+
+protected:
+ SoupSession* _session;
+ const string _engine_url;
+ int _client_port;
+ int32_t _id;
+ bool _enabled;
+};
+
+
+} // namespace Client
+} // namespace Ingen
+
+#endif // HTTPENGINESENDER_H
+
diff --git a/src/libs/client/Makefile.am b/src/libs/client/Makefile.am
index 88e2b393..76835de6 100644
--- a/src/libs/client/Makefile.am
+++ b/src/libs/client/Makefile.am
@@ -15,7 +15,8 @@ libingen_client_la_CXXFLAGS = \
@LXML2_CFLAGS@ \
@RAUL_CFLAGS@ \
@REDLANDMM_CFLAGS@ \
- @SLV2_CFLAGS@
+ @SLV2_CFLAGS@ \
+ @SOUP_CFLAGS@
libingen_client_la_LIBADD = \
../shared/libingen_shared.la \
@@ -25,14 +26,21 @@ libingen_client_la_LIBADD = \
@LXML2_LIBS@ \
@RAUL_LIBS@ \
@REDLANDMM_LIBS@ \
- @SLV2_LIBS@
+ @SLV2_LIBS@ \
+ @SOUP_LIBS@
libingen_client_la_SOURCES = \
$(top_srcdir)/ingen/src/common/interface/ClientInterface.hpp \
$(top_srcdir)/ingen/src/common/interface/EngineInterface.hpp \
+ ClientStore.cpp \
+ ClientStore.hpp \
ConnectionModel.hpp \
DeprecatedLoader.cpp \
DeprecatedLoader.hpp \
+ HTTPClientReceiver.cpp \
+ HTTPClientReceiver.hpp \
+ HTTPEngineSender.cpp \
+ HTTPEngineSender.hpp \
NodeModel.cpp \
NodeModel.hpp \
OSCClientReceiver.cpp \
@@ -45,13 +53,11 @@ libingen_client_la_SOURCES = \
PatchModel.hpp \
PluginModel.cpp \
PluginModel.hpp \
- PluginUI.hpp \
PluginUI.cpp \
+ PluginUI.hpp \
PortModel.cpp \
PortModel.hpp \
SigClientInterface.hpp \
- ClientStore.cpp \
- ClientStore.hpp \
ThreadedSigClientInterface.cpp \
ThreadedSigClientInterface.hpp \
client.cpp \
diff --git a/src/libs/client/NodeModel.cpp b/src/libs/client/NodeModel.cpp
index 02a0a678..ac0c8e68 100644
--- a/src/libs/client/NodeModel.cpp
+++ b/src/libs/client/NodeModel.cpp
@@ -69,7 +69,7 @@ void
NodeModel::remove_port(SharedPtr<PortModel> port)
{
// FIXME: slow
- for (PortModelList::iterator i = _ports.begin(); i != _ports.end(); ++i) {
+ for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) {
if ((*i) == port) {
_ports.erase(i);
break;
@@ -83,7 +83,7 @@ void
NodeModel::remove_port(const Path& port_path)
{
// FIXME: slow
- for (PortModelList::iterator i = _ports.begin(); i != _ports.end(); ++i) {
+ for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) {
if ((*i)->path() == port_path) {
_ports.erase(i);
break;
@@ -141,7 +141,7 @@ NodeModel::add_port(SharedPtr<PortModel> pm)
assert(pm->path().is_child_of(_path));
assert(pm->parent().get() == this);
- PortModelList::iterator existing = find(_ports.begin(), _ports.end(), pm);
+ Ports::iterator existing = find(_ports.begin(), _ports.end(), pm);
// Store should have handled this by merging the two
assert(existing == _ports.end());
@@ -155,7 +155,7 @@ SharedPtr<PortModel>
NodeModel::get_port(const string& port_name) const
{
assert(port_name.find("/") == string::npos);
- for (PortModelList::const_iterator i = _ports.begin(); i != _ports.end(); ++i)
+ for (Ports::const_iterator i = _ports.begin(); i != _ports.end(); ++i)
if ((*i)->path().name() == port_name)
return (*i);
return SharedPtr<PortModel>();
@@ -211,8 +211,10 @@ void
NodeModel::set(SharedPtr<ObjectModel> model)
{
SharedPtr<NodeModel> node = PtrCast<NodeModel>(model);
- if (node)
+ if (node) {
+ _plugin_uri = node->_plugin_uri;
_plugin = node->_plugin;
+ }
ObjectModel::set(model);
}
diff --git a/src/libs/client/NodeModel.hpp b/src/libs/client/NodeModel.hpp
index a4bcf4d8..03afc17c 100644
--- a/src/libs/client/NodeModel.hpp
+++ b/src/libs/client/NodeModel.hpp
@@ -50,6 +50,8 @@ class NodeModel : public ObjectModel, virtual public Ingen::Shared::Node
public:
NodeModel(const NodeModel& copy);
virtual ~NodeModel();
+
+ typedef vector<SharedPtr<PortModel> > Ports;
SharedPtr<PortModel> get_port(const string& port_name) const;
@@ -58,7 +60,7 @@ public:
const string& plugin_uri() const { return _plugin_uri; }
const Shared::Plugin* plugin() const { return _plugin.get(); }
uint32_t num_ports() const { return _ports.size(); }
- const PortModelList& ports() const { return _ports; }
+ const Ports& ports() const { return _ports; }
void port_value_range(SharedPtr<PortModel> port, float& min, float& max);
@@ -84,7 +86,7 @@ protected:
virtual void clear();
- PortModelList _ports; ///< List of ports (not a Table to preserve order)
+ Ports _ports; ///< Vector of ports (not a Table to preserve order)
string _plugin_uri; ///< Plugin URI (if PluginModel is unknown)
SharedPtr<PluginModel> _plugin; ///< The plugin this node is an instance of
uint32_t _num_values; ///< Size of _min_values and _max_values
@@ -93,9 +95,6 @@ protected:
};
-typedef Table<string, SharedPtr<NodeModel> > NodeModelMap;
-
-
} // namespace Client
} // namespace Ingen
diff --git a/src/libs/client/OSCClientReceiver.hpp b/src/libs/client/OSCClientReceiver.hpp
index f1d71dbb..ea5871b3 100644
--- a/src/libs/client/OSCClientReceiver.hpp
+++ b/src/libs/client/OSCClientReceiver.hpp
@@ -25,18 +25,13 @@
#include "raul/Deletable.hpp"
namespace Ingen {
-
-/** Client library */
namespace Client {
-//class NodeModel;
-
-/* Some boilerplate killing macros... */
+/** Arguments to a liblo handler */
#define LO_HANDLER_ARGS const char* path, const char* types, lo_arg** argv, int argc, lo_message msg
-/* Defines a static handler to be passed to lo_add_method, which is a trivial
- * wrapper around a non-static method that does the real work. Makes a whoole
- * lot of ugly boiler plate go away */
+/** Define a static handler to be passed to lo_add_method, which is a trivial
+ * wrapper around a non-static method that does the real work. */
#define LO_HANDLER(name) \
int _##name##_cb (LO_HANDLER_ARGS);\
inline static int name##_cb(LO_HANDLER_ARGS, void* osc_listener)\
@@ -62,6 +57,8 @@ public:
OSCClientReceiver(int listen_port, SharedPtr<Shared::ClientInterface> target);
~OSCClientReceiver();
+ std::string uri() const { return lo_server_thread_get_url(_st); }
+
void start(bool dump_osc);
void stop();
@@ -105,7 +102,6 @@ private:
} // namespace Client
-
} // namespace Ingen
#endif // OSCCLIENTRECEIVER_H
diff --git a/src/libs/client/OSCEngineSender.hpp b/src/libs/client/OSCEngineSender.hpp
index dbb7e8f5..4c92afdb 100644
--- a/src/libs/client/OSCEngineSender.hpp
+++ b/src/libs/client/OSCEngineSender.hpp
@@ -44,7 +44,7 @@ public:
~OSCEngineSender();
- string engine_url() { return _engine_url; }
+ std::string uri() const { return _engine_url; }
inline int32_t next_id()
{ int32_t ret = (_id == -1) ? -1 : _id++; return ret; }
@@ -148,9 +148,9 @@ public:
void request_all_objects();
protected:
- string _engine_url;
- int _client_port;
- int32_t _id;
+ const string _engine_url;
+ int _client_port;
+ int32_t _id;
};
diff --git a/src/libs/client/ObjectModel.cpp b/src/libs/client/ObjectModel.cpp
index e9a491a6..ede5f822 100644
--- a/src/libs/client/ObjectModel.cpp
+++ b/src/libs/client/ObjectModel.cpp
@@ -119,21 +119,26 @@ ObjectModel::polyphonic() const
* @a model as correct. The paths of the two models MUST be equal.
*/
void
-ObjectModel::set(SharedPtr<ObjectModel> model)
+ObjectModel::set(SharedPtr<ObjectModel> o)
{
- assert(_path == model->path());
-
- for (Variables::const_iterator other = model->variables().begin();
- other != model->variables().end(); ++other) {
-
- Variables::const_iterator mine = _variables.find(other->first);
-
- if (mine != _variables.end()) {
- cerr << "WARNING: " << _path << "Client/Server data mismatch: " << other->first << endl;
- }
-
- _variables[other->first] = other->second;
- signal_variable.emit(other->first, other->second);
+ assert(_path == o->path());
+ if (o->_parent)
+ _parent = o->_parent;
+
+ for (Variables::const_iterator v = o->variables().begin(); v != o->variables().end(); ++v) {
+ Variables::const_iterator mine = _variables.find(v->first);
+ if (mine != _variables.end())
+ cerr << "WARNING: " << _path << "Client/Server variable mismatch: " << v->first << endl;
+ _variables[v->first] = v->second;
+ signal_variable.emit(v->first, v->second);
+ }
+
+ for (Properties::const_iterator v = o->properties().begin(); v != o->properties().end(); ++v) {
+ Properties::const_iterator mine = _properties.find(v->first);
+ if (mine != _properties.end())
+ cerr << "WARNING: " << _path << "Client/Server property mismatch: " << v->first << endl;
+ _properties[v->first] = v->second;
+ signal_variable.emit(v->first, v->second);
}
}
diff --git a/src/libs/client/PortModel.cpp b/src/libs/client/PortModel.cpp
index fa3cb345..c18378db 100644
--- a/src/libs/client/PortModel.cpp
+++ b/src/libs/client/PortModel.cpp
@@ -51,7 +51,11 @@ PortModel::set(SharedPtr<ObjectModel> model)
{
SharedPtr<PortModel> port = PtrCast<PortModel>(model);
if (port) {
+ _index = port->_index;
+ _type = port->_type;
+ _direction = port->_direction;
_current_val = port->_current_val;
+ _connections = port->_connections;
signal_value_changed.emit(_current_val);
}
diff --git a/src/libs/client/PortModel.hpp b/src/libs/client/PortModel.hpp
index a86c9188..a7f52679 100644
--- a/src/libs/client/PortModel.hpp
+++ b/src/libs/client/PortModel.hpp
@@ -105,8 +105,6 @@ private:
size_t _connections;
};
-typedef vector<SharedPtr<PortModel> > PortModelList;
-
} // namespace Client
} // namespace Ingen
diff --git a/src/libs/client/SigClientInterface.hpp b/src/libs/client/SigClientInterface.hpp
index 32a0a43b..7ab32c12 100644
--- a/src/libs/client/SigClientInterface.hpp
+++ b/src/libs/client/SigClientInterface.hpp
@@ -41,6 +41,8 @@ class SigClientInterface : public Ingen::Shared::ClientInterface, public sigc::t
{
public:
SigClientInterface() : _enabled(true) {}
+
+ bool enabled() const { return _enabled; }
std::string uri() const { return "(internal)"; }
diff --git a/src/libs/client/ThreadedSigClientInterface.cpp b/src/libs/client/ThreadedSigClientInterface.cpp
index 3b7af80c..ef95133b 100644
--- a/src/libs/client/ThreadedSigClientInterface.cpp
+++ b/src/libs/client/ThreadedSigClientInterface.cpp
@@ -17,7 +17,8 @@
#include "ThreadedSigClientInterface.hpp"
#include <iostream>
-using std::cerr; using std::endl;
+
+using namespace std;
namespace Ingen {
namespace Client {
@@ -28,23 +29,19 @@ namespace Client {
void
ThreadedSigClientInterface::push_sig(Closure ev)
{
+ _attached = true;
if (!_enabled)
return;
bool success = false;
- bool first = true;
-
- // (Very) slow busy-wait if the queue is full
- // FIXME: Make this wait on a signal from process_sigs iff this happens
while (!success) {
- //printf("push %zu\n", _sigs.fill());
success = _sigs.push(ev);
if (!success) {
- if (first) {
- cerr << "[ThreadedSigClientInterface] WARNING: (Client) event queue full. Waiting to try again..." << endl;
- first = false;
- }
- usleep(200000); // 100 milliseconds (2* rate process_sigs is called)
+ cerr << "WARNING: Client event queue full. Waiting..." << endl;
+ _mutex.lock();
+ _cond.wait(_mutex);
+ _mutex.unlock();
+ cerr << "Queue drained, continuing" << endl;
}
}
}
@@ -58,18 +55,21 @@ ThreadedSigClientInterface::push_sig(Closure ev)
bool
ThreadedSigClientInterface::emit_signals()
{
- // Process a maximum of queue-size events, to prevent locking the GTK
+ // Process a limited number of events, to prevent locking the GTK
// thread indefinitely while processing continually arriving events
- const size_t limit = _sigs.capacity();
+
size_t num_processed = 0;
- while (!_sigs.empty() && num_processed++ < limit) {
- //printf("emit %zu\n", _sigs.fill());
+ while (!_sigs.empty() && num_processed++ < (_sigs.capacity() * 3 / 4)) {
Closure& ev = _sigs.front();
- _sigs.pop();
ev();
ev.disconnect();
+ _sigs.pop();
}
+ _mutex.lock();
+ _cond.broadcast();
+ _mutex.unlock();
+
return true;
}
diff --git a/src/libs/client/ThreadedSigClientInterface.hpp b/src/libs/client/ThreadedSigClientInterface.hpp
index b3a1b72c..3014c139 100644
--- a/src/libs/client/ThreadedSigClientInterface.hpp
+++ b/src/libs/client/ThreadedSigClientInterface.hpp
@@ -21,10 +21,12 @@
#include <inttypes.h>
#include <string>
#include <sigc++/sigc++.h>
+#include <glibmm/thread.h>
#include "interface/ClientInterface.hpp"
#include "SigClientInterface.hpp"
-#include <raul/SRSWQueue.hpp>
#include <raul/Atom.hpp>
+#include <raul/SRSWQueue.hpp>
+
using std::string;
/** Returns nothing and takes no parameters (because they have all been bound) */
@@ -65,12 +67,15 @@ public:
, port_activity_slot(signal_port_activity.make_slot())
, program_add_slot(signal_program_add.make_slot())
, program_remove_slot(signal_program_remove.make_slot())
- {}
+ {
+ }
virtual std::string uri() const { return "(internal)"; }
virtual void subscribe(Shared::EngineInterface* engine) { throw; }
+ bool enabled() const { return _attached; }
+
void bundle_begin()
{ push_sig(bundle_begin_slot); }
@@ -143,7 +148,11 @@ public:
private:
void push_sig(Closure ev);
+ Glib::Mutex _mutex;
+ Glib::Cond _cond;
+
Raul::SRSWQueue<Closure> _sigs;
+ bool _attached;
sigc::slot<void> bundle_begin_slot;
sigc::slot<void> bundle_end_slot;
diff --git a/src/libs/client/client.cpp b/src/libs/client/client.cpp
index 8b86e958..32380378 100644
--- a/src/libs/client/client.cpp
+++ b/src/libs/client/client.cpp
@@ -15,21 +15,37 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <iostream>
#include "client.hpp"
#include "OSCEngineSender.hpp"
+#include "HTTPEngineSender.hpp"
+
+using namespace std;
namespace Ingen {
namespace Client {
SharedPtr<Ingen::Shared::EngineInterface>
-new_osc_interface(const std::string& url)
+new_remote_interface(const std::string& url)
{
- OSCEngineSender* oes = new OSCEngineSender(url);
- oes->attach(rand(), true);
- return SharedPtr<Shared::EngineInterface>(oes);
+ const string scheme = url.substr(0, url.find(":"));
+ cout << "SCHEME: " << scheme << endl;
+ if (scheme == "osc.udp" || scheme == "osc.tcp") {
+ OSCEngineSender* oes = new OSCEngineSender(url);
+ oes->attach(rand(), true);
+ return SharedPtr<Shared::EngineInterface>(oes);
+ } else if (scheme == "http") {
+ HTTPEngineSender* hes = new HTTPEngineSender(url);
+ hes->attach(rand(), true);
+ return SharedPtr<Shared::EngineInterface>(hes);
+ } else {
+ cerr << "WARNING: Unknown URI scheme '" << scheme << "'" << endl;
+ return SharedPtr<Shared::EngineInterface>();
+ }
}
+
} // namespace Client
} // namespace Ingen
diff --git a/src/libs/client/client.hpp b/src/libs/client/client.hpp
index 931e4c45..82166da5 100644
--- a/src/libs/client/client.hpp
+++ b/src/libs/client/client.hpp
@@ -30,7 +30,7 @@ namespace Client {
extern "C" {
- SharedPtr<Shared::EngineInterface> new_osc_interface(const std::string& url);
+ SharedPtr<Shared::EngineInterface> new_remote_interface(const std::string& url);
SharedPtr<Shared::EngineInterface> new_queued_interface(SharedPtr<Ingen::Engine> engine);
}
diff --git a/src/libs/engine/OSCClientSender.hpp b/src/libs/engine/OSCClientSender.hpp
index d62dd1d3..c8c8418f 100644
--- a/src/libs/engine/OSCClientSender.hpp
+++ b/src/libs/engine/OSCClientSender.hpp
@@ -48,6 +48,8 @@ public:
virtual ~OSCClientSender()
{ lo_address_free(_address); }
+ bool enabled() const { return _enabled; }
+
void enable() { _enabled = true; }
void disable() { _enabled = false; }
diff --git a/src/libs/engine/OSCEngineReceiver.cpp b/src/libs/engine/OSCEngineReceiver.cpp
index a63c826b..f71bdb83 100644
--- a/src/libs/engine/OSCEngineReceiver.cpp
+++ b/src/libs/engine/OSCEngineReceiver.cpp
@@ -70,7 +70,7 @@ OSCEngineReceiver::OSCEngineReceiver(Engine& engine, size_t queue_size, uint16_t
}
// For debugging, print all incoming OSC messages
- lo_server_add_method(_server, NULL, NULL, generic_cb, NULL);
+ //lo_server_add_method(_server, NULL, NULL, generic_cb, NULL);
// Set response address for this message.
// It's important this is first and returns nonzero.
diff --git a/src/libs/engine/QueuedEngineInterface.hpp b/src/libs/engine/QueuedEngineInterface.hpp
index 17f8c75a..3aba9c7e 100644
--- a/src/libs/engine/QueuedEngineInterface.hpp
+++ b/src/libs/engine/QueuedEngineInterface.hpp
@@ -62,12 +62,13 @@ public:
QueuedEngineInterface(Engine& engine, size_t queued_size, size_t stamped_size);
virtual ~QueuedEngineInterface() {}
+ std::string uri() const { return "ingen:internal"; }
+
void set_next_response_id(int32_t id);
// Client registration
virtual void register_client(ClientInterface* client);
virtual void unregister_client(const string& uri);
-
// Engine commands
virtual void load_plugins();
diff --git a/src/libs/gui/ConnectWindow.cpp b/src/libs/gui/ConnectWindow.cpp
index 03f8408a..eb095af5 100644
--- a/src/libs/gui/ConnectWindow.cpp
+++ b/src/libs/gui/ConnectWindow.cpp
@@ -29,6 +29,7 @@
#include "engine/Engine.hpp"
#include "engine/QueuedEngineInterface.hpp"
#include "client/OSCClientReceiver.hpp"
+#include "client/HTTPClientReceiver.hpp"
#include "client/OSCEngineSender.hpp"
#include "client/ThreadedSigClientInterface.hpp"
#include "client/ClientStore.hpp"
@@ -143,7 +144,9 @@ ConnectWindow::set_connecting_widget_states()
void
ConnectWindow::connect(bool existing)
{
- assert(!_attached);
+ if (_attached)
+ _attached = false;
+
assert(!App::instance().client());
_connect_stage = 0;
@@ -153,15 +156,22 @@ ConnectWindow::connect(bool existing)
if (_mode == CONNECT_REMOTE) {
if (!existing) {
- const string url = (_widgets_loaded ? _url_entry->get_text() : "osc.udp://localhost:16180");
+ const string url = (_widgets_loaded ? (string)_url_entry->get_text() : world->engine->uri());
world->engine = SharedPtr<EngineInterface>(new OSCEngineSender(url));
}
-
- // FIXME: static args
+
SharedPtr<ThreadedSigClientInterface> tsci(new ThreadedSigClientInterface(1024));
- SharedPtr<OSCClientReceiver> client(new OSCClientReceiver(16181, tsci));
- App::instance().attach(tsci, client);
+ SharedPtr<Raul::Deletable> client;
+
+ const string& uri = world->engine->uri();
+ const string& scheme = uri.substr(0, uri.find(":"));
+ if (scheme == "osc.udp" || scheme == "osc.tcp")
+ client = SharedPtr<OSCClientReceiver>(new OSCClientReceiver(16181, tsci)); // FIXME: port
+ else if (scheme == "http")
+ client = SharedPtr<HTTPClientReceiver>(new HTTPClientReceiver(world, uri, tsci));
+ App::instance().attach(tsci, client);
+
Glib::signal_timeout().connect(
sigc::mem_fun(App::instance(), &App::gtk_main_iteration), 40, G_PRIORITY_DEFAULT);
@@ -377,7 +387,7 @@ ConnectWindow::gtk_callback()
assert(App::instance().client());
App::instance().client()->signal_response_ok.connect(
- sigc::mem_fun(this, &ConnectWindow::response_ok_received));
+ sigc::mem_fun(this, &ConnectWindow::on_response));
_ping_id = abs(rand()) / 2 * 2; // avoid -1
App::instance().engine()->set_next_response_id(_ping_id);
@@ -391,7 +401,7 @@ ConnectWindow::gtk_callback()
++_connect_stage;
} else if (_connect_stage == 1) {
- if (_attached) {
+ if (_attached || App::instance().client()->enabled()) {
App::instance().engine()->activate();
++_connect_stage;
} else {
diff --git a/src/libs/gui/ConnectWindow.hpp b/src/libs/gui/ConnectWindow.hpp
index 8410783d..fb75d4b2 100644
--- a/src/libs/gui/ConnectWindow.hpp
+++ b/src/libs/gui/ConnectWindow.hpp
@@ -53,7 +53,7 @@ public:
void set_connected_to(SharedPtr<Shared::EngineInterface> engine);
void start(Ingen::Shared::World* world);
- void response_ok_received(int32_t id) { if (id == _ping_id) _attached = true; }
+ void on_response(int32_t id) { _attached = true; }
private:
enum Mode { CONNECT_REMOTE, LAUNCH_REMOTE, INTERNAL };
diff --git a/src/libs/gui/ControlPanel.cpp b/src/libs/gui/ControlPanel.cpp
index 84f1163a..032f5758 100644
--- a/src/libs/gui/ControlPanel.cpp
+++ b/src/libs/gui/ControlPanel.cpp
@@ -69,7 +69,7 @@ ControlPanel::init(SharedPtr<NodeModel> node, uint32_t poly)
_voice_control_box->hide();
}
- for (PortModelList::const_iterator i = node->ports().begin(); i != node->ports().end(); ++i) {
+ for (NodeModel::Ports::const_iterator i = node->ports().begin(); i != node->ports().end(); ++i) {
add_port(*i);
}
diff --git a/src/libs/gui/Makefile.am b/src/libs/gui/Makefile.am
index fa956fca..48063d35 100644
--- a/src/libs/gui/Makefile.am
+++ b/src/libs/gui/Makefile.am
@@ -23,7 +23,8 @@ libingen_gui_la_CXXFLAGS = \
@LIBLO_CFLAGS@ \
@REDLANDMM_CFLAGS@ \
@RAUL_CFLAGS@ \
- @SLV2_CFLAGS@
+ @SLV2_CFLAGS@ \
+ @SOUP_CFLAGS@
libingen_gui_la_LDFLAGS = -no-undefined -module -avoid-version
@@ -40,7 +41,8 @@ libingen_gui_la_LIBADD = \
@LIBLO_LIBS@ \
@REDLANDMM_LIBS@ \
@RAUL_LIBS@ \
- @SLV2_LIBS@
+ @SLV2_LIBS@ \
+ @SOUP_LIBS@
libingen_gui_la_SOURCES = \
gui.hpp \
diff --git a/src/libs/gui/NodeControlWindow.cpp b/src/libs/gui/NodeControlWindow.cpp
index 95a07b2b..293d28f5 100644
--- a/src/libs/gui/NodeControlWindow.cpp
+++ b/src/libs/gui/NodeControlWindow.cpp
@@ -114,7 +114,7 @@ NodeControlWindow::resize()
void
NodeControlWindow::on_show()
{
- for (PortModelList::const_iterator i = _node->ports().begin();
+ for (NodeModel::Ports::const_iterator i = _node->ports().begin();
i != _node->ports().end(); ++i)
if ((*i)->type().is_control() && (*i)->is_input())
App::instance().engine()->request_port_value((*i)->path());
diff --git a/src/libs/gui/NodeMenu.cpp b/src/libs/gui/NodeMenu.cpp
index 05139540..529eb52c 100644
--- a/src/libs/gui/NodeMenu.cpp
+++ b/src/libs/gui/NodeMenu.cpp
@@ -141,7 +141,7 @@ bool
NodeMenu::has_control_inputs()
{
const NodeModel* const nm = (NodeModel*)_object.get();
- for (PortModelList::const_iterator i = nm->ports().begin(); i != nm->ports().end(); ++i)
+ for (NodeModel::Ports::const_iterator i = nm->ports().begin(); i != nm->ports().end(); ++i)
if ((*i)->is_input() && (*i)->type().is_control())
return true;
diff --git a/src/libs/gui/NodeModule.cpp b/src/libs/gui/NodeModule.cpp
index 21415be9..b3898b94 100644
--- a/src/libs/gui/NodeModule.cpp
+++ b/src/libs/gui/NodeModule.cpp
@@ -90,7 +90,7 @@ NodeModule::create(boost::shared_ptr<PatchCanvas> canvas, SharedPtr<NodeModel> n
for (GraphObject::Variables::const_iterator m = node->variables().begin(); m != node->variables().end(); ++m)
ret->set_variable(m->first, m->second);
- for (PortModelList::const_iterator p = node->ports().begin(); p != node->ports().end(); ++p) {
+ for (NodeModel::Ports::const_iterator p = node->ports().begin(); p != node->ports().end(); ++p) {
ret->add_port(*p, false);
}
@@ -151,7 +151,7 @@ NodeModule::embed_gui(bool embed)
if (_gui_widget) {
_gui_widget->show_all();
- for (PortModelList::const_iterator p = _node->ports().begin();
+ for (NodeModel::Ports::const_iterator p = _node->ports().begin();
p != _node->ports().end(); ++p)
if ((*p)->type().is_control() && (*p)->is_output())
App::instance().engine()->set_property((*p)->path(), "ingen:broadcast", true);
@@ -162,7 +162,7 @@ NodeModule::embed_gui(bool embed)
FlowCanvas::Module::embed(NULL);
_plugin_ui.reset();
- for (PortModelList::const_iterator p = _node->ports().begin(); p != _node->ports().end(); ++p)
+ for (NodeModel::Ports::const_iterator p = _node->ports().begin(); p != _node->ports().end(); ++p)
if ((*p)->type().is_control() && (*p)->is_output())
App::instance().engine()->set_property((*p)->path(), "ingen:broadcast", false);
}
@@ -262,7 +262,7 @@ void
NodeModule::initialise_gui_values()
{
uint32_t index=0;
- for (PortModelList::const_iterator p = _node->ports().begin(); p != _node->ports().end(); ++p) {
+ for (NodeModel::Ports::const_iterator p = _node->ports().begin(); p != _node->ports().end(); ++p) {
if ((*p)->type().is_control())
value_changed(index, (*p)->value());
++index;
diff --git a/src/libs/gui/NodePropertiesWindow.cpp b/src/libs/gui/NodePropertiesWindow.cpp
index 9848d872..ae2c23b5 100644
--- a/src/libs/gui/NodePropertiesWindow.cpp
+++ b/src/libs/gui/NodePropertiesWindow.cpp
@@ -53,8 +53,6 @@ NodePropertiesWindow::set_node(SharedPtr<NodeModel> node_model)
_node_polyphonic_toggle->set_active(node_model->polyphonic());
const PluginModel* pm = dynamic_cast<const PluginModel*>(node_model->plugin());
- assert(pm);
-
if (pm) {
_plugin_type_label->set_text(pm->type_uri());
_plugin_uri_label->set_text(pm->uri());
diff --git a/src/libs/gui/PatchCanvas.cpp b/src/libs/gui/PatchCanvas.cpp
index f527041b..5d064124 100644
--- a/src/libs/gui/PatchCanvas.cpp
+++ b/src/libs/gui/PatchCanvas.cpp
@@ -269,7 +269,7 @@ PatchCanvas::build()
}
// Create pseudo modules for ports (ports on this canvas, not on our module)
- for (PortModelList::const_iterator i = _patch->ports().begin();
+ for (NodeModel::Ports::const_iterator i = _patch->ports().begin();
i != _patch->ports().end(); ++i) {
add_port(*i);
}
@@ -590,8 +590,7 @@ PatchCanvas::paste()
clipboard.new_patch("/", _patch->poly());
ClashAvoider avoider(*App::instance().store().get(), _patch->path(), clipboard, &clipboard);
- parser->parse_string(App::instance().world(), &avoider, str, "/",
- boost::optional<Glib::ustring>(), (Glib::ustring)_patch->path());
+ parser->parse_string(App::instance().world(), &avoider, str, "/", _patch->path());
for (Store::iterator i = clipboard.begin(); i != clipboard.end(); ++i) {
cout << "************ OBJECT: " << i->first << endl;
diff --git a/src/libs/gui/PatchTreeWindow.cpp b/src/libs/gui/PatchTreeWindow.cpp
index ee831cb3..87393cec 100644
--- a/src/libs/gui/PatchTreeWindow.cpp
+++ b/src/libs/gui/PatchTreeWindow.cpp
@@ -89,7 +89,7 @@ PatchTreeWindow::add_patch(SharedPtr<PatchModel> pm)
Gtk::TreeModel::Row row = *iter;
if (pm->path() == "/") {
SharedPtr<OSCEngineSender> osc_sender = PtrCast<OSCEngineSender>(App::instance().engine());
- string root_name = osc_sender ? osc_sender->engine_url() : "Internal";
+ string root_name = osc_sender ? osc_sender->uri() : "Internal";
// Hack off trailing '/' if it's there (ugly)
//if (root_name.substr(root_name.length()-1,1) == "/")
// root_name = root_name.substr(0, root_name.length()-1);
diff --git a/src/libs/gui/PatchWindow.cpp b/src/libs/gui/PatchWindow.cpp
index 125adeea..01f74436 100644
--- a/src/libs/gui/PatchWindow.cpp
+++ b/src/libs/gui/PatchWindow.cpp
@@ -210,7 +210,7 @@ PatchWindow::set_patch(SharedPtr<PatchModel> patch, SharedPtr<PatchView> view)
_menu_view_control_window->property_sensitive() = false;
- for (PortModelList::const_iterator p = patch->ports().begin();
+ for (NodeModel::Ports::const_iterator p = patch->ports().begin();
p != patch->ports().end(); ++p) {
if ((*p)->type().is_control() && (*p)->is_input()) {
_menu_view_control_window->property_sensitive() = true;
@@ -257,7 +257,7 @@ PatchWindow::patch_port_removed(SharedPtr<PortModel> port)
bool found_control = false;
- for (PortModelList::const_iterator i = _patch->ports().begin(); i != _patch->ports().end(); ++i) {
+ for (NodeModel::Ports::const_iterator i = _patch->ports().begin(); i != _patch->ports().end(); ++i) {
if ((*i)->type().is_control() && (*i)->is_input()) {
found_control = true;
break;
diff --git a/src/libs/serialisation/Parser.cpp b/src/libs/serialisation/Parser.cpp
index cc8b4e4b..79c69648 100644
--- a/src/libs/serialisation/Parser.cpp
+++ b/src/libs/serialisation/Parser.cpp
@@ -63,7 +63,7 @@ Parser::parse_document(
Ingen::Shared::CommonInterface* target,
const Glib::ustring& document_uri,
Glib::ustring object_uri,
- boost::optional<Glib::ustring> engine_base,
+ Glib::ustring engine_base,
boost::optional<Raul::Symbol> symbol,
boost::optional<GraphObject::Variables> data)
{
@@ -74,7 +74,7 @@ Parser::parse_document(
else
cout << "Parsing " << object_uri << " from " << document_uri << endl;
- return parse(world, target, model, document_uri, object_uri, engine_base, symbol, data);;
+ return parse(world, target, model, document_uri, engine_base, object_uri, symbol, data);;
}
@@ -84,8 +84,8 @@ Parser::parse_string(
Ingen::Shared::CommonInterface* target,
const Glib::ustring& str,
const Glib::ustring& base_uri,
+ Glib::ustring engine_base,
boost::optional<Glib::ustring> object_uri,
- boost::optional<Glib::ustring> engine_base,
boost::optional<Raul::Symbol> symbol,
boost::optional<GraphObject::Variables> data)
{
@@ -96,10 +96,11 @@ Parser::parse_string(
else
cout << "Parsing all objects found in string (base " << base_uri << ")" << endl;
- bool ret = parse(world, target, model, base_uri, object_uri, engine_base, symbol, data);
+ bool ret = parse(world, target, model, base_uri, engine_base, object_uri, symbol, data);
if (ret) {
const Glib::ustring subject = Glib::ustring("<") + base_uri + Glib::ustring(">");
- parse_connections(world, target, model, base_uri, subject, (engine_base ? (string)engine_base.get() : "/"));
+ parse_connections(world, target, model, base_uri, subject,
+ Path((engine_base == "") ? "/" : engine_base));
}
return ret;
@@ -112,13 +113,16 @@ Parser::parse(
Ingen::Shared::CommonInterface* target,
Redland::Model& model,
Glib::ustring base_uri,
+ Glib::ustring engine_base,
boost::optional<Glib::ustring> object_uri,
- boost::optional<Glib::ustring> engine_base,
boost::optional<Raul::Symbol> symbol,
boost::optional<GraphObject::Variables> data)
{
const Redland::Node::Type res = Redland::Node::RESOURCE;
Glib::ustring query_str;
+ if (object_uri && object_uri.get()[0] == '/')
+ object_uri = object_uri.get().substr(1);
+
if (object_uri)
query_str = Glib::ustring("SELECT DISTINCT ?class WHERE { <") + object_uri.get() + "> a ?class . }";
else
@@ -132,8 +136,13 @@ Parser::parse(
const Redland::Node in_port_class(*world->rdf_world, res, NS_INGEN "InputPort");
const Redland::Node out_port_class(*world->rdf_world, res, NS_INGEN "OutputPort");
- const Redland::Node subject_uri(*world->rdf_world, res,
- (object_uri ? object_uri.get() : "http://example.org"));
+ string subject_str = ((object_uri && object_uri.get() != "") ? object_uri.get() : base_uri);
+ if (subject_str[0] == '/')
+ subject_str = subject_str.substr(1);
+ if (subject_str == "")
+ subject_str = base_uri;
+
+ const Redland::Node subject_uri(*world->rdf_world, res, subject_str);
bool ret = false;
@@ -141,7 +150,9 @@ Parser::parse(
const Redland::Node subject = (object_uri ? subject_uri : (*i)["subject"]);
const Redland::Node rdf_class = (*i)["class"];
if (!object_uri) {
- std::string path_str = "/" + uri_relative_to_base(base_uri, subject.to_c_string());
+ std::string path_str = uri_relative_to_base(base_uri, subject.to_c_string());
+ if (path_str[0] != '/')
+ path_str = string("/").append(path_str);
if (Path(path_str).parent() != "/")
continue;
}
@@ -150,12 +161,13 @@ Parser::parse(
rdf_class == in_port_class || rdf_class == out_port_class) {
Raul::Path path("/");
if (base_uri != subject.to_c_string()) {
- string path_str = string("/") + (string)uri_relative_to_base(
- base_uri, subject.to_c_string());
+ string path_str = (string)uri_relative_to_base(base_uri, subject.to_c_string());
+ if (path_str[0] != '/')
+ path_str = string("/").append(path_str);
if (Path::is_valid(path_str)) {
path = path_str;
} else {
- cerr << "[Parser] ERROR: Invalid path " << path << endl;
+ cerr << "[Parser] ERROR: Invalid path '" << path << "'" << endl;
continue;
}
}
@@ -164,8 +176,8 @@ Parser::parse(
continue;
if (rdf_class == patch_class) {
- ret = parse_patch(world, target, model, base_uri, subject.to_c_string(),
- engine_base.get(), data);
+ ret = parse_patch(world, target, model, base_uri, engine_base,
+ subject.to_c_string(), data);
if (ret)
target->set_variable(path, "ingen:document", Atom(base_uri.c_str()));
} else if (rdf_class == node_class) {
@@ -193,8 +205,8 @@ Parser::parse_patch(
Ingen::Shared::CommonInterface* target,
Redland::Model& model,
const Glib::ustring& base_uri,
- const Glib::ustring& object_uri,
Glib::ustring engine_base,
+ const Glib::ustring& object_uri,
boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>())
{
std::set<Path> created;
@@ -222,6 +234,7 @@ Parser::parse_patch(
if (results.size() == 0) {
cerr << "[Parser] ERROR: No polyphony found!" << endl;
+ cerr << "Query was:" << endl << query.string() << endl;
return false;
}
@@ -237,10 +250,12 @@ Parser::parse_patch(
patch_path = "/";
else if (engine_base[engine_base.length()-1] == '/')
patch_path = Path(engine_base + symbol);
- else
+ else if (Path::is_valid(engine_base))
patch_path = (Path)engine_base;
+ else
+ cerr << "WARNING: Illegal engine base path '" << engine_base << "', loading patch to root" << endl;
- if (patch_path != "/")
+ //if (patch_path != "/")
target->new_patch(patch_path, patch_poly);
/* Plugin nodes */
diff --git a/src/libs/serialisation/Parser.hpp b/src/libs/serialisation/Parser.hpp
index 2e088f51..7b8a35eb 100644
--- a/src/libs/serialisation/Parser.hpp
+++ b/src/libs/serialisation/Parser.hpp
@@ -44,8 +44,8 @@ public:
Ingen::Shared::World* world,
Shared::CommonInterface* target,
const Glib::ustring& document_uri,
+ Glib::ustring engine_base,
Glib::ustring object_uri,
- boost::optional<Glib::ustring> engine_base=boost::optional<Glib::ustring>(),
boost::optional<Raul::Symbol> symbol=boost::optional<Raul::Symbol>(),
boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>());
@@ -54,8 +54,8 @@ public:
Shared::CommonInterface* target,
const Glib::ustring& str,
const Glib::ustring& base_uri,
+ Glib::ustring engine_base,
boost::optional<Glib::ustring> object_uri=boost::optional<Glib::ustring>(),
- boost::optional<Glib::ustring> engine_base=boost::optional<Glib::ustring>(),
boost::optional<Raul::Symbol> symbol=boost::optional<Raul::Symbol>(),
boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>());
@@ -68,8 +68,8 @@ private:
Shared::CommonInterface* target,
Redland::Model& model,
Glib::ustring base_uri,
+ Glib::ustring engine_base,
boost::optional<Glib::ustring> object_uri=boost::optional<Glib::ustring>(),
- boost::optional<Glib::ustring> engine_base=boost::optional<Glib::ustring>(),
boost::optional<Raul::Symbol> symbol=boost::optional<Raul::Symbol>(),
boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>());
@@ -78,8 +78,8 @@ private:
Ingen::Shared::CommonInterface* target,
Redland::Model& model,
const Glib::ustring& base_uri,
- const Glib::ustring& object_uri,
Glib::ustring engine_base,
+ const Glib::ustring& object_uri,
boost::optional<GraphObject::Variables> data);
bool parse_node(
diff --git a/src/libs/shared/OSCSender.cpp b/src/libs/shared/OSCSender.cpp
index 340786db..3936cf96 100644
--- a/src/libs/shared/OSCSender.cpp
+++ b/src/libs/shared/OSCSender.cpp
@@ -94,8 +94,8 @@ void
OSCSender::send_message(const char* path, lo_message msg)
{
// FIXME: size? liblo doesn't export this.
- // Don't want to exceed max UDP packet size (1500 bytes?)
- static const size_t MAX_BUNDLE_SIZE = 1500 - 32*5;
+ // Don't want to exceed max UDP packet size (good default value?)
+ static const size_t MAX_BUNDLE_SIZE = 1024;
if (!_enabled)
return;
diff --git a/src/libs/shared/OSCSender.hpp b/src/libs/shared/OSCSender.hpp
index 16b6dd22..da91caed 100644
--- a/src/libs/shared/OSCSender.hpp
+++ b/src/libs/shared/OSCSender.hpp
@@ -27,7 +27,7 @@ namespace Shared {
class OSCSender {
public:
OSCSender();
- ~OSCSender();
+ virtual ~OSCSender() {}
lo_address address() const { return _address; }