From ad07c414d557629251b2f4ea4078c22f241cc865 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 13 Feb 2010 22:07:26 +0000 Subject: Learn and remove bindings exclusively through property interface. Note this commit breaks some aspects of OSC and HTTP control for now. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2442 a436a847-0d15-0410-975c-d299462d15a1 --- src/client/ClientStore.cpp | 23 ++++++ src/client/ClientStore.hpp | 2 + src/client/HTTPEngineSender.cpp | 15 ++-- src/client/HTTPEngineSender.hpp | 7 +- src/client/OSCClientReceiver.cpp | 23 +++--- src/client/OSCClientReceiver.hpp | 1 - src/client/OSCEngineSender.cpp | 57 +++++++------ src/client/OSCEngineSender.hpp | 7 +- src/client/SigClientInterface.hpp | 10 ++- src/client/ThreadedSigClientInterface.hpp | 6 ++ src/common/interface/CommonInterface.hpp | 4 + src/common/interface/EngineInterface.hpp | 2 - src/engine/ClientBroadcaster.hpp | 6 ++ src/engine/ControlBindings.cpp | 23 ++++++ src/engine/ControlBindings.hpp | 6 ++ src/engine/HTTPClientSender.cpp | 8 ++ src/engine/HTTPClientSender.hpp | 4 + src/engine/LV2Node.cpp | 1 - src/engine/OSCClientSender.cpp | 53 +++++++----- src/engine/OSCClientSender.hpp | 4 + src/engine/OSCEngineReceiver.cpp | 116 +++++++++++--------------- src/engine/QueuedEngineInterface.cpp | 33 ++++---- src/engine/QueuedEngineInterface.hpp | 6 +- src/engine/events.hpp | 1 - src/engine/events/Learn.cpp | 99 ---------------------- src/engine/events/Learn.hpp | 61 -------------- src/engine/events/SetMetadata.cpp | 131 ++++++++++++++++++++---------- src/engine/events/SetMetadata.hpp | 11 ++- src/engine/internals/Controller.cpp | 1 - src/engine/wscript | 1 - src/gui/ObjectMenu.cpp | 21 ++++- src/gui/ObjectMenu.hpp | 2 + src/gui/PortMenu.cpp | 1 + src/gui/ingen_gui.glade | 7 ++ src/serialisation/Parser.cpp | 6 +- src/serialisation/Serialiser.cpp | 2 + src/shared/ClashAvoider.cpp | 9 ++ src/shared/ClashAvoider.hpp | 4 + src/shared/LV2URIMap.cpp | 1 + src/shared/LV2URIMap.hpp | 1 + src/shared/ResourceImpl.cpp | 52 ++++++++++++ src/shared/ResourceImpl.hpp | 4 + 42 files changed, 454 insertions(+), 378 deletions(-) delete mode 100644 src/engine/events/Learn.cpp delete mode 100644 src/engine/events/Learn.hpp diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index e5fbab6a..cf05e599 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -48,6 +48,7 @@ ClientStore::ClientStore(SharedPtr engine, SharedPtrsignal_object_deleted.connect(sigc::mem_fun(this, &ClientStore::del)); emitter->signal_object_moved.connect(sigc::mem_fun(this, &ClientStore::move)); emitter->signal_put.connect(sigc::mem_fun(this, &ClientStore::put)); + emitter->signal_delta.connect(sigc::mem_fun(this, &ClientStore::delta)); emitter->signal_connection.connect(sigc::mem_fun(this, &ClientStore::connect)); emitter->signal_disconnection.connect(sigc::mem_fun(this, &ClientStore::disconnect)); emitter->signal_property_change.connect(sigc::mem_fun(this, &ClientStore::set_property)); @@ -337,6 +338,28 @@ ClientStore::put(const URI& uri, const Resource::Properties& properties) } +void +ClientStore::delta(const URI& uri, const Resource::Properties& remove, const Resource::Properties& add) +{ + bool is_meta = ResourceImpl::is_meta_uri(uri); + string path_str = is_meta ? (string("/") + uri.chop_start("#")) : uri.str(); + if (!Path::is_valid(path_str)) { + LOG(error) << "Bad path: " << uri.str() << " - " << path_str << endl; + return; + } + + Path path(is_meta ? (string("/") + uri.chop_start("#")) : uri.str()); + + SharedPtr obj = object(path); + if (obj) { + obj->remove_properties(remove); + obj->add_properties(add); + } else { + LOG(warn) << "Failed to find object `" << path << "'" << endl; + } +} + + void ClientStore::set_property(const URI& subject_uri, const URI& predicate, const Atom& value) { diff --git a/src/client/ClientStore.hpp b/src/client/ClientStore.hpp index 38df414e..978bc7d5 100644 --- a/src/client/ClientStore.hpp +++ b/src/client/ClientStore.hpp @@ -69,6 +69,8 @@ public: // CommonInterface bool new_object(const Shared::GraphObject* object); void put(const Raul::URI& path, const Shared::Resource::Properties& properties); + void delta(const Raul::URI& path, const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add); void move(const Raul::Path& old_path, const Raul::Path& new_path); void set_property(const Raul::URI& subject_path, const Raul::URI& predicate, const Raul::Atom& value); void set_voice_value(const Raul::Path& port_path, uint32_t voice, const Raul::Atom& value); diff --git a/src/client/HTTPEngineSender.cpp b/src/client/HTTPEngineSender.cpp index 0b544600..d515926b 100644 --- a/src/client/HTTPEngineSender.cpp +++ b/src/client/HTTPEngineSender.cpp @@ -134,6 +134,15 @@ HTTPEngineSender::put(const URI& uri, } +void +HTTPEngineSender::delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add) +{ + warn << "FIXME: HTTP DELTA" << endl; +} + + void HTTPEngineSender::move(const Path& old_path, const Path& new_path) @@ -185,12 +194,6 @@ HTTPEngineSender::set_voice_value(const Path& port_path, } -void -HTTPEngineSender::learn(const Path& path) -{ -} - - void HTTPEngineSender::set_property(const URI& subject, const URI& predicate, diff --git a/src/client/HTTPEngineSender.hpp b/src/client/HTTPEngineSender.hpp index dc0a24c7..570ab3e9 100644 --- a/src/client/HTTPEngineSender.hpp +++ b/src/client/HTTPEngineSender.hpp @@ -83,6 +83,10 @@ public: virtual void put(const Raul::URI& path, const Shared::Resource::Properties& properties); + virtual void delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add); + virtual void del(const Raul::Path& path); virtual void move(const Raul::Path& old_path, @@ -105,9 +109,6 @@ public: uint32_t voice, const Raul::Atom& value); - virtual void learn(const Raul::Path& path); - - // Requests // void ping(); void get(const Raul::URI& uri); diff --git a/src/client/OSCClientReceiver.cpp b/src/client/OSCClientReceiver.cpp index faccef15..4cf28156 100644 --- a/src/client/OSCClientReceiver.cpp +++ b/src/client/OSCClientReceiver.cpp @@ -140,18 +140,17 @@ OSCClientReceiver::unknown_cb(const char* path, const char* types, lo_arg** argv 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", "sss", plugin_cb, this); - lo_server_thread_add_method(_st, "/ingen/put", NULL, put_cb, this); - lo_server_thread_add_method(_st, "/ingen/move", "ss", move_cb, this); - lo_server_thread_add_method(_st, "/ingen/delete", "s", del_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_port", "sisi", new_port_cb, this); - lo_server_thread_add_method(_st, "/ingen/set_property", NULL, set_property_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/activity", "s", activity_cb, this); + 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, "/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, "/set_voice_value", "sif", set_voice_value_cb, this); + lo_server_thread_add_method(_st, "/activity", "s", activity_cb, this); } diff --git a/src/client/OSCClientReceiver.hpp b/src/client/OSCClientReceiver.hpp index 8f191f9c..31082858 100644 --- a/src/client/OSCClientReceiver.hpp +++ b/src/client/OSCClientReceiver.hpp @@ -89,7 +89,6 @@ private: LO_HANDLER(move); LO_HANDLER(connection); LO_HANDLER(disconnection); - LO_HANDLER(new_port); LO_HANDLER(put); LO_HANDLER(set_property); LO_HANDLER(set_voice_value); diff --git a/src/client/OSCEngineSender.cpp b/src/client/OSCEngineSender.cpp index 150f8020..30f5cb76 100644 --- a/src/client/OSCEngineSender.cpp +++ b/src/client/OSCEngineSender.cpp @@ -89,14 +89,14 @@ OSCEngineSender::attach(int32_t ping_id, bool block) void OSCEngineSender::register_client(Shared::ClientInterface* client) { - send("/ingen/register_client", "i", next_id(), LO_ARGS_END, LO_ARGS_END); + send("/register_client", "i", next_id(), LO_ARGS_END, LO_ARGS_END); } void OSCEngineSender::unregister_client(const URI& uri) { - send("/ingen/unregister_client", "i", next_id(), LO_ARGS_END); + send("/unregister_client", "i", next_id(), LO_ARGS_END); } @@ -104,28 +104,28 @@ OSCEngineSender::unregister_client(const URI& uri) void OSCEngineSender::load_plugins() { - send("/ingen/load_plugins", "i", next_id(), LO_ARGS_END); + send("/load_plugins", "i", next_id(), LO_ARGS_END); } void OSCEngineSender::activate() { - send("/ingen/activate", "i", next_id(), LO_ARGS_END); + send("/activate", "i", next_id(), LO_ARGS_END); } void OSCEngineSender::deactivate() { - send("/ingen/deactivate", "i", next_id(), LO_ARGS_END); + send("/deactivate", "i", next_id(), LO_ARGS_END); } void OSCEngineSender::quit() { - send("/ingen/quit", "i", next_id(), LO_ARGS_END); + send("/quit", "i", next_id(), LO_ARGS_END); } @@ -145,7 +145,16 @@ OSCEngineSender::put(const Raul::URI& path, lo_message_add_string(m, i->first.c_str()); Raul::AtomLiblo::lo_message_add_atom(m, i->second); } - send_message("/ingen/put", m); + send_message("/put", m); +} + + +void +OSCEngineSender::delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add) +{ + warn << "FIXME: OSC DELTA" << endl; } @@ -153,7 +162,7 @@ void OSCEngineSender::move(const Path& old_path, const Path& new_path) { - send("/ingen/move", "iss", + send("/move", "iss", next_id(), old_path.c_str(), new_path.c_str(), @@ -164,7 +173,7 @@ OSCEngineSender::move(const Path& old_path, void OSCEngineSender::del(const Path& path) { - send("/ingen/delete", "is", + send("/delete", "is", next_id(), path.c_str(), LO_ARGS_END); @@ -175,7 +184,7 @@ void OSCEngineSender::connect(const Path& src_port_path, const Path& dst_port_path) { - send("/ingen/connect", "iss", + send("/connect", "iss", next_id(), src_port_path.c_str(), dst_port_path.c_str(), @@ -187,7 +196,7 @@ void OSCEngineSender::disconnect(const Path& src_port_path, const Path& dst_port_path) { - send("/ingen/disconnect", "iss", + send("/disconnect", "iss", next_id(), src_port_path.c_str(), dst_port_path.c_str(), @@ -199,7 +208,7 @@ void OSCEngineSender::disconnect_all(const Path& parent_patch_path, const Path& path) { - send("/ingen/disconnect_all", "iss", + send("/disconnect_all", "iss", next_id(), parent_patch_path.c_str(), path.c_str(), @@ -219,17 +228,7 @@ OSCEngineSender::set_voice_value(const Path& port_path, if (value.type() == Atom::BLOB) lo_message_add_string(m, value.get_blob_type()); Raul::AtomLiblo::lo_message_add_atom(m, value); - send_message("/ingen/set_port_value", m); -} - - -void -OSCEngineSender::learn(const Path& path) -{ - send("/ingen/learn", "is", - next_id(), - path.c_str(), - LO_ARGS_END); + send_message("/set_port_value", m); } @@ -243,7 +242,7 @@ OSCEngineSender::set_property(const URI& subject, lo_message_add_string(m, subject.c_str()); lo_message_add_string(m, predicate.c_str()); Raul::AtomLiblo::lo_message_add_atom(m, value); - send_message("/ingen/set_property", m); + send_message("/set_property", m); } @@ -253,14 +252,14 @@ OSCEngineSender::set_property(const URI& subject, void OSCEngineSender::ping() { - send("/ingen/ping", "i", next_id(), LO_ARGS_END); + send("/ping", "i", next_id(), LO_ARGS_END); } void OSCEngineSender::get(const URI& uri) { - send("/ingen/get", "is", + send("/get", "is", next_id(), uri.c_str(), LO_ARGS_END); @@ -270,7 +269,7 @@ OSCEngineSender::get(const URI& uri) void OSCEngineSender::request_property(const URI& object_path, const URI& key) { - send("/ingen/request_property", "iss", + send("/request_property", "iss", next_id(), object_path.c_str(), key.c_str(), @@ -281,14 +280,14 @@ OSCEngineSender::request_property(const URI& object_path, const URI& key) void OSCEngineSender::request_plugins() { - send("/ingen/request_plugins", "i", next_id(), LO_ARGS_END); + send("/request_plugins", "i", next_id(), LO_ARGS_END); } void OSCEngineSender::request_all_objects() { - send("/ingen/request_all_objects", "i", next_id(), LO_ARGS_END); + send("/request_all_objects", "i", next_id(), LO_ARGS_END); } diff --git a/src/client/OSCEngineSender.hpp b/src/client/OSCEngineSender.hpp index e3d76b01..916d1466 100644 --- a/src/client/OSCEngineSender.hpp +++ b/src/client/OSCEngineSender.hpp @@ -80,6 +80,10 @@ public: virtual void put(const Raul::URI& path, const Shared::Resource::Properties& properties); + virtual void delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add); + virtual void del(const Raul::Path& path); virtual void move(const Raul::Path& old_path, @@ -102,9 +106,6 @@ public: uint32_t voice, const Raul::Atom& value); - virtual void learn(const Raul::Path& path); - - // Requests // void ping(); void get(const Raul::URI& uri); diff --git a/src/client/SigClientInterface.hpp b/src/client/SigClientInterface.hpp index bc2ee3f9..3334c5c7 100644 --- a/src/client/SigClientInterface.hpp +++ b/src/client/SigClientInterface.hpp @@ -51,6 +51,8 @@ public: sigc::signal signal_new_patch; sigc::signal signal_new_port; sigc::signal signal_put; + sigc::signal signal_delta; sigc::signal signal_object_moved; sigc::signal signal_object_deleted; sigc::signal signal_connection; @@ -88,8 +90,12 @@ protected: void error(const std::string& msg) { EMIT(error, msg); } - void put(const Raul::URI& path, const Shared::Resource::Properties& properties) - { EMIT(put, path, properties); } + void put(const Raul::URI& uri, const Shared::Resource::Properties& properties) + { EMIT(put, uri, properties); } + + void delta(const Raul::URI& uri, + const Shared::Resource::Properties& remove, const Shared::Resource::Properties& add) + { EMIT(delta, uri, remove, add); } void connect(const Raul::Path& src_port_path, const Raul::Path& dst_port_path) { EMIT(connection, src_port_path, dst_port_path); } diff --git a/src/client/ThreadedSigClientInterface.hpp b/src/client/ThreadedSigClientInterface.hpp index 128f6d86..bb86d65a 100644 --- a/src/client/ThreadedSigClientInterface.hpp +++ b/src/client/ThreadedSigClientInterface.hpp @@ -86,6 +86,10 @@ public: void put(const Raul::URI& path, const Shared::Resource::Properties& properties) { push_sig(sigc::bind(put_slot, path, properties)); } + void delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, const Shared::Resource::Properties& add) + { push_sig(sigc::bind(delta_slot, path, remove, add)); } + void connect(const Raul::Path& src_port_path, const Raul::Path& dst_port_path) { push_sig(sigc::bind(connection_slot, src_port_path, dst_port_path)); } @@ -127,6 +131,8 @@ private: sigc::slot new_plugin_slot; sigc::slot new_port_slot; sigc::slot put_slot; + sigc::slot delta_slot; sigc::slot connection_slot; sigc::slot object_deleted_slot; sigc::slot object_moved_slot; diff --git a/src/common/interface/CommonInterface.hpp b/src/common/interface/CommonInterface.hpp index d1297aa5..3ee91f52 100644 --- a/src/common/interface/CommonInterface.hpp +++ b/src/common/interface/CommonInterface.hpp @@ -48,6 +48,10 @@ public: virtual void put(const Raul::URI& uri, const Resource::Properties& properties) = 0; + virtual void delta(const Raul::URI& uri, + const Resource::Properties& remove, + const Resource::Properties& add) = 0; + virtual void move(const Raul::Path& old_path, const Raul::Path& new_path) = 0; diff --git a/src/common/interface/EngineInterface.hpp b/src/common/interface/EngineInterface.hpp index 644eaea5..d4efac11 100644 --- a/src/common/interface/EngineInterface.hpp +++ b/src/common/interface/EngineInterface.hpp @@ -58,8 +58,6 @@ public: virtual void disconnect_all(const Raul::Path& parent_patch_path, const Raul::Path& path) = 0; - virtual void learn(const Raul::Path& path) = 0; - // Requests virtual void ping() = 0; diff --git a/src/engine/ClientBroadcaster.hpp b/src/engine/ClientBroadcaster.hpp index 37593730..38073dc1 100644 --- a/src/engine/ClientBroadcaster.hpp +++ b/src/engine/ClientBroadcaster.hpp @@ -74,6 +74,12 @@ public: BROADCAST(put, uri, properties); } + void delta(const Raul::URI& uri, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add) { + BROADCAST(delta, uri, remove, add); + } + void move(const Raul::Path& old_path, const Raul::Path& new_path) { BROADCAST(move, old_path, new_path); diff --git a/src/engine/ControlBindings.cpp b/src/engine/ControlBindings.cpp index 91d425a4..e183404a 100644 --- a/src/engine/ControlBindings.cpp +++ b/src/engine/ControlBindings.cpp @@ -301,6 +301,29 @@ ControlBindings::remove(const Raul::Path& path) } +SharedPtr +ControlBindings::remove(PortImpl* port) +{ + ThreadManager::assert_thread(THREAD_PRE_PROCESS); + + SharedPtr old_bindings(_bindings); + SharedPtr copy(new Bindings(*_bindings.get())); + + for (Bindings::iterator i = copy->begin(); i != copy->end();) { + Bindings::iterator next = i; + ++next; + + if (i->second == port) + copy->erase(i); + + i = next; + } + + _bindings = copy; + return old_bindings; +} + + void ControlBindings::pre_process(ProcessContext& context, EventBuffer* buffer) { diff --git a/src/engine/ControlBindings.hpp b/src/engine/ControlBindings.hpp index 458d153a..1b684b9a 100644 --- a/src/engine/ControlBindings.hpp +++ b/src/engine/ControlBindings.hpp @@ -72,6 +72,12 @@ public: */ SharedPtr remove(const Raul::Path& path); + /** Remove binding for a particular port. + * The caller must safely drop the returned reference in the + * post-processing thread after at least one process thread has run. + */ + SharedPtr remove(PortImpl* port); + private: Key port_binding(PortImpl* port); Key midi_event_key(uint16_t size, uint8_t* buf, uint16_t& value); diff --git a/src/engine/HTTPClientSender.cpp b/src/engine/HTTPClientSender.cpp index dcea6288..996aa7cd 100644 --- a/src/engine/HTTPClientSender.cpp +++ b/src/engine/HTTPClientSender.cpp @@ -71,6 +71,14 @@ HTTPClientSender::put(const URI& uri, } +void +HTTPClientSender::delta(const URI& uri, + const Resource::Properties& remove, + const Resource::Properties& add) +{ +} + + void HTTPClientSender::del(const Path& path) { diff --git a/src/engine/HTTPClientSender.hpp b/src/engine/HTTPClientSender.hpp index cbfd17f0..dc4b9edf 100644 --- a/src/engine/HTTPClientSender.hpp +++ b/src/engine/HTTPClientSender.hpp @@ -69,6 +69,10 @@ public: virtual void put(const Raul::URI& path, const Shared::Resource::Properties& properties); + virtual void delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add); + virtual void del(const Raul::Path& path); virtual void move(const Raul::Path& old_path, diff --git a/src/engine/LV2Node.cpp b/src/engine/LV2Node.cpp index cdc29b15..956bf3af 100644 --- a/src/engine/LV2Node.cpp +++ b/src/engine/LV2Node.cpp @@ -301,7 +301,6 @@ LV2Node::instantiate(BufferFactory& bufs) for (uint32_t i = 0; i < slv2_values_size(properties); ++i) { SLV2Value p = slv2_values_get_at(properties, i); if (slv2_value_is_uri(p)) { - Raul::info << "SET PORT PROPERTY " << slv2_value_as_uri(p) << endl; port->set_property(uris.lv2_portProperty, Raul::URI(slv2_value_as_uri(p))); } } diff --git a/src/engine/OSCClientSender.cpp b/src/engine/OSCClientSender.cpp index 115b22de..c0f8e039 100644 --- a/src/engine/OSCClientSender.cpp +++ b/src/engine/OSCClientSender.cpp @@ -42,7 +42,7 @@ namespace Ingen { /** \page client_osc_namespace - *

/ingen/ok

+ *

/ok

* \arg \b response-id (int) - Request ID this is a response to * * Successful response to some command. @@ -53,7 +53,7 @@ OSCClientSender::response_ok(int32_t id) if (!_enabled) return; - if (lo_send(_address, "/ingen/ok", "i", id) < 0) { + if (lo_send(_address, "/ok", "i", id) < 0) { Raul::error << "Unable to send OK " << id << "! (" << lo_address_errstr(_address) << ")" << endl; } @@ -61,7 +61,7 @@ OSCClientSender::response_ok(int32_t id) /** \page client_osc_namespace - *

/ingen/error

+ *

/error

* \arg \b response-id (int) - Request ID this is a response to * \arg \b message (string) - Error message (natural language text) * @@ -73,7 +73,7 @@ OSCClientSender::response_error(int32_t id, const std::string& msg) if (!_enabled) return; - if (lo_send(_address, "/ingen/error", "is", id, msg.c_str()) < 0) { + if (lo_send(_address, "/error", "is", id, msg.c_str()) < 0) { Raul::error << "Unable to send error " << id << "! (" << lo_address_errstr(_address) << ")" << endl; } @@ -81,7 +81,7 @@ OSCClientSender::response_error(int32_t id, const std::string& msg) /** \page client_osc_namespace - *

/ingen/error

+ *

/error

* \arg \b message (string) - Error message (natural language text) * * Notification that an error has occurred. @@ -91,12 +91,12 @@ OSCClientSender::response_error(int32_t id, const std::string& msg) void OSCClientSender::error(const std::string& msg) { - send("/ingen/error", "s", msg.c_str(), LO_ARGS_END); + send("/error", "s", msg.c_str(), LO_ARGS_END); } /** \page client_osc_namespace - *

/ingen/put

+ *

/put

* \arg \b path (string) - Path of object * \arg \b predicate * \arg \b value @@ -115,12 +115,21 @@ OSCClientSender::put(const Raul::URI& path, lo_message_add_string(m, i->first.c_str()); Raul::AtomLiblo::lo_message_add_atom(m, i->second); } - send_message("/ingen/put", m); + send_message("/put", m); +} + + +void +OSCClientSender::delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add) +{ + warn << "FIXME: OSC DELTA" << endl; } /** \page client_osc_namespace - *

/ingen/move

+ *

/move

* \arg \b old-path (string) - Old path of object * \arg \b new-path (string) - New path of object * @@ -130,13 +139,13 @@ OSCClientSender::put(const Raul::URI& path, void OSCClientSender::move(const Path& old_path, const Path& new_path) { - send("/ingen/move", "ss", old_path.c_str(), new_path.c_str(), LO_ARGS_END); + send("/move", "ss", old_path.c_str(), new_path.c_str(), LO_ARGS_END); } /** \page client_osc_namespace - *

/ingen/delete

+ *

/delete

* \arg \b path (string) - Path of object (which no longer exists) * * DELETE an object (see \ref methods). @@ -144,12 +153,12 @@ OSCClientSender::move(const Path& old_path, const Path& new_path) void OSCClientSender::del(const Path& path) { - send("/ingen/delete", "s", path.c_str(), LO_ARGS_END); + send("/delete", "s", path.c_str(), LO_ARGS_END); } /** \page client_osc_namespace - *

/ingen/new_connection

+ *

/connect

* \arg \b src-path (string) - Path of the source port * \arg \b dst-path (string) - Path of the destination port * @@ -158,12 +167,12 @@ OSCClientSender::del(const Path& path) void OSCClientSender::connect(const Path& src_port_path, const Path& dst_port_path) { - send("/ingen/new_connection", "ss", src_port_path.c_str(), dst_port_path.c_str(), LO_ARGS_END); + send("/connect", "ss", src_port_path.c_str(), dst_port_path.c_str(), LO_ARGS_END); } /** \page client_osc_namespace - *

/ingen/disconnection

+ *

/disconnect

* \arg \b src-path (string) - Path of the source port * \arg \b dst-path (string) - Path of the destination port * @@ -172,12 +181,12 @@ OSCClientSender::connect(const Path& src_port_path, const Path& dst_port_path) void OSCClientSender::disconnect(const Path& src_port_path, const Path& dst_port_path) { - send("/ingen/disconnection", "ss", src_port_path.c_str(), dst_port_path.c_str(), LO_ARGS_END); + send("/disconnect", "ss", src_port_path.c_str(), dst_port_path.c_str(), LO_ARGS_END); } /** \page client_osc_namespace - *

/ingen/set_property

+ *

/set_property

* \arg \b path (string) - Path of the object associated with property (node, patch, or port) * \arg \b key (string) * \arg \b value (string) @@ -191,12 +200,12 @@ OSCClientSender::set_property(const URI& path, const URI& key, const Atom& value lo_message_add_string(m, path.c_str()); lo_message_add_string(m, key.c_str()); AtomLiblo::lo_message_add_atom(m, value); - send_message("/ingen/set_property", m); + send_message("/set_property", m); } /** \page client_osc_namespace - *

/ingen/set_port_value

+ *

/set_port_value

* \arg \b path (string) - Path of port * \arg \b voice (int) - Voice which is set to this value * \arg \b value (any) - New value of port @@ -209,12 +218,12 @@ OSCClientSender::set_voice_value(const Path& port_path, uint32_t voice, const At lo_message m = lo_message_new(); lo_message_add_string(m, port_path.c_str()); AtomLiblo::lo_message_add_atom(m, value); - send_message("/ingen/set_port_value", m); + send_message("/set_port_value", m); } /** \page client_osc_namespace - *

/ingen/activity

+ *

/activity

* \arg \b path (string) - Path of object * * Notification of "activity" (e.g. port message blinkenlights). @@ -225,7 +234,7 @@ OSCClientSender::activity(const Path& path) if (!_enabled) return; - lo_send(_address, "/ingen/activity", "s", path.c_str(), LO_ARGS_END); + lo_send(_address, "/activity", "s", path.c_str(), LO_ARGS_END); } diff --git a/src/engine/OSCClientSender.hpp b/src/engine/OSCClientSender.hpp index f8e3023b..ca0783b0 100644 --- a/src/engine/OSCClientSender.hpp +++ b/src/engine/OSCClientSender.hpp @@ -69,6 +69,10 @@ public: virtual void put(const Raul::URI& path, const Shared::Resource::Properties& properties); + virtual void delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add); + virtual void del(const Raul::Path& path); virtual void move(const Raul::Path& old_path, diff --git a/src/engine/OSCEngineReceiver.cpp b/src/engine/OSCEngineReceiver.cpp index c186dbcd..38ef3273 100644 --- a/src/engine/OSCEngineReceiver.cpp +++ b/src/engine/OSCEngineReceiver.cpp @@ -85,32 +85,31 @@ OSCEngineReceiver::OSCEngineReceiver(Engine& engine, size_t queue_size, uint16_t lo_server_add_method(_server, NULL, NULL, set_response_address_cb, this); // Commands - lo_server_add_method(_server, "/ingen/ping", "i", ping_cb, this); - lo_server_add_method(_server, "/ingen/ping_queued", "i", ping_slow_cb, this); - lo_server_add_method(_server, "/ingen/quit", "i", quit_cb, this); - //lo_server_add_method(_server, "/ingen/register_client", "is", register_client_cb, this); - lo_server_add_method(_server, "/ingen/register_client", "i", register_client_cb, this); - lo_server_add_method(_server, "/ingen/unregister_client", "i", unregister_client_cb, this); - lo_server_add_method(_server, "/ingen/load_plugins", "i", load_plugins_cb, this); - lo_server_add_method(_server, "/ingen/activate", "i", engine_activate_cb, this); - lo_server_add_method(_server, "/ingen/deactivate", "i", engine_deactivate_cb, this); - lo_server_add_method(_server, "/ingen/put", NULL, put_cb, this); - lo_server_add_method(_server, "/ingen/move", "iss", move_cb, this); - lo_server_add_method(_server, "/ingen/delete", "is", del_cb, this); - lo_server_add_method(_server, "/ingen/connect", "iss", connect_cb, this); - lo_server_add_method(_server, "/ingen/disconnect", "iss", disconnect_cb, this); - lo_server_add_method(_server, "/ingen/disconnect_all", "iss", disconnect_all_cb, this); - lo_server_add_method(_server, "/ingen/note_on", "isii", note_on_cb, this); - lo_server_add_method(_server, "/ingen/note_off", "isi", note_off_cb, this); - lo_server_add_method(_server, "/ingen/all_notes_off", "isi", all_notes_off_cb, this); - lo_server_add_method(_server, "/ingen/learn", "is", learn_cb, this); - lo_server_add_method(_server, "/ingen/set_property", NULL, set_property_cb, this); + lo_server_add_method(_server, "/ping", "i", ping_cb, this); + lo_server_add_method(_server, "/ping_queued", "i", ping_slow_cb, this); + lo_server_add_method(_server, "/quit", "i", quit_cb, this); + lo_server_add_method(_server, "/register_client", "i", register_client_cb, this); + lo_server_add_method(_server, "/unregister_client", "i", unregister_client_cb, this); + lo_server_add_method(_server, "/load_plugins", "i", load_plugins_cb, this); + lo_server_add_method(_server, "/activate", "i", engine_activate_cb, this); + lo_server_add_method(_server, "/deactivate", "i", engine_deactivate_cb, this); + lo_server_add_method(_server, "/put", NULL, put_cb, this); + lo_server_add_method(_server, "/move", "iss", move_cb, this); + lo_server_add_method(_server, "/delete", "is", del_cb, this); + lo_server_add_method(_server, "/connect", "iss", connect_cb, this); + lo_server_add_method(_server, "/disconnect", "iss", disconnect_cb, this); + lo_server_add_method(_server, "/disconnect_all", "iss", disconnect_all_cb, this); + lo_server_add_method(_server, "/note_on", "isii", note_on_cb, this); + lo_server_add_method(_server, "/note_off", "isi", note_off_cb, this); + lo_server_add_method(_server, "/all_notes_off", "isi", all_notes_off_cb, this); + lo_server_add_method(_server, "/learn", "is", learn_cb, this); + lo_server_add_method(_server, "/set_property", NULL, set_property_cb, this); // Queries - lo_server_add_method(_server, "/ingen/request_property", "iss", request_property_cb, this); - lo_server_add_method(_server, "/ingen/get", "is", get_cb, this); - lo_server_add_method(_server, "/ingen/request_plugins", "i", request_plugins_cb, this); - lo_server_add_method(_server, "/ingen/request_all_objects", "i", request_all_objects_cb, this); + lo_server_add_method(_server, "/request_property", "iss", request_property_cb, this); + lo_server_add_method(_server, "/get", "is", get_cb, this); + lo_server_add_method(_server, "/request_plugins", "i", request_plugins_cb, this); + lo_server_add_method(_server, "/request_all_objects", "i", request_all_objects_cb, this); lo_server_add_method(_server, NULL, NULL, unknown_cb, NULL); @@ -237,7 +236,7 @@ OSCEngineReceiver::error_cb(int num, const char* msg, const char* path) /** \page engine_osc_namespace - *

/ingen/ping

+ *

/ping

* \arg \b response-id (integer) * * Reply to sender immediately with a successful response. @@ -246,14 +245,14 @@ int OSCEngineReceiver::_ping_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { const lo_address addr = lo_message_get_source(msg); - if (lo_send(addr, "/ingen/ok", "i", argv[0]->i) < 0) + if (lo_send(addr, "/ok", "i", argv[0]->i) < 0) warn << "Unable to send response (" << lo_address_errstr(addr) << ")" << endl; return 0; } /** \page engine_osc_namespace - *

/ingen/ping_queued

+ *

/ping_queued

* \arg \b response-id (integer) * * Reply to sender with a successful response after going through the event queue. @@ -270,7 +269,7 @@ OSCEngineReceiver::_ping_slow_cb(const char* path, const char* types, lo_arg** a /** \page engine_osc_namespace - *

/ingen/quit

+ *

/quit

* \arg \b response-id (integer) * * Terminate the engine. @@ -287,7 +286,7 @@ OSCEngineReceiver::_quit_cb(const char* path, const char* types, lo_arg** argv, /** \page engine_osc_namespace - *

/ingen/register_client

+ *

/register_client

* \arg \b response-id (integer) * * Register a new client with the engine. @@ -309,7 +308,7 @@ OSCEngineReceiver::_register_client_cb(const char* path, const char* types, lo_a /** \page engine_osc_namespace - *

/ingen/unregister_client

+ *

/unregister_client

* \arg \b response-id (integer) * * Unregister a client. @@ -328,7 +327,7 @@ OSCEngineReceiver::_unregister_client_cb(const char* path, const char* types, lo /** \page engine_osc_namespace - *

/ingen/load_plugins

+ *

/load_plugins

* \arg \b response-id (integer) * * Locate all available plugins, making them available for use. @@ -342,7 +341,7 @@ OSCEngineReceiver::_load_plugins_cb(const char* path, const char* types, lo_arg* /** \page engine_osc_namespace - *

/ingen/activate

+ *

/activate

* \arg \b response-id (integer) * * Activate the engine (event processing and all drivers, e.g. audio and MIDI). @@ -358,7 +357,7 @@ OSCEngineReceiver::_engine_activate_cb(const char* path, const char* types, lo_a /** \page engine_osc_namespace - *

/ingen/deactivate

+ *

/deactivate

* \arg \b response-id (integer) * * Deactivate the engine. @@ -372,7 +371,7 @@ OSCEngineReceiver::_engine_deactivate_cb(const char* path, const char* types, lo /** \page engine_osc_namespace - *

/ingen/get

+ *

/get

* \arg \b response-id (integer) * \arg \b uri (string) - URI of object (patch, port, node, plugin) to send * @@ -387,7 +386,7 @@ OSCEngineReceiver::_get_cb(const char* path, const char* types, lo_arg** argv, i /** \page engine_osc_namespace - *

/ingen/put

+ *

/put

* \arg \b response-id (integer) * \arg \b path (string) - Path of object * \arg \b predicate @@ -409,7 +408,7 @@ OSCEngineReceiver::_put_cb(const char* path, const char* types, lo_arg** argv, i /** \page engine_osc_namespace - *

/ingen/move

+ *

/move

* \arg \b response-id (integer) * \arg \b old-path - Object's path * \arg \b new-path - Object's new path @@ -428,7 +427,7 @@ OSCEngineReceiver::_move_cb(const char* path, const char* types, lo_arg** argv, /** \page engine_osc_namespace - *

/ingen/del

+ *

/del

* \arg \b response-id (integer) * \arg \b path (string) - Full path of the object * @@ -445,7 +444,7 @@ OSCEngineReceiver::_del_cb(const char* path, const char* types, lo_arg** argv, i /** \page engine_osc_namespace - *

/ingen/connect

+ *

/connect

* \arg \b response-id (integer) * \arg \b src-port-path (string) - Full path of source port * \arg \b dst-port-path (string) - Full path of destination port @@ -464,7 +463,7 @@ OSCEngineReceiver::_connect_cb(const char* path, const char* types, lo_arg** arg /** \page engine_osc_namespace - *

/ingen/disconnect

+ *

/disconnect

* \arg \b response-id (integer) * \arg \b src-port-path (string) - Full path of source port * \arg \b dst-port-path (string) - Full path of destination port @@ -483,7 +482,7 @@ OSCEngineReceiver::_disconnect_cb(const char* path, const char* types, lo_arg** /** \page engine_osc_namespace - *

/ingen/disconnect_all

+ *

/disconnect_all

* \arg \b response-id (integer) * \arg \b patch-path (string) - The (parent) patch in which to disconnect object. * \arg \b object-path (string) - Full path of object. @@ -502,7 +501,7 @@ OSCEngineReceiver::_disconnect_all_cb(const char* path, const char* types, lo_ar /** \page engine_osc_namespace - *

/ingen/note_on

+ *

/note_on

* \arg \b response-id (integer) * \arg \b node-path (string) - Patch of Node to trigger (must be a trigger or note node) * \arg \b note-num (int) - MIDI style note number (0-127) @@ -525,7 +524,7 @@ OSCEngineReceiver::_note_on_cb(const char* path, const char* types, lo_arg** arg /** \page engine_osc_namespace - *

/ingen/note_off

+ *

/note_off

* \arg \b response-id (integer) * \arg \b node-path (string) - Patch of Node to trigger (must be a trigger or note node) * \arg \b note-num (int) - MIDI style note number (0-127) @@ -546,7 +545,7 @@ OSCEngineReceiver::_note_off_cb(const char* path, const char* types, lo_arg** ar /** \page engine_osc_namespace - *

/ingen/all_notes_off

+ *

/all_notes_off

* \arg \b response-id (integer) * \arg \b patch-path (string) - Patch of patch to send event to * @@ -566,27 +565,7 @@ OSCEngineReceiver::_all_notes_off_cb(const char* path, const char* types, lo_arg /** \page engine_osc_namespace - *

/ingen/learn

- * \arg \b response-id (integer) - * \arg \b node-path (string) - Path of control node. - * - * Initiate MIDI learn for a given control node. - * The node will learn the next MIDI control event it receives and set - * its outputs accordingly. - * This command does nothing for objects that are not a control internal. - */ -int -OSCEngineReceiver::_learn_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) -{ - const char* object_path = &argv[1]->s; - - learn(object_path); - return 0; -} - - -/** \page engine_osc_namespace - *

/ingen/set_property

+ *

/set_property

* \arg \b response-id (integer) * \arg \b object-path (string) - Full path of object to associate property with * \arg \b key (string) - URI for predicate of this property (e.g. "http://drobilla.net/ns/ingen#enabled") @@ -603,6 +582,9 @@ OSCEngineReceiver::_set_property_cb(const char* path, const char* types, lo_arg* const char* object_path = &argv[1]->s; const char* key = &argv[2]->s; + cout << "SET PROPERTY " << object_path << " : " << key << " PENDING: " << + lo_server_events_pending(_server) << endl; + Raul::Atom value = Raul::AtomLiblo::lo_arg_to_atom(types[3], argv[3]); set_property(object_path, key, value); @@ -611,7 +593,7 @@ OSCEngineReceiver::_set_property_cb(const char* path, const char* types, lo_arg* /** \page engine_osc_namespace - *

/ingen/request_property

+ *

/request_property

* \arg \b response-id (integer) * \arg \b uri (string) - Subject * \arg \b key (string) - Predicate @@ -630,7 +612,7 @@ OSCEngineReceiver::_request_property_cb(const char* path, const char* types, lo_ /** \page engine_osc_namespace - *

/ingen/request_plugins

+ *

/request_plugins

* \arg \b response-id (integer) * * Request the engine send a list of all known plugins. @@ -644,7 +626,7 @@ OSCEngineReceiver::_request_plugins_cb(const char* path, const char* types, lo_a /** \page engine_osc_namespace - *

/ingen/request_all_objects

+ *

/request_all_objects

* \arg \b response-id (integer) * * Requests all information about all known objects. diff --git a/src/engine/QueuedEngineInterface.cpp b/src/engine/QueuedEngineInterface.cpp index dbbc0099..6122c80d 100644 --- a/src/engine/QueuedEngineInterface.cpp +++ b/src/engine/QueuedEngineInterface.cpp @@ -160,16 +160,22 @@ QueuedEngineInterface::put(const URI& uri, bool meta = ResourceImpl::is_meta_uri(uri); URI subject(meta ? (string("path:/") + uri.substr(6)) : uri.str()); - LOG(debug) << "PUT " << subject << " {" << endl; - typedef Resource::Properties::const_iterator iterator; - for (iterator i = properties.begin(); i != properties.end(); ++i) - LOG(debug) << " " << i->first << " = " << i->second << " :: " << i->second.type() << endl; - LOG(debug) << "}" << endl; - push_queued(new Events::SetMetadata(_engine, _request, now(), true, meta, subject, properties)); } +void +QueuedEngineInterface::delta(const URI& uri, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add) +{ + bool meta = ResourceImpl::is_meta_uri(uri); + URI subject(meta ? (string("path:/") + uri.substr(6)) : uri.str()); + + push_queued(new Events::SetMetadata(_engine, _request, now(), false, meta, subject, add, remove)); +} + + void QueuedEngineInterface::move(const Path& old_path, const Path& new_path) @@ -219,13 +225,6 @@ QueuedEngineInterface::set_voice_value(const Path& port_path, } -void -QueuedEngineInterface::learn(const Path& path) -{ - push_queued(new Events::Learn(_engine, _request, now(), path)); -} - - void QueuedEngineInterface::set_property(const URI& uri, const URI& predicate, @@ -234,9 +233,11 @@ QueuedEngineInterface::set_property(const URI& uri, size_t hash = uri.find("#"); bool meta = (hash != string::npos); Path path = meta ? (string("/") + path.chop_start("/")) : uri.str(); - Resource::Properties properties; - properties.insert(make_pair(predicate, value)); - push_queued(new Events::SetMetadata(_engine, _request, now(), true, meta, path, properties)); + Resource::Properties remove; + remove.insert(make_pair(predicate, Shared::LV2URIMap::instance().wildcard)); + Resource::Properties add; + add.insert(make_pair(predicate, value)); + push_queued(new Events::SetMetadata(_engine, _request, now(), false, meta, path, add, remove)); } // Requests // diff --git a/src/engine/QueuedEngineInterface.hpp b/src/engine/QueuedEngineInterface.hpp index 463cdfc3..8aa44f31 100644 --- a/src/engine/QueuedEngineInterface.hpp +++ b/src/engine/QueuedEngineInterface.hpp @@ -74,6 +74,10 @@ public: virtual void put(const Raul::URI& path, const Shared::Resource::Properties& properties); + virtual void delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add); + virtual void move(const Raul::Path& old_path, const Raul::Path& new_path); @@ -98,8 +102,6 @@ public: virtual void disconnect_all(const Raul::Path& parent_patch_path, const Raul::Path& path); - virtual void learn(const Raul::Path& path); - // Requests virtual void ping(); virtual void get(const Raul::URI& uri); diff --git a/src/engine/events.hpp b/src/engine/events.hpp index ea8d7efd..54fb63c7 100644 --- a/src/engine/events.hpp +++ b/src/engine/events.hpp @@ -30,7 +30,6 @@ #include "events/Disconnect.hpp" #include "events/DisconnectAll.hpp" #include "events/Get.hpp" -#include "events/Learn.hpp" #include "events/LoadPlugins.hpp" #include "events/Move.hpp" #include "events/Note.hpp" diff --git a/src/engine/events/Learn.cpp b/src/engine/events/Learn.cpp deleted file mode 100644 index bf453bc3..00000000 --- a/src/engine/events/Learn.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* This file is part of Ingen. - * Copyright (C) 2007-2009 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 "events/Learn.hpp" -#include "ClientBroadcaster.hpp" -#include "ControlBindings.hpp" -#include "Engine.hpp" -#include "EngineStore.hpp" -#include "NodeImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "Request.hpp" -#include "internals/Controller.hpp" - -using namespace std; - -namespace Ingen { -namespace Events { - - -Learn::Learn(Engine& engine, SharedPtr request, SampleCount timestamp, const Raul::Path& path) - : QueuedEvent(engine, request, timestamp) - , _error(NO_ERROR) - , _path(path) - , _object(NULL) - , _done(false) -{ -} - - -void -Learn::pre_process() -{ - _object = _engine.engine_store()->find_object(_path); - - PortImpl* port = dynamic_cast(_object); - if (port) { - _done = true; - if (port->type() == Shared::PortType::CONTROL) - _engine.control_bindings()->learn(port); - } - - QueuedEvent::pre_process(); -} - - -void -Learn::execute(ProcessContext& context) -{ - QueuedEvent::execute(context); - - if (_done || !_object) - return; - - NodeImpl* node = dynamic_cast(_object); - if (node) { - if (node->plugin_impl()->type() == Shared::Plugin::Internal) { - ((NodeBase*)_object)->learn(); - } else { - _error = INVALID_NODE_TYPE; - } - } -} - - -void -Learn::post_process() -{ - if (_error == NO_ERROR) { - _request->respond_ok(); - } else if (_object == NULL) { - string msg = "Did not find node '"; - msg.append(_path.str()).append("' for learn."); - _request->respond_error(msg); - } else { - const string msg = string("Object '") + _path.str() + "' is not capable of learning."; - _request->respond_error(msg); - } -} - - -} // namespace Ingen -} // namespace Events - - diff --git a/src/engine/events/Learn.hpp b/src/engine/events/Learn.hpp deleted file mode 100644 index fea8a53e..00000000 --- a/src/engine/events/Learn.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* This file is part of Ingen. - * Copyright (C) 2007-2009 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 INGEN_EVENTS_LEARN_HPP -#define INGEN_EVENTS_LEARN_HPP - -#include "QueuedEvent.hpp" -#include "internals/Controller.hpp" -#include "types.hpp" - -namespace Ingen { - -class NodeImpl; - -namespace Events { - - -/** A MIDI learn event (used by control node to learn controller number). - * - * \ingroup engine - */ -class Learn : public QueuedEvent -{ -public: - Learn(Engine& engine, SharedPtr request, SampleCount timestamp, const Raul::Path& path); - - void pre_process(); - void execute(ProcessContext& context); - void post_process(); - -private: - enum ErrorType { - NO_ERROR, - INVALID_NODE_TYPE - }; - - ErrorType _error; - const Raul::Path _path; - GraphObjectImpl* _object; - bool _done; -}; - - -} // namespace Ingen -} // namespace Events - -#endif // INGEN_EVENTS_LEARN_HPP diff --git a/src/engine/events/SetMetadata.cpp b/src/engine/events/SetMetadata.cpp index 77b67543..48de6b85 100644 --- a/src/engine/events/SetMetadata.cpp +++ b/src/engine/events/SetMetadata.cpp @@ -35,6 +35,8 @@ #include "SetMetadata.hpp" #include "SetPortValue.hpp" +#define LOG(s) s << "[SetMetadata] " + using namespace std; using namespace Raul; @@ -49,22 +51,34 @@ SetMetadata::SetMetadata( Engine& engine, SharedPtr request, SampleCount timestamp, - bool replace, + bool create, bool meta, const URI& subject, - const Properties& properties) + const Properties& properties, + const Properties& remove) : QueuedEvent(engine, request, timestamp, false) , _error(NO_ERROR) , _create_event(NULL) , _subject(subject) , _properties(properties) + , _remove(remove) , _object(NULL) , _patch(NULL) , _compiled_patch(NULL) - , _replace(replace) + , _create(create) , _is_meta(meta) - , _success(false) { + LOG(debug) << "Set " << subject << " {" << endl; + typedef Resource::Properties::const_iterator iterator; + for (iterator i = properties.begin(); i != properties.end(); ++i) + LOG(debug) << " " << i->first << " = " << i->second << " :: " << i->second.type() << endl; + LOG(debug) << "}" << endl; + + LOG(debug) << "Unset " << subject << " {" << endl; + typedef Resource::Properties::const_iterator iterator; + for (iterator i = remove.begin(); i != remove.end(); ++i) + LOG(debug) << " " << i->first << " = " << i->second << " :: " << i->second.type() << endl; + LOG(debug) << "}" << endl; } @@ -88,7 +102,7 @@ SetMetadata::pre_process() ? _engine.engine_store()->find_object(Path(_subject.str())) : _object = _engine.node_factory()->plugin(_subject); - if (!_object && !is_graph_object) { + if (!_object && (!is_graph_object || !_create)) { _error = NOT_FOUND; QueuedEvent::pre_process(); return; @@ -133,6 +147,7 @@ SetMetadata::pre_process() GraphObjectImpl* obj = dynamic_cast(_object); +#if 0 // If we're replacing (i.e. this is a PUT, not a POST), first remove all properties // with keys we will later set. This must be done first so a PUT with several properties // of the same predicate (e.g. rdf:type) retains the multiple values. Only previously @@ -140,6 +155,7 @@ SetMetadata::pre_process() if (_replace) for (Properties::iterator p = _properties.begin(); p != _properties.end(); ++p) obj->properties().erase(p->first); +#endif for (Properties::iterator p = _properties.begin(); p != _properties.end(); ++p) { const Raul::URI& key = p->first; @@ -149,14 +165,38 @@ SetMetadata::pre_process() Resource& resource = _is_meta ? obj->meta() : *obj; resource.add_property(key, value); - _patch = dynamic_cast(_object); - - if (key == uris.ingen_broadcast) { - if (value.type() == Atom::BOOL) - op = ENABLE_BROADCAST; - else - _error = BAD_VALUE_TYPE; - } else if (_patch) { + PortImpl* port = dynamic_cast(_object); + if (port) { + if (key == uris.ingen_broadcast) { + if (value.type() == Atom::BOOL) { + op = ENABLE_BROADCAST; + } else { + _error = BAD_VALUE_TYPE; + } + } else if (key == uris.ingen_value) { + PortImpl* port = dynamic_cast(_object); + if (port) { + SetPortValue* ev = new SetPortValue(_engine, _request, _time, port, value); + ev->pre_process(); + _set_events.push_back(ev); + } else { + _error = BAD_OBJECT_TYPE; + } + } else if (key == uris.ingen_controlBinding) { + PortImpl* port = dynamic_cast(_object); + if (port && port->type() == Shared::PortType::CONTROL) { + if (value == uris.wildcard) { + _engine.control_bindings()->learn(port); + } else if (value.type() == Atom::DICT) { + op = CONTROL_BINDING; + } else { + _error = BAD_VALUE_TYPE; + } + } else { + _error = BAD_OBJECT_TYPE; + } + } + } else if ((_patch = dynamic_cast(_object))) { if (key == uris.ingen_enabled) { if (value.type() == Atom::BOOL) { op = ENABLE; @@ -179,26 +219,6 @@ SetMetadata::pre_process() _error = BAD_VALUE_TYPE; } } - } else if (key == uris.ingen_value) { - PortImpl* port = dynamic_cast(_object); - if (port) { - SetPortValue* ev = new SetPortValue(_engine, _request, _time, port, value); - ev->pre_process(); - _set_events.push_back(ev); - } else { - warn << "Set value for non-port " << _object->uri() << endl; - } - } else if (key == uris.ingen_controlBinding) { - PortImpl* port = dynamic_cast(_object); - if (port) { - if (value.type() == Atom::DICT) { - op = CONTROL_BINDING; - } else { - _error = BAD_VALUE_TYPE; - } - } else { - warn << "Set binding for non-port " << _object->uri() << endl; - } } } @@ -210,6 +230,17 @@ SetMetadata::pre_process() _types.push_back(op); } + for (Properties::iterator p = _remove.begin(); p != _remove.end(); ++p) { + const Raul::URI& key = p->first; + const Raul::Atom& value = p->second; + if (key == uris.ingen_controlBinding && value == uris.wildcard) { + PortImpl* port = dynamic_cast(_object); + if (port) + _old_bindings = _engine.control_bindings()->remove(port); + } + _object->remove_property(key, value); + } + QueuedEvent::pre_process(); } @@ -233,14 +264,16 @@ SetMetadata::execute(ProcessContext& context) for (SetEvents::iterator i = _set_events.begin(); i != _set_events.end(); ++i) (*i)->execute(context); + GraphObjectImpl* const object = dynamic_cast(_object); + NodeBase* const node = dynamic_cast(_object); + PortImpl* const port = dynamic_cast(_object); + std::vector::const_iterator t = _types.begin(); - for (Properties::iterator p = _properties.begin(); p != _properties.end(); ++p, ++t) { - const Raul::Atom& value = p->second; - PortImpl* port = 0; - GraphObjectImpl* object = 0; + for (Properties::const_iterator p = _properties.begin(); p != _properties.end(); ++p, ++t) { + const Raul::Atom& value = p->second; switch (*t) { case ENABLE_BROADCAST: - if ((port = dynamic_cast(_object))) + if (port) port->broadcast(value.get_bool()); break; case ENABLE: @@ -253,7 +286,7 @@ SetMetadata::execute(ProcessContext& context) } break; case POLYPHONIC: - if ((object = dynamic_cast(_object))) + if (object) if (!object->set_polyphonic(*_engine.maid(), value.get_bool())) _error = INTERNAL; break; @@ -262,13 +295,22 @@ SetMetadata::execute(ProcessContext& context) _error = INTERNAL; break; case CONTROL_BINDING: - if ((port = dynamic_cast(_object))) + if (port) { _engine.control_bindings()->port_binding_changed(context, port); - default: - _success = true; + } else if (node) { + if (node->plugin_impl()->type() == Shared::Plugin::Internal) { + node->learn(); + } + } + break; + case NONE: + break; } } + for (Properties::const_iterator p = _remove.begin(); p != _remove.end(); ++p, ++t) + _object->remove_property(p->first, p->second); + QueuedEvent::execute(context); } @@ -282,7 +324,10 @@ SetMetadata::post_process() switch (_error) { case NO_ERROR: _request->respond_ok(); - _engine.broadcaster()->put(_subject, _properties); + if (_create) + _engine.broadcaster()->put(_subject, _properties); + else + _engine.broadcaster()->delta(_subject, _remove, _properties); if (_create_event) _create_event->post_process(); break; diff --git a/src/engine/events/SetMetadata.hpp b/src/engine/events/SetMetadata.hpp index 0abdd52a..b4b1d0ef 100644 --- a/src/engine/events/SetMetadata.hpp +++ b/src/engine/events/SetMetadata.hpp @@ -69,10 +69,11 @@ public: Engine& engine, SharedPtr request, SampleCount timestamp, - bool replace, + bool create, bool meta, const Raul::URI& subject, - const Shared::Resource::Properties& properties); + const Shared::Resource::Properties& properties, + const Shared::Resource::Properties& remove=Shared::Resource::Properties()); ~SetMetadata(); @@ -102,15 +103,19 @@ private: QueuedEvent* _create_event; SetEvents _set_events; std::vector _types; + std::vector _remove_types; Raul::URI _subject; Shared::Resource::Properties _properties; + Shared::Resource::Properties _remove; Shared::ResourceImpl* _object; PatchImpl* _patch; CompiledPatch* _compiled_patch; std::string _error_predicate; - bool _replace; + bool _create; bool _is_meta; bool _success; + + SharedPtr _old_bindings; }; diff --git a/src/engine/internals/Controller.cpp b/src/engine/internals/Controller.cpp index 941f7e49..634fc152 100644 --- a/src/engine/internals/Controller.cpp +++ b/src/engine/internals/Controller.cpp @@ -20,7 +20,6 @@ #include "shared/LV2URIMap.hpp" #include "internals/Controller.hpp" #include "PostProcessor.hpp" -#include "events/Learn.hpp" #include "events/SendPortValue.hpp" #include "InputPort.hpp" #include "OutputPort.hpp" diff --git a/src/engine/wscript b/src/engine/wscript index 7e630387..12e61121 100644 --- a/src/engine/wscript +++ b/src/engine/wscript @@ -43,7 +43,6 @@ def build(bld): events/Disconnect.cpp events/DisconnectAll.cpp events/Get.cpp - events/Learn.cpp events/LoadPlugins.cpp events/Move.cpp events/Note.cpp diff --git a/src/gui/ObjectMenu.cpp b/src/gui/ObjectMenu.cpp index 5151fadc..41505e99 100644 --- a/src/gui/ObjectMenu.cpp +++ b/src/gui/ObjectMenu.cpp @@ -15,6 +15,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include "interface/EngineInterface.hpp" #include "shared/LV2URIMap.hpp" @@ -39,6 +40,7 @@ ObjectMenu::ObjectMenu(BaseObjectType* cobject, const Glib::RefPtrget_widget("object_learn_menuitem", _learn_menuitem); + xml->get_widget("object_unlearn_menuitem", _unlearn_menuitem); xml->get_widget("object_polyphonic_menuitem", _polyphonic_menuitem); xml->get_widget("object_disconnect_menuitem", _disconnect_menuitem); xml->get_widget("object_rename_menuitem", _rename_menuitem); @@ -62,6 +64,9 @@ ObjectMenu::init(SharedPtr object) _learn_menuitem->signal_activate().connect( sigc::mem_fun(this, &ObjectMenu::on_menu_learn)); + _unlearn_menuitem->signal_activate().connect( + sigc::mem_fun(this, &ObjectMenu::on_menu_unlearn)); + _disconnect_menuitem->signal_activate().connect( sigc::mem_fun(this, &ObjectMenu::on_menu_disconnect)); @@ -78,6 +83,7 @@ ObjectMenu::init(SharedPtr object) object->signal_property.connect(sigc::mem_fun(this, &ObjectMenu::property_changed)); _learn_menuitem->hide(); + _unlearn_menuitem->hide(); _enable_signal = true; } @@ -86,7 +92,20 @@ ObjectMenu::init(SharedPtr object) void ObjectMenu::on_menu_learn() { - App::instance().engine()->learn(_object->path()); + App::instance().engine()->set_property(_object->path(), + App::instance().uris().ingen_controlBinding, + App::instance().uris().wildcard); +} + + +void +ObjectMenu::on_menu_unlearn() +{ + Resource::Properties remove; + remove.insert(std::make_pair( + App::instance().uris().ingen_controlBinding, + App::instance().uris().wildcard)); + App::instance().engine()->delta(_object->path(), remove, Resource::Properties()); } diff --git a/src/gui/ObjectMenu.hpp b/src/gui/ObjectMenu.hpp index 83857b2b..85160b2e 100644 --- a/src/gui/ObjectMenu.hpp +++ b/src/gui/ObjectMenu.hpp @@ -45,6 +45,7 @@ public: protected: void on_menu_learn(); + void on_menu_unlearn(); virtual void on_menu_disconnect() = 0; void on_menu_polyphonic(); void on_menu_destroy(); @@ -55,6 +56,7 @@ protected: bool _enable_signal; SharedPtr _object; Gtk::MenuItem* _learn_menuitem; + Gtk::MenuItem* _unlearn_menuitem; Gtk::CheckMenuItem* _polyphonic_menuitem; Gtk::MenuItem* _disconnect_menuitem; Gtk::MenuItem* _rename_menuitem; diff --git a/src/gui/PortMenu.cpp b/src/gui/PortMenu.cpp index d52500bc..b9c538e1 100644 --- a/src/gui/PortMenu.cpp +++ b/src/gui/PortMenu.cpp @@ -66,6 +66,7 @@ PortMenu::init(SharedPtr port, bool patch_port) if (port->type() == PortType::CONTROL) { _learn_menuitem->show(); + _unlearn_menuitem->show(); items().push_front(Gtk::Menu_Helpers::SeparatorElem()); diff --git a/src/gui/ingen_gui.glade b/src/gui/ingen_gui.glade index 1e297c12..85058105 100644 --- a/src/gui/ingen_gui.glade +++ b/src/gui/ingen_gui.glade @@ -3071,6 +3071,13 @@ Thank you for contributing. True + + + True + _Unlearn + True + + Dis_connect diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp index 92fe78d1..395014a6 100644 --- a/src/serialisation/Parser.cpp +++ b/src/serialisation/Parser.cpp @@ -138,8 +138,8 @@ Parser::parse_string( LOG(info) << "Parsing " << (data_path ? data_path->str() : "*") << " from string"; if (!base_uri.empty()) - LOG(info) << " (base " << base_uri << ")"; - LOG(info) << endl; + info << " (base " << base_uri << ")"; + info << endl; bool ret = parse(world, target, model, base_uri, data_path, parent, symbol, data); Redland::Resource subject(*world->rdf_world, base_uri); @@ -162,6 +162,8 @@ Parser::parse_update( { Redland::Model model(*world->rdf_world, str.c_str(), str.length(), base_uri); + std::cout << "PARSE UPDATE " << str << endl; + // Delete anything explicitly declared to not exist Glib::ustring query_str = Glib::ustring("SELECT DISTINCT ?o WHERE { ?o a owl:Nothing }"); Redland::Query query(*world->rdf_world, query_str); diff --git a/src/serialisation/Serialiser.cpp b/src/serialisation/Serialiser.cpp index f70c59bc..35d304f8 100644 --- a/src/serialisation/Serialiser.cpp +++ b/src/serialisation/Serialiser.cpp @@ -225,7 +225,9 @@ Serialiser::finish() } } + delete _model; _base_uri = ""; + return ret; } diff --git a/src/shared/ClashAvoider.cpp b/src/shared/ClashAvoider.cpp index c6aec06d..c86d9cde 100644 --- a/src/shared/ClashAvoider.cpp +++ b/src/shared/ClashAvoider.cpp @@ -151,6 +151,15 @@ ClashAvoider::put(const Raul::URI& path, } +void +ClashAvoider::delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add) +{ + _target.delta(map_uri(path), remove, add); +} + + void ClashAvoider::move(const Raul::Path& old_path, const Raul::Path& new_path) diff --git a/src/shared/ClashAvoider.hpp b/src/shared/ClashAvoider.hpp index 50a036da..9c131e0e 100644 --- a/src/shared/ClashAvoider.hpp +++ b/src/shared/ClashAvoider.hpp @@ -51,6 +51,10 @@ public: virtual void put(const Raul::URI& path, const Resource::Properties& properties); + virtual void delta(const Raul::URI& path, + const Shared::Resource::Properties& remove, + const Shared::Resource::Properties& add); + virtual void move(const Raul::Path& old_path, const Raul::Path& new_path); diff --git a/src/shared/LV2URIMap.cpp b/src/shared/LV2URIMap.cpp index 5717a4a9..f83f7aa5 100644 --- a/src/shared/LV2URIMap.cpp +++ b/src/shared/LV2URIMap.cpp @@ -104,6 +104,7 @@ LV2URIMap::LV2URIMap() , rdfs_seeAlso(NS_RDFS "seeAlso") , string_transfer("http://lv2plug.in/ns/dev/string-port#StringTransfer") , ui_format_events("http://lv2plug.in/ns/extensions/ui#Events") + , wildcard(NS_INGEN "wildcard") { uri_map_feature_data.uri_to_id = &LV2URIMap::uri_map_uri_to_id; uri_map_feature_data.callback_data = this; diff --git a/src/shared/LV2URIMap.hpp b/src/shared/LV2URIMap.hpp index d14314b7..6b298e79 100644 --- a/src/shared/LV2URIMap.hpp +++ b/src/shared/LV2URIMap.hpp @@ -112,6 +112,7 @@ public: const Quark rdfs_seeAlso; const Quark string_transfer; const Quark ui_format_events; + const Quark wildcard; }; diff --git a/src/shared/ResourceImpl.cpp b/src/shared/ResourceImpl.cpp index ea64a5d7..230d53b8 100644 --- a/src/shared/ResourceImpl.cpp +++ b/src/shared/ResourceImpl.cpp @@ -64,6 +64,24 @@ ResourceImpl::set_property(const Raul::URI& uri, const Raul::Atom& value) } +void +ResourceImpl::remove_property(const Raul::URI& uri, const Raul::Atom& value) +{ + const LV2URIMap& uris = Shared::LV2URIMap::instance(); + if (value == uris.wildcard) { + _properties.erase(uri); + } else { + Properties::iterator i = _properties.find(uri); + for (; (i != _properties.end()) && (i->first == uri); ++i) { + if (i->second == value) { + _properties.erase(i); + return; + } + } + } +} + + bool ResourceImpl::has_property(const Raul::URI& uri, const Raul::Atom& value) const { @@ -177,5 +195,39 @@ ResourceImpl::add_properties(const Properties& p) } +void +ResourceImpl::remove_properties(const Properties& p) +{ + const LV2URIMap& uris = Shared::LV2URIMap::instance(); + typedef Resource::Properties::const_iterator iterator; + for (iterator i = p.begin(); i != p.end(); ++i) { + if (i->second == uris.wildcard) { + _properties.erase(i->first); + } else { + for (Properties::iterator j = _properties.find(i->first); + (j != _properties.end()) && (j->first == i->first); ++j) { + if (j->second == i->second) { + _properties.erase(j); + break; + } + } + } + } +} + + +void + +ResourceImpl::dump(std::ostream& os) const +{ + typedef Resource::Properties::const_iterator iterator; + os << _uri << " [" << endl; + for (iterator i = _properties.begin(); i != _properties.end(); ++i) { + os << "\t" << i->first << " " << i->second << " ;" << endl; + } + os << "]" << endl; +} + + } // namespace Shared } // namespace Ingen diff --git a/src/shared/ResourceImpl.hpp b/src/shared/ResourceImpl.hpp index eb80a46c..8e827df8 100644 --- a/src/shared/ResourceImpl.hpp +++ b/src/shared/ResourceImpl.hpp @@ -40,10 +40,14 @@ public: const Raul::Atom& get_property(const Raul::URI& uri) const; Raul::Atom& set_property(const Raul::URI& uri, const Raul::Atom& value); + void remove_property(const Raul::URI& uri, const Raul::Atom& value); bool has_property(const Raul::URI& uri, const Raul::Atom& value) const; void add_property(const Raul::URI& uri, const Raul::Atom& value); void set_properties(const Properties& p); void add_properties(const Properties& p); + void remove_properties(const Properties& p); + + void dump(std::ostream& os) const; sigc::signal signal_property; -- cgit v1.2.1