summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bindings/Client.hpp1
-rw-r--r--src/client/ClientStore.cpp9
-rw-r--r--src/client/ClientStore.hpp3
-rw-r--r--src/client/SigClientInterface.hpp4
-rw-r--r--src/client/ThreadedSigClientInterface.hpp6
-rw-r--r--src/common/interface/ClientInterface.hpp3
-rw-r--r--src/common/interface/MessageType.hpp120
-rw-r--r--src/engine/ClientBroadcaster.hpp4
-rw-r--r--src/engine/ControlBindings.cpp26
-rw-r--r--src/engine/ControlBindings.hpp3
-rw-r--r--src/engine/HTTPClientSender.cpp7
-rw-r--r--src/engine/HTTPClientSender.hpp2
-rw-r--r--src/engine/OSCClientSender.cpp20
-rw-r--r--src/engine/OSCClientSender.hpp2
-rw-r--r--src/engine/events/SendBinding.cpp39
-rw-r--r--src/engine/events/SendBinding.hpp68
-rw-r--r--src/engine/wscript1
17 files changed, 310 insertions, 8 deletions
diff --git a/src/bindings/Client.hpp b/src/bindings/Client.hpp
index 690d2214..d23166e9 100644
--- a/src/bindings/Client.hpp
+++ b/src/bindings/Client.hpp
@@ -27,4 +27,5 @@ public:
void set_port_value(const Raul::Path& port_path, const Raul::Atom& value) {}
void set_voice_value(const Raul::Path& port_path, uint32_t voice, const Raul::Atom& value) {}
void activity(const Raul::Path& port_path) {}
+ void binding(const Raul::Path& path, const MessageType& type) {}
};
diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp
index 73d2b23e..40c11323 100644
--- a/src/client/ClientStore.cpp
+++ b/src/client/ClientStore.cpp
@@ -17,6 +17,7 @@
#include "raul/log.hpp"
#include "raul/PathTable.hpp"
+#include "interface/MessageType.hpp"
#include "ClientStore.hpp"
#include "ObjectModel.hpp"
#include "PatchModel.hpp"
@@ -53,6 +54,7 @@ ClientStore::ClientStore(SharedPtr<EngineInterface> engine, SharedPtr<SigClientI
emitter->signal_port_value.connect(sigc::mem_fun(this, &ClientStore::set_port_value));
emitter->signal_voice_value.connect(sigc::mem_fun(this, &ClientStore::set_voice_value));
emitter->signal_activity.connect(sigc::mem_fun(this, &ClientStore::activity));
+ emitter->signal_binding.connect(sigc::mem_fun(this, &ClientStore::binding));
}
@@ -383,6 +385,13 @@ ClientStore::activity(const Path& path)
}
+void
+ClientStore::binding(const Path& path, const Shared::MessageType& type)
+{
+ LOG(info) << "Bind " << path << " : " << type << endl;
+}
+
+
SharedPtr<PatchModel>
ClientStore::connection_patch(const Path& src_port_path, const Path& dst_port_path)
{
diff --git a/src/client/ClientStore.hpp b/src/client/ClientStore.hpp
index ba32b362..63b03dae 100644
--- a/src/client/ClientStore.hpp
+++ b/src/client/ClientStore.hpp
@@ -33,7 +33,7 @@ namespace Raul { class Atom; }
namespace Ingen {
-namespace Shared { class GraphObject; }
+namespace Shared { class GraphObject; class MessageType; }
namespace Client {
@@ -96,6 +96,7 @@ private:
// Slots for SigClientInterface signals
void object_moved(const Raul::Path& old_path, const Raul::Path& new_path);
void activity(const Raul::Path& path);
+ void binding(const Raul::Path& path, const Shared::MessageType& type);
bool attempt_connection(const Raul::Path& src_port_path, const Raul::Path& dst_port_path);
diff --git a/src/client/SigClientInterface.hpp b/src/client/SigClientInterface.hpp
index 785f6ac8..3a3ce9d4 100644
--- a/src/client/SigClientInterface.hpp
+++ b/src/client/SigClientInterface.hpp
@@ -60,6 +60,7 @@ public:
sigc::signal<void, Raul::Path, Raul::Atom> signal_port_value;
sigc::signal<void, Raul::Path, uint32_t, Raul::Atom> signal_voice_value;
sigc::signal<void, Raul::Path> signal_activity;
+ sigc::signal<void, Raul::Path, Shared::MessageType> signal_binding;
/** Fire pending signals. Only does anything on derived classes (that may queue) */
virtual bool emit_signals() { return false; }
@@ -114,6 +115,9 @@ protected:
void activity(const Raul::Path& port_path)
{ EMIT(activity, port_path); }
+
+ void binding(const Raul::Path& path, const Shared::MessageType& type)
+ { EMIT(binding, path, type); }
};
diff --git a/src/client/ThreadedSigClientInterface.hpp b/src/client/ThreadedSigClientInterface.hpp
index 901fd4a6..456aa67f 100644
--- a/src/client/ThreadedSigClientInterface.hpp
+++ b/src/client/ThreadedSigClientInterface.hpp
@@ -24,6 +24,7 @@
#include <glibmm/thread.h>
#include "raul/Atom.hpp"
#include "interface/ClientInterface.hpp"
+#include "interface/MessageType.hpp"
#include "SigClientInterface.hpp"
#include "raul/SRSWQueue.hpp"
@@ -60,6 +61,7 @@ public:
, property_change_slot(signal_property_change.make_slot())
, port_value_slot(signal_port_value.make_slot())
, activity_slot(signal_activity.make_slot())
+ , binding_slot(signal_binding.make_slot())
{
}
@@ -110,6 +112,9 @@ public:
void activity(const Raul::Path& port_path)
{ push_sig(sigc::bind(activity_slot, port_path)); }
+ void binding(const Raul::Path& path, const Shared::MessageType& type)
+ { push_sig(sigc::bind(binding_slot, path, type)); }
+
/** Process all queued events - Called from GTK thread to emit signals. */
bool emit_signals();
@@ -139,6 +144,7 @@ private:
sigc::slot<void, Raul::Path, Raul::Atom> port_value_slot;
sigc::slot<void, Raul::Path, uint32_t, Raul::Atom> voice_value_slot;
sigc::slot<void, Raul::Path> activity_slot;
+ sigc::slot<void, Raul::Path, Shared::MessageType> binding_slot;
};
diff --git a/src/common/interface/ClientInterface.hpp b/src/common/interface/ClientInterface.hpp
index 619c48b8..9ec875ac 100644
--- a/src/common/interface/ClientInterface.hpp
+++ b/src/common/interface/ClientInterface.hpp
@@ -28,6 +28,7 @@ namespace Raul { class Path; class URI; }
namespace Ingen {
namespace Shared {
+class MessageType;
/** The (only) interface the engine uses to communicate with clients.
* Purely virtual (except for the destructor).
@@ -55,6 +56,8 @@ public:
virtual void error(const std::string& msg) = 0;
virtual void activity(const Raul::Path& path) = 0;
+
+ virtual void binding(const Raul::Path& path, const MessageType& type) = 0;
};
diff --git a/src/common/interface/MessageType.hpp b/src/common/interface/MessageType.hpp
new file mode 100644
index 00000000..ea6bc726
--- /dev/null
+++ b/src/common/interface/MessageType.hpp
@@ -0,0 +1,120 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MESSAGE_TYPE_HPP
+#define MESSAGE_TYPE_HPP
+
+#include <cassert>
+#include <iostream>
+#include <string>
+
+namespace Ingen {
+namespace Shared {
+
+
+/** A type of control message that could be bound to a control port.
+ *
+ * \ingroup interface
+ */
+class MessageType
+{
+public:
+ enum Type {
+ MIDI_PITCH,
+ MIDI_CC,
+ MIDI_RPN,
+ MIDI_NRPN
+ };
+
+ MessageType(Type type, int16_t num)
+ : _type(type)
+ {
+ switch (type) {
+ case MIDI_PITCH:
+ break;
+ case MIDI_CC:
+ assert(num >= 0 && num < 128);
+ _id.midi_cc = num;
+ break;
+ case MIDI_RPN:
+ assert(num >= 0 && num < 16384);
+ _id.midi_pn = num;
+ break;
+ case MIDI_NRPN:
+ assert(num >= 0 && num < 16384);
+ _id.midi_pn = num;
+ break;
+ }
+ }
+
+ inline Type type() const { return _type; }
+ inline int8_t midi_cc_num() const { assert(_type == MIDI_CC); return _id.midi_cc; }
+ inline int8_t midi_rpn_num() const { assert(_type == MIDI_RPN); return _id.midi_pn; }
+ inline int8_t midi_nrpn_num() const { assert(_type == MIDI_NRPN); return _id.midi_pn; }
+
+ inline int num() const {
+ switch (_type) {
+ case MIDI_CC:
+ return _id.midi_cc;
+ case MIDI_RPN:
+ case MIDI_NRPN:
+ return _id.midi_pn;
+ default:
+ return -1;
+ }
+ }
+
+ inline const char* type_uri() const {
+ switch (_type) {
+ case MIDI_PITCH:
+ return "midi:PitchBend";
+ case MIDI_CC:
+ return "midi:Control";
+ case MIDI_RPN:
+ return "midi:RPN";
+ case MIDI_NRPN:
+ return "midi:NRPN";
+ }
+ }
+
+private:
+ union {
+ int8_t midi_cc; ///< Controller number [0..2^7)
+ int16_t midi_pn; ///< RPN or NRPN number [0..2^14)
+ } _id;
+
+ Type _type;
+};
+
+
+} // namespace Shared
+} // namespace Ingen
+
+
+static inline std::ostream& operator<<(std::ostream& os, const Ingen::Shared::MessageType& type)
+{
+ using namespace Ingen::Shared;
+ switch (type.type()) {
+ case MessageType::MIDI_PITCH: return os << "MIDI Pitch Bender";
+ case MessageType::MIDI_CC: return os << "MIDI CC " << type.num();
+ case MessageType::MIDI_RPN: return os << "MIDI RPN " << type.num();
+ case MessageType::MIDI_NRPN: return os << "MIDI NRPN " << type.num();
+ }
+ return os;
+}
+
+#endif // MESSAGE_TYPE_HPP
diff --git a/src/engine/ClientBroadcaster.hpp b/src/engine/ClientBroadcaster.hpp
index 9de7aeff..fa44bc43 100644
--- a/src/engine/ClientBroadcaster.hpp
+++ b/src/engine/ClientBroadcaster.hpp
@@ -123,6 +123,10 @@ public:
void error(const std::string& msg) { BROADCAST(error, msg); }
void activity(const Raul::Path& path) { BROADCAST(activity, path); }
+ void binding(const Raul::Path& path, const Shared::MessageType& type) {
+ BROADCAST(binding, path, type);
+ }
+
private:
typedef std::map<Raul::URI, Shared::ClientInterface*> Clients;
Clients _clients;
diff --git a/src/engine/ControlBindings.cpp b/src/engine/ControlBindings.cpp
index 00241b54..b74a3124 100644
--- a/src/engine/ControlBindings.cpp
+++ b/src/engine/ControlBindings.cpp
@@ -18,6 +18,7 @@
#include "raul/log.hpp"
#include "raul/midi_events.h"
#include "events/SendPortValue.hpp"
+#include "events/SendBinding.hpp"
#include "ControlBindings.hpp"
#include "EventBuffer.hpp"
#include "PortImpl.hpp"
@@ -41,21 +42,35 @@ ControlBindings::learn(PortImpl* port)
void
-ControlBindings::set_port_value(ProcessContext& context, PortImpl* port, int8_t value)
+ControlBindings::set_port_value(ProcessContext& context, PortImpl* port, int8_t cc_value)
{
+ // TODO: cache these to avoid the lookup
float min = port->get_property("lv2:minimum").get_float();
float max = port->get_property("lv2:maximum").get_float();
- Raul::Atom scaled_value(static_cast<float>(((float)value / 127.0) * (max - min) + min));
- port->set_value(scaled_value);
+ Raul::Atom value(static_cast<float>(((float)cc_value / 127.0) * (max - min) + min));
+ port->set_value(value);
const Events::SendPortValue ev(context.engine(), context.start(), port, true, 0,
- scaled_value.get_float());
+ value.get_float());
context.event_sink().write(sizeof(ev), &ev);
}
void
+ControlBindings::bind(ProcessContext& context, int8_t cc_num)
+{
+ _bindings.insert(make_pair(cc_num, _learn_port));
+
+ const Events::SendBinding ev(context.engine(), context.start(), _learn_port,
+ MessageType(MessageType::MIDI_CC, cc_num));
+ context.event_sink().write(sizeof(ev), &ev);
+
+ _learn_port = NULL;
+}
+
+
+void
ControlBindings::process(ProcessContext& context, EventBuffer* buffer)
{
uint32_t frames = 0;
@@ -69,8 +84,7 @@ ControlBindings::process(ProcessContext& context, EventBuffer* buffer)
while (buffer->get_event(&frames, &subframes, &type, &size, &buf)) {
if (type == _map->midi_event && (buf[0] & 0xF0) == MIDI_CMD_CONTROL) {
const int8_t controller = static_cast<const int8_t>(buf[1]);
- _bindings.insert(make_pair(controller, _learn_port));
- _learn_port = NULL;
+ bind(context, controller);
break;
}
buffer->increment();
diff --git a/src/engine/ControlBindings.hpp b/src/engine/ControlBindings.hpp
index 5e1e123d..8477a0fa 100644
--- a/src/engine/ControlBindings.hpp
+++ b/src/engine/ControlBindings.hpp
@@ -46,7 +46,8 @@ private:
SharedPtr<Shared::LV2URIMap> _map;
PortImpl* _learn_port;
- void set_port_value(ProcessContext& context, PortImpl* port, int8_t value);
+ void set_port_value(ProcessContext& context, PortImpl* port, int8_t cc_value);
+ void bind(ProcessContext& context, int8_t cc_num);
typedef std::map<int8_t, PortImpl*> Bindings;
Bindings _bindings;
diff --git a/src/engine/HTTPClientSender.cpp b/src/engine/HTTPClientSender.cpp
index 8804c65c..0c14b06f 100644
--- a/src/engine/HTTPClientSender.cpp
+++ b/src/engine/HTTPClientSender.cpp
@@ -143,6 +143,13 @@ HTTPClientSender::activity(const Path& path)
void
+HTTPClientSender::binding(const Path& path, const MessageType& type)
+{
+ warn << "TODO: HTTP binding" << endl;
+}
+
+
+void
HTTPClientSender::move(const Path& old_path, const Path& new_path)
{
string msg = string(
diff --git a/src/engine/HTTPClientSender.hpp b/src/engine/HTTPClientSender.hpp
index d3bc9505..e7120e81 100644
--- a/src/engine/HTTPClientSender.hpp
+++ b/src/engine/HTTPClientSender.hpp
@@ -93,6 +93,8 @@ public:
virtual void activity(const Raul::Path& path);
+ virtual void binding(const Raul::Path& path, const Shared::MessageType& type);
+
private:
Engine& _engine;
std::string _url;
diff --git a/src/engine/OSCClientSender.cpp b/src/engine/OSCClientSender.cpp
index 13147a42..f07668ca 100644
--- a/src/engine/OSCClientSender.cpp
+++ b/src/engine/OSCClientSender.cpp
@@ -20,6 +20,7 @@
#include "raul/log.hpp"
#include "raul/AtomLiblo.hpp"
#include "interface/ClientInterface.hpp"
+#include "interface/MessageType.hpp"
#include "EngineStore.hpp"
#include "NodeImpl.hpp"
#include "OSCClientSender.hpp"
@@ -246,4 +247,23 @@ OSCClientSender::activity(const Path& path)
}
+/** \page client_osc_namespace
+ * <h2>/ingen/binding</h2>
+ * \arg \b path (string) - Path of object
+ * \arg \b type (string) - Type of message (URI)
+ * \arg \b id (int) - Controller number (if applicable)
+ *
+ * Notification of "activity" (e.g. port message blinkenlights).
+ */
+void
+OSCClientSender::binding(const Path& path, const MessageType& type)
+{
+ if (!_enabled)
+ return;
+
+ lo_send(_address, "/ingen/binding", "ssi",
+ path.c_str(), type.type_uri(), type.num(), LO_ARGS_END);
+}
+
+
} // namespace Ingen
diff --git a/src/engine/OSCClientSender.hpp b/src/engine/OSCClientSender.hpp
index c5317a14..1ce58d45 100644
--- a/src/engine/OSCClientSender.hpp
+++ b/src/engine/OSCClientSender.hpp
@@ -93,6 +93,8 @@ public:
virtual void activity(const Raul::Path& path);
+ virtual void binding(const Raul::Path& path, const Shared::MessageType& type);
+
private:
Raul::URI _url;
};
diff --git a/src/engine/events/SendBinding.cpp b/src/engine/events/SendBinding.cpp
new file mode 100644
index 00000000..7168b142
--- /dev/null
+++ b/src/engine/events/SendBinding.cpp
@@ -0,0 +1,39 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <sstream>
+#include "events/SendBinding.hpp"
+#include "Engine.hpp"
+#include "PortImpl.hpp"
+#include "ClientBroadcaster.hpp"
+
+using namespace std;
+
+namespace Ingen {
+namespace Events {
+
+
+void
+SendBinding::post_process()
+{
+ _engine.broadcaster()->binding(_port->path(), _type);
+}
+
+
+} // namespace Ingen
+} // namespace Events
+
diff --git a/src/engine/events/SendBinding.hpp b/src/engine/events/SendBinding.hpp
new file mode 100644
index 00000000..303e29fa
--- /dev/null
+++ b/src/engine/events/SendBinding.hpp
@@ -0,0 +1,68 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SENDBINDINGEVENT_H
+#define SENDBINDINGEVENT_H
+
+#include "raul/Atom.hpp"
+#include "interface/MessageType.hpp"
+#include "engine/Event.hpp"
+#include "engine/types.hpp"
+
+namespace Ingen {
+
+class PortImpl;
+
+namespace Events {
+
+
+/** A special event used internally to send control bindings from the audio thread.
+ *
+ * See SendPortValue documentation for details.
+ *
+ * \ingroup engine
+ */
+class SendBinding : public Event
+{
+public:
+ inline SendBinding(
+ Engine& engine,
+ SampleCount timestamp,
+ PortImpl* port,
+ const Shared::MessageType& type)
+ : Event(engine, SharedPtr<Responder>(), timestamp)
+ , _port(port)
+ , _type(type)
+ {}
+
+ inline void operator=(const SendBinding& ev) {
+ _port = ev._port;
+ _type = ev._type;
+ }
+
+ void post_process();
+
+private:
+ PortImpl* _port;
+ Shared::MessageType _type;
+};
+
+
+} // namespace Ingen
+} // namespace Events
+
+#endif // SENDBINDINGEVENT_H
diff --git a/src/engine/wscript b/src/engine/wscript
index e0ac6d69..7e630387 100644
--- a/src/engine/wscript
+++ b/src/engine/wscript
@@ -51,6 +51,7 @@ def build(bld):
events/RequestAllObjects.cpp
events/RequestMetadata.cpp
events/RequestPlugins.cpp
+ events/SendBinding.cpp
events/SendPortActivity.cpp
events/SendPortValue.cpp
events/SetMetadata.cpp