diff options
author | David Robillard <d@drobilla.net> | 2011-10-22 00:21:43 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2011-10-22 00:21:43 +0000 |
commit | 14ab4dcff7f8461dfed27b6352249b683c1f4bae (patch) | |
tree | f263ecca5c5c2a220bd00c69bba11a03ad266dc5 /src/client | |
parent | 91bd13d3767452ba0575d69447f23eed1c508603 (diff) | |
download | ingen-14ab4dcff7f8461dfed27b6352249b683c1f4bae.tar.gz ingen-14ab4dcff7f8461dfed27b6352249b683c1f4bae.tar.bz2 ingen-14ab4dcff7f8461dfed27b6352249b683c1f4bae.zip |
Move *all* OSC and HTTP stuff to their respective modules.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@3578 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/client')
-rw-r--r-- | src/client/HTTPClientReceiver.cpp | 241 | ||||
-rw-r--r-- | src/client/HTTPClientReceiver.hpp | 85 | ||||
-rw-r--r-- | src/client/HTTPEngineSender.cpp | 194 | ||||
-rw-r--r-- | src/client/HTTPEngineSender.hpp | 126 | ||||
-rw-r--r-- | src/client/OSCClientReceiver.cpp | 303 | ||||
-rw-r--r-- | src/client/OSCClientReceiver.hpp | 98 | ||||
-rw-r--r-- | src/client/OSCEngineSender.cpp | 241 | ||||
-rw-r--r-- | src/client/OSCEngineSender.hpp | 117 | ||||
-rw-r--r-- | src/client/ingen_client.cpp | 50 | ||||
-rw-r--r-- | src/client/wscript | 15 |
10 files changed, 4 insertions, 1466 deletions
diff --git a/src/client/HTTPClientReceiver.cpp b/src/client/HTTPClientReceiver.cpp deleted file mode 100644 index 0ec5aaa4..00000000 --- a/src/client/HTTPClientReceiver.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David 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 <assert.h> -#include <errno.h> -#include <string.h> -#include <sys/socket.h> - -#include <libsoup/soup.h> - -#include "ingen/shared/World.hpp" -#include "raul/log.hpp" - -#include "HTTPClientReceiver.hpp" - -#define LOG(s) s << "[HTTPClientReceiver] " - -using namespace std; -using namespace Raul; - -namespace Ingen { - -using namespace Serialisation; - -namespace Client { - -static SoupSession* client_session = NULL; -static HTTPClientReceiver* client_receiver = NULL; - -HTTPClientReceiver::HTTPClientReceiver( - Shared::World* world, - const std::string& url, - SharedPtr<ClientInterface> target) - : _target(target) - , _world(world) - , _url(url) -{ - start(false); - client_receiver = this; -} - -HTTPClientReceiver::~HTTPClientReceiver() -{ - stop(); - if (client_receiver == this) - client_receiver = NULL; -} - -HTTPClientReceiver::Listener::Listener(HTTPClientReceiver* receiver, const std::string& uri) - : _uri(uri) - , _receiver(receiver) -{ - const string port_str = uri.substr(uri.find_last_of(":")+1); - int port = atoi(port_str.c_str()); - - LOG(info) << "Client HTTP listen: " << uri << " (port " << port << ")" << endl; - - struct sockaddr_in servaddr; - - // Create listen address - memset(&servaddr, 0, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(port); - - // Create listen socket - if ((_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - LOG(error) << "Error creating listening socket: %s" << strerror(errno) << endl; - _sock = -1; - return; - } - - // Set remote address (FIXME: always localhost) - if (inet_aton("127.0.0.1", &servaddr.sin_addr) <= 0) { - LOG(error) << "Invalid remote IP address" << endl; - _sock = -1; - return; - } - - // Connect to server - if (connect(_sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { - LOG(error) << "Error calling connect: " << strerror(errno) << endl; - _sock = -1; - return; - } -} - -HTTPClientReceiver::Listener::~Listener() -{ - close(_sock); -} - -void -HTTPClientReceiver::send(SoupMessage* msg) -{ - if (!client_session) { - LOG(debug) << "Starting session" << endl; - client_session = soup_session_sync_new(); - } - - assert(SOUP_IS_MESSAGE(msg)); - soup_session_queue_message(client_session, msg, message_callback, client_receiver); -} - -void -HTTPClientReceiver::close_session() -{ - if (client_session) { - SoupSession* s = client_session; - client_session = NULL; - soup_session_abort(s); - } -} - -void -HTTPClientReceiver::update(const std::string& str) -{ - //LOG(info) << _world->parser()->parse_update(_world, _target.get(), str, _url); -} - -void -HTTPClientReceiver::Listener::_run() -{ - char in = '\0'; - char last = '\0'; - char llast = '\0'; - string recv; - - while (true) { - while (read(_sock, &in, 1) > 0 ) { - recv += in; - if (in == '\n' && last == '\n' && llast == '\n') { - if (!recv.empty()) { - _receiver->update(recv); - recv.clear(); - last = '\0'; - llast = '\0'; - } - break; - } - llast = last; - last = in; - } - } - - LOG(info) << "HTTP listener finished" << endl; -} - -void -HTTPClientReceiver::message_callback(SoupSession* session, SoupMessage* msg, void* ptr) -{ - if (ptr == NULL) - return; - - HTTPClientReceiver* me = (HTTPClientReceiver*)ptr; - const string path = soup_message_get_uri(msg)->path; - - if (msg->response_body->data == NULL) { - LOG(error) << "Empty client message" << endl; - return; - } - - if (path == "/") { - me->_target->response_ok(0); - - } else if (path == "/plugins") { - if (msg->response_body->data == NULL) { - LOG(error) << "Empty response" << endl; - } else { - Glib::Mutex::Lock lock(me->_mutex); - me->_target->response_ok(0); - me->_world->parser()->parse_string(me->_world, me->_target.get(), - Glib::ustring(msg->response_body->data), me->_url); - } - - } else if (path.substr(0, 6) == "/patch") { - if (msg->response_body->data == NULL) { - LOG(error) << "Empty response" << endl; - } else { - Glib::Mutex::Lock lock(me->_mutex); - me->_target->response_ok(0); - me->_world->parser()->parse_string( - me->_world, - me->_target.get(), - Glib::ustring(msg->response_body->data), - path); - } - - } else if (path == "/stream") { - if (msg->response_body->data == NULL) { - LOG(error) << "Empty response" << endl; - } else { - Glib::Mutex::Lock lock(me->_mutex); - string uri = string(soup_uri_to_string(soup_message_get_uri(msg), false)); - uri = uri.substr(0, uri.find_last_of(":")); - uri += string(":") + msg->response_body->data; - LOG(info) << "Stream URI: " << uri << endl; - me->_listener = boost::shared_ptr<Listener>(new Listener(me, uri)); - me->_listener->start(); - } - - } else { - LOG(error) << "Unknown message: " << path << endl; - me->update(msg->response_body->data); - } -} - -void -HTTPClientReceiver::start(bool dump) -{ - if (!_world->parser()) - _world->load_module("serialisation"); - - SoupMessage* msg = soup_message_new("GET", (_url + "/stream").c_str()); - assert(SOUP_IS_MESSAGE(msg)); - soup_session_queue_message(client_session, msg, message_callback, this); -} - -void -HTTPClientReceiver::stop() -{ - //unregister_client(); - close_session(); -} - -} // namespace Client -} // namespace Ingen - diff --git a/src/client/HTTPClientReceiver.hpp b/src/client/HTTPClientReceiver.hpp deleted file mode 100644 index d7165c81..00000000 --- a/src/client/HTTPClientReceiver.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David 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 INGEN_CLIENT_HTTPCLIENTRECEIVER_HPP -#define INGEN_CLIENT_HTTPCLIENTRECEIVER_HPP - -#include <cstdlib> - -#include <boost/utility.hpp> -#include <glibmm/thread.h> - -#include "ingen/ClientInterface.hpp" -#include "ingen/serialisation/Parser.hpp" -#include "raul/Deletable.hpp" -#include "raul/SharedPtr.hpp" -#include "raul/Thread.hpp" -#include "sord/sordmm.hpp" - -typedef struct _SoupSession SoupSession; -typedef struct _SoupMessage SoupMessage; - -namespace Ingen { -namespace Client { - -class HTTPClientReceiver : public boost::noncopyable, public Raul::Deletable -{ -public: - HTTPClientReceiver(Shared::World* world, - const std::string& url, - SharedPtr<ClientInterface> target); - - ~HTTPClientReceiver(); - - static void send(SoupMessage* msg); - static void close_session(); - - std::string uri() const { return _url; } - - void start(bool dump); - void stop(); - -private: - static void message_callback(SoupSession* session, SoupMessage* msg, void* ptr); - - void update(const std::string& str); - - class Listener : public Raul::Thread { - public: - Listener(HTTPClientReceiver* receiver, const std::string& uri); - ~Listener(); - void _run(); - private: - std::string _uri; - int _sock; - HTTPClientReceiver* _receiver; - }; - - friend class Listener; - - SharedPtr<Listener> _listener; - Glib::Mutex _mutex; - SharedPtr<ClientInterface> _target; - Shared::World* _world; - const std::string _url; - bool _quit_flag; -}; - -} // namespace Client -} // namespace Ingen - -#endif // INGEN_CLIENT_HTTPCLIENTRECEIVER_HPP diff --git a/src/client/HTTPEngineSender.cpp b/src/client/HTTPEngineSender.cpp deleted file mode 100644 index 43a3d44c..00000000 --- a/src/client/HTTPEngineSender.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David 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 <libsoup/soup.h> - -#include "raul/AtomRDF.hpp" -#include "raul/log.hpp" -#include "sord/sordmm.hpp" - -#include "ingen/shared/World.hpp" -#include "HTTPEngineSender.hpp" -#include "HTTPClientReceiver.hpp" - -#define LOG(s) s << "[HTTPEngineSender] " - -using namespace std; -using namespace Raul; - -namespace Ingen { - -using namespace Shared; - -namespace Client { - -HTTPEngineSender::HTTPEngineSender(World* world, - const URI& engine_url, - SharedPtr<Raul::Deletable> receiver) - : _receiver(receiver) - , _world(*world->rdf_world()) - , _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) -{ - LOG(debug) << "Attaching to " << _engine_url << endl; - SoupMessage* msg = soup_message_new ("GET", _engine_url.c_str()); - HTTPClientReceiver::send(msg); -} - -/* *** ServerInterface 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 ServerInterface. - */ -void -HTTPEngineSender::register_client(ClientInterface* client) -{ - /*SoupMessage* msg = soup_message_new("GET", (_engine_url.str() + "/stream").c_str()); - HTTPClientReceiver::send(msg);*/ -} - -void -HTTPEngineSender::unregister_client(const URI& uri) -{ -} - -// Object commands - -void -HTTPEngineSender::put(const URI& uri, - const Resource::Properties& properties, - Resource::Graph ctx) -{ - const string path = (uri.substr(0, 6) == "path:/") ? uri.substr(6) : uri.str(); - const string full_uri = _engine_url.str() + "/" + path; - - Sord::Model model(_world); - for (Resource::Properties::const_iterator i = properties.begin(); i != properties.end(); ++i) - model.add_statement(Sord::URI(_world, path), - AtomRDF::atom_to_node(model, i->first), - AtomRDF::atom_to_node(model, i->second)); - - const string str = model.write_to_string(""); - SoupMessage* msg = soup_message_new(SOUP_METHOD_PUT, full_uri.c_str()); - assert(msg); - soup_message_set_request(msg, "application/x-turtle", SOUP_MEMORY_COPY, str.c_str(), str.length()); - soup_session_send_message(_session, msg); -} - -void -HTTPEngineSender::delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add) -{ - LOG(warn) << "TODO: HTTP delta" << endl; -} - -void -HTTPEngineSender::move(const Path& old_path, - const Path& new_path) -{ - SoupMessage* msg = soup_message_new(SOUP_METHOD_MOVE, - (_engine_url.str() + old_path.str()).c_str()); - soup_message_headers_append(msg->request_headers, "Destination", - (_engine_url.str() + new_path.str()).c_str()); - soup_session_send_message(_session, msg); -} - -void -HTTPEngineSender::del(const URI& uri) -{ - const string path = (uri.substr(0, 6) == "path:/") ? uri.substr(6) : uri.str(); - const string full_uri = _engine_url.str() + "/" + path; - SoupMessage* msg = soup_message_new(SOUP_METHOD_DELETE, full_uri.c_str()); - soup_session_send_message(_session, msg); -} - -void -HTTPEngineSender::connect(const Path& src_port_path, - const Path& dst_port_path) -{ - LOG(warn) << "TODO: HTTP connect" << endl; -} - -void -HTTPEngineSender::disconnect(const URI& src, - const URI& dst) -{ - LOG(warn) << "TODO: HTTP disconnect" << endl; -} - -void -HTTPEngineSender::disconnect_all(const Path& parent_patch_path, - const Path& path) -{ - LOG(warn) << "TODO: HTTP disconnect_all" << endl; -} - -void -HTTPEngineSender::set_property(const URI& subject, - const URI& predicate, - const Atom& value) -{ - Resource::Properties prop; - prop.insert(make_pair(predicate, value)); - put(subject, prop); -} - -// Requests // - -void -HTTPEngineSender::ping() -{ - LOG(debug) << "Ping " << _engine_url << endl; - get(_engine_url); -} - -void -HTTPEngineSender::get(const URI& uri) -{ - if (!Raul::Path::is_path(uri) && uri.scheme() != "http") { - LOG(warn) << "Ignoring GET of non-HTTP URI " << uri << endl; - return; - } - - const std::string request_uri = (Raul::Path::is_path(uri)) - ?_engine_url.str() + "/patch" + uri.substr(uri.find("/")) - : uri.str(); - cout << "Get " << request_uri << endl; - LOG(debug) << "Get " << request_uri << endl; - SoupMessage* msg = soup_message_new("GET", request_uri.c_str()); - HTTPClientReceiver::send(msg); -} - -} // namespace Client -} // namespace Ingen - diff --git a/src/client/HTTPEngineSender.hpp b/src/client/HTTPEngineSender.hpp deleted file mode 100644 index 14439e39..00000000 --- a/src/client/HTTPEngineSender.hpp +++ /dev/null @@ -1,126 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2008-2011 David 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 INGEN_CLIENT_HTTPENGINESENDER_HPP -#define INGEN_CLIENT_HTTPENGINESENDER_HPP - -#include <inttypes.h> - -#include <string> - -#include "raul/Deletable.hpp" -#include "raul/Path.hpp" -#include "sord/sordmm.hpp" - -#include "ingen/ServerInterface.hpp" - -typedef struct _SoupSession SoupSession; - -namespace Ingen { - -namespace Shared { class World; } - -namespace Client { - -class HTTPClientReceiver; - -/* HTTP (via libsoup) interface to the engine. - * - * Clients can use this opaquely as an ServerInterface to control the engine - * over HTTP (whether over a network or not). - * - * \ingroup IngenClient - */ -class HTTPEngineSender : public ServerInterface -{ -public: - HTTPEngineSender(Shared::World* world, - const Raul::URI& engine_url, - SharedPtr<Raul::Deletable> receiver); - - ~HTTPEngineSender(); - - Raul::URI uri() const { return _engine_url; } - - inline int32_t next_id() - { int32_t ret = (_id == -1) ? -1 : _id++; return ret; } - - void respond_to(ClientInterface* client, int32_t id) { _id = id; } - void disable_responses() { _id = -1; } - - void attach(int32_t ping_id, bool block); - - /* *** ServerInterface implementation below here *** */ - - void enable() { _enabled = true; } - void disable() { _enabled = false; } - - void bundle_begin() {} - void bundle_end() {} - - // Client registration - void register_client(ClientInterface* client); - void unregister_client(const Raul::URI& uri); - - // Object commands - - virtual void put(const Raul::URI& path, - const Resource::Properties& properties, - Resource::Graph ctx=Resource::DEFAULT); - - virtual void delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add); - - virtual void del(const Raul::URI& uri); - - virtual void move(const Raul::Path& old_path, - const Raul::Path& new_path); - - virtual void connect(const Raul::Path& src_port_path, - const Raul::Path& dst_port_path); - - virtual void disconnect(const Raul::URI& src, - const Raul::URI& dst); - - virtual void disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path); - - virtual void set_property(const Raul::URI& subject, - const Raul::URI& predicate, - const Raul::Atom& value); - - // Requests // - void ping(); - void get(const Raul::URI& uri); - -protected: - SharedPtr<Raul::Deletable> _receiver; - - SoupSession* _session; - Sord::World& _world; - const Raul::URI _engine_url; - int _client_port; - int32_t _id; - bool _enabled; -}; - -} // namespace Client -} // namespace Ingen - -#endif // INGEN_CLIENT_HTTPENGINESENDER_HPP - diff --git a/src/client/OSCClientReceiver.cpp b/src/client/OSCClientReceiver.cpp deleted file mode 100644 index 4fef1d1c..00000000 --- a/src/client/OSCClientReceiver.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David 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 <assert.h> -#include <stdio.h> -#include <string.h> - -#include "raul/log.hpp" -#include "raul/AtomLiblo.hpp" -#include "raul/Path.hpp" - -#include "ingen-config.h" -#include "OSCClientReceiver.hpp" - -#define LOG(s) s << "[OSCClientReceiver] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Client { - -OSCClientReceiver::OSCClientReceiver(int listen_port, - SharedPtr<ClientInterface> target) - : _target(target) - , _st(NULL) - , _listen_port(listen_port) -{ -#ifdef RAUL_LOG_DEBUG - start(true); -#else - start(false); // true = dump, false = shutup -#endif -} - -OSCClientReceiver::~OSCClientReceiver() -{ - stop(); -} - -void -OSCClientReceiver::start(bool dump_osc) -{ - if (_st != NULL) - return; - - // Attempt preferred port - if (_listen_port != 0) { - char port_str[8]; - snprintf(port_str, 8, "%d", _listen_port); - _st = lo_server_thread_new(port_str, lo_error_cb); - } - - // Find a free port - if (!_st) { - _st = lo_server_thread_new(NULL, lo_error_cb); - _listen_port = lo_server_thread_get_port(_st); - } - - if (_st == NULL) { - LOG(error) << "Could not start OSC listener. Aborting." << endl; - exit(EXIT_FAILURE); - } else { - LOG(info) << "Started OSC listener on port " << lo_server_thread_get_port(_st) << endl; - } - - // Print all incoming messages - if (dump_osc) - lo_server_thread_add_method(_st, NULL, NULL, generic_cb, NULL); - - setup_callbacks(); - - // Display any uncaught messages to the console - //lo_server_thread_add_method(_st, NULL, NULL, unknown_cb, NULL); - - lo_server_thread_start(_st); -} - -void -OSCClientReceiver::stop() -{ - if (_st != NULL) { - //unregister_client(); - lo_server_thread_free(_st); - _st = NULL; - } -} - -int -OSCClientReceiver::generic_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data) -{ - printf("[OSCClientReceiver] %s (%s)\t", path, types); - - for (int i=0; i < argc; ++i) { - lo_arg_pp(lo_type(types[i]), argv[i]); - printf("\t"); - } - printf("\n"); - - return 1; // not handled -} - -void -OSCClientReceiver::lo_error_cb(int num, const char* msg, const char* path) -{ - LOG(error) << "Got error from server: " << msg << endl; -} - -int -OSCClientReceiver::unknown_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data) -{ - std::string msg = "Received unknown OSC message: "; - msg += path; - - LOG(error) << msg << endl; - - return 0; -} - -void -OSCClientReceiver::setup_callbacks() -{ - if (!_target) - return; - - lo_server_thread_add_method(_st, "/ok", "i", response_ok_cb, this); - lo_server_thread_add_method(_st, "/error", "is", response_error_cb, this); - lo_server_thread_add_method(_st, "/plugin", "sss", plugin_cb, this); - lo_server_thread_add_method(_st, "/put", NULL, put_cb, this); - lo_server_thread_add_method(_st, "/delta_begin", NULL, delta_begin_cb, this); - lo_server_thread_add_method(_st, "/delta_remove", NULL, delta_remove_cb, this); - lo_server_thread_add_method(_st, "/delta_add", NULL, delta_add_cb, this); - lo_server_thread_add_method(_st, "/delta_end", NULL, delta_end_cb, this); - lo_server_thread_add_method(_st, "/move", "ss", move_cb, this); - lo_server_thread_add_method(_st, "/delete", "s", del_cb, this); - lo_server_thread_add_method(_st, "/connect", "ss", connection_cb, this); - lo_server_thread_add_method(_st, "/disconnect", "ss", disconnection_cb, this); - lo_server_thread_add_method(_st, "/set_property", NULL, set_property_cb, this); - lo_server_thread_add_method(_st, "/activity", "sT", activity_cb, this); - lo_server_thread_add_method(_st, "/activity", "sf", activity_cb, this); -} - -/** Catches errors that aren't a direct result of a client request. - */ -int -OSCClientReceiver::_error_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - _target->error((char*)argv[0]); - return 0; -} - -int -OSCClientReceiver::_del_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - _target->del((const char*)&argv[0]->s); - return 0; -} - -int -OSCClientReceiver::_put_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* obj_path = &argv[0]->s; - const char* ctx = &argv[1]->s; - Resource::Properties prop; - for (int i = 2; i < argc-1; i += 2) - prop.insert(make_pair(&argv[i]->s, - AtomLiblo::lo_arg_to_atom(types[i+1], argv[i+1]))); - _target->put(obj_path, prop, Resource::uri_to_graph(ctx)); - return 0; -} - -int -OSCClientReceiver::_delta_begin_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* obj_path = &argv[0]->s; - assert(_delta_remove.empty()); - assert(_delta_add.empty()); - _delta_uri = obj_path; - return 0; -} - -int -OSCClientReceiver::_delta_remove_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - _delta_remove.insert(make_pair(&argv[0]->s, - AtomLiblo::lo_arg_to_atom(types[1], argv[1]))); - return 0; -} - -int -OSCClientReceiver::_delta_add_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - _delta_add.insert(make_pair(&argv[0]->s, - AtomLiblo::lo_arg_to_atom(types[1], argv[1]))); - return 0; -} - -int -OSCClientReceiver::_delta_end_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - _target->delta(_delta_uri, _delta_remove, _delta_add); - _delta_uri = Raul::URI(); - _delta_remove.clear(); - _delta_add.clear(); - return 0; -} - -int -OSCClientReceiver::_move_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* old_path = &argv[1]->s; - const char* new_path = &argv[2]->s; - - _target->move(old_path, new_path); - return 0; -} - -int -OSCClientReceiver::_connection_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* const src_port_path = &argv[0]->s; - const char* const dst_port_path = &argv[1]->s; - - _target->connect(src_port_path, dst_port_path); - - return 0; -} - -int -OSCClientReceiver::_disconnection_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* src_uri = &argv[0]->s; - const char* dst_uri = &argv[1]->s; - - _target->disconnect(src_uri, dst_uri); - - return 0; -} - -/** Notification of a new or updated property. - */ -int -OSCClientReceiver::_set_property_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - if (argc != 3 || types[0] != 's' || types[1] != 's') - return 1; - - const char* obj_uri = &argv[0]->s; - const char* key = &argv[1]->s; - - Atom value = AtomLiblo::lo_arg_to_atom(types[2], argv[2]); - - _target->set_property(obj_uri, key, value); - - return 0; -} - -int -OSCClientReceiver::_activity_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* const port_path = &argv[0]->s; - - Atom value = AtomLiblo::lo_arg_to_atom(types[1], argv[1]); - - _target->activity(port_path, value); - - return 0; -} - -int -OSCClientReceiver::_response_ok_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - assert(!strcmp(types, "i")); - _target->response_ok(argv[0]->i); - - return 0; -} - -int -OSCClientReceiver::_response_error_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - assert(!strcmp(types, "is")); - _target->response_error(argv[0]->i, &argv[1]->s); - - return 0; -} - -} // namespace Client -} // namespace Ingen diff --git a/src/client/OSCClientReceiver.hpp b/src/client/OSCClientReceiver.hpp deleted file mode 100644 index 3b7f5db0..00000000 --- a/src/client/OSCClientReceiver.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David 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 INGEN_CLIENT_OSCCLIENTRECEIVER_HPP -#define INGEN_CLIENT_OSCCLIENTRECEIVER_HPP - -#include <cstdlib> - -#include <boost/utility.hpp> -#include <lo/lo.h> - -#include "ingen/ClientInterface.hpp" -#include "raul/Deletable.hpp" -#include "raul/SharedPtr.hpp" - -namespace Ingen { -namespace Client { - -/** Arguments to a liblo handler */ -#define LO_HANDLER_ARGS const char* path, const char* types, lo_arg** argv, int argc, lo_message msg - -/** 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)\ -{ return ((OSCClientReceiver*)osc_listener)->_##name##_cb(path, types, argv, argc, msg); } - -/** Client-side receiver for OSC messages from the engine. - * - * \ingroup IngenClient - */ -class OSCClientReceiver : public boost::noncopyable, public Raul::Deletable -{ -public: - OSCClientReceiver(int listen_port, SharedPtr<ClientInterface> target); - ~OSCClientReceiver(); - - std::string uri() const { return lo_server_thread_get_url(_st); } - - void start(bool dump_osc); - void stop(); - - int listen_port() { return _listen_port; } - std::string listen_url() { return lo_server_thread_get_url(_st); } - -private: - void setup_callbacks(); - - static void lo_error_cb(int num, const char* msg, const char* path); - - static int generic_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data); - static int unknown_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* osc_receiver); - - SharedPtr<ClientInterface> _target; - lo_server_thread _st; - Raul::URI _delta_uri; - Resource::Properties _delta_remove; - Resource::Properties _delta_add; - int _listen_port; - - LO_HANDLER(error); - LO_HANDLER(response_ok); - LO_HANDLER(response_error); - LO_HANDLER(plugin); - LO_HANDLER(plugin_list_end); - LO_HANDLER(new_patch); - LO_HANDLER(del); - LO_HANDLER(move); - LO_HANDLER(connection); - LO_HANDLER(disconnection); - LO_HANDLER(put); - LO_HANDLER(delta_begin); - LO_HANDLER(delta_remove); - LO_HANDLER(delta_add); - LO_HANDLER(delta_end); - LO_HANDLER(set_property); - LO_HANDLER(activity); -}; - -} // namespace Client -} // namespace Ingen - -#endif // INGEN_CLIENT_OSCCLIENTRECEIVER_HPP diff --git a/src/client/OSCEngineSender.cpp b/src/client/OSCEngineSender.cpp deleted file mode 100644 index e2436af7..00000000 --- a/src/client/OSCEngineSender.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David 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 "raul/log.hpp" -#include "raul/AtomLiblo.hpp" -#include "raul/Path.hpp" - -#include "ingen/Patch.hpp" -#include "ingen/Port.hpp" -#include "ingen/Plugin.hpp" - -#include "OSCEngineSender.hpp" - -#define LOG(s) s << "[OSCEngineSender] " - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Client { - -/** Note the sending port is implicitly set by liblo, lo_send by default sends - * from the most recently created server, so create the OSC listener before - * this to have it all happen on the same port. Yeah, this is a big magic :/ - */ -OSCEngineSender::OSCEngineSender(const URI& engine_url, - size_t max_packet_size, - SharedPtr<Raul::Deletable> receiver) - : Shared::OSCSender(max_packet_size) - , _receiver(receiver) - , _engine_url(engine_url) - , _id(0) -{ - _address = lo_address_new_from_url(engine_url.c_str()); -} - -OSCEngineSender::~OSCEngineSender() -{ - lo_address_free(_address); -} - -/** Attempt to connect to the engine (by pinging it). - * - * This doesn't register a client (or otherwise affect the client/engine state). - * To check for success wait for the ping response with id @a ping_id (using the - * relevant OSCClientReceiver). - * - * Passing a client_port of 0 will automatically choose a free port. If the - * @a block parameter is true, this function will not return until a connection - * has successfully been made. - */ -void -OSCEngineSender::attach(int32_t ping_id, bool block) -{ - if (!_address) - _address = lo_address_new_from_url(_engine_url.c_str()); - - if (_address == NULL) { - LOG(error) << "Unable to connect to " << _engine_url << endl; - exit(EXIT_FAILURE); - } - - LOG(info) << "Attempting to contact engine at " << _engine_url << " ..." << endl; - - _id = ping_id; - this->ping(); -} - -/* *** ServerInterface implementation below here *** */ - -/** Register with the engine via OSC. - * - * Note that this does not actually use 'client', since the engine creates - * it's own key for OSC clients (namely the incoming URL), for NAT - * traversal. It is a parameter to remain compatible with ServerInterface. - */ -void -OSCEngineSender::register_client(ClientInterface* client) -{ - send("/register_client", "i", next_id(), LO_ARGS_END); -} - -void -OSCEngineSender::unregister_client(const URI& uri) -{ - send("/unregister_client", "i", next_id(), LO_ARGS_END); -} - -// Object commands - -void -OSCEngineSender::put(const Raul::URI& path, - const Resource::Properties& properties, - Resource::Graph ctx) -{ - typedef Resource::Properties::const_iterator iterator; - lo_message m = lo_message_new(); - lo_message_add_int32(m, next_id()); - lo_message_add_string(m, path.c_str()); - lo_message_add_string(m, Resource::graph_to_uri(ctx).c_str()); - for (iterator i = properties.begin(); i != properties.end(); ++i) { - lo_message_add_string(m, i->first.c_str()); - Raul::AtomLiblo::lo_message_add_atom(m, i->second); - } - send_message("/put", m); -} - -void -OSCEngineSender::delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add) -{ - typedef Resource::Properties::const_iterator iterator; - - const bool bundle = !_bundle; - if (bundle) - bundle_begin(); - - const int32_t id = next_id(); - send("/delta_begin", "is", id, path.c_str(), LO_ARGS_END); - - for (iterator i = remove.begin(); i != remove.end(); ++i) { - lo_message m = lo_message_new(); - lo_message_add_string(m, i->first.c_str()); - Raul::AtomLiblo::lo_message_add_atom(m, i->second); - send_message("/delta_remove", m); - } - - for (iterator i = add.begin(); i != add.end(); ++i) { - lo_message m = lo_message_new(); - lo_message_add_string(m, i->first.c_str()); - Raul::AtomLiblo::lo_message_add_atom(m, i->second); - send_message("/delta_add", m); - } - - send("/delta_end", "i", id, LO_ARGS_END); - - if (bundle) - bundle_end(); -} - -void -OSCEngineSender::move(const Path& old_path, - const Path& new_path) -{ - send("/move", "iss", - next_id(), - old_path.c_str(), - new_path.c_str(), - LO_ARGS_END); -} - -void -OSCEngineSender::del(const URI& uri) -{ - send("/delete", "is", - next_id(), - uri.c_str(), - LO_ARGS_END); -} - -void -OSCEngineSender::connect(const Path& src_port_path, - const Path& dst_port_path) -{ - send("/connect", "iss", - next_id(), - src_port_path.c_str(), - dst_port_path.c_str(), - LO_ARGS_END); -} - -void -OSCEngineSender::disconnect(const URI& src, - const URI& dst) -{ - send("/disconnect", "iss", - next_id(), - src.c_str(), - dst.c_str(), - LO_ARGS_END); -} - -void -OSCEngineSender::disconnect_all(const Path& parent_patch_path, - const Path& path) -{ - send("/disconnect_all", "iss", - next_id(), - parent_patch_path.c_str(), - path.c_str(), - LO_ARGS_END); -} - -void -OSCEngineSender::set_property(const URI& subject, - const URI& predicate, - const Atom& value) -{ - lo_message m = lo_message_new(); - lo_message_add_int32(m, next_id()); - lo_message_add_string(m, subject.c_str()); - lo_message_add_string(m, predicate.c_str()); - Raul::AtomLiblo::lo_message_add_atom(m, value); - send_message("/set_property", m); -} - -// Requests // - -void -OSCEngineSender::ping() -{ - send("/ping", "i", next_id(), LO_ARGS_END); -} - -void -OSCEngineSender::get(const URI& uri) -{ - send("/get", "is", - next_id(), - uri.c_str(), - LO_ARGS_END); -} - -} // namespace Client -} // namespace Ingen - diff --git a/src/client/OSCEngineSender.hpp b/src/client/OSCEngineSender.hpp deleted file mode 100644 index 75569ec0..00000000 --- a/src/client/OSCEngineSender.hpp +++ /dev/null @@ -1,117 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David 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 INGEN_CLIENT_OSCENGINESENDER_HPP -#define INGEN_CLIENT_OSCENGINESENDER_HPP - -#include <stddef.h> - -#include <string> - -#include <lo/lo.h> - -#include "raul/Deletable.hpp" - -#include "ingen/ServerInterface.hpp" -#include "../shared/OSCSender.hpp" - -namespace Ingen { - -namespace Client { - -/* OSC (via liblo) interface to the engine. - * - * Clients can use this opaquely as an ServerInterface* to control the engine - * over OSC (whether over a network or not, etc). - * - * \ingroup IngenClient - */ -class OSCEngineSender : public ServerInterface, public Shared::OSCSender { -public: - OSCEngineSender(const Raul::URI& engine_url, - size_t max_packet_size, - SharedPtr<Raul::Deletable> receiver); - - ~OSCEngineSender(); - - Raul::URI uri() const { return _engine_url; } - - inline int32_t next_id() - { int32_t ret = (_id == -1) ? -1 : _id++; return ret; } - - void respond_to(ClientInterface* client, int32_t id) { _id = id; } - void disable_responses() { _id = -1; } - - void attach(int32_t ping_id, bool block); - - /* *** ServerInterface implementation below here *** */ - - void enable() { _enabled = true; } - void disable() { _enabled = false; } - - void bundle_begin() { OSCSender::bundle_begin(); } - void bundle_end() { OSCSender::bundle_end(); } - - // Client registration - void register_client(ClientInterface* client); - void unregister_client(const Raul::URI& uri); - - // Object commands - - virtual void put(const Raul::URI& path, - const Resource::Properties& properties, - Resource::Graph ctx=Resource::DEFAULT); - - virtual void delta(const Raul::URI& path, - const Resource::Properties& remove, - const Resource::Properties& add); - - virtual void del(const Raul::URI& uri); - - virtual void move(const Raul::Path& old_path, - const Raul::Path& new_path); - - virtual void connect(const Raul::Path& src_port_path, - const Raul::Path& dst_port_path); - - virtual void disconnect(const Raul::URI& src, - const Raul::URI& dst); - - virtual void disconnect_all(const Raul::Path& parent_patch_path, - const Raul::Path& path); - - virtual void set_property(const Raul::URI& subject_path, - const Raul::URI& predicate, - const Raul::Atom& value); - - // Requests // - void ping(); - void get(const Raul::URI& uri); - -protected: - SharedPtr<Raul::Deletable> _receiver; - - const Raul::URI _engine_url; - int _client_port; - int32_t _id; -}; - -} // namespace Client -} // namespace Ingen - -#endif // INGEN_CLIENT_OSCENGINESENDER_HPP - diff --git a/src/client/ingen_client.cpp b/src/client/ingen_client.cpp index 03056f65..2e3e2c74 100644 --- a/src/client/ingen_client.cpp +++ b/src/client/ingen_client.cpp @@ -15,60 +15,16 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "ingen-config.h" -#include "raul/SharedPtr.hpp" #include "ingen/shared/Module.hpp" #include "ingen/shared/World.hpp" -#ifdef HAVE_LIBLO -#include "OSCClientReceiver.hpp" -#include "OSCEngineSender.hpp" -#endif -#ifdef HAVE_SOUP -#include "HTTPClientReceiver.hpp" -#include "HTTPEngineSender.hpp" -#endif - -using namespace Ingen; +#include "raul/SharedPtr.hpp" -#ifdef HAVE_LIBLO -SharedPtr<Ingen::ServerInterface> -new_osc_interface(Ingen::Shared::World* world, - const std::string& url, - SharedPtr<ClientInterface> respond_to) -{ - SharedPtr<Client::OSCClientReceiver> receiver( - new Client::OSCClientReceiver(16181, respond_to)); - Client::OSCEngineSender* oes = new Client::OSCEngineSender( - url, world->conf()->option("packet-size").get_int32(), receiver); - oes->attach(rand(), true); - return SharedPtr<ServerInterface>(oes); -} -#endif +#include "ingen-config.h" -#ifdef HAVE_SOUP -SharedPtr<Ingen::ServerInterface> -new_http_interface(Ingen::Shared::World* world, - const std::string& url, - SharedPtr<ClientInterface> respond_to) -{ - SharedPtr<Client::HTTPClientReceiver> receiver( - new Client::HTTPClientReceiver(world, url, respond_to)); - Client::HTTPEngineSender* hes = new Client::HTTPEngineSender( - world, url, receiver); - hes->attach(rand(), true); - return SharedPtr<ServerInterface>(hes); -} -#endif +using namespace Ingen; struct IngenClientModule : public Ingen::Shared::Module { void load(Ingen::Shared::World* world) { -#ifdef HAVE_LIBLO - world->add_interface_factory("osc.udp", &new_osc_interface); - world->add_interface_factory("osc.tcp", &new_osc_interface); -#endif -#ifdef HAVE_SOUP - world->add_interface_factory("http", &new_http_interface); -#endif } }; diff --git a/src/client/wscript b/src/client/wscript index 9047859a..29ac636d 100644 --- a/src/client/wscript +++ b/src/client/wscript @@ -9,7 +9,7 @@ def build(bld): target = 'ingen_client', install_path = '${LIBDIR}', use = 'libingen_shared') - autowaf.use_lib(bld, obj, 'GLIBMM LV2CORE LILV SUIL RAUL SORD SOUP SIGCPP LIBLO SOUP') + autowaf.use_lib(bld, obj, 'GLIBMM LV2CORE LILV SUIL RAUL SORD SIGCPP') obj.source = ''' ClientStore.cpp @@ -22,16 +22,3 @@ def build(bld): ThreadedSigClientInterface.cpp ingen_client.cpp ''' - - if bld.is_defined('HAVE_SOUP'): - obj.source += ''' - HTTPClientReceiver.cpp - HTTPEngineSender.cpp - ''' - - if bld.is_defined('HAVE_LIBLO'): - obj.source += ''' - OSCClientReceiver.cpp - OSCEngineSender.cpp - ''' - |