From 43d51948ccae71b8f0a1c1710e25cf36da8d7d7c Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 8 Sep 2006 06:23:25 +0000 Subject: Renamed communications classes for consistency. Removed engine dependency on OSC (mostly). git-svn-id: http://svn.drobilla.net/lad/ingen@120 a436a847-0d15-0410-975c-d299462d15a1 --- src/libs/client/Makefile.am | 8 +- src/libs/client/ModelEngineInterface.h | 1 - src/libs/client/OSCClientReceiver.cpp | 415 ++++++++++++++++++++++++++++ src/libs/client/OSCClientReceiver.h | 120 ++++++++ src/libs/client/OSCEngineInterface.cpp | 348 ----------------------- src/libs/client/OSCEngineInterface.h | 145 ---------- src/libs/client/OSCEngineSender.cpp | 348 +++++++++++++++++++++++ src/libs/client/OSCEngineSender.h | 145 ++++++++++ src/libs/client/OSCListener.cpp | 415 ---------------------------- src/libs/client/OSCListener.h | 121 -------- src/libs/client/OSCModelEngineInterface.cpp | 4 +- src/libs/client/OSCModelEngineInterface.h | 13 +- src/libs/client/Store.cpp | 2 +- 13 files changed, 1038 insertions(+), 1047 deletions(-) create mode 100644 src/libs/client/OSCClientReceiver.cpp create mode 100644 src/libs/client/OSCClientReceiver.h delete mode 100644 src/libs/client/OSCEngineInterface.cpp delete mode 100644 src/libs/client/OSCEngineInterface.h create mode 100644 src/libs/client/OSCEngineSender.cpp create mode 100644 src/libs/client/OSCEngineSender.h delete mode 100644 src/libs/client/OSCListener.cpp delete mode 100644 src/libs/client/OSCListener.h (limited to 'src/libs/client') diff --git a/src/libs/client/Makefile.am b/src/libs/client/Makefile.am index 01cff357..f8a9a1cf 100644 --- a/src/libs/client/Makefile.am +++ b/src/libs/client/Makefile.am @@ -7,12 +7,12 @@ libomclient_la_CXXFLAGS = -I$(top_srcdir)/src/common -DPKGDATADIR=\"$(pkgdatadir libomclient_la_SOURCES = \ ClientInterface.h \ - OSCEngineInterface.h \ - OSCEngineInterface.cpp \ + OSCEngineSender.h \ + OSCEngineSender.cpp \ OSCModelEngineInterface.h \ OSCModelEngineInterface.cpp \ - OSCListener.h \ - OSCListener.cpp \ + OSCClientReceiver.h \ + OSCClientReceiver.cpp \ SigClientInterface.h \ DirectSigClientInterface.h \ ThreadedSigClientInterface.h \ diff --git a/src/libs/client/ModelEngineInterface.h b/src/libs/client/ModelEngineInterface.h index 763cdc69..2bc5db14 100644 --- a/src/libs/client/ModelEngineInterface.h +++ b/src/libs/client/ModelEngineInterface.h @@ -31,7 +31,6 @@ namespace Client { class NodeModel; class PresetModel; class PatchModel; -class OSCListener; class ModelClientInterface; diff --git a/src/libs/client/OSCClientReceiver.cpp b/src/libs/client/OSCClientReceiver.cpp new file mode 100644 index 00000000..56d8ea14 --- /dev/null +++ b/src/libs/client/OSCClientReceiver.cpp @@ -0,0 +1,415 @@ +/* This file is part of Ingen. Copyright (C) 2006 Dave 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 "OSCClientReceiver.h" +//#include "NodeModel.h" +//#include "PluginModel.h" +#include +#include +#include +#include +using std::cerr; using std::cout; using std::endl; + +namespace Ingen { +namespace Client { + + +/** Construct a OSCClientReceiver with a user-provided ModelClientInterface object for notification + * of engine events. + */ +OSCClientReceiver::OSCClientReceiver(int listen_port) +: _listen_port(listen_port), + _st(NULL)//, +// _receiving_node(false), +// _receiving_node_model(NULL), +// _receiving_node_num_ports(0), +// _num_received_ports(0) +{ + start(); +} + + +OSCClientReceiver::~OSCClientReceiver() +{ + stop(); +} + + +void +OSCClientReceiver::start() +{ + if (_st != NULL) + return; + + if (_listen_port == 0) { + _st = lo_server_thread_new(NULL, error_cb); + _listen_port = lo_server_thread_get_port(_st); + } else { + char port_str[8]; + snprintf(port_str, 8, "%d", _listen_port); + _st = lo_server_thread_new(port_str, error_cb); + } + + 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; + } + + // FIXME + lo_server_thread_add_method(_st, NULL, NULL, generic_cb, NULL); + + //lo_server_thread_add_method(_st, "/om/response/ok", "i", om_response_ok_cb, this); + //lo_server_thread_add_method(_st, "/om/response/error", "is", om_responseerror_cb, this); + + 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::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) +{ + string msg = "Received unknown OSC message: "; + msg += path; + + cerr << msg << endl; + + return 0; +} + + +void +OSCClientReceiver::setup_callbacks() +{ + lo_server_thread_add_method(_st, "/om/num_plugins", "i", num_plugins_cb, this); + lo_server_thread_add_method(_st, "/om/plugin", "sss", plugin_cb, this); + lo_server_thread_add_method(_st, "/om/new_patch", "si", new_patch_cb, this); + lo_server_thread_add_method(_st, "/om/destroyed", "s", destroyed_cb, this); + lo_server_thread_add_method(_st, "/om/patch_enabled", "s", patch_enabled_cb, this); + lo_server_thread_add_method(_st, "/om/patch_disabled", "s", patch_disabled_cb, this); + lo_server_thread_add_method(_st, "/om/patch_cleared", "s", patch_cleared_cb, this); + lo_server_thread_add_method(_st, "/om/object_renamed", "ss", object_renamed_cb, this); + lo_server_thread_add_method(_st, "/om/new_connection", "ss", connection_cb, this); + lo_server_thread_add_method(_st, "/om/disconnection", "ss", disconnection_cb, this); + lo_server_thread_add_method(_st, "/om/new_node", "sssii", new_node_cb, this); + lo_server_thread_add_method(_st, "/om/new_port", "ssi", new_port_cb, this); + lo_server_thread_add_method(_st, "/om/metadata/update", "sss", metadata_update_cb, this); + lo_server_thread_add_method(_st, "/om/control_change", "sf", control_change_cb, this); + lo_server_thread_add_method(_st, "/om/program_add", "siis", program_add_cb, this); + lo_server_thread_add_method(_st, "/om/program_remove", "sii", program_remove_cb, this); +} + + +/** Catches errors that aren't a direct result of a client request. + */ +int +OSCClientReceiver::m_error_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + cerr << "ERROR: " << argv[0]->s << endl; + // FIXME + //error((char*)argv[0]); + return 0; +} + + +int +OSCClientReceiver::m_new_patch_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + new_patch(&argv[0]->s, argv[1]->i); // path, poly + return 0; +} + + +int +OSCClientReceiver::m_destroyed_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + object_destroyed((const char*)&argv[0]->s); + return 0; +} + + +int +OSCClientReceiver::m_patch_enabled_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + patch_enabled((const char*)&argv[0]->s); + return 0; +} + + +int +OSCClientReceiver::m_patch_disabled_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + patch_disabled((const char*)&argv[0]->s); + return 0; +} + + +int +OSCClientReceiver::m_patch_cleared_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + patch_cleared((const char*)&argv[0]->s); + return 0; +} + + +int +OSCClientReceiver::m_object_renamed_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + object_renamed((const char*)&argv[0]->s, (const char*)&argv[1]->s); + return 0; +} + + +int +OSCClientReceiver::m_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; + + connection(src_port_path, dst_port_path); + + return 0; +} + + +int +OSCClientReceiver::m_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; + + disconnection(src_port_path, dst_port_path); + + return 0; +} + + +/** Notification of a new node creation. + */ +int +OSCClientReceiver::m_new_node_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* type = &argv[0]->s; + const char* uri = &argv[1]->s; + const char* node_path = &argv[2]->s; + const int32_t poly = argv[3]->i; + const int32_t num_ports = argv[4]->i; + + new_node(type, uri, node_path, poly, num_ports); + + /*_receiving_node_model = new NodeModel(node_path); + _receiving_node_model->polyphonic((poly == 1)); + _receiving_node_num_ports = num_ports; + + PluginModel* pi = new PluginModel(type, uri); + _receiving_node_model->plugin(pi); + + _receiving_node = true; + _num_received_ports = 0; + */ + return 0; +} + + +/** Notification of a new port creation. + */ +int +OSCClientReceiver::m_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 char* type = &argv[1]->s; + bool is_output = (argv[2]->i == 1); + /*const char* direction = &argv[2]->s; + const char* hint = &argv[3]->s; + float default_val = argv[4]->f; + float min_val = argv[5]->f; + float max_val = argv[6]->f;*/ + + new_port(port_path, type, is_output); +#if 0 + PortModel::Type ptype = PortModel::CONTROL; + if (!strcmp(type, "AUDIO")) ptype = PortModel::AUDIO; + else if (!strcmp(type, "CONTROL")) ptype = PortModel::CONTROL; + else if (!strcmp(type, "MIDI")) ptype = PortModel::MIDI; + else cerr << "[OSCClientReceiver] WARNING: Unknown port type received (" << type << ")" << endl; + +#if 0 + PortModel::Direction pdir = PortModel::INPUT; + if (!strcmp(direction, "INPUT")) pdir = PortModel::INPUT; + else if (!strcmp(direction, "OUTPUT")) pdir = PortModel::OUTPUT; + else cerr << "[OSCClientReceiver] WARNING: Unknown port direction received (" << direction << ")" << endl; +#endif + PortModel::Direction pdir = is_output ? PortModel::OUTPUT : PortModel::INPUT; + +/* + PortModel::Hint phint = PortModel::NONE; + if (!strcmp(hint, "LOGARITHMIC")) phint = PortModel::LOGARITHMIC; + else if (!strcmp(hint, "INTEGER")) phint = PortModel::INTEGER; + else if (!strcmp(hint, "TOGGLE")) phint = PortModel::TOGGLE; + + PortModel* port_model = new PortModel(port_path, ptype, pdir, phint, default_val, min_val, max_val); +*/ + PortModel* port_model = new PortModel(port_path, ptype, pdir); + if (m_receiving_node) { + assert(m_receiving_node_model); + m_receiving_node_model->add_port(port_model); + ++m_num_received_ports; + + // If transmission is done, send new node to client + if (m_num_received_ports == m_receiving_node_num_ports) { + new_node_model(m_receiving_node_model); + m_receiving_node = false; + m_receiving_node_model = NULL; + m_num_received_ports = 0; + } + } else { + new_port_model(port_model); + } + +#endif + return 0; +} + + +/** Notification of a new or updated piece of metadata. + */ +int +OSCClientReceiver::m_metadata_update_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* obj_path = &argv[0]->s; + const char* key = &argv[1]->s; + const char* value = &argv[2]->s; + + metadata_update(obj_path, key, value); + + return 0; +} + + +int +OSCClientReceiver::m_control_change_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; + + control_change(port_path, value); + + return 0; +} + + +/** Number of plugins in engine, should precede /om/plugin messages in response + * to a /om/send_plugins + */ +int +OSCClientReceiver::m_num_plugins_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + /** Not worth it implementing a ModelClientInterface callback for this (?) + * Or I'm just lazy. FIXME? */ + num_plugins(argv[0]->i); + + return 0; +} + + +/** A plugin info response from the server, in response to a /send_plugins + */ +int +OSCClientReceiver::m_plugin_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + assert(argc == 3 && !strcmp(types, "sss")); + new_plugin(&argv[0]->s, &argv[1]->s, &argv[2]->s); // type, uri + + return 0; +} + + +int +OSCClientReceiver::m_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; + + program_add(node_path, bank, program, name); + + return 0; +} + + +int +OSCClientReceiver::m_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; + + program_remove(node_path, bank, program); + + return 0; +} + + +} // namespace Client +} // namespace Ingen diff --git a/src/libs/client/OSCClientReceiver.h b/src/libs/client/OSCClientReceiver.h new file mode 100644 index 00000000..60fa9495 --- /dev/null +++ b/src/libs/client/OSCClientReceiver.h @@ -0,0 +1,120 @@ +/* This file is part of Ingen. Copyright (C) 2006 Dave 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 + */ + +#ifndef OSCCLIENTRECEIVER_H +#define OSCCLIENTRECEIVER_H + +#include +#include +#include "interface/ClientInterface.h" + +namespace Ingen { + +/** Client library */ +namespace Client { + +//class NodeModel; +//class PresetModel; + +/* Some boilerplate killing macros... */ +#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 LO_HANDLER(name) \ +int m_##name##_cb (LO_HANDLER_ARGS);\ +inline static int name##_cb(LO_HANDLER_ARGS, void* osc_listener)\ +{ return ((OSCClientReceiver*)osc_listener)->m_##name##_cb(path, types, argv, argc, msg); } + + +/** Callbacks for "notification band" OSC messages. + * + * Receives all notification of engine state, but not replies on the "control + * band". See OSC namespace documentation for details. + * + * Right now this class and Comm share the same lo_server_thread and the barrier + * between them is a bit odd, but eventually this class will be able to listen + * on a completely different port (ie have it's own lo_server_thread) to allow + * things like listening to the notification band over TCP while sending commands + * on the control band over UDP. + * + * \ingroup IngenClient + */ +class OSCClientReceiver : virtual public Ingen::Shared::ClientInterface +{ +public: + OSCClientReceiver(int listen_port); + ~OSCClientReceiver(); + + void start(); + void stop(); + + int listen_port() { return _listen_port; } + string listen_url() { return lo_server_thread_get_url(_st); } + +private: + // Prevent copies + OSCClientReceiver(const OSCClientReceiver& copy); + OSCClientReceiver& operator=(const OSCClientReceiver& copy); + + void setup_callbacks(); + + static void 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); + /* + inline static int om_response_ok_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* comm); + int m_om_response_ok_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data); + inline static int om_response_error_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* comm); + int m_om_response_error_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data); +*/ + int _listen_port; + lo_server_thread _st; + + // Used for receiving nodes - multiple messages are received before + // sending an event to the client (via ModelClientInterface) + //bool _receiving_node; + //NodeModel* _receiving_node_model; + //int32_t _receiving_node_num_ports; + //int32_t _num_received_ports; + + LO_HANDLER(error); + LO_HANDLER(num_plugins); + LO_HANDLER(plugin); + LO_HANDLER(plugin_list_end); + LO_HANDLER(new_patch); + LO_HANDLER(destroyed); + LO_HANDLER(patch_enabled); + LO_HANDLER(patch_disabled); + LO_HANDLER(patch_cleared); + LO_HANDLER(object_renamed); + LO_HANDLER(connection); + LO_HANDLER(disconnection); + LO_HANDLER(new_node); + LO_HANDLER(new_port); + LO_HANDLER(metadata_update); + LO_HANDLER(control_change); + LO_HANDLER(program_add); + LO_HANDLER(program_remove); +}; + + +} // namespace Client + +} // namespace Ingen + +#endif // OSCCLIENTRECEIVER_H diff --git a/src/libs/client/OSCEngineInterface.cpp b/src/libs/client/OSCEngineInterface.cpp deleted file mode 100644 index b747e2e4..00000000 --- a/src/libs/client/OSCEngineInterface.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave 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 "OSCEngineInterface.h" -#include "interface/ClientKey.h" - -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 :/ - */ -OSCEngineInterface::OSCEngineInterface(const string& engine_url) -: _engine_url(engine_url) -, _engine_addr(lo_address_new_from_url(engine_url.c_str())) -, _id(0) -{ -} - - -OSCEngineInterface::~OSCEngineInterface() -{ - lo_address_free(_engine_addr); -} - - -/* *** EngineInterface implementation below here *** */ - - -/** Register with the engine via OSC. - * - * Note that this does not actually use 'key', 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 EngineInterface. - */ -void -OSCEngineInterface::register_client(ClientKey key, CountedPtr client) -{ - // FIXME: use parameters.. er, somehow. - assert(_engine_addr); - lo_send(_engine_addr, "/om/engine/register_client", "i", next_id()); -} - - -void -OSCEngineInterface::unregister_client(ClientKey key) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/engine/unregister_client", "i", next_id()); -} - - - -// Engine commands -void -OSCEngineInterface::load_plugins() -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/engine/load_plugins", "i", next_id()); -} - - -void -OSCEngineInterface::activate() -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/engine/activate", "i", next_id()); -} - - -void -OSCEngineInterface::deactivate() -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/engine/deactivate", "i", next_id()); -} - - -void -OSCEngineInterface::quit() -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/engine/quit", "i", next_id()); -} - - - -// Object commands - -void -OSCEngineInterface::create_patch(const string& path, - uint32_t poly) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/create_patch", "isi", - next_id(), - path.c_str(), - poly); -} - - -void -OSCEngineInterface::create_port(const string& path, - const string& data_type, - bool is_output) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/create_port", "issi", - next_id(), - path.c_str(), - data_type.c_str(), - (is_output ? 1 : 0)); -} - - -void -OSCEngineInterface::create_node(const string& path, - const string& plugin_type, - const string& plugin_uri, - bool polyphonic) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/create_node", "isssi", - next_id(), - path.c_str(), - plugin_type.c_str(), - plugin_uri.c_str(), - (polyphonic ? 1 : 0)); -} - - -void -OSCEngineInterface::rename(const string& old_path, - const string& new_name) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/rename", "iss", - next_id(), - old_path.c_str(), - new_name.c_str()); -} - - -void -OSCEngineInterface::destroy(const string& path) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/destroy", "is", - next_id(), - path.c_str()); -} - - -void -OSCEngineInterface::clear_patch(const string& patch_path) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/clear_patch", "is", - next_id(), - patch_path.c_str()); -} - - -void -OSCEngineInterface::enable_patch(const string& patch_path) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/enable_patch", "is", - next_id(), - patch_path.c_str()); -} - - -void -OSCEngineInterface::disable_patch(const string& patch_path) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/disable_patch", "is", - next_id(), - patch_path.c_str()); -} - - -void -OSCEngineInterface::connect(const string& src_port_path, - const string& dst_port_path) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/connect", "iss", - next_id(), - src_port_path.c_str(), - dst_port_path.c_str()); -} - - -void -OSCEngineInterface::disconnect(const string& src_port_path, - const string& dst_port_path) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/disconnect", "iss", - next_id(), - src_port_path.c_str(), - dst_port_path.c_str()); -} - - -void -OSCEngineInterface::disconnect_all(const string& node_path) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/disconnect_all", "is", - next_id(), - node_path.c_str()); -} - - -void -OSCEngineInterface::set_port_value(const string& port_path, - float val) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/set_port_value", "isf", - next_id(), - port_path.c_str(), - val); -} - - -void -OSCEngineInterface::set_port_value(const string& port_path, - uint32_t voice, - float val) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/set_port_value", "isif", - next_id(), - port_path.c_str(), - voice, - val); -} - - -void -OSCEngineInterface::set_port_value_queued(const string& port_path, - float val) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/set_port_value_queued", "isf", - next_id(), - port_path.c_str(), - val); -} - - -void -OSCEngineInterface::set_program(const string& node_path, - uint32_t bank, - uint32_t program) -{ - assert(_engine_addr); - lo_send(_engine_addr, - (string("/dssi") + node_path + "/program").c_str(), - "ii", - bank, - program); -} - - -void -OSCEngineInterface::midi_learn(const string& node_path) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/synth/midi_learn", "is", - next_id(), - node_path.c_str()); -} - - -void -OSCEngineInterface::set_metadata(const string& obj_path, - const string& predicate, - const string& value) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/metadata/set", "isss", - next_id(), - obj_path.c_str(), - predicate.c_str(), - value.c_str()); -} - - -// Requests // - -void -OSCEngineInterface::ping() -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/ping", "i", next_id()); -} - - -void -OSCEngineInterface::request_port_value(const string& port_path) -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/request/port_value", "is", - next_id(), - port_path.c_str()); -} - - -void -OSCEngineInterface::request_plugins() -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/request/plugins", "i", next_id()); -} - - -void -OSCEngineInterface::request_all_objects() -{ - assert(_engine_addr); - lo_send(_engine_addr, "/om/request/all_objects", "i", next_id()); -} - - - -} // namespace Client -} // namespace Ingen - - diff --git a/src/libs/client/OSCEngineInterface.h b/src/libs/client/OSCEngineInterface.h deleted file mode 100644 index 4405438c..00000000 --- a/src/libs/client/OSCEngineInterface.h +++ /dev/null @@ -1,145 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave 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 - */ - -#ifndef OSCENGINEINTERFACE_H -#define OSCENGINEINTERFACE_H - -#include -#include -#include -#include "interface/EngineInterface.h" -using std::string; -using Ingen::Shared::EngineInterface; -using Ingen::Shared::ClientInterface; -using Ingen::Shared::ClientKey; - - -namespace Ingen { -namespace Client { - -/* OSC (via liblo) interface to the engine. - * - * Clients can use this opaquely as an EngineInterface* to control the engine - * over OSC (whether over a network or not, etc). - * - * \ingroup IngenClient - */ -class OSCEngineInterface : public EngineInterface -{ -public: - OSCEngineInterface(const string& engine_url); - - ~OSCEngineInterface(); - - string engine_url() { return _engine_url; } - - inline size_t next_id() - { if (_id != -1) { _id = (_id == -2) ? 0 : _id+1; } return _id; } - - void enable_responses() { _id = 0; } - void disable_responses() { _id = -1; } - - - /* *** EngineInterface implementation below here *** */ - - // Client registration - void register_client(ClientKey key, CountedPtr client); - void unregister_client(ClientKey key); - - - // Engine commands - void load_plugins(); - void activate(); - void deactivate(); - void quit(); - - - // Object commands - - void create_patch(const string& path, - uint32_t poly); - - void create_port(const string& path, - const string& data_type, - bool is_output); - - void create_node(const string& path, - const string& plugin_type, - const string& plugin_uri, - bool polyphonic); - - void rename(const string& old_path, - const string& new_name); - - void destroy(const string& path); - - void clear_patch(const string& patch_path); - - void enable_patch(const string& patch_path); - - void disable_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& node_path); - - void set_port_value(const string& port_path, - float val); - - void set_port_value(const string& port_path, - uint32_t voice, - float val); - - void set_port_value_queued(const string& port_path, - float val); - - void set_program(const string& node_path, - uint32_t bank, - uint32_t program); - - void midi_learn(const string& node_path); - - void set_metadata(const string& obj_path, - const string& predicate, - const string& value); - - // Requests // - - void ping(); - - void request_port_value(const string& port_path); - - void request_plugins(); - - void request_all_objects(); - -protected: - string _engine_url; - lo_address _engine_addr; - int _client_port; - int32_t _id; -}; - - -} // namespace Client -} // namespace Ingen - -#endif // OSCENGINEINTERFACE_H - diff --git a/src/libs/client/OSCEngineSender.cpp b/src/libs/client/OSCEngineSender.cpp new file mode 100644 index 00000000..cc70dc8e --- /dev/null +++ b/src/libs/client/OSCEngineSender.cpp @@ -0,0 +1,348 @@ +/* This file is part of Ingen. Copyright (C) 2006 Dave 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 "OSCEngineSender.h" +#include "interface/ClientKey.h" + +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 string& engine_url) +: _engine_url(engine_url) +, _engine_addr(lo_address_new_from_url(engine_url.c_str())) +, _id(0) +{ +} + + +OSCEngineSender::~OSCEngineSender() +{ + lo_address_free(_engine_addr); +} + + +/* *** EngineInterface implementation below here *** */ + + +/** Register with the engine via OSC. + * + * Note that this does not actually use 'key', 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 EngineInterface. + */ +void +OSCEngineSender::register_client(ClientKey key, CountedPtr client) +{ + // FIXME: use parameters.. er, somehow. + assert(_engine_addr); + lo_send(_engine_addr, "/om/engine/register_client", "i", next_id()); +} + + +void +OSCEngineSender::unregister_client(ClientKey key) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/engine/unregister_client", "i", next_id()); +} + + + +// Engine commands +void +OSCEngineSender::load_plugins() +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/engine/load_plugins", "i", next_id()); +} + + +void +OSCEngineSender::activate() +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/engine/activate", "i", next_id()); +} + + +void +OSCEngineSender::deactivate() +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/engine/deactivate", "i", next_id()); +} + + +void +OSCEngineSender::quit() +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/engine/quit", "i", next_id()); +} + + + +// Object commands + +void +OSCEngineSender::create_patch(const string& path, + uint32_t poly) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/create_patch", "isi", + next_id(), + path.c_str(), + poly); +} + + +void +OSCEngineSender::create_port(const string& path, + const string& data_type, + bool is_output) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/create_port", "issi", + next_id(), + path.c_str(), + data_type.c_str(), + (is_output ? 1 : 0)); +} + + +void +OSCEngineSender::create_node(const string& path, + const string& plugin_type, + const string& plugin_uri, + bool polyphonic) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/create_node", "isssi", + next_id(), + path.c_str(), + plugin_type.c_str(), + plugin_uri.c_str(), + (polyphonic ? 1 : 0)); +} + + +void +OSCEngineSender::rename(const string& old_path, + const string& new_name) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/rename", "iss", + next_id(), + old_path.c_str(), + new_name.c_str()); +} + + +void +OSCEngineSender::destroy(const string& path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/destroy", "is", + next_id(), + path.c_str()); +} + + +void +OSCEngineSender::clear_patch(const string& patch_path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/clear_patch", "is", + next_id(), + patch_path.c_str()); +} + + +void +OSCEngineSender::enable_patch(const string& patch_path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/enable_patch", "is", + next_id(), + patch_path.c_str()); +} + + +void +OSCEngineSender::disable_patch(const string& patch_path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/disable_patch", "is", + next_id(), + patch_path.c_str()); +} + + +void +OSCEngineSender::connect(const string& src_port_path, + const string& dst_port_path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/connect", "iss", + next_id(), + src_port_path.c_str(), + dst_port_path.c_str()); +} + + +void +OSCEngineSender::disconnect(const string& src_port_path, + const string& dst_port_path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/disconnect", "iss", + next_id(), + src_port_path.c_str(), + dst_port_path.c_str()); +} + + +void +OSCEngineSender::disconnect_all(const string& node_path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/disconnect_all", "is", + next_id(), + node_path.c_str()); +} + + +void +OSCEngineSender::set_port_value(const string& port_path, + float val) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/set_port_value", "isf", + next_id(), + port_path.c_str(), + val); +} + + +void +OSCEngineSender::set_port_value(const string& port_path, + uint32_t voice, + float val) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/set_port_value", "isif", + next_id(), + port_path.c_str(), + voice, + val); +} + + +void +OSCEngineSender::set_port_value_queued(const string& port_path, + float val) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/set_port_value_queued", "isf", + next_id(), + port_path.c_str(), + val); +} + + +void +OSCEngineSender::set_program(const string& node_path, + uint32_t bank, + uint32_t program) +{ + assert(_engine_addr); + lo_send(_engine_addr, + (string("/dssi") + node_path + "/program").c_str(), + "ii", + bank, + program); +} + + +void +OSCEngineSender::midi_learn(const string& node_path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/synth/midi_learn", "is", + next_id(), + node_path.c_str()); +} + + +void +OSCEngineSender::set_metadata(const string& obj_path, + const string& predicate, + const string& value) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/metadata/set", "isss", + next_id(), + obj_path.c_str(), + predicate.c_str(), + value.c_str()); +} + + +// Requests // + +void +OSCEngineSender::ping() +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/ping", "i", next_id()); +} + + +void +OSCEngineSender::request_port_value(const string& port_path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/request/port_value", "is", + next_id(), + port_path.c_str()); +} + + +void +OSCEngineSender::request_plugins() +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/request/plugins", "i", next_id()); +} + + +void +OSCEngineSender::request_all_objects() +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/request/all_objects", "i", next_id()); +} + + + +} // namespace Client +} // namespace Ingen + + diff --git a/src/libs/client/OSCEngineSender.h b/src/libs/client/OSCEngineSender.h new file mode 100644 index 00000000..184c0569 --- /dev/null +++ b/src/libs/client/OSCEngineSender.h @@ -0,0 +1,145 @@ +/* This file is part of Ingen. Copyright (C) 2006 Dave 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 + */ + +#ifndef OSCENGINESENDER_H +#define OSCENGINESENDER_H + +#include +#include +#include +#include "interface/EngineInterface.h" +using std::string; +using Ingen::Shared::EngineInterface; +using Ingen::Shared::ClientInterface; +using Ingen::Shared::ClientKey; + + +namespace Ingen { +namespace Client { + +/* OSC (via liblo) interface to the engine. + * + * Clients can use this opaquely as an EngineInterface* to control the engine + * over OSC (whether over a network or not, etc). + * + * \ingroup IngenClient + */ +class OSCEngineSender : public EngineInterface +{ +public: + OSCEngineSender(const string& engine_url); + + ~OSCEngineSender(); + + string engine_url() { return _engine_url; } + + inline size_t next_id() + { if (_id != -1) { _id = (_id == -2) ? 0 : _id+1; } return _id; } + + void enable_responses() { _id = 0; } + void disable_responses() { _id = -1; } + + + /* *** EngineInterface implementation below here *** */ + + // Client registration + void register_client(ClientKey key, CountedPtr client); + void unregister_client(ClientKey key); + + + // Engine commands + void load_plugins(); + void activate(); + void deactivate(); + void quit(); + + + // Object commands + + void create_patch(const string& path, + uint32_t poly); + + void create_port(const string& path, + const string& data_type, + bool is_output); + + void create_node(const string& path, + const string& plugin_type, + const string& plugin_uri, + bool polyphonic); + + void rename(const string& old_path, + const string& new_name); + + void destroy(const string& path); + + void clear_patch(const string& patch_path); + + void enable_patch(const string& patch_path); + + void disable_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& node_path); + + void set_port_value(const string& port_path, + float val); + + void set_port_value(const string& port_path, + uint32_t voice, + float val); + + void set_port_value_queued(const string& port_path, + float val); + + void set_program(const string& node_path, + uint32_t bank, + uint32_t program); + + void midi_learn(const string& node_path); + + void set_metadata(const string& obj_path, + const string& predicate, + const string& value); + + // Requests // + + void ping(); + + void request_port_value(const string& port_path); + + void request_plugins(); + + void request_all_objects(); + +protected: + string _engine_url; + lo_address _engine_addr; + int _client_port; + int32_t _id; +}; + + +} // namespace Client +} // namespace Ingen + +#endif // OSCENGINESENDER_H + diff --git a/src/libs/client/OSCListener.cpp b/src/libs/client/OSCListener.cpp deleted file mode 100644 index c63ffd85..00000000 --- a/src/libs/client/OSCListener.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave 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 "OSCListener.h" -//#include "NodeModel.h" -//#include "PluginModel.h" -#include -#include -#include -#include -using std::cerr; using std::cout; using std::endl; - -namespace Ingen { -namespace Client { - - -/** Construct a OSCListener with a user-provided ModelClientInterface object for notification - * of engine events. - */ -OSCListener::OSCListener(int listen_port) -: _listen_port(listen_port), - _st(NULL)//, -// _receiving_node(false), -// _receiving_node_model(NULL), -// _receiving_node_num_ports(0), -// _num_received_ports(0) -{ - start(); -} - - -OSCListener::~OSCListener() -{ - stop(); -} - - -void -OSCListener::start() -{ - if (_st != NULL) - return; - - if (_listen_port == 0) { - _st = lo_server_thread_new(NULL, error_cb); - _listen_port = lo_server_thread_get_port(_st); - } else { - char port_str[8]; - snprintf(port_str, 8, "%d", _listen_port); - _st = lo_server_thread_new(port_str, error_cb); - } - - if (_st == NULL) { - cerr << "[OSCListener] Could not start OSC listener. Aborting." << endl; - exit(EXIT_FAILURE); - } else { - cout << "[OSCListener] Started OSC listener on port " << lo_server_thread_get_port(_st) << endl; - } - - // FIXME - lo_server_thread_add_method(_st, NULL, NULL, generic_cb, NULL); - - //lo_server_thread_add_method(_st, "/om/response/ok", "i", om_response_ok_cb, this); - //lo_server_thread_add_method(_st, "/om/response/error", "is", om_responseerror_cb, this); - - 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 -OSCListener::stop() -{ - if (_st != NULL) { - //unregister_client(); - lo_server_thread_free(_st); - _st = NULL; - } -} - - -int -OSCListener::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 -OSCListener::error_cb(int num, const char* msg, const char* path) -{ - cerr << "Got error from server: " << msg << endl; -} - - - -int -OSCListener::unknown_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data) -{ - string msg = "Received unknown OSC message: "; - msg += path; - - cerr << msg << endl; - - return 0; -} - - -void -OSCListener::setup_callbacks() -{ - lo_server_thread_add_method(_st, "/om/num_plugins", "i", num_plugins_cb, this); - lo_server_thread_add_method(_st, "/om/plugin", "sss", plugin_cb, this); - lo_server_thread_add_method(_st, "/om/new_patch", "si", new_patch_cb, this); - lo_server_thread_add_method(_st, "/om/destroyed", "s", destroyed_cb, this); - lo_server_thread_add_method(_st, "/om/patch_enabled", "s", patch_enabled_cb, this); - lo_server_thread_add_method(_st, "/om/patch_disabled", "s", patch_disabled_cb, this); - lo_server_thread_add_method(_st, "/om/patch_cleared", "s", patch_cleared_cb, this); - lo_server_thread_add_method(_st, "/om/object_renamed", "ss", object_renamed_cb, this); - lo_server_thread_add_method(_st, "/om/new_connection", "ss", connection_cb, this); - lo_server_thread_add_method(_st, "/om/disconnection", "ss", disconnection_cb, this); - lo_server_thread_add_method(_st, "/om/new_node", "sssii", new_node_cb, this); - lo_server_thread_add_method(_st, "/om/new_port", "ssi", new_port_cb, this); - lo_server_thread_add_method(_st, "/om/metadata/update", "sss", metadata_update_cb, this); - lo_server_thread_add_method(_st, "/om/control_change", "sf", control_change_cb, this); - lo_server_thread_add_method(_st, "/om/program_add", "siis", program_add_cb, this); - lo_server_thread_add_method(_st, "/om/program_remove", "sii", program_remove_cb, this); -} - - -/** Catches errors that aren't a direct result of a client request. - */ -int -OSCListener::m_error_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - cerr << "ERROR: " << argv[0]->s << endl; - // FIXME - //error((char*)argv[0]); - return 0; -} - - -int -OSCListener::m_new_patch_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - new_patch(&argv[0]->s, argv[1]->i); // path, poly - return 0; -} - - -int -OSCListener::m_destroyed_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - object_destroyed((const char*)&argv[0]->s); - return 0; -} - - -int -OSCListener::m_patch_enabled_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - patch_enabled((const char*)&argv[0]->s); - return 0; -} - - -int -OSCListener::m_patch_disabled_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - patch_disabled((const char*)&argv[0]->s); - return 0; -} - - -int -OSCListener::m_patch_cleared_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - patch_cleared((const char*)&argv[0]->s); - return 0; -} - - -int -OSCListener::m_object_renamed_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - object_renamed((const char*)&argv[0]->s, (const char*)&argv[1]->s); - return 0; -} - - -int -OSCListener::m_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; - - connection(src_port_path, dst_port_path); - - return 0; -} - - -int -OSCListener::m_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; - - disconnection(src_port_path, dst_port_path); - - return 0; -} - - -/** Notification of a new node creation. - */ -int -OSCListener::m_new_node_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* type = &argv[0]->s; - const char* uri = &argv[1]->s; - const char* node_path = &argv[2]->s; - const int32_t poly = argv[3]->i; - const int32_t num_ports = argv[4]->i; - - new_node(type, uri, node_path, poly, num_ports); - - /*_receiving_node_model = new NodeModel(node_path); - _receiving_node_model->polyphonic((poly == 1)); - _receiving_node_num_ports = num_ports; - - PluginModel* pi = new PluginModel(type, uri); - _receiving_node_model->plugin(pi); - - _receiving_node = true; - _num_received_ports = 0; - */ - return 0; -} - - -/** Notification of a new port creation. - */ -int -OSCListener::m_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 char* type = &argv[1]->s; - bool is_output = (argv[2]->i == 1); - /*const char* direction = &argv[2]->s; - const char* hint = &argv[3]->s; - float default_val = argv[4]->f; - float min_val = argv[5]->f; - float max_val = argv[6]->f;*/ - - new_port(port_path, type, is_output); -#if 0 - PortModel::Type ptype = PortModel::CONTROL; - if (!strcmp(type, "AUDIO")) ptype = PortModel::AUDIO; - else if (!strcmp(type, "CONTROL")) ptype = PortModel::CONTROL; - else if (!strcmp(type, "MIDI")) ptype = PortModel::MIDI; - else cerr << "[OSCListener] WARNING: Unknown port type received (" << type << ")" << endl; - -#if 0 - PortModel::Direction pdir = PortModel::INPUT; - if (!strcmp(direction, "INPUT")) pdir = PortModel::INPUT; - else if (!strcmp(direction, "OUTPUT")) pdir = PortModel::OUTPUT; - else cerr << "[OSCListener] WARNING: Unknown port direction received (" << direction << ")" << endl; -#endif - PortModel::Direction pdir = is_output ? PortModel::OUTPUT : PortModel::INPUT; - -/* - PortModel::Hint phint = PortModel::NONE; - if (!strcmp(hint, "LOGARITHMIC")) phint = PortModel::LOGARITHMIC; - else if (!strcmp(hint, "INTEGER")) phint = PortModel::INTEGER; - else if (!strcmp(hint, "TOGGLE")) phint = PortModel::TOGGLE; - - PortModel* port_model = new PortModel(port_path, ptype, pdir, phint, default_val, min_val, max_val); -*/ - PortModel* port_model = new PortModel(port_path, ptype, pdir); - if (m_receiving_node) { - assert(m_receiving_node_model); - m_receiving_node_model->add_port(port_model); - ++m_num_received_ports; - - // If transmission is done, send new node to client - if (m_num_received_ports == m_receiving_node_num_ports) { - new_node_model(m_receiving_node_model); - m_receiving_node = false; - m_receiving_node_model = NULL; - m_num_received_ports = 0; - } - } else { - new_port_model(port_model); - } - -#endif - return 0; -} - - -/** Notification of a new or updated piece of metadata. - */ -int -OSCListener::m_metadata_update_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* obj_path = &argv[0]->s; - const char* key = &argv[1]->s; - const char* value = &argv[2]->s; - - metadata_update(obj_path, key, value); - - return 0; -} - - -int -OSCListener::m_control_change_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; - - control_change(port_path, value); - - return 0; -} - - -/** Number of plugins in engine, should precede /om/plugin messages in response - * to a /om/send_plugins - */ -int -OSCListener::m_num_plugins_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - /** Not worth it implementing a ModelClientInterface callback for this (?) - * Or I'm just lazy. FIXME? */ - num_plugins(argv[0]->i); - - return 0; -} - - -/** A plugin info response from the server, in response to a /send_plugins - */ -int -OSCListener::m_plugin_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - assert(argc == 3 && !strcmp(types, "sss")); - new_plugin(&argv[0]->s, &argv[1]->s, &argv[2]->s); // type, uri - - return 0; -} - - -int -OSCListener::m_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; - - program_add(node_path, bank, program, name); - - return 0; -} - - -int -OSCListener::m_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; - - program_remove(node_path, bank, program); - - return 0; -} - - -} // namespace Client -} // namespace Ingen diff --git a/src/libs/client/OSCListener.h b/src/libs/client/OSCListener.h deleted file mode 100644 index 3e9d165d..00000000 --- a/src/libs/client/OSCListener.h +++ /dev/null @@ -1,121 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave 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 - */ - - -#ifndef OSCLISTENER_H -#define OSCLISTENER_H - -#include -#include -#include "interface/ClientInterface.h" - -namespace Ingen { - -/** Client library */ -namespace Client { - -//class NodeModel; -//class PresetModel; - -/* Some boilerplate killing macros... */ -#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 LO_HANDLER(name) \ -int m_##name##_cb (LO_HANDLER_ARGS);\ -inline static int name##_cb(LO_HANDLER_ARGS, void* osc_listener)\ -{ return ((OSCListener*)osc_listener)->m_##name##_cb(path, types, argv, argc, msg); } - - -/** Callbacks for "notification band" OSC messages. - * - * Receives all notification of engine state, but not replies on the "control - * band". See OSC namespace documentation for details. - * - * Right now this class and Comm share the same lo_server_thread and the barrier - * between them is a bit odd, but eventually this class will be able to listen - * on a completely different port (ie have it's own lo_server_thread) to allow - * things like listening to the notification band over TCP while sending commands - * on the control band over UDP. - * - * \ingroup IngenClient - */ -class OSCListener : virtual public Ingen::Shared::ClientInterface -{ -public: - OSCListener(int listen_port); - ~OSCListener(); - - void start(); - void stop(); - - int listen_port() { return _listen_port; } - string listen_url() { return lo_server_thread_get_url(_st); } - -private: - // Prevent copies - OSCListener(const OSCListener& copy); - OSCListener& operator=(const OSCListener& copy); - - void setup_callbacks(); - - static void 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); - /* - inline static int om_response_ok_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* comm); - int m_om_response_ok_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data); - inline static int om_response_error_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* comm); - int m_om_response_error_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data); -*/ - int _listen_port; - lo_server_thread _st; - - // Used for receiving nodes - multiple messages are received before - // sending an event to the client (via ModelClientInterface) - //bool _receiving_node; - //NodeModel* _receiving_node_model; - //int32_t _receiving_node_num_ports; - //int32_t _num_received_ports; - - LO_HANDLER(error); - LO_HANDLER(num_plugins); - LO_HANDLER(plugin); - LO_HANDLER(plugin_list_end); - LO_HANDLER(new_patch); - LO_HANDLER(destroyed); - LO_HANDLER(patch_enabled); - LO_HANDLER(patch_disabled); - LO_HANDLER(patch_cleared); - LO_HANDLER(object_renamed); - LO_HANDLER(connection); - LO_HANDLER(disconnection); - LO_HANDLER(new_node); - LO_HANDLER(new_port); - LO_HANDLER(metadata_update); - LO_HANDLER(control_change); - LO_HANDLER(program_add); - LO_HANDLER(program_remove); -}; - - -} // namespace Client - -} // namespace Ingen - -#endif // OSCLISTENER_H diff --git a/src/libs/client/OSCModelEngineInterface.cpp b/src/libs/client/OSCModelEngineInterface.cpp index 2e831705..14f2fe3a 100644 --- a/src/libs/client/OSCModelEngineInterface.cpp +++ b/src/libs/client/OSCModelEngineInterface.cpp @@ -21,7 +21,7 @@ #include #include #include -#include "OSCListener.h" +#include "OSCClientReceiver.h" #include "PatchModel.h" #include "ConnectionModel.h" #include "PresetModel.h" @@ -39,7 +39,7 @@ namespace Client { * of engine events. */ OSCModelEngineInterface::OSCModelEngineInterface(const string& engine_url) -: OSCEngineInterface(engine_url), +: OSCEngineSender(engine_url), m_request_id(0), m_is_attached(false), m_is_registered(false) diff --git a/src/libs/client/OSCModelEngineInterface.h b/src/libs/client/OSCModelEngineInterface.h index a2172e23..f600fb8f 100644 --- a/src/libs/client/OSCModelEngineInterface.h +++ b/src/libs/client/OSCModelEngineInterface.h @@ -21,7 +21,7 @@ #include #include "util/Semaphore.h" #include "interface/EngineInterface.h" -#include "OSCEngineInterface.h" +#include "OSCEngineSender.h" #include "ModelEngineInterface.h" using std::string; @@ -34,29 +34,22 @@ namespace Client { class NodeModel; class PresetModel; class PatchModel; -class OSCListener; class ModelClientInterface; /** Old model-based OSC engine command interface. * * This is an old class from before when the well-defined interfaces between - * engine and client were defined. I've wrapped it around OSCEngineInterface + * engine and client were defined. I've wrapped it around OSCEngineSender * so all the common functions are implemented there, and implemented the * remaining functions using those, for compatibility. Hopefully something * better gets figured out and this can go away completely, but for now this * gets the existing clients working through EngineInterface in the easiest * way possible. This class needs to die. * - * Old comment: - * Handles all OSC communication on the "control band". For the time being, - * manages the OSCListener which handles the "notification band", but this - * will change in the future (for complete separation). See OSC namespace - * documentation for more details. - * * \ingroup IngenClient */ -class OSCModelEngineInterface : public OSCEngineInterface, public ModelEngineInterface +class OSCModelEngineInterface : public OSCEngineSender, public ModelEngineInterface { public: //OSCModelEngineInterface(ModelClientInterface* const client_hooks, const string& engine_url); diff --git a/src/libs/client/Store.cpp b/src/libs/client/Store.cpp index 403264f2..219ea13f 100644 --- a/src/libs/client/Store.cpp +++ b/src/libs/client/Store.cpp @@ -297,7 +297,7 @@ Store::new_port_event(const string& path, const string& type, bool is_output) if (type == "AUDIO") ptype = PortModel::AUDIO; else if (type == "CONTROL") ptype = PortModel::CONTROL; else if (type== "MIDI") ptype = PortModel::MIDI; - else cerr << "[OSCListener] WARNING: Unknown port type received (" << type << ")" << endl; + else cerr << "[Store] WARNING: Unknown port type received (" << type << ")" << endl; PortModel::Direction pdir = is_output ? PortModel::OUTPUT : PortModel::INPUT; -- cgit v1.2.1