From 4e736d0b31c56a7ab397c7399b3a53f726466c78 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 9 Jun 2008 17:21:44 +0000 Subject: Bump liblo dependency to 0.24. Bundleify communications where order is relevant (fixes 'random' issues like node positions being off, ticket #89, etc). git-svn-id: http://svn.drobilla.net/lad/ingen@1248 a436a847-0d15-0410-975c-d299462d15a1 --- src/libs/client/OSCClientReceiver.cpp | 6 +- src/libs/engine/ClientBroadcaster.cpp | 16 ++++ src/libs/engine/ClientBroadcaster.hpp | 3 + src/libs/engine/OSCClientSender.cpp | 148 ++++++++++++++++---------------- src/libs/engine/OSCClientSender.hpp | 11 ++- src/libs/engine/ObjectSender.cpp | 20 +++-- src/libs/engine/events/DestroyEvent.cpp | 4 + 7 files changed, 120 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/libs/client/OSCClientReceiver.cpp b/src/libs/client/OSCClientReceiver.cpp index 6002ca59..3f5447d0 100644 --- a/src/libs/client/OSCClientReceiver.cpp +++ b/src/libs/client/OSCClientReceiver.cpp @@ -31,9 +31,9 @@ namespace Client { OSCClientReceiver::OSCClientReceiver(int listen_port) -: ClientInterface("localhost"), - _listen_port(listen_port), - _st(NULL) + : ClientInterface("localhost") + , _listen_port(listen_port) + , _st(NULL) { start(false); // true = dump, false = shutup } diff --git a/src/libs/engine/ClientBroadcaster.cpp b/src/libs/engine/ClientBroadcaster.cpp index 16785b42..a3e7bc42 100644 --- a/src/libs/engine/ClientBroadcaster.cpp +++ b/src/libs/engine/ClientBroadcaster.cpp @@ -91,6 +91,22 @@ ClientBroadcaster::client(const string& uri) } } + +void +ClientBroadcaster::bundle_begin() +{ + for (Clients::const_iterator i = _clients.begin(); i != _clients.end(); ++i) + (*i).second->bundle_begin(); +} + + +void +ClientBroadcaster::bundle_end() +{ + for (Clients::const_iterator i = _clients.begin(); i != _clients.end(); ++i) + (*i).second->bundle_end(); +} + void ClientBroadcaster::send_error(const string& msg) diff --git a/src/libs/engine/ClientBroadcaster.hpp b/src/libs/engine/ClientBroadcaster.hpp index 73353588..800f6950 100644 --- a/src/libs/engine/ClientBroadcaster.hpp +++ b/src/libs/engine/ClientBroadcaster.hpp @@ -60,6 +60,9 @@ public: //void send_client_registration(const string& url, int client_id); + void bundle_begin(); + void bundle_end(); + // Error that isn't the direct result of a request void send_error(const string& msg); diff --git a/src/libs/engine/OSCClientSender.cpp b/src/libs/engine/OSCClientSender.cpp index 7a62b3b7..aff7fa50 100644 --- a/src/libs/engine/OSCClientSender.cpp +++ b/src/libs/engine/OSCClientSender.cpp @@ -38,14 +38,15 @@ namespace Ingen { void OSCClientSender::bundle_begin() { - // FIXME: Don't split bundles as for 'transfers' + assert(!_transfer); _transfer = lo_bundle_new(LO_TT_IMMEDIATE); + _send_state = SendingBundle; + } void OSCClientSender::bundle_end() { - // FIXME: Don't split bundles as for 'transfers' transfer_end(); } @@ -53,20 +54,72 @@ OSCClientSender::bundle_end() void OSCClientSender::transfer_begin() { + //cerr << "TRANSFER {" << endl; + assert(!_transfer); _transfer = lo_bundle_new(LO_TT_IMMEDIATE); + _send_state = SendingTransfer; } void OSCClientSender::transfer_end() { + //cerr << "} TRANSFER" << endl; assert(_transfer); lo_send_bundle(_address, _transfer); lo_bundle_free(_transfer); _transfer = NULL; + _send_state = Immediate; +} + + +int +OSCClientSender::send(const char *path, const char *types, ...) +{ + if (!_enabled) + return 0; + + va_list args; + va_start(args, types); + + lo_message msg = lo_message_new(); + int ret = lo_message_add_varargs(msg, types, args); + + if (!ret) + send_message(path, msg); + + va_end(args); + + return ret; +} + + +void +OSCClientSender::send_message(const char* path, lo_message msg) +{ + // FIXME: size? liblo doesn't export this. + // Don't want to exceed max UDP packet size (1500 bytes?}) + static const size_t MAX_BUNDLE_SIZE = 1500 - 32*5; + + if (!_enabled) + return; + + if (_transfer) { + if (lo_bundle_length(_transfer) + lo_message_length(msg, path) > MAX_BUNDLE_SIZE) { + if (_send_state == SendingBundle) + cerr << "WARNING: Maximum bundle size reached, bundle split" << endl; + lo_send_bundle(_address, _transfer); + _transfer = lo_bundle_new(LO_TT_IMMEDIATE); + } + lo_bundle_add_message(_transfer, path, msg); + + } else { + lo_send_message(_address, path, msg); + } } + /*! \page client_osc_namespace Client OSC Namespace Documentation * *

NOTE: this comment doesn't really apply any longer.. sort of. @@ -149,10 +202,7 @@ OSCClientSender::response_error(int32_t id, const std::string& msg) void OSCClientSender::error(const std::string& msg) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/error", "s", msg.c_str()); + send("/ingen/error", "s", msg.c_str(), LO_ARGS_END); } @@ -173,12 +223,7 @@ OSCClientSender::error(const std::string& msg) void OSCClientSender::num_plugins(uint32_t num) { - if (!_enabled) - return; - - lo_message m = lo_message_new(); - lo_message_add_int32(m, num); - lo_send_message(_address, "/ingen/num_plugins", m); + send("/ingen/num_plugins", "i", num, LO_ARGS_END); } @@ -255,15 +300,12 @@ void OSCClientSender::new_node(const std::string& plugin_uri, bool is_polyphonic, uint32_t num_ports) { - if (!_enabled) - return; - if (is_polyphonic) - lo_send(_address, "/ingen/new_node", "ssTi", plugin_uri.c_str(), - node_path.c_str(), num_ports); + send("/ingen/new_node", "ssTi", plugin_uri.c_str(), + node_path.c_str(), num_ports, LO_ARGS_END); else - lo_send(_address, "/ingen/new_node", "ssFi", plugin_uri.c_str(), - node_path.c_str(), num_ports); + send("/ingen/new_node", "ssFi", plugin_uri.c_str(), + node_path.c_str(), num_ports, LO_ARGS_END); } @@ -289,10 +331,7 @@ OSCClientSender::new_port(const std::string& path, const std::string& data_type, bool is_output) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/new_port", "sisi", path.c_str(), index, data_type.c_str(), is_output); + send("/ingen/new_port", "sisi", path.c_str(), index, data_type.c_str(), is_output, LO_ARGS_END); } @@ -327,12 +366,9 @@ OSCClientSender::polyphonic(const std::string& path, void OSCClientSender::object_destroyed(const std::string& path) { - if (!_enabled) - return; - assert(path != "/"); - lo_send(_address, "/ingen/destroyed", "s", path.c_str()); + send("/ingen/destroyed", "s", path.c_str(), LO_ARGS_END); } @@ -343,10 +379,7 @@ OSCClientSender::object_destroyed(const std::string& path) void OSCClientSender::patch_cleared(const std::string& patch_path) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/patch_cleared", "s", patch_path.c_str()); + send("/ingen/patch_cleared", "s", patch_path.c_str(), LO_ARGS_END); } @@ -357,10 +390,7 @@ OSCClientSender::patch_cleared(const std::string& patch_path) void OSCClientSender::patch_enabled(const std::string& patch_path) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/patch_enabled", "s", patch_path.c_str()); + send("/ingen/patch_enabled", "s", patch_path.c_str(), LO_ARGS_END); } @@ -371,10 +401,7 @@ OSCClientSender::patch_enabled(const std::string& patch_path) void OSCClientSender::patch_disabled(const std::string& patch_path) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/patch_disabled", "s", patch_path.c_str()); + send("/ingen/patch_disabled", "s", patch_path.c_str(), LO_ARGS_END); } @@ -401,10 +428,7 @@ OSCClientSender::patch_polyphony(const std::string& patch_path, uint32_t poly) void OSCClientSender::connection(const std::string& src_port_path, const std::string& dst_port_path) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/new_connection", "ss", src_port_path.c_str(), dst_port_path.c_str()); + send("/ingen/new_connection", "ss", src_port_path.c_str(), dst_port_path.c_str(), LO_ARGS_END); } @@ -416,10 +440,7 @@ OSCClientSender::connection(const std::string& src_port_path, const std::string& void OSCClientSender::disconnection(const std::string& src_port_path, const std::string& dst_port_path) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/disconnection", "ss", src_port_path.c_str(), dst_port_path.c_str()); + send("/ingen/disconnection", "ss", src_port_path.c_str(), dst_port_path.c_str(), LO_ARGS_END); } @@ -432,14 +453,11 @@ OSCClientSender::disconnection(const std::string& src_port_path, const std::stri void OSCClientSender::variable_change(const std::string& path, const std::string& key, const Atom& value) { - if (!_enabled) - return; - lo_message m = lo_message_new(); lo_message_add_string(m, path.c_str()); lo_message_add_string(m, key.c_str()); Raul::AtomLiblo::lo_message_add_atom(m, value); - lo_send_message(_address, "/ingen/variable_change", m); + send_message("/ingen/variable_change", m); } @@ -451,10 +469,7 @@ OSCClientSender::variable_change(const std::string& path, const std::string& key void OSCClientSender::control_change(const std::string& port_path, float value) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/control_change", "sf", port_path.c_str(), value); + send("/ingen/control_change", "sf", port_path.c_str(), value, LO_ARGS_END); } @@ -485,9 +500,6 @@ OSCClientSender::new_plugin(const std::string& uri, const std::string& symbol, const std::string& name) { - if (!_enabled) - return; - // FIXME: size? liblo doesn't export this. // Don't want to exceed max UDP packet size (1500 bytes) static const size_t MAX_BUNDLE_SIZE = 1500 - 32*5; @@ -521,10 +533,7 @@ OSCClientSender::new_plugin(const std::string& uri, void OSCClientSender::new_patch(const std::string& path, uint32_t poly) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/new_patch", "si", path.c_str(), poly); + send("/ingen/new_patch", "si", path.c_str(), poly, LO_ARGS_END); /* if (p->process()) @@ -547,10 +556,7 @@ OSCClientSender::new_patch(const std::string& path, uint32_t poly) void OSCClientSender::object_renamed(const std::string& old_path, const std::string& new_path) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/object_renamed", "ss", old_path.c_str(), new_path.c_str()); + send("/ingen/object_renamed", "ss", old_path.c_str(), new_path.c_str(), LO_ARGS_END); } @@ -559,10 +565,7 @@ OSCClientSender::object_renamed(const std::string& old_path, const std::string& void OSCClientSender::program_add(const std::string& node_path, uint32_t bank, uint32_t program, const std::string& name) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/program_add", "siis", + send("/ingen/program_add", "siis", node_path.c_str(), bank, program, name.c_str()); } @@ -570,10 +573,7 @@ OSCClientSender::program_add(const std::string& node_path, uint32_t bank, uint32 void OSCClientSender::program_remove(const std::string& node_path, uint32_t bank, uint32_t program) { - if (!_enabled) - return; - - lo_send(_address, "/ingen/program_remove", "sii", + send("/ingen/program_remove", "sii", node_path.c_str(), bank, program); } diff --git a/src/libs/engine/OSCClientSender.hpp b/src/libs/engine/OSCClientSender.hpp index d6a25fd2..cd2264df 100644 --- a/src/libs/engine/OSCClientSender.hpp +++ b/src/libs/engine/OSCClientSender.hpp @@ -134,11 +134,16 @@ public: uint32_t program); private: - lo_address _address; + int send(const char *path, const char *types, ...); + void send_message(const char* path, lo_message m); - lo_bundle _transfer; + enum SendState { Immediate, SendingBundle, SendingTransfer }; - bool _enabled; + string _url; + lo_address _address; + SendState _send_state; + lo_bundle _transfer; + bool _enabled; }; diff --git a/src/libs/engine/ObjectSender.cpp b/src/libs/engine/ObjectSender.cpp index f51f0ad0..fff2a797 100644 --- a/src/libs/engine/ObjectSender.cpp +++ b/src/libs/engine/ObjectSender.cpp @@ -33,9 +33,21 @@ namespace Ingen { void ObjectSender::send_patch(ClientInterface* client, const PatchImpl* patch, bool recursive) { + client->bundle_begin(); + client->new_patch(patch->path(), patch->internal_polyphony()); client->polyphonic(patch->path(), patch->polyphonic()); + // Send variable + const GraphObjectImpl::Variables& data = patch->variables(); + for (GraphObjectImpl::Variables::const_iterator j = data.begin(); j != data.end(); ++j) + client->variable_change(patch->path(), (*j).first, (*j).second); + + if (patch->enabled()) + client->patch_enabled(patch->path()); + + client->bundle_end(); + if (recursive) { // Send nodes @@ -60,14 +72,6 @@ ObjectSender::send_patch(ClientInterface* client, const PatchImpl* patch, bool r client->connection((*j)->src_port_path(), (*j)->dst_port_path()); } - - // Send variable - const GraphObjectImpl::Variables& data = patch->variables(); - for (GraphObjectImpl::Variables::const_iterator j = data.begin(); j != data.end(); ++j) - client->variable_change(patch->path(), (*j).first, (*j).second); - - if (patch->enabled()) - client->patch_enabled(patch->path()); } diff --git a/src/libs/engine/events/DestroyEvent.cpp b/src/libs/engine/events/DestroyEvent.cpp index 9a235807..eef7ea0e 100644 --- a/src/libs/engine/events/DestroyEvent.cpp +++ b/src/libs/engine/events/DestroyEvent.cpp @@ -182,16 +182,20 @@ DestroyEvent::post_process() assert(_node); _node->deactivate(); _responder->respond_ok(); + _engine.broadcaster()->bundle_begin(); if (_disconnect_node_event) _disconnect_node_event->post_process(); _engine.broadcaster()->send_destroyed(_path); + _engine.broadcaster()->bundle_end(); _engine.maid()->push(_patch_node_listnode); } else if (_patch_port_listnode) { assert(_port); _responder->respond_ok(); + _engine.broadcaster()->bundle_begin(); if (_disconnect_port_event) _disconnect_port_event->post_process(); _engine.broadcaster()->send_destroyed(_path); + _engine.broadcaster()->bundle_end(); _engine.maid()->push(_patch_port_listnode); } else { _responder->respond_error("Unable to destroy object"); -- cgit v1.2.1