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/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 ++- 15 files changed, 123 insertions(+), 89 deletions(-) (limited to 'src/libs/engine') 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; }; -- cgit v1.2.1