summaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/client/OSCClientReceiver.cpp18
-rw-r--r--src/libs/client/OSCClientReceiver.hpp5
-rw-r--r--src/libs/client/PortModel.hpp3
-rw-r--r--src/libs/client/SigClientInterface.hpp4
-rw-r--r--src/libs/client/Store.cpp12
-rw-r--r--src/libs/client/Store.hpp1
-rw-r--r--src/libs/client/ThreadedSigClientInterface.hpp5
-rw-r--r--src/libs/engine/ClientBroadcaster.cpp8
-rw-r--r--src/libs/engine/ClientBroadcaster.hpp1
-rw-r--r--src/libs/engine/DuplexPort.cpp25
-rw-r--r--src/libs/engine/InputPort.cpp22
-rw-r--r--src/libs/engine/InputPort.hpp1
-rw-r--r--src/libs/engine/Makefile.am2
-rw-r--r--src/libs/engine/OSCClientSender.cpp79
-rw-r--r--src/libs/engine/OSCClientSender.hpp2
-rw-r--r--src/libs/engine/OutputPort.cpp10
-rw-r--r--src/libs/engine/Port.cpp33
-rw-r--r--src/libs/engine/Port.hpp8
-rw-r--r--src/libs/engine/events/EnablePortBroadcastingEvent.cpp2
-rw-r--r--src/libs/engine/events/Makefile.am2
-rw-r--r--src/libs/engine/events/SendPortValueEvent.cpp6
-rw-r--r--src/libs/engine/events/SendPortValueEvent.hpp11
-rw-r--r--src/libs/gui/App.cpp42
-rw-r--r--src/libs/gui/App.hpp9
-rw-r--r--src/libs/gui/NodeModule.cpp2
-rw-r--r--src/libs/gui/Port.cpp9
-rw-r--r--src/libs/gui/Port.hpp1
27 files changed, 220 insertions, 103 deletions
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);
}
@@ -336,6 +333,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)
{
assert(!strcmp(types, "i"));
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<void, float> signal_control; ///< "Control" ports only
+ sigc::signal<void, float> signal_control; ///< Control ports
+ sigc::signal<void> signal_activity; ///< Message ports
sigc::signal<void, SharedPtr<PortModel> > signal_connection;
sigc::signal<void, SharedPtr<PortModel> > 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<void, string, string> signal_disconnection;
sigc::signal<void, string, string, Raul::Atom> signal_metadata_update;
sigc::signal<void, string, float> signal_control_change;
+ sigc::signal<void, string> signal_port_activity;
sigc::signal<void, string, uint32_t, uint32_t, string> signal_program_add;
sigc::signal<void, string, uint32_t, uint32_t> 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<EngineInterface> engine, SharedPtr<SigClientInterface> 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<PortModel> port = PtrCast<PortModel>(object(port_path));
+ if (port)
+ port->signal_activity.emit();
+ else
+ cerr << "ERROR: activity for nonexistant port " << port_path << endl;
+}
+
SharedPtr<PatchModel>
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<void, string, string> disconnection_slot;
sigc::slot<void, string, string, Raul::Atom> metadata_update_slot;
sigc::slot<void, string, float> control_change_slot;
+ sigc::slot<void, string> port_activity_slot;
sigc::slot<void, string, uint32_t, uint32_t, string> program_add_slot;
sigc::slot<void, string, uint32_t, uint32_t> 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
@@ -228,6 +228,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)
{
for (Clients::const_iterator i = _clients.begin(); i != _clients.end(); ++i)
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...
+ // <BrainHurt>
+ 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);
+ // </BrainHurt>
}
void
DuplexPort::post_process(ProcessContext& context)
{
- // Think about it...
-
-// if (_is_output)
-// InputPort::pre_process(nframes, start, end);
-//else
- OutputPort::pre_process(context);
+ // <BrainHurt>
+ if (_is_output)
+ broadcast(context);
+
+ OutputPort::pre_process(context);
+ // </BrainHurt>
}
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<Connection*>* 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
* <p> \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)
* </p> \n \n
*/
void
@@ -142,7 +142,7 @@ OSCClientSender::response_error(int32_t id, const std::string& msg)
/** \page client_osc_namespace
* <p> \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.</p> \n \n
*/
@@ -184,11 +184,11 @@ OSCClientSender::num_plugins(uint32_t num)
/** \page client_osc_namespace
* <p> \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")
* </p> \n \n
*/
/*
@@ -242,8 +242,8 @@ OSCClientSender::plugins()
/** \page client_osc_namespace
* <p> \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
* <p> \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
* <p> \b /ingen/destroyed - Notification an object has been destroyed
- * \arg \b path (const std::string&) - Path of object (which no longer exists) </p> \n \n
+ * \arg \b path (string) - Path of object (which no longer exists) </p> \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
* <p> \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)</p> \n \n
+ * \arg \b path (string) - Path of patch (which is now empty)</p> \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
* <p> \b /ingen/patch_enabled - Notification a patch's DSP processing has been enabled.
- * \arg \b path (const std::string&) - Path of enabled patch</p> \n \n
+ * \arg \b path (string) - Path of enabled patch</p> \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
* <p> \b /ingen/patch_disabled - Notification a patch's DSP processing has been disabled.
- * \arg \b path (const std::string&) - Path of disabled patch</p> \n \n
+ * \arg \b path (string) - Path of disabled patch</p> \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
* <p> \b /ingen/patch_polyphony - Notification a patch's DSP processing has been polyphony.
- * \arg \b path (const std::string&) - Path of polyphony patch</p> \n \n
+ * \arg \b path (string) - Path of polyphony patch</p> \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
* <p> \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</p> \n \n
+ * \arg \b src-path (string) - Path of the source port
+ * \arg \b dst-path (string) - Path of the destination port</p> \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
* <p> \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</p> \n \n
+ * \arg \b src-path (string) - Path of the source port
+ * \arg \b dst-path (string) - Path of the destination port</p> \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
* <p> \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&)</p> \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)</p> \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
* <p> \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!</p> \n \n
+ * \arg \b path (string) - Path of port
+ * \arg \b value (float) - New value of port </p> \n \n
*/
void
OSCClientSender::control_change(const std::string& port_path, float value)
@@ -460,10 +457,24 @@ OSCClientSender::control_change(const std::string& port_path, float value)
/** \page client_osc_namespace
+ * <p> \b /ingen/port_activity - Notification of activity for a port (e.g. MIDI messages)
+ * \arg \b path (string) - Path of port </p> \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
* <p> \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
* <p> \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) </p> \n \n
*/
void
@@ -523,8 +534,8 @@ OSCClientSender::new_patch(const std::string& path, uint32_t poly)
/** \page client_osc_namespace
* <p> \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 </p> \n \n
+ * \arg \b old-path (string) - Old path of object
+ * \arg \b new-path (string) - New path of object </p> \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 <iostream>
#include <raul/Array.hpp>
#include <raul/Maid.hpp>
#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<Buffer*>(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<Buffer*>* _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 <sstream>
-#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 <slv2/slv2.h>
#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<EngineInterface> engine, SharedPtr<SigClientInterface> cli
_loader = SharedPtr<ThreadedLoader>(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<ActivityPorts::iterator, bool> 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<EngineInterface> _engine;
@@ -125,6 +130,10 @@ protected:
Ingen::Shared::World* _world;
+ /// <Port, whether it has been seen in gtk callback yet>
+ typedef std::map<Port*, bool> 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<FlowCanvas::Module> module, SharedPtr<PortModel> 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: