diff options
author | David Robillard <d@drobilla.net> | 2011-09-23 18:11:49 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2011-09-23 18:11:49 +0000 |
commit | 9a99f038176a7fadc59bbeaa3d3d57f16e4abb74 (patch) | |
tree | f3c1dbb555ff095c1ba7a296009924390e60db09 | |
parent | 650a13f7c18a4caf4387c0845b708e2c2bf1625d (diff) | |
download | ingen-9a99f038176a7fadc59bbeaa3d3d57f16e4abb74.tar.gz ingen-9a99f038176a7fadc59bbeaa3d3d57f16e4abb74.tar.bz2 ingen-9a99f038176a7fadc59bbeaa3d3d57f16e4abb74.zip |
Animate audio port colours based on levels.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@3475 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | include/ingen/ClientInterface.hpp | 3 | ||||
-rw-r--r-- | include/ingen/client/ClientStore.hpp | 2 | ||||
-rw-r--r-- | include/ingen/client/PortModel.hpp | 2 | ||||
-rw-r--r-- | include/ingen/client/SigClientInterface.hpp | 6 | ||||
-rw-r--r-- | include/ingen/client/ThreadedSigClientInterface.hpp | 6 | ||||
-rw-r--r-- | src/client/ClientStore.cpp | 4 | ||||
-rw-r--r-- | src/client/OSCClientReceiver.cpp | 7 | ||||
-rw-r--r-- | src/gui/Configuration.cpp | 4 | ||||
-rw-r--r-- | src/gui/Port.cpp | 59 | ||||
-rw-r--r-- | src/gui/Port.hpp | 2 | ||||
-rw-r--r-- | src/server/AudioBuffer.cpp | 11 | ||||
-rw-r--r-- | src/server/AudioBuffer.hpp | 11 | ||||
-rw-r--r-- | src/server/ClientBroadcaster.hpp | 6 | ||||
-rw-r--r-- | src/server/HTTPClientSender.cpp | 18 | ||||
-rw-r--r-- | src/server/HTTPClientSender.hpp | 3 | ||||
-rw-r--r-- | src/server/InputPort.cpp | 15 | ||||
-rw-r--r-- | src/server/Notification.cpp | 2 | ||||
-rw-r--r-- | src/server/OSCClientSender.cpp | 7 | ||||
-rw-r--r-- | src/server/OSCClientSender.hpp | 3 | ||||
-rw-r--r-- | src/server/OutputPort.cpp | 3 | ||||
-rw-r--r-- | src/server/PortImpl.cpp | 10 |
21 files changed, 143 insertions, 41 deletions
diff --git a/include/ingen/ClientInterface.hpp b/include/ingen/ClientInterface.hpp index fc212850..a2086926 100644 --- a/include/ingen/ClientInterface.hpp +++ b/include/ingen/ClientInterface.hpp @@ -48,7 +48,8 @@ public: virtual void error(const std::string& msg) = 0; - virtual void activity(const Raul::Path& path) = 0; + virtual void activity(const Raul::Path& path, + const Raul::Atom& value) = 0; }; } // namespace Ingen diff --git a/include/ingen/client/ClientStore.hpp b/include/ingen/client/ClientStore.hpp index 05576cdc..a2cb5346 100644 --- a/include/ingen/client/ClientStore.hpp +++ b/include/ingen/client/ClientStore.hpp @@ -121,7 +121,7 @@ private: void bundle_end() {} // Slots for SigClientInterface signals - void activity(const Raul::Path& path); + void activity(const Raul::Path& path, const Raul::Atom& value); bool attempt_connection(const Raul::Path& src_port_path, const Raul::Path& dst_port_path); diff --git a/include/ingen/client/PortModel.hpp b/include/ingen/client/PortModel.hpp index 36ab847f..f3e8f319 100644 --- a/include/ingen/client/PortModel.hpp +++ b/include/ingen/client/PortModel.hpp @@ -80,7 +80,7 @@ public: // Signals INGEN_SIGNAL(value_changed, void, const Raul::Atom&); INGEN_SIGNAL(voice_changed, void, uint32_t, const Raul::Atom&); - INGEN_SIGNAL(activity, void); + INGEN_SIGNAL(activity, void, const Raul::Atom&); INGEN_SIGNAL(connection, void, SharedPtr<PortModel>); INGEN_SIGNAL(disconnection, void, SharedPtr<PortModel>); diff --git a/include/ingen/client/SigClientInterface.hpp b/include/ingen/client/SigClientInterface.hpp index 2241425b..ae42b169 100644 --- a/include/ingen/client/SigClientInterface.hpp +++ b/include/ingen/client/SigClientInterface.hpp @@ -61,7 +61,7 @@ public: INGEN_SIGNAL(variable_change, void, Raul::URI, Raul::URI, Raul::Atom) INGEN_SIGNAL(property_change, void, Raul::URI, Raul::URI, Raul::Atom) INGEN_SIGNAL(port_value, void, Raul::Path, Raul::Atom) - INGEN_SIGNAL(activity, void, Raul::Path) + INGEN_SIGNAL(activity, void, Raul::Path, Raul::Atom) /** Fire pending signals. Only does anything on derived classes (that may queue) */ virtual bool emit_signals() { return false; } @@ -115,8 +115,8 @@ protected: void set_property(const Raul::URI& subject, const Raul::URI& key, const Raul::Atom& value) { EMIT(property_change, subject, key, value); } - void activity(const Raul::Path& port_path) - { EMIT(activity, port_path); } + void activity(const Raul::Path& port_path, const Raul::Atom& value) + { EMIT(activity, port_path, value); } }; } // namespace Client diff --git a/include/ingen/client/ThreadedSigClientInterface.hpp b/include/ingen/client/ThreadedSigClientInterface.hpp index c30b62da..64901e8f 100644 --- a/include/ingen/client/ThreadedSigClientInterface.hpp +++ b/include/ingen/client/ThreadedSigClientInterface.hpp @@ -113,8 +113,8 @@ public: void set_property(const Raul::URI& subject, const Raul::URI& key, const Raul::Atom& value) { push_sig(sigc::bind(property_change_slot, subject, key, value)); } - void activity(const Raul::Path& port_path) - { push_sig(sigc::bind(activity_slot, port_path)); } + void activity(const Raul::Path& port_path, const Raul::Atom& value) + { push_sig(sigc::bind(activity_slot, port_path, value)); } /** Process all queued events - Called from GTK thread to emit signals. */ bool emit_signals(); @@ -146,7 +146,7 @@ private: sigc::slot<void, Raul::URI, Raul::URI, Raul::Atom> variable_change_slot; sigc::slot<void, Raul::URI, Raul::URI, Raul::Atom> property_change_slot; sigc::slot<void, Raul::Path, Raul::Atom> port_value_slot; - sigc::slot<void, Raul::Path> activity_slot; + sigc::slot<void, Raul::Path, Raul::Atom> activity_slot; }; } // namespace Client diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index d8f36302..6725d961 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -419,11 +419,11 @@ ClientStore::set_property(const URI& subject_uri, const URI& predicate, const At } void -ClientStore::activity(const Path& path) +ClientStore::activity(const Path& path, const Atom& value) { SharedPtr<PortModel> port = PtrCast<PortModel>(_object(path)); if (port) - port->signal_activity().emit(); + port->signal_activity().emit(value); else LOG(error) << "Activity for non-existent port " << path << endl; } diff --git a/src/client/OSCClientReceiver.cpp b/src/client/OSCClientReceiver.cpp index c163da60..e71d19d5 100644 --- a/src/client/OSCClientReceiver.cpp +++ b/src/client/OSCClientReceiver.cpp @@ -153,7 +153,8 @@ OSCClientReceiver::setup_callbacks() 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, "/activity", "s", activity_cb, this); + lo_server_thread_add_method(_st, "/activity", "sT", activity_cb, this); + lo_server_thread_add_method(_st, "/activity", "sf", activity_cb, this); } /** Catches errors that aren't a direct result of a client request. @@ -276,7 +277,9 @@ OSCClientReceiver::_activity_cb(const char* path, const char* types, lo_arg** ar { const char* const port_path = &argv[0]->s; - _target->activity(port_path); + Atom value = AtomLiblo::lo_arg_to_atom(types[1], argv[1]); + + _target->activity(port_path, value); return 0; } diff --git a/src/gui/Configuration.cpp b/src/gui/Configuration.cpp index 8eb39cd7..5018cbf1 100644 --- a/src/gui/Configuration.cpp +++ b/src/gui/Configuration.cpp @@ -40,8 +40,8 @@ using namespace Ingen::Client; Configuration::Configuration() // Colours from the Tango palette with modified V and alpha : _name_style(HUMAN) - , _audio_port_color( 0x244678C0) // Blue - , _control_port_color(0x4A8A0EC0) // Green + , _audio_port_color( 0x4A8A0EC0) // Green + , _control_port_color(0x244678C0) // Blue , _event_port_color( 0x960909C0) // Red , _string_port_color( 0x5C3566C0) // Plum , _value_port_color( 0xBABDB6C0) // Aluminum diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp index 9b2a1c8f..450b75cf 100644 --- a/src/gui/Port.cpp +++ b/src/gui/Port.cpp @@ -77,7 +77,7 @@ Port::Port(FlowCanvas::Module& module, ArtVpathDash* dash = this->dash(); _rect.property_dash() = dash; - set_border_width(dash ? 2.0 : 0.0); + set_border_width(1.0); pm->signal_moved().connect(sigc::mem_fun(this, &Port::moved)); @@ -162,10 +162,63 @@ Port::on_event(GdkEvent* ev) return false; } +/* Peak colour stuff */ + +static inline uint32_t +rgba_to_uint(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return ((((uint32_t)(r)) << 24) | + (((uint32_t)(g)) << 16) | + (((uint32_t)(b)) << 8) | + (((uint32_t)(a)))); +} + +static inline uint8_t +mono_interpolate(uint8_t v1, uint8_t v2, float f) +{ + return ((int)rint((v2) * (f) + (v1) * (1 - (f)))); +} + +#define RGBA_R(x) (((uint32_t)(x)) >> 24) +#define RGBA_G(x) ((((uint32_t)(x)) >> 16) & 0xFF) +#define RGBA_B(x) ((((uint32_t)(x)) >> 8) & 0xFF) +#define RGBA_A(x) (((uint32_t)(x)) & 0xFF) + +static inline uint32_t +rgba_interpolate(uint32_t c1, uint32_t c2, float f) +{ + return rgba_to_uint( + mono_interpolate(RGBA_R(c1), RGBA_R(c2), f), + mono_interpolate(RGBA_G(c1), RGBA_G(c2), f), + mono_interpolate(RGBA_B(c1), RGBA_B(c2), f), + mono_interpolate(RGBA_A(c1), RGBA_A(c2), f)); +} + +inline static uint32_t +peak_color(float peak) +{ + static const uint32_t min = 0x4A8A0EC0; + static const uint32_t max = 0xFFCE1FC0; + static const uint32_t peak_min = 0xFF561FC0; + static const uint32_t peak_max = 0xFF0A38C0; + + if (peak < 1.0) { + return rgba_interpolate(min, max, peak); + } else { + return rgba_interpolate(peak_min, peak_max, fminf(peak, 2.0f) - 1.0f); + } +} + +/* End peak colour stuff */ + void -Port::activity() +Port::activity(const Raul::Atom& value) { - App::instance().port_activity(this); + if (model()->is_a(PortType::AUDIO)) { + set_fill_color(peak_color(value.get_float())); + } else { + App::instance().port_activity(this); + } } void diff --git a/src/gui/Port.hpp b/src/gui/Port.hpp index 65f7c2e2..788baa0e 100644 --- a/src/gui/Port.hpp +++ b/src/gui/Port.hpp @@ -55,7 +55,7 @@ public: virtual void set_control(float value, bool signal); void value_changed(const Raul::Atom& value); - void activity(); + void activity(const Raul::Atom& value); void set_selected(bool b); diff --git a/src/server/AudioBuffer.cpp b/src/server/AudioBuffer.cpp index 27b78cfb..7a8e7c48 100644 --- a/src/server/AudioBuffer.cpp +++ b/src/server/AudioBuffer.cpp @@ -184,6 +184,17 @@ AudioBuffer::copy(Context& context, const Buffer* src) } } +float +AudioBuffer::peak(Context& context) const +{ + float peak = 0.0f; + // FIXME: use context time range? + for (FrameTime i = 0; i < nframes(); ++i) { + peak = fmaxf(peak, value_at(i)); + } + return peak; +} + void AudioBuffer::prepare_read(Context& context) { diff --git a/src/server/AudioBuffer.hpp b/src/server/AudioBuffer.hpp index 4a7869e2..5ecbcea5 100644 --- a/src/server/AudioBuffer.hpp +++ b/src/server/AudioBuffer.hpp @@ -18,12 +18,15 @@ #ifndef INGEN_ENGINE_AUDIOBUFFER_HPP #define INGEN_ENGINE_AUDIOBUFFER_HPP -#include <cstddef> #include <cassert> +#include <cmath> +#include <cstddef> + #include <boost/utility.hpp> -#include "types.hpp" -#include "ObjectBuffer.hpp" + #include "Context.hpp" +#include "ObjectBuffer.hpp" +#include "types.hpp" using namespace std; @@ -43,6 +46,8 @@ public: void copy(Context& context, const Buffer* src); void accumulate(Context& context, const AudioBuffer* src); + float peak(Context& context) const; + inline bool is_control() const { return _type.symbol() == PortType::CONTROL; } inline Sample* data() const { diff --git a/src/server/ClientBroadcaster.hpp b/src/server/ClientBroadcaster.hpp index c34bb34b..3d49dc4a 100644 --- a/src/server/ClientBroadcaster.hpp +++ b/src/server/ClientBroadcaster.hpp @@ -119,7 +119,11 @@ public: void response_error(int32_t id, const std::string& msg) {} ///< N/A void error(const std::string& msg) { BROADCAST(error, msg); } - void activity(const Raul::Path& path) { BROADCAST(activity, path); } + + void activity(const Raul::Path& path, + const Raul::Atom& value) { + BROADCAST(activity, path, value); + } private: typedef std::map<Raul::URI, ClientInterface*> Clients; diff --git a/src/server/HTTPClientSender.cpp b/src/server/HTTPClientSender.cpp index a71701eb..990b28e5 100644 --- a/src/server/HTTPClientSender.cpp +++ b/src/server/HTTPClientSender.cpp @@ -124,12 +124,22 @@ HTTPClientSender::set_property(const URI& subject, const URI& key, const Atom& v } void -HTTPClientSender::activity(const Path& path) +HTTPClientSender::activity(const Path& path, const Raul::Atom& value) { - const string msg = string( + if (value.type() == Atom::BOOL) { + const string msg = string( "@prefix ingen: <http://drobilla.net/ns/ingen#> .\n\n<").append( - path.str()).append("> ingen:activity true .\n"); - send_chunk(msg); + path.str()).append("> ingen:activity true .\n"); + send_chunk(msg); + } else if (value.type() == Atom::FLOAT) { + const string msg = string( + "@prefix ingen: <http://drobilla.net/ns/ingen#> .\n\n<").append( + path.str()).append("> ingen:activity ").append( + value.get_bool() ? "true" : "false").append(" .\n"); + send_chunk(msg); + } else { + warn << "Unknown activity type at " << path << endl; + } } void diff --git a/src/server/HTTPClientSender.hpp b/src/server/HTTPClientSender.hpp index 71f705da..ae286af1 100644 --- a/src/server/HTTPClientSender.hpp +++ b/src/server/HTTPClientSender.hpp @@ -93,7 +93,8 @@ public: const Raul::URI& predicate, const Raul::Atom& value); - virtual void activity(const Raul::Path& path); + virtual void activity(const Raul::Path& path, + const Raul::Atom& value); private: Engine& _engine; diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index 2f871e44..b0866fde 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -25,6 +25,7 @@ #include "ConnectionImpl.hpp" #include "EventBuffer.hpp" #include "NodeImpl.hpp" +#include "Notification.hpp" #include "OutputPort.hpp" #include "ProcessContext.hpp" #include "ThreadManager.hpp" @@ -122,9 +123,8 @@ InputPort::add_connection(Connections::Node* const c) _connections.push_back(c); - // Automatically broadcast connected control inputs - if (is_a(PortType::CONTROL)) - _broadcast = true; + // Broadcast value/activity of connected input + _broadcast = true; } /** Remove a connection. Realtime safe. @@ -156,8 +156,15 @@ InputPort::remove_connection(ProcessContext& context, const OutputPort* src_port } // Turn off broadcasting if we're no longer connected - if (is_a(PortType::CONTROL) && _connections.size() == 0) + if (_connections.size() == 0) { + if (is_a(PortType::AUDIO)) { + // Send an update peak of 0.0 to reset to silence + const Notification note = Notification::make( + Notification::PORT_ACTIVITY, context.start(), this, 0.0f); + context.event_sink().write(sizeof(note), ¬e); + } _broadcast = false; + } return connection; } diff --git a/src/server/Notification.cpp b/src/server/Notification.cpp index 9181147f..0808c00e 100644 --- a/src/server/Notification.cpp +++ b/src/server/Notification.cpp @@ -35,7 +35,7 @@ Notification::post_process(Notification& note, engine.world()->uris()->ingen_value, note.value); break; case PORT_ACTIVITY: - engine.broadcaster()->activity(note.port->path()); + engine.broadcaster()->activity(note.port->path(), note.value); break; case PORT_BINDING: { const Ingen::Shared::LV2URIMap& uris = *engine.world()->uris().get(); diff --git a/src/server/OSCClientSender.cpp b/src/server/OSCClientSender.cpp index ad2e179c..5e9c01f0 100644 --- a/src/server/OSCClientSender.cpp +++ b/src/server/OSCClientSender.cpp @@ -261,12 +261,15 @@ OSCClientSender::set_property(const URI& path, * Notification of "activity" (e.g. port message blinkenlights). */ void -OSCClientSender::activity(const Path& path) +OSCClientSender::activity(const Path& path, const Raul::Atom& value) { if (!_enabled) return; - lo_send(_address, "/activity", "s", path.c_str(), LO_ARGS_END); + lo_message m = lo_message_new(); + lo_message_add_string(m, path.c_str()); + AtomLiblo::lo_message_add_atom(m, value); + send_message("/activity", m); } } // namespace Server diff --git a/src/server/OSCClientSender.hpp b/src/server/OSCClientSender.hpp index 208497b1..95f3ea4f 100644 --- a/src/server/OSCClientSender.hpp +++ b/src/server/OSCClientSender.hpp @@ -96,7 +96,8 @@ public: const Raul::URI& predicate, const Raul::Atom& value); - virtual void activity(const Raul::Path& path); + virtual void activity(const Raul::Path& path, + const Raul::Atom& value); private: Raul::URI _url; diff --git a/src/server/OutputPort.cpp b/src/server/OutputPort.cpp index 487832c3..c96c6b04 100644 --- a/src/server/OutputPort.cpp +++ b/src/server/OutputPort.cpp @@ -40,8 +40,7 @@ OutputPort::OutputPort(BufferFactory& bufs, if (!dynamic_cast<Patch*>(parent)) add_property(bufs.uris().rdf_type, bufs.uris().lv2_OutputPort); - if (type == PortType::CONTROL) - _broadcast = true; + _broadcast = true; setup_buffers(bufs, poly); } diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp index 2e1ad61e..73953b5c 100644 --- a/src/server/PortImpl.cpp +++ b/src/server/PortImpl.cpp @@ -76,9 +76,6 @@ PortImpl::PortImpl(BufferFactory& bufs, add_property(uris.rdf_type, type.uri()); set_property(uris.lv2_index, Atom((int32_t)index)); set_context(_context); - - if (type == PortType::EVENTS) - _broadcast = true; // send activity blips } PortImpl::~PortImpl() @@ -208,6 +205,13 @@ PortImpl::broadcast_value(Context& context, bool force) case PortType::UNKNOWN: break; case PortType::AUDIO: + val = ((AudioBuffer*)buffer(0).get())->peak(context); + { + const Notification note = Notification::make( + Notification::PORT_ACTIVITY, context.start(), this, val); + context.event_sink().write(sizeof(note), ¬e); + } + return; case PortType::CONTROL: val = ((AudioBuffer*)buffer(0).get())->value_at(0); break; |