From 14ab4dcff7f8461dfed27b6352249b683c1f4bae Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 22 Oct 2011 00:21:43 +0000 Subject: 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 --- src/osc/OSCClientReceiver.cpp | 303 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 src/osc/OSCClientReceiver.cpp (limited to 'src/osc/OSCClientReceiver.cpp') diff --git a/src/osc/OSCClientReceiver.cpp b/src/osc/OSCClientReceiver.cpp new file mode 100644 index 00000000..4fef1d1c --- /dev/null +++ b/src/osc/OSCClientReceiver.cpp @@ -0,0 +1,303 @@ +/* This file is part of Ingen. + * Copyright 2007-2011 David Robillard + * + * Ingen is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#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 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 -- cgit v1.2.1