diff options
author | David Robillard <d@drobilla.net> | 2008-09-30 16:50:21 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-09-30 16:50:21 +0000 |
commit | 93850c202de8b073a1ce1dd8bd246d407bce4e2f (patch) | |
tree | 6910b135bf4eff12de1af116cef73f6e9c107cd0 /src/client/OSCClientReceiver.cpp | |
parent | a8bf5272d096de73507d2eab47f282c345f4ca8a (diff) | |
download | ingen-93850c202de8b073a1ce1dd8bd246d407bce4e2f.tar.gz ingen-93850c202de8b073a1ce1dd8bd246d407bce4e2f.tar.bz2 ingen-93850c202de8b073a1ce1dd8bd246d407bce4e2f.zip |
Flatten ingen source directory heirarchy a bit.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@1551 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/client/OSCClientReceiver.cpp')
-rw-r--r-- | src/client/OSCClientReceiver.cpp | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/src/client/OSCClientReceiver.cpp b/src/client/OSCClientReceiver.cpp new file mode 100644 index 00000000..8ebd9d8e --- /dev/null +++ b/src/client/OSCClientReceiver.cpp @@ -0,0 +1,394 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 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 "OSCClientReceiver.hpp" +#include <raul/AtomLiblo.hpp> +#include <list> +#include <cassert> +#include <cstring> +#include <iostream> +#include <sstream> + +using namespace std; +using namespace Raul; + +namespace Ingen { +namespace Client { + + +OSCClientReceiver::OSCClientReceiver(int listen_port, SharedPtr<Shared::ClientInterface> target) + : _target(target) + , _listen_port(listen_port) + , _st(NULL) +{ + start(false); // true = dump, false = shutup +} + + +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) { + cerr << "[OSCClientReceiver] Could not start OSC listener. Aborting." << endl; + exit(EXIT_FAILURE); + } else { + cout << "[OSCClientReceiver] 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("[OSCMsg] %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"); + + /*for (int i=0; i < argc; ++i) { + printf(" '%c' ", types[i]); + lo_arg_pp(lo_type(types[i]), argv[i]); + printf("\n"); + } + printf("\n");*/ + + return 1; // not handled +} + + +void +OSCClientReceiver::lo_error_cb(int num, const char* msg, const char* path) +{ + cerr << "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; + + cerr << msg << endl; + + return 0; +} + + +void +OSCClientReceiver::setup_callbacks() +{ + lo_server_thread_add_method(_st, "/ingen/ok", "i", response_ok_cb, this); + lo_server_thread_add_method(_st, "/ingen/error", "is", response_error_cb, this); + lo_server_thread_add_method(_st, "/ingen/plugin", "ssss", plugin_cb, this); + lo_server_thread_add_method(_st, "/ingen/new_patch", "si", new_patch_cb, this); + lo_server_thread_add_method(_st, "/ingen/destroyed", "s", destroyed_cb, this); + lo_server_thread_add_method(_st, "/ingen/patch_cleared", "s", patch_cleared_cb, this); + lo_server_thread_add_method(_st, "/ingen/object_renamed", "ss", object_renamed_cb, this); + lo_server_thread_add_method(_st, "/ingen/new_connection", "ss", connection_cb, this); + lo_server_thread_add_method(_st, "/ingen/disconnection", "ss", disconnection_cb, this); + lo_server_thread_add_method(_st, "/ingen/new_node", "ss", new_node_cb, this); + lo_server_thread_add_method(_st, "/ingen/new_port", "sisi", new_port_cb, this); + lo_server_thread_add_method(_st, "/ingen/set_variable", NULL, set_variable_cb, this); + lo_server_thread_add_method(_st, "/ingen/set_property", NULL, set_property_cb, this); + lo_server_thread_add_method(_st, "/ingen/set_port_value", "sf", set_port_value_cb, this); + lo_server_thread_add_method(_st, "/ingen/set_voice_value", "sif", set_voice_value_cb, this); + lo_server_thread_add_method(_st, "/ingen/port_activity", "s", port_activity_cb, this); + lo_server_thread_add_method(_st, "/ingen/program_add", "siis", program_add_cb, this); + lo_server_thread_add_method(_st, "/ingen/program_remove", "sii", program_remove_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::_new_patch_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + _target->new_patch(&argv[0]->s, argv[1]->i); // path, poly + return 0; +} + + +int +OSCClientReceiver::_destroyed_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + _target->destroy((const char*)&argv[0]->s); + return 0; +} + + +int +OSCClientReceiver::_patch_cleared_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + _target->patch_cleared((const char*)&argv[0]->s); + return 0; +} + + +int +OSCClientReceiver::_object_renamed_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + _target->object_renamed((const char*)&argv[0]->s, (const char*)&argv[1]->s); + 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_port_path = &argv[0]->s; + const char* dst_port_path = &argv[1]->s; + + _target->disconnect(src_port_path, dst_port_path); + + return 0; +} + + +/** Notification of a new node creation. + */ +int +OSCClientReceiver::_new_node_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* uri = &argv[0]->s; + const char* node_path = &argv[1]->s; + + _target->new_node(uri, node_path); + + return 0; +} + + +/** Notification of a new port creation. + */ +int +OSCClientReceiver::_new_port_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* port_path = &argv[0]->s; + const uint32_t index = argv[1]->i; + const char* type = &argv[2]->s; + const bool is_output = (argv[3]->i == 1); + + _target->new_port(port_path, index, type, is_output); + + return 0; +} + + +/** Notification of a new or updated variable. + */ +int +OSCClientReceiver::_set_variable_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_path = &argv[0]->s; + const char* key = &argv[1]->s; + + Atom value = AtomLiblo::lo_arg_to_atom(types[2], argv[2]); + + _target->set_variable(obj_path, key, value); + + 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_path = &argv[0]->s; + const char* key = &argv[1]->s; + + Atom value = AtomLiblo::lo_arg_to_atom(types[2], argv[2]); + + _target->set_property(obj_path, key, value); + + return 0; +} + + +int +OSCClientReceiver::_set_port_value_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* const port_path = &argv[0]->s; + const float value = argv[1]->f; + + _target->set_port_value(port_path, value); + + return 0; +} + + +int +OSCClientReceiver::_set_voice_value_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* const port_path = &argv[0]->s; + const int voice = argv[1]->i; + const float value = argv[2]->f; + + _target->set_voice_value(port_path, voice, value); + + return 0; +} + + +int +OSCClientReceiver::_port_activity_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* const port_path = &argv[0]->s; + + _target->port_activity(port_path); + + 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; +} + + +/** A plugin info response from the server, in response to an /ingen/send_plugins + */ +int +OSCClientReceiver::_plugin_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + assert(argc == 4 && !strcmp(types, "ssss")); + _target->new_plugin(&argv[0]->s, &argv[1]->s, &argv[2]->s, &argv[3]->s); // uri, type, symbol, name + + return 0; +} + + +int +OSCClientReceiver::_program_add_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* node_path = &argv[0]->s; + int32_t bank = argv[1]->i; + int32_t program = argv[2]->i; + const char* name = &argv[3]->s; + + _target->program_add(node_path, bank, program, name); + + return 0; +} + + +int +OSCClientReceiver::_program_remove_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* node_path = &argv[0]->s; + int32_t bank = argv[1]->i; + int32_t program = argv[2]->i; + + _target->program_remove(node_path, bank, program); + + return 0; +} + + +} // namespace Client +} // namespace Ingen |