summaryrefslogtreecommitdiffstats
path: root/src/libs/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/client')
-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
18 files changed, 729 insertions, 73 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);
}