From a47220df59c076eaa717710dc2ffc6614bee268c Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 1 Oct 2007 05:27:41 +0000 Subject: Blink MIDI ports on message transmission. git-svn-id: http://svn.drobilla.net/lad/ingen@794 a436a847-0d15-0410-975c-d299462d15a1 --- src/common/interface/ClientInterface.hpp | 2 + src/libs/client/OSCClientReceiver.cpp | 18 +++-- src/libs/client/OSCClientReceiver.hpp | 5 +- src/libs/client/PortModel.hpp | 3 +- src/libs/client/SigClientInterface.hpp | 4 ++ src/libs/client/Store.cpp | 12 ++++ src/libs/client/Store.hpp | 1 + src/libs/client/ThreadedSigClientInterface.hpp | 5 ++ src/libs/engine/ClientBroadcaster.cpp | 8 +++ src/libs/engine/ClientBroadcaster.hpp | 1 + src/libs/engine/DuplexPort.cpp | 25 +++---- src/libs/engine/InputPort.cpp | 22 ++---- src/libs/engine/InputPort.hpp | 1 - src/libs/engine/Makefile.am | 2 + src/libs/engine/OSCClientSender.cpp | 79 ++++++++++++---------- src/libs/engine/OSCClientSender.hpp | 2 + src/libs/engine/OutputPort.cpp | 10 +-- src/libs/engine/Port.cpp | 33 ++++++++- src/libs/engine/Port.hpp | 8 ++- .../engine/events/EnablePortBroadcastingEvent.cpp | 2 +- src/libs/engine/events/Makefile.am | 2 + src/libs/engine/events/SendPortValueEvent.cpp | 6 -- src/libs/engine/events/SendPortValueEvent.hpp | 11 ++- src/libs/gui/App.cpp | 42 +++++++++++- src/libs/gui/App.hpp | 9 +++ src/libs/gui/NodeModule.cpp | 2 +- src/libs/gui/Port.cpp | 9 +++ src/libs/gui/Port.hpp | 1 + 28 files changed, 222 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/common/interface/ClientInterface.hpp b/src/common/interface/ClientInterface.hpp index 110f2905..b5fd7667 100644 --- a/src/common/interface/ClientInterface.hpp +++ b/src/common/interface/ClientInterface.hpp @@ -116,6 +116,8 @@ public: virtual void control_change(const std::string& port_path, float value) = 0; + virtual void port_activity(const std::string& port_path) = 0; + virtual void program_add(const std::string& node_path, uint32_t bank, uint32_t program, diff --git a/src/libs/client/OSCClientReceiver.cpp b/src/libs/client/OSCClientReceiver.cpp index 63bf5b69..b9f5a70d 100644 --- a/src/libs/client/OSCClientReceiver.cpp +++ b/src/libs/client/OSCClientReceiver.cpp @@ -33,11 +33,7 @@ namespace Client { OSCClientReceiver::OSCClientReceiver(int listen_port) : ClientInterface("localhost"), _listen_port(listen_port), - _st(NULL)//, -// _receiving_node(false), -// _receiving_node_model(NULL), -// _receiving_node_num_ports(0), -// _num_received_ports(0) + _st(NULL) { start(false); } @@ -164,6 +160,7 @@ OSCClientReceiver::setup_callbacks() lo_server_thread_add_method(_st, "/ingen/polyphonic", "sF", polyphonic_cb, this); lo_server_thread_add_method(_st, "/ingen/metadata_update", NULL, metadata_update_cb, this); lo_server_thread_add_method(_st, "/ingen/control_change", "sf", control_change_cb, this); + lo_server_thread_add_method(_st, "/ingen/port_activity", "s", port_activity_cb, this); lo_server_thread_add_method(_st, "/ingen/program_add", "siis", program_add_cb, this); lo_server_thread_add_method(_st, "/ingen/program_remove", "sii", program_remove_cb, this); } @@ -335,6 +332,17 @@ OSCClientReceiver::_control_change_cb(const char* path, const char* types, lo_ar } +int +OSCClientReceiver::_port_activity_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + const char* const port_path = &argv[0]->s; + + port_activity(port_path); + + return 0; +} + + int OSCClientReceiver::_response_ok_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { diff --git a/src/libs/client/OSCClientReceiver.hpp b/src/libs/client/OSCClientReceiver.hpp index 4c036ebf..82c4ff4c 100644 --- a/src/libs/client/OSCClientReceiver.hpp +++ b/src/libs/client/OSCClientReceiver.hpp @@ -62,10 +62,6 @@ public: OSCClientReceiver(int listen_port); ~OSCClientReceiver(); - // Engine side only - //void enable() {} - //void disable() {} - void start(bool dump_osc); void stop(); @@ -103,6 +99,7 @@ private: LO_HANDLER(polyphonic); LO_HANDLER(metadata_update); LO_HANDLER(control_change); + LO_HANDLER(port_activity); LO_HANDLER(program_add); LO_HANDLER(program_remove); }; diff --git a/src/libs/client/PortModel.hpp b/src/libs/client/PortModel.hpp index 80d5e524..8548a898 100644 --- a/src/libs/client/PortModel.hpp +++ b/src/libs/client/PortModel.hpp @@ -66,7 +66,8 @@ public: } // Signals - sigc::signal signal_control; ///< "Control" ports only + sigc::signal signal_control; ///< Control ports + sigc::signal signal_activity; ///< Message ports sigc::signal > signal_connection; sigc::signal > signal_disconnection; diff --git a/src/libs/client/SigClientInterface.hpp b/src/libs/client/SigClientInterface.hpp index bdfdd783..895b4cde 100644 --- a/src/libs/client/SigClientInterface.hpp +++ b/src/libs/client/SigClientInterface.hpp @@ -64,6 +64,7 @@ public: sigc::signal signal_disconnection; sigc::signal signal_metadata_update; sigc::signal signal_control_change; + sigc::signal signal_port_activity; sigc::signal signal_program_add; sigc::signal signal_program_remove; @@ -133,6 +134,9 @@ protected: void control_change(const string& port_path, float value) { signal_control_change.emit(port_path, value); } + + void port_activity(const string& port_path) + { signal_port_activity.emit(port_path); } void program_add(const string& path, uint32_t bank, uint32_t program, const string& name) { signal_program_add.emit(path, bank, program, name); } diff --git a/src/libs/client/Store.cpp b/src/libs/client/Store.cpp index e3d93d60..b399505d 100644 --- a/src/libs/client/Store.cpp +++ b/src/libs/client/Store.cpp @@ -51,6 +51,7 @@ Store::Store(SharedPtr engine, SharedPtr em emitter->signal_disconnection.connect(sigc::mem_fun(this, &Store::disconnection_event)); emitter->signal_metadata_update.connect(sigc::mem_fun(this, &Store::metadata_update_event)); emitter->signal_control_change.connect(sigc::mem_fun(this, &Store::control_change_event)); + emitter->signal_port_activity.connect(sigc::mem_fun(this, &Store::port_activity_event)); } @@ -509,6 +510,17 @@ Store::control_change_event(const Path& port_path, float value) cerr << "ERROR: control change for nonexistant port " << port_path << endl; } + +void +Store::port_activity_event(const Path& port_path) +{ + SharedPtr port = PtrCast(object(port_path)); + if (port) + port->signal_activity.emit(); + else + cerr << "ERROR: activity for nonexistant port " << port_path << endl; +} + SharedPtr Store::connection_patch(const Path& src_port_path, const Path& dst_port_path) diff --git a/src/libs/client/Store.hpp b/src/libs/client/Store.hpp index 6b0ec7d3..af241097 100644 --- a/src/libs/client/Store.hpp +++ b/src/libs/client/Store.hpp @@ -104,6 +104,7 @@ private: void patch_cleared_event(const Path& path); void metadata_update_event(const Path& subject_path, const string& predicate, const Atom& value); void control_change_event(const Path& port_path, float value); + void port_activity_event(const Path& port_path); void connection_event(const Path& src_port_path, const Path& dst_port_path); void disconnection_event(const Path& src_port_path, const Path& dst_port_path); diff --git a/src/libs/client/ThreadedSigClientInterface.hpp b/src/libs/client/ThreadedSigClientInterface.hpp index 22f03118..c79ed090 100644 --- a/src/libs/client/ThreadedSigClientInterface.hpp +++ b/src/libs/client/ThreadedSigClientInterface.hpp @@ -65,6 +65,7 @@ public: , disconnection_slot(signal_disconnection.make_slot()) , metadata_update_slot(signal_metadata_update.make_slot()) , control_change_slot(signal_control_change.make_slot()) + , port_activity_slot(signal_port_activity.make_slot()) , program_add_slot(signal_program_add.make_slot()) , program_remove_slot(signal_program_remove.make_slot()) {} @@ -137,6 +138,9 @@ public: void control_change(const string& port_path, float value) { push_sig(sigc::bind(control_change_slot, port_path, value)); } + + void port_activity(const string& port_path) + { push_sig(sigc::bind(port_activity_slot, port_path)); } void program_add(const string& path, uint32_t bank, uint32_t program, const string& name) { push_sig(sigc::bind(program_add_slot, path, bank, program, name)); } @@ -176,6 +180,7 @@ private: sigc::slot disconnection_slot; sigc::slot metadata_update_slot; sigc::slot control_change_slot; + sigc::slot port_activity_slot; sigc::slot program_add_slot; sigc::slot program_remove_slot; }; diff --git a/src/libs/engine/ClientBroadcaster.cpp b/src/libs/engine/ClientBroadcaster.cpp index 94452e73..be765390 100644 --- a/src/libs/engine/ClientBroadcaster.cpp +++ b/src/libs/engine/ClientBroadcaster.cpp @@ -227,6 +227,14 @@ ClientBroadcaster::send_control_change(const string& port_path, float value) } +void +ClientBroadcaster::send_port_activity(const string& port_path) +{ + for (Clients::const_iterator i = _clients.begin(); i != _clients.end(); ++i) + (*i).second->port_activity(port_path); +} + + void ClientBroadcaster::send_program_add(const string& node_path, int bank, int program, const string& name) { diff --git a/src/libs/engine/ClientBroadcaster.hpp b/src/libs/engine/ClientBroadcaster.hpp index 7977cc6f..ea2563be 100644 --- a/src/libs/engine/ClientBroadcaster.hpp +++ b/src/libs/engine/ClientBroadcaster.hpp @@ -78,6 +78,7 @@ public: void send_patch_polyphony(const string& patch_path, uint32_t poly); void send_metadata_update(const string& node_path, const string& key, const Raul::Atom& value); void send_control_change(const string& port_path, float value); + void send_port_activity(const string& port_path); void send_program_add(const string& node_path, int bank, int program, const string& name); void send_program_remove(const string& node_path, int bank, int program); diff --git a/src/libs/engine/DuplexPort.cpp b/src/libs/engine/DuplexPort.cpp index 6297a9be..04b97460 100644 --- a/src/libs/engine/DuplexPort.cpp +++ b/src/libs/engine/DuplexPort.cpp @@ -42,27 +42,24 @@ DuplexPort::DuplexPort(Node* parent, const string& name, uint32_t index, uint32_ void DuplexPort::pre_process(ProcessContext& context) { - // Think about it... + // + InputPort::pre_process(context); -// if (_is_output) { - InputPort::pre_process(context); -// } else { - //for (uint32_t i=0; i < _poly; ++i) - // _buffers->at(i)->rewind(); -// OutputPort::pre_process(nframes, start, end); -// } + if ( ! _is_output) + broadcast(context); + // } void DuplexPort::post_process(ProcessContext& context) { - // Think about it... - -// if (_is_output) -// InputPort::pre_process(nframes, start, end); -//else - OutputPort::pre_process(context); + // + if (_is_output) + broadcast(context); + + OutputPort::pre_process(context); + // } diff --git a/src/libs/engine/InputPort.cpp b/src/libs/engine/InputPort.cpp index 16a1c86a..bb3e57ce 100644 --- a/src/libs/engine/InputPort.cpp +++ b/src/libs/engine/InputPort.cpp @@ -33,7 +33,6 @@ namespace Ingen { InputPort::InputPort(Node* parent, const string& name, uint32_t index, uint32_t poly, DataType type, size_t buffer_size) : Port(parent, name, index, poly, type, buffer_size) - , _last_reported_value(0.0f) // default? { } @@ -78,11 +77,9 @@ InputPort::add_connection(Raul::ListNode* const c) Port::connect_buffers(); } - // Automatically monitor connected control inputs - if (_type == DataType::FLOAT && _buffer_size == 1) { - cerr << path() << " monitor enable" << endl; - _monitor = true; - } + // Automatically broadcast connected control inputs + if (_type == DataType::FLOAT && _buffer_size == 1) + _broadcast = true; } @@ -124,9 +121,9 @@ InputPort::remove_connection(const OutputPort* src_port) if (modify_buffers) Port::connect_buffers(); - // Turn off monitoring if we're not connected any more (FIXME: not quite right..) + // Turn off broadcasting if we're not connected any more (FIXME: not quite right..) if (_type == DataType::FLOAT && _buffer_size == 1 && _connections.size() == 0) - _monitor = false; + _broadcast = false; return connection; } @@ -220,14 +217,7 @@ InputPort::pre_process(ProcessContext& context) void InputPort::post_process(ProcessContext& context) { - if (_monitor && _type == DataType::FLOAT && _buffer_size == 1) { - const Sample value = ((AudioBuffer*)(*_buffers)[0])->value_at(0); - if (value != _last_reported_value) { - const SendPortValueEvent ev(context.engine(), context.start(), this, false, 0, value); - context.event_sink().write(sizeof(ev), &ev); - _last_reported_value = value; - } - } + broadcast(context); // Prepare for next cycle for (uint32_t i=0; i < _poly; ++i) diff --git a/src/libs/engine/InputPort.hpp b/src/libs/engine/InputPort.hpp index ca62470b..bb8bf26b 100644 --- a/src/libs/engine/InputPort.hpp +++ b/src/libs/engine/InputPort.hpp @@ -69,7 +69,6 @@ public: private: Connections _connections; - Sample _last_reported_value; }; diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am index 59835dd2..b5c910f8 100644 --- a/src/libs/engine/Makefile.am +++ b/src/libs/engine/Makefile.am @@ -153,6 +153,8 @@ libingen_engine_la_SOURCES = \ events/RequestPluginsEvent.hpp \ events/RequestPortValueEvent.cpp \ events/RequestPortValueEvent.hpp \ + events/SendPortActivityEvent.cpp \ + events/SendPortActivityEvent.hpp \ events/SendPortValueEvent.cpp \ events/SendPortValueEvent.hpp \ events/SetMetadataEvent.cpp \ diff --git a/src/libs/engine/OSCClientSender.cpp b/src/libs/engine/OSCClientSender.cpp index 35b17f36..d719cfa1 100644 --- a/src/libs/engine/OSCClientSender.cpp +++ b/src/libs/engine/OSCClientSender.cpp @@ -118,7 +118,7 @@ OSCClientSender::response_ok(int32_t id) /** \page client_osc_namespace *

\b /ingen/response - Respond to a user command * \arg \b response-id (int) - Request ID this is a response to - * \arg \b message (const std::string&) - Error message (natural language text) + * \arg \b message (string) - Error message (natural language text) *

\n \n */ void @@ -142,7 +142,7 @@ OSCClientSender::response_error(int32_t id, const std::string& msg) /** \page client_osc_namespace *

\b /ingen/error - Notification that an error has occurred - * \arg \b message (const std::string&) - Error message (natural language text) \n\n + * \arg \b message (string) - Error message (natural language text) \n\n * \li This is for notification of errors that aren't a direct response to a * user command, ie "unexpected" errors.

\n \n */ @@ -184,11 +184,11 @@ OSCClientSender::num_plugins(uint32_t num) /** \page client_osc_namespace *

\b /ingen/plugin - Notification of the existance of a plugin - * \arg \b type (const std::string&) - Type if plugin ("LADSPA", "DSSI", or "Internal") - * \arg \b uri (const std::string&) - URI of the plugin (see engine namespace documentation) \n - * \arg \b lib-name (const std::string&) - Name of shared library plugin resides in (ie "cmt.so") - * \arg \b plug-label (const std::string&) - Label of the plugin (ie "dahdsr_iaoa") - * \arg \b name (const std::string&) - Descriptive human-readable name of plugin (ie "ADSR Envelope") + * \arg \b type (string) - Type if plugin ("LADSPA", "DSSI", or "Internal") + * \arg \b uri (string) - URI of the plugin (see engine namespace documentation) \n + * \arg \b lib-name (string) - Name of shared library plugin resides in (ie "cmt.so") + * \arg \b plug-label (string) - Label of the plugin (ie "dahdsr_iaoa") + * \arg \b name (string) - Descriptive human-readable name of plugin (ie "ADSR Envelope") *

\n \n */ /* @@ -242,8 +242,8 @@ OSCClientSender::plugins() /** \page client_osc_namespace *

\b /ingen/new_node - Notification of a new node's creation. - * \arg \b plug-uri (const std::string&) - URI of the plugin new node is an instance of - * \arg \b path (const std::string&) - Path of the new node + * \arg \b plug-uri (string) - URI of the plugin new node is an instance of + * \arg \b path (string) - Path of the new node * \arg \b polyphonic (boolean) - Node is polyphonic * \arg \b num-ports (integer) - Number of ports (number of new_port messages to expect)\n\n * \li New nodes are sent as a bundle. The first message in the bundle will be @@ -270,8 +270,8 @@ void OSCClientSender::new_node(const std::string& plugin_uri, /** \page client_osc_namespace *

\b /ingen/new_port - Notification of a new port's creation. - * \arg \b path (const std::string&) - Path of new port - * \arg \b data-type (const std::string&) - Type of port (ingen:audio, ingen:control, ingen:midi, or ingen:osc) + * \arg \b path (string) - Path of new port + * \arg \b data-type (string) - Type of port (ingen:audio, ingen:control, ingen:midi, or ingen:osc) * \arg \b direction ("is-output") (integer) - Direction of data flow (Input = 0, Output = 1) * * \li Note that in the event of loading a patch, this message could be @@ -320,7 +320,7 @@ OSCClientSender::polyphonic(const std::string& path, /** \page client_osc_namespace *

\b /ingen/destroyed - Notification an object has been destroyed - * \arg \b path (const std::string&) - Path of object (which no longer exists)

\n \n + * \arg \b path (string) - Path of object (which no longer exists)

\n \n */ void OSCClientSender::object_destroyed(const std::string& path) @@ -336,7 +336,7 @@ OSCClientSender::object_destroyed(const std::string& path) /** \page client_osc_namespace *

\b /ingen/patch_cleared - Notification a patch has been cleared (all children destroyed) - * \arg \b path (const std::string&) - Path of patch (which is now empty)

\n \n + * \arg \b path (string) - Path of patch (which is now empty)

\n \n */ void OSCClientSender::patch_cleared(const std::string& patch_path) @@ -350,7 +350,7 @@ OSCClientSender::patch_cleared(const std::string& patch_path) /** \page client_osc_namespace *

\b /ingen/patch_enabled - Notification a patch's DSP processing has been enabled. - * \arg \b path (const std::string&) - Path of enabled patch

\n \n + * \arg \b path (string) - Path of enabled patch

\n \n */ void OSCClientSender::patch_enabled(const std::string& patch_path) @@ -364,7 +364,7 @@ OSCClientSender::patch_enabled(const std::string& patch_path) /** \page client_osc_namespace *

\b /ingen/patch_disabled - Notification a patch's DSP processing has been disabled. - * \arg \b path (const std::string&) - Path of disabled patch

\n \n + * \arg \b path (string) - Path of disabled patch

\n \n */ void OSCClientSender::patch_disabled(const std::string& patch_path) @@ -378,7 +378,7 @@ OSCClientSender::patch_disabled(const std::string& patch_path) /** \page client_osc_namespace *

\b /ingen/patch_polyphony - Notification a patch's DSP processing has been polyphony. - * \arg \b path (const std::string&) - Path of polyphony patch

\n \n + * \arg \b path (string) - Path of polyphony patch

\n \n */ void OSCClientSender::patch_polyphony(const std::string& patch_path, uint32_t poly) @@ -393,8 +393,8 @@ OSCClientSender::patch_polyphony(const std::string& patch_path, uint32_t poly) /** \page client_osc_namespace *

\b /ingen/new_connection - Notification a new connection has been made. - * \arg \b src-path (const std::string&) - Path of the source port - * \arg \b dst-path (const std::string&) - Path of the destination port

\n \n + * \arg \b src-path (string) - Path of the source port + * \arg \b dst-path (string) - Path of the destination port

\n \n */ void OSCClientSender::connection(const std::string& src_port_path, const std::string& dst_port_path) @@ -408,8 +408,8 @@ OSCClientSender::connection(const std::string& src_port_path, const std::string& /** \page client_osc_namespace *

\b /ingen/disconnection - Notification a connection has been unmade. - * \arg \b src-path (const std::string&) - Path of the source port - * \arg \b dst-path (const std::string&) - Path of the destination port

\n \n + * \arg \b src-path (string) - Path of the source port + * \arg \b dst-path (string) - Path of the destination port

\n \n */ void OSCClientSender::disconnection(const std::string& src_port_path, const std::string& dst_port_path) @@ -423,9 +423,9 @@ OSCClientSender::disconnection(const std::string& src_port_path, const std::stri /** \page client_osc_namespace *

\b /ingen/metadata_update - Notification of a piece of metadata. - * \arg \b path (const std::string&) - Path of the object associated with metadata (can be a node, patch, or port) - * \arg \b key (const std::string&) - * \arg \b value (const std::string&)

\n \n + * \arg \b path (string) - Path of the object associated with metadata (can be a node, patch, or port) + * \arg \b key (string) + * \arg \b value (string)

\n \n */ void OSCClientSender::metadata_update(const std::string& path, const std::string& key, const Atom& value) @@ -443,11 +443,8 @@ OSCClientSender::metadata_update(const std::string& path, const std::string& key /** \page client_osc_namespace *

\b /ingen/control_change - Notification the value of a port has changed - * \arg \b path (const std::string&) - Path of port - * \arg \b value (float) - New value of port - * - * \li This will only send updates for values set by clients of course - not values - * changing because of connections to other ports!

\n \n + * \arg \b path (string) - Path of port + * \arg \b value (float) - New value of port

\n \n */ void OSCClientSender::control_change(const std::string& port_path, float value) @@ -459,11 +456,25 @@ OSCClientSender::control_change(const std::string& port_path, float value) } +/** \page client_osc_namespace + *

\b /ingen/port_activity - Notification of activity for a port (e.g. MIDI messages) + * \arg \b path (string) - Path of port

\n \n + */ +void +OSCClientSender::port_activity(const std::string& port_path) +{ + if (!_enabled) + return; + + lo_send(_address, "/ingen/port_activity", "s", port_path.c_str()); +} + + /** \page client_osc_namespace *

\b /ingen/plugin - Notification of the existance of a plugin - * \arg \b type (const std::string&) - Type of plugin ("LADSPA", "DSSI", or "Internal") - * \arg \b uri (const std::string&) - Type of plugin ("LADSPA", "DSSI", or "Internal") - * \arg \b name (const std::string&) - Descriptive human-readable name of plugin (ie "ADSR Envelope") + * \arg \b type (string) - Type of plugin ("LADSPA", "DSSI", or "Internal") + * \arg \b uri (string) - Type of plugin ("LADSPA", "DSSI", or "Internal") + * \arg \b name (string) - Descriptive human-readable name of plugin (ie "ADSR Envelope") */ void OSCClientSender::new_plugin(const std::string& uri, const std::string& type_uri, const std::string& name) @@ -497,7 +508,7 @@ OSCClientSender::new_plugin(const std::string& uri, const std::string& type_uri, /** \page client_osc_namespace *

\b /ingen/new_patch - Notification of a new patch - * \arg \b path (const std::string&) - Path of new patch + * \arg \b path (string) - Path of new patch * \arg \b poly (int) - Polyphony of new patch (\em not a boolean like new_node)

\n \n */ void @@ -523,8 +534,8 @@ OSCClientSender::new_patch(const std::string& path, uint32_t poly) /** \page client_osc_namespace *

\b /ingen/object_renamed - Notification of an object's renaming - * \arg \b old-path (const std::string&) - Old path of object - * \arg \b new-path (const std::string&) - New path of object

\n \n + * \arg \b old-path (string) - Old path of object + * \arg \b new-path (string) - New path of object

\n \n */ void OSCClientSender::object_renamed(const std::string& old_path, const std::string& new_path) diff --git a/src/libs/engine/OSCClientSender.hpp b/src/libs/engine/OSCClientSender.hpp index b1fcc0f4..0d46545b 100644 --- a/src/libs/engine/OSCClientSender.hpp +++ b/src/libs/engine/OSCClientSender.hpp @@ -120,6 +120,8 @@ public: virtual void control_change(const std::string& port_path, float value); + virtual void port_activity(const std::string& port_path); + virtual void program_add(const std::string& node_path, uint32_t bank, uint32_t program, diff --git a/src/libs/engine/OutputPort.cpp b/src/libs/engine/OutputPort.cpp index 6d49a1d1..024f6f39 100644 --- a/src/libs/engine/OutputPort.cpp +++ b/src/libs/engine/OutputPort.cpp @@ -16,7 +16,7 @@ */ #include "OutputPort.hpp" -#include "AudioBuffer.hpp" +#include "Buffer.hpp" #include "ProcessContext.hpp" namespace Ingen { @@ -33,14 +33,10 @@ OutputPort::pre_process(ProcessContext& context) void OutputPort::post_process(ProcessContext& context) { - if (_monitor && _type == DataType::FLOAT && _buffer_size == 1) { - const Sample value = ((AudioBuffer*)(*_buffers)[0])->value_at(0); - const SendPortValueEvent ev(context.engine(), context.start(), this, false, 0, value); - context.event_sink().write(sizeof(ev), &ev); - } - for (uint32_t i=0; i < _poly; ++i) _buffers->at(i)->prepare_read(context.nframes()); + + broadcast(context); } diff --git a/src/libs/engine/Port.cpp b/src/libs/engine/Port.cpp index d1813f3f..d85c1790 100644 --- a/src/libs/engine/Port.cpp +++ b/src/libs/engine/Port.cpp @@ -15,14 +15,19 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include "Port.hpp" #include "Node.hpp" #include "DataType.hpp" #include "AudioBuffer.hpp" +#include "MidiBuffer.hpp" #include "BufferFactory.hpp" #include "ProcessContext.hpp" +#include "SendPortActivityEvent.hpp" + +using namespace std; namespace Ingen { @@ -38,7 +43,8 @@ Port::Port(Node* const node, const string& name, uint32_t index, uint32_t poly, , _buffer_size(buffer_size) , _type(type) , _fixed_buffers(false) - , _monitor(false) + , _broadcast(false) + , _last_broadcasted_value(0.0f) // default? , _buffers(new Raul::Array(poly)) { assert(node != NULL); @@ -49,6 +55,9 @@ Port::Port(Node* const node, const string& name, uint32_t index, uint32_t poly, if (node->parent() == NULL) _polyphonic = false; + + if (type == DataType::MIDI) + _broadcast = true; // send activity blips assert(_buffers->size() > 0); } @@ -138,6 +147,28 @@ Port::clear_buffers() for (uint32_t i=0; i < _poly; ++i) _buffers->at(i)->clear(); } + + +void +Port::broadcast(ProcessContext& context) +{ + if (_broadcast) { + if (_type == DataType::FLOAT && _buffer_size == 1) { + const Sample value = ((AudioBuffer*)(*_buffers)[0])->value_at(0); + if (value != _last_broadcasted_value) { + const SendPortValueEvent ev(context.engine(), context.start(), this, false, 0, value); + context.event_sink().write(sizeof(ev), &ev); + _last_broadcasted_value = value; + } + } else if (_type == DataType::MIDI) { + if (((MidiBuffer*)(*_buffers)[0])->event_count() > 0) { + const SendPortActivityEvent ev(context.engine(), context.start(), this); + context.event_sink().write(sizeof(ev), &ev); + } + } + } +} + } // namespace Ingen diff --git a/src/libs/engine/Port.hpp b/src/libs/engine/Port.hpp index 35bf0f9b..e504507c 100644 --- a/src/libs/engine/Port.hpp +++ b/src/libs/engine/Port.hpp @@ -87,21 +87,23 @@ public: void fixed_buffers(bool b) { _fixed_buffers = b; } bool fixed_buffers() { return _fixed_buffers; } - void monitor(bool b) { _monitor = b; } - bool monitor() { return _monitor; } + void broadcast(bool b) { _broadcast = b; } + bool broadcast() { return _broadcast; } protected: Port(Node* const node, const std::string& name, uint32_t index, uint32_t poly, DataType type, size_t buffer_size); virtual void allocate_buffers(); virtual void connect_buffers(); + virtual void broadcast(ProcessContext& context); uint32_t _index; uint32_t _poly; uint32_t _buffer_size; DataType _type; bool _fixed_buffers; - bool _monitor; + bool _broadcast; + Sample _last_broadcasted_value; Raul::Array* _buffers; diff --git a/src/libs/engine/events/EnablePortBroadcastingEvent.cpp b/src/libs/engine/events/EnablePortBroadcastingEvent.cpp index 27603e86..018fd3cf 100644 --- a/src/libs/engine/events/EnablePortBroadcastingEvent.cpp +++ b/src/libs/engine/events/EnablePortBroadcastingEvent.cpp @@ -58,7 +58,7 @@ EnablePortBroadcastingEvent::execute(ProcessContext& context) QueuedEvent::execute(context); if (_port) - _port->monitor(_enable); + _port->broadcast(_enable); } diff --git a/src/libs/engine/events/Makefile.am b/src/libs/engine/events/Makefile.am index 22e13205..67ccf0e5 100644 --- a/src/libs/engine/events/Makefile.am +++ b/src/libs/engine/events/Makefile.am @@ -58,6 +58,8 @@ EXTRA_DIST = \ RequestPluginsEvent.hpp \ RequestPortValueEvent.cpp \ RequestPortValueEvent.hpp \ + SendPortActivityEvent.cpp \ + SendPortActivityEvent.hpp \ SendPortValueEvent.cpp \ SendPortValueEvent.hpp \ SetMetadataEvent.cpp \ diff --git a/src/libs/engine/events/SendPortValueEvent.cpp b/src/libs/engine/events/SendPortValueEvent.cpp index 91bbb64e..f663f85c 100644 --- a/src/libs/engine/events/SendPortValueEvent.cpp +++ b/src/libs/engine/events/SendPortValueEvent.cpp @@ -16,21 +16,15 @@ */ #include -#include "Responder.hpp" #include "SendPortValueEvent.hpp" #include "Engine.hpp" #include "Port.hpp" #include "ClientBroadcaster.hpp" -#include "Node.hpp" -#include "ObjectStore.hpp" -#include "AudioBuffer.hpp" -#include "MidiBuffer.hpp" using namespace std; namespace Ingen { -class Engine; void SendPortValueEvent::post_process() diff --git a/src/libs/engine/events/SendPortValueEvent.hpp b/src/libs/engine/events/SendPortValueEvent.hpp index e80682d0..407f0119 100644 --- a/src/libs/engine/events/SendPortValueEvent.hpp +++ b/src/libs/engine/events/SendPortValueEvent.hpp @@ -35,8 +35,7 @@ class Port; * which are created in the pre-processor thread then run through the audio * thread). This event's job is done entirely in post_process. * - * This only works for control ports right now. Variable size data is harder. - * Need some clever variable sized event RT allocation in flat buffer thingie.. + * This only works for control ports right now. * * \ingroup engine */ @@ -67,10 +66,10 @@ public: void post_process(); private: - Port* _port; - bool _omni; - uint32_t _voice_num; - Sample _value; + Port* _port; + bool _omni; + uint32_t _voice_num; + Sample _value; }; diff --git a/src/libs/gui/App.cpp b/src/libs/gui/App.cpp index feeae181..dc3db30d 100644 --- a/src/libs/gui/App.cpp +++ b/src/libs/gui/App.cpp @@ -47,11 +47,12 @@ #ifdef HAVE_SLV2 #include #endif -using std::cerr; using std::cout; using std::endl; -using std::string; -namespace Ingen { namespace Client { class PluginModel; } } + +using namespace std; using namespace Ingen::Client; +namespace Ingen { namespace Client { class PluginModel; } } + namespace Ingen { namespace GUI { @@ -145,6 +146,9 @@ App::attach(SharedPtr engine, SharedPtr cli _loader = SharedPtr(new ThreadedLoader(engine)); _patch_tree_window->init(*_store); + + Glib::signal_timeout().connect(sigc::mem_fun(this, &App::animate_callback), + 100, G_PRIORITY_DEFAULT_IDLE); } @@ -172,6 +176,38 @@ App::error_message(const string& str) } +void +App::port_activity(Port* port) +{ + std::pair inserted = _activity_ports.insert(make_pair(port, false)); + if (inserted.second) + inserted.first->second = false; + + port->set_highlighted(true, false, true, false); +} + + +bool +App::animate_callback() +{ + for (ActivityPorts::iterator i = _activity_ports.begin(); i != _activity_ports.end() ; ) { + ActivityPorts::iterator next = i; + ++next; + + if ((*i).second) { // saw it last time, unhighlight and pop + (*i).first->set_highlighted(false, false, true, false); + _activity_ports.erase(i); + } else { + (*i).second = true; + } + + i = next; + } + + return true; +} + + /* bool App::idle_callback() diff --git a/src/libs/gui/App.hpp b/src/libs/gui/App.hpp index 298fc44e..7629cd0e 100644 --- a/src/libs/gui/App.hpp +++ b/src/libs/gui/App.hpp @@ -61,6 +61,7 @@ class ConnectWindow; class Configuration; class ThreadedLoader; class WindowFactory; +class Port; /** Singleton master class most everything is contained within. @@ -84,6 +85,8 @@ public: void quit(); + void port_activity(Port* port); + ConnectWindow* connect_window() const { return _connect_window; } Gtk::AboutDialog* about_dialog() const { return _about_dialog; } MessagesWindow* messages_dialog() const { return _messages_window; } @@ -108,6 +111,8 @@ public: protected: App(Ingen::Shared::World* world); + bool animate_callback(); + static App* _instance; SharedPtr _engine; @@ -125,6 +130,10 @@ protected: Ingen::Shared::World* _world; + /// + typedef std::map ActivityPorts; + ActivityPorts _activity_ports; + /** Used to avoid feedback loops with (eg) process checkbutton * FIXME: Maybe this should be globally implemented at the Controller level, * disable all command sending while handling events to avoid feedback diff --git a/src/libs/gui/NodeModule.cpp b/src/libs/gui/NodeModule.cpp index 39df7151..4ac973f9 100644 --- a/src/libs/gui/NodeModule.cpp +++ b/src/libs/gui/NodeModule.cpp @@ -187,7 +187,7 @@ NodeModule::embed_gui(bool embed) _gui = NULL; } - slv2_ui_instance_free(_slv2_ui); + //slv2_ui_instance_free(_slv2_ui); // FIXME: leak _slv2_ui = NULL; _ports_y_offset = 0; diff --git a/src/libs/gui/Port.cpp b/src/libs/gui/Port.cpp index a75d9cee..228e4598 100644 --- a/src/libs/gui/Port.cpp +++ b/src/libs/gui/Port.cpp @@ -61,6 +61,8 @@ Port::Port(boost::shared_ptr module, SharedPtr pm pm->signal_metadata.connect(sigc::mem_fun(this, &Port::metadata_update)); _port_model->signal_control.connect(sigc::mem_fun(this, &Port::control_changed)); } + + _port_model->signal_activity.connect(sigc::mem_fun(this, &Port::activity)); control_changed(_port_model->value()); } @@ -90,6 +92,13 @@ Port::control_changed(float value) FlowCanvas::Port::set_control(value); } + +void +Port::activity() +{ + App::instance().port_activity(this); +} + void Port::set_control(float value, bool signal) diff --git a/src/libs/gui/Port.hpp b/src/libs/gui/Port.hpp index 5e7b6bbe..e381c59b 100644 --- a/src/libs/gui/Port.hpp +++ b/src/libs/gui/Port.hpp @@ -48,6 +48,7 @@ public: virtual void set_control(float value, bool signal); void control_changed(float value); + void activity(); private: -- cgit v1.2.1