summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-09-23 18:11:49 +0000
committerDavid Robillard <d@drobilla.net>2011-09-23 18:11:49 +0000
commit9a99f038176a7fadc59bbeaa3d3d57f16e4abb74 (patch)
treef3c1dbb555ff095c1ba7a296009924390e60db09
parent650a13f7c18a4caf4387c0845b708e2c2bf1625d (diff)
downloadingen-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.hpp3
-rw-r--r--include/ingen/client/ClientStore.hpp2
-rw-r--r--include/ingen/client/PortModel.hpp2
-rw-r--r--include/ingen/client/SigClientInterface.hpp6
-rw-r--r--include/ingen/client/ThreadedSigClientInterface.hpp6
-rw-r--r--src/client/ClientStore.cpp4
-rw-r--r--src/client/OSCClientReceiver.cpp7
-rw-r--r--src/gui/Configuration.cpp4
-rw-r--r--src/gui/Port.cpp59
-rw-r--r--src/gui/Port.hpp2
-rw-r--r--src/server/AudioBuffer.cpp11
-rw-r--r--src/server/AudioBuffer.hpp11
-rw-r--r--src/server/ClientBroadcaster.hpp6
-rw-r--r--src/server/HTTPClientSender.cpp18
-rw-r--r--src/server/HTTPClientSender.hpp3
-rw-r--r--src/server/InputPort.cpp15
-rw-r--r--src/server/Notification.cpp2
-rw-r--r--src/server/OSCClientSender.cpp7
-rw-r--r--src/server/OSCClientSender.hpp3
-rw-r--r--src/server/OutputPort.cpp3
-rw-r--r--src/server/PortImpl.cpp10
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), &note);
+ }
_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), &note);
+ }
+ return;
case PortType::CONTROL:
val = ((AudioBuffer*)buffer(0).get())->value_at(0);
break;