summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-09-22 23:51:00 +0000
committerDavid Robillard <d@drobilla.net>2007-09-22 23:51:00 +0000
commitc1160ffc8a5dfb38891b0faa6373c9eecdd8e4c9 (patch)
tree1baf40b7a90bc96c4b0832103ff0cdabdf1ed1a6
parent4bd53e016b8bb912e48d77e756720516d876d5c2 (diff)
downloadingen-c1160ffc8a5dfb38891b0faa6373c9eecdd8e4c9.tar.gz
ingen-c1160ffc8a5dfb38891b0faa6373c9eecdd8e4c9.tar.bz2
ingen-c1160ffc8a5dfb38891b0faa6373c9eecdd8e4c9.zip
Type oblivious set_port_value interface.
git-svn-id: http://svn.drobilla.net/lad/ingen@765 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/common/interface/EngineInterface.hpp18
-rw-r--r--src/libs/client/DeprecatedLoader.cpp3
-rw-r--r--src/libs/client/OSCClientReceiver.cpp2
-rw-r--r--src/libs/client/OSCEngineSender.cpp43
-rw-r--r--src/libs/client/OSCEngineSender.hpp18
-rw-r--r--src/libs/client/PluginModel.cpp13
-rw-r--r--src/libs/engine/MidiBuffer.cpp5
-rw-r--r--src/libs/engine/MidiBuffer.hpp3
-rw-r--r--src/libs/engine/OSCEngineReceiver.cpp63
-rw-r--r--src/libs/engine/OSCEngineReceiver.hpp3
-rw-r--r--src/libs/engine/QueuedEngineInterface.cpp27
-rw-r--r--src/libs/engine/QueuedEngineInterface.hpp20
-rw-r--r--src/libs/engine/events/SetPortValueEvent.cpp84
-rw-r--r--src/libs/engine/events/SetPortValueEvent.hpp26
-rw-r--r--src/libs/engine/events/SetPortValueQueuedEvent.cpp56
-rw-r--r--src/libs/engine/events/SetPortValueQueuedEvent.hpp26
-rw-r--r--src/libs/gui/ControlPanel.cpp4
-rw-r--r--src/libs/gui/Port.cpp2
-rw-r--r--src/libs/serialisation/Loader.cpp8
19 files changed, 311 insertions, 113 deletions
diff --git a/src/common/interface/EngineInterface.hpp b/src/common/interface/EngineInterface.hpp
index 3d28bbd2..ac4d3395 100644
--- a/src/common/interface/EngineInterface.hpp
+++ b/src/common/interface/EngineInterface.hpp
@@ -95,17 +95,25 @@ public:
virtual void disconnect(const string& src_port_path,
const string& dst_port_path) = 0;
- virtual void disconnect_all(const string& node_path) = 0;
+ virtual void disconnect_all(const string& path) = 0;
virtual void set_port_value(const string& port_path,
- float val) = 0;
+ uint32_t data_size,
+ const void* data) = 0;
virtual void set_port_value(const string& port_path,
uint32_t voice,
- float val) = 0;
+ uint32_t data_size,
+ const void* data) = 0;
- virtual void set_port_value_queued(const string& port_path,
- float val) = 0;
+ virtual void set_port_value_immediate(const string& port_path,
+ uint32_t data_size,
+ const void* data) = 0;
+
+ virtual void set_port_value_immediate(const string& port_path,
+ uint32_t voice,
+ uint32_t data_size,
+ const void* data) = 0;
virtual void set_program(const string& node_path,
uint32_t bank,
diff --git a/src/libs/client/DeprecatedLoader.cpp b/src/libs/client/DeprecatedLoader.cpp
index f6c07ecd..9cff9422 100644
--- a/src/libs/client/DeprecatedLoader.cpp
+++ b/src/libs/client/DeprecatedLoader.cpp
@@ -258,7 +258,8 @@ DeprecatedLoader::load_patch(const Glib::ustring& filename,
if (pm->name() == "default") {
list<ControlModel>::const_iterator i = pm->controls().begin();
for ( ; i != pm->controls().end(); ++i) {
- _engine->set_port_value(i->port_path(), i->value());
+ const float value = i->value();
+ _engine->set_port_value(i->port_path(), sizeof(float), &value);
}
} else {
cerr << "WARNING: Unknown preset: \"" << pm->name() << endl;
diff --git a/src/libs/client/OSCClientReceiver.cpp b/src/libs/client/OSCClientReceiver.cpp
index 63bf5b69..d6ce3f81 100644
--- a/src/libs/client/OSCClientReceiver.cpp
+++ b/src/libs/client/OSCClientReceiver.cpp
@@ -39,7 +39,7 @@ OSCClientReceiver::OSCClientReceiver(int listen_port)
// _receiving_node_num_ports(0),
// _num_received_ports(0)
{
- start(false);
+ start(true);
}
diff --git a/src/libs/client/OSCEngineSender.cpp b/src/libs/client/OSCEngineSender.cpp
index 46181195..90f27676 100644
--- a/src/libs/client/OSCEngineSender.cpp
+++ b/src/libs/client/OSCEngineSender.cpp
@@ -16,9 +16,10 @@
*/
#include <iostream>
-#include "OSCEngineSender.hpp"
#include <raul/AtomLiblo.hpp>
-using std::cout; using std::cerr; using std::endl;
+#include "OSCEngineSender.hpp"
+
+using namespace std;
namespace Ingen {
namespace Client {
@@ -350,39 +351,61 @@ OSCEngineSender::disconnect_all(const string& node_path)
void
OSCEngineSender::set_port_value(const string& port_path,
- float val)
+ uint32_t data_size,
+ const void* data)
{
assert(_engine_addr);
+ assert(data_size == 4);
lo_send(_engine_addr, "/ingen/set_port_value", "isf",
next_id(),
port_path.c_str(),
- val);
+ *(float*)data);
}
void
OSCEngineSender::set_port_value(const string& port_path,
uint32_t voice,
- float val)
+ uint32_t data_size,
+ const void* data)
{
assert(_engine_addr);
+ assert(data_size == 4);
lo_send(_engine_addr, "/ingen/set_port_value", "isif",
next_id(),
port_path.c_str(),
voice,
- val);
+ *(float*)data);
+}
+
+
+void
+OSCEngineSender::set_port_value_immediate(const string& port_path,
+ uint32_t data_size,
+ const void* data)
+{
+ assert(_engine_addr);
+ assert(data_size == 4);
+ lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isf",
+ next_id(),
+ port_path.c_str(),
+ *(float*)data);
}
void
-OSCEngineSender::set_port_value_queued(const string& port_path,
- float val)
+OSCEngineSender::set_port_value_immediate(const string& port_path,
+ uint32_t voice,
+ uint32_t data_size,
+ const void* data)
{
assert(_engine_addr);
- lo_send(_engine_addr, "/ingen/set_port_value_queued", "isf",
+ assert(data_size == 4);
+ lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isif",
next_id(),
port_path.c_str(),
- val);
+ voice,
+ *(float*)data);
}
diff --git a/src/libs/client/OSCEngineSender.hpp b/src/libs/client/OSCEngineSender.hpp
index c3a9b46a..bdaf8337 100644
--- a/src/libs/client/OSCEngineSender.hpp
+++ b/src/libs/client/OSCEngineSender.hpp
@@ -112,14 +112,22 @@ public:
void disconnect_all(const string& node_path);
void set_port_value(const string& port_path,
- float val);
+ uint32_t data_size,
+ const void* data);
void set_port_value(const string& port_path,
uint32_t voice,
- float val);
-
- void set_port_value_queued(const string& port_path,
- float val);
+ uint32_t data_size,
+ const void* data);
+
+ void set_port_value_immediate(const string& port_path,
+ uint32_t data_size,
+ const void* data);
+
+ void set_port_value_immediate(const string& port_path,
+ uint32_t voice,
+ uint32_t data_size,
+ const void* data);
void set_program(const string& node_path,
uint32_t bank,
diff --git a/src/libs/client/PluginModel.cpp b/src/libs/client/PluginModel.cpp
index 442cbb43..6fb7e95a 100644
--- a/src/libs/client/PluginModel.cpp
+++ b/src/libs/client/PluginModel.cpp
@@ -55,11 +55,16 @@ PluginModel::default_node_name(SharedPtr<PatchModel> parent)
void
lv2_ui_write(LV2UI_Controller controller,
- uint32_t port,
- uint32_t buffer_size,
- const void* buffer)
+ uint32_t port,
+ uint32_t buffer_size,
+ const void* buffer)
{
- cerr << "********* LV2 UI WRITE" << endl;
+ cerr << "********* LV2 UI WRITE port " << port << ", size "
+ << buffer_size << endl;
+ for (uint32_t i=0; i < buffer_size; ++i) {
+ fprintf(stderr, "( %X )", *((uint8_t*)buffer + i));
+ }
+ fprintf(stderr, "\n");
}
diff --git a/src/libs/engine/MidiBuffer.cpp b/src/libs/engine/MidiBuffer.cpp
index 5a8dbc4e..0e10a44e 100644
--- a/src/libs/engine/MidiBuffer.cpp
+++ b/src/libs/engine/MidiBuffer.cpp
@@ -30,6 +30,7 @@ namespace Ingen {
*/
MidiBuffer::MidiBuffer(size_t capacity)
: Buffer(DataType(DataType::MIDI), capacity)
+ , _latest_stamp(0)
, _joined_buf(NULL)
{
if (capacity > UINT32_MAX) {
@@ -167,7 +168,7 @@ MidiBuffer::increment() const
/** Append a MIDI event to the buffer.
*
- * \a timestamp must be > the latest event in the buffer,
+ * \a timestamp must be >= the latest event in the buffer,
* and < this_nframes()
*
* \return true on success
@@ -182,6 +183,7 @@ MidiBuffer::append(double timestamp,
assert(size > 0);
assert(data[0] >= 0x80);
+ assert(timestamp >= _latest_stamp);
*(double*)(_buf->data + _buf->size) = timestamp;
_buf->size += sizeof(double);
@@ -191,6 +193,7 @@ MidiBuffer::append(double timestamp,
_buf->size += size;
++_buf->event_count;
+ _latest_stamp = timestamp;
return true;
}
diff --git a/src/libs/engine/MidiBuffer.hpp b/src/libs/engine/MidiBuffer.hpp
index 15548625..a7db7e77 100644
--- a/src/libs/engine/MidiBuffer.hpp
+++ b/src/libs/engine/MidiBuffer.hpp
@@ -57,18 +57,21 @@ public:
inline void rewind() const { _position = 0; }
inline void clear() { if (_joined_buf) reset(_this_nframes); }
inline void reset(SampleCount nframes) {
+ _latest_stamp = 0;
_position = 0;
_buf->event_count = 0;
_buf->size = 0;
}
double increment() const;
+ double latest_stamp() const { return _latest_stamp; }
double get_event(double* timestamp, uint32_t* size, unsigned char** data) const;
bool append(double timestamp, uint32_t size, const unsigned char* data);
private:
+ double _latest_stamp; ///< Highest timestamp of all events
uint32_t _this_nframes; ///< Current cycle nframes
mutable uint32_t _position; ///< Index into _buf
MidiBuffer* _joined_buf; ///< Buffer to mirror, if joined
diff --git a/src/libs/engine/OSCEngineReceiver.cpp b/src/libs/engine/OSCEngineReceiver.cpp
index 3229aed5..caaf0d73 100644
--- a/src/libs/engine/OSCEngineReceiver.cpp
+++ b/src/libs/engine/OSCEngineReceiver.cpp
@@ -98,7 +98,8 @@ OSCEngineReceiver::OSCEngineReceiver(Engine& engine, size_t queue_size, uint16_t
lo_server_add_method(_server, "/ingen/disconnect_all", "is", disconnect_all_cb, this);
lo_server_add_method(_server, "/ingen/set_port_value", "isf", set_port_value_cb, this);
lo_server_add_method(_server, "/ingen/set_port_value", "isif", set_port_value_voice_cb, this);
- lo_server_add_method(_server, "/ingen/set_port_value_queued", "isf", set_port_value_slow_cb, this);
+ lo_server_add_method(_server, "/ingen/set_port_value_immediate", "isf", set_port_value_immediate_cb, this);
+ lo_server_add_method(_server, "/ingen/set_port_value_immediate", "isif", set_port_value_immediate_voice_cb, this);
lo_server_add_method(_server, "/ingen/note_on", "isii", note_on_cb, this);
lo_server_add_method(_server, "/ingen/note_off", "isi", note_off_cb, this);
lo_server_add_method(_server, "/ingen/all_notes_off", "isi", all_notes_off_cb, this);
@@ -605,58 +606,90 @@ OSCEngineReceiver::_disconnect_all_cb(const char* path, const char* types, lo_ar
/** \page engine_osc_namespace
- * <p> \b /ingen/set_port_value - Sets the value of a port for all voices (both AR and CR)
+ * <p> \b /ingen/set_port_value_immediate - Sets the value of a port for all voices (both AR and CR)
* \arg \b response-id (integer)
* \arg \b port-path (string) - Name of port
- * \arg \b value (float) - Value to set port to
+ * \arg \b value (float) - Value to set port to </p> \n \n
*/
int
-OSCEngineReceiver::_set_port_value_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg)
+OSCEngineReceiver::_set_port_value_immediate_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg)
{
const char* port_path = &argv[1]->s;
const float value = argv[2]->f;
- set_port_value(port_path, value);
+ set_port_value_immediate(port_path, sizeof(float), &value);
return 0;
}
/** \page engine_osc_namespace
- * <p> \b /ingen/set_port_value - Sets the value of a port for a specific voice (both AR and CR)
+ * <p> \b /ingen/set_port_value_immediate - Sets the value of a port for a specific voice (both AR and CR)
* \arg \b response-id (integer)
* \arg \b port-path (string) - Name of port
* \arg \b voice (integer) - Voice to set port value for
- * \arg \b value (float) - Value to set port to
+ * \arg \b value (float) - Value to set port to </p> \n \n
+ *
+ * See documentation for set_port_value for the distinction between these two messages.
*/
int
-OSCEngineReceiver::_set_port_value_voice_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg)
+OSCEngineReceiver::_set_port_value_immediate_voice_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg)
{
const char* port_path = &argv[1]->s;
const int32_t voice = argv[2]->i;
const float value = argv[3]->f;
- set_port_value(port_path, voice, value);
+ set_port_value_immediate(port_path, voice, sizeof(float), &value);
return 0;
}
/** \page engine_osc_namespace
- * <p> \b /ingen/set_port_value_queued - Sets the value of a port for all voices (as a QueuedEvent)
+ * <p> \b /ingen/set_port_value - Sets the value of a port for all voices (as a QueuedEvent)
* \arg \b response-id (integer)
* \arg \b port-path (string) - Name of port
* \arg \b value (float) - Value to set port to
*
- * \li This version exists so you can send it immediately after a QueuedEvent it may depend on (ie a
- * node creation) and be sure it happens after the event (a normal set_port_value could beat the
- * queued event and arrive out of order). </p> \n \n
+ * \li This is the queued way to set a port value (it is in the same threading class as e.g.
+ * node creation). This way the client can stream a sequence of events which depend on each
+ * other (e.g. a node creation followed by several set_port_value messages to set the node's
+ * controls) without needing to wait on a response to the first (node creation) message.
+ *
+ * There is also a fast "immediate" version of this message, set_port_value_immediate, which
+ * does not have this ordering guarantee.</p> \n \n
*/
int
-OSCEngineReceiver::_set_port_value_slow_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg)
+OSCEngineReceiver::_set_port_value_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg)
{
const char* port_path = &argv[1]->s;
const float value = argv[2]->f;
- set_port_value_queued(port_path, value);
+ set_port_value(port_path, sizeof(float), &value);
+ return 0;
+}
+
+
+/** \page engine_osc_namespace
+ * <p> \b /ingen/set_port_value - Sets the value of a port for all voices (as a QueuedEvent)
+ * \arg \b response-id (integer)
+ * \arg \b port-path (string) - Name of port
+ * \arg \b value (float) - Value to set port to
+ *
+ * \li This is the queued way to set a port value (it is in the same threading class as e.g.
+ * node creation). This way the client can stream a sequence of events which depend on each
+ * other (e.g. a node creation followed by several set_port_value messages to set the node's
+ * controls) without needing to wait on a response to the first (node creation) message.
+ *
+ * There is also a fast "immediate" version of this message, set_port_value_immediate, which
+ * does not have this ordering guarantee.</p> \n \n
+ */
+int
+OSCEngineReceiver::_set_port_value_voice_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg)
+{
+ const char* port_path = &argv[1]->s;
+ const int32_t voice = argv[2]->i;
+ const float value = argv[3]->f;
+
+ set_port_value(port_path, voice, sizeof(float), &value);
return 0;
}
diff --git a/src/libs/engine/OSCEngineReceiver.hpp b/src/libs/engine/OSCEngineReceiver.hpp
index 264b66c1..e6ecebac 100644
--- a/src/libs/engine/OSCEngineReceiver.hpp
+++ b/src/libs/engine/OSCEngineReceiver.hpp
@@ -100,7 +100,8 @@ private:
LO_HANDLER(disconnect_all);
LO_HANDLER(set_port_value);
LO_HANDLER(set_port_value_voice);
- LO_HANDLER(set_port_value_slow);
+ LO_HANDLER(set_port_value_immediate);
+ LO_HANDLER(set_port_value_immediate_voice);
LO_HANDLER(note_on);
LO_HANDLER(note_off);
LO_HANDLER(all_notes_off);
diff --git a/src/libs/engine/QueuedEngineInterface.cpp b/src/libs/engine/QueuedEngineInterface.cpp
index badbf78d..41780e92 100644
--- a/src/libs/engine/QueuedEngineInterface.cpp
+++ b/src/libs/engine/QueuedEngineInterface.cpp
@@ -233,26 +233,39 @@ QueuedEngineInterface::disconnect_all(const string& node_path)
void
QueuedEngineInterface::set_port_value(const string& port_path,
- float value)
+ uint32_t data_size,
+ const void* data)
{
- push_stamped(new SetPortValueEvent(_engine, _responder, now(), port_path, value));
+ push_queued(new SetPortValueQueuedEvent(_engine, _responder, now(), port_path, data_size, data));
}
void
QueuedEngineInterface::set_port_value(const string& port_path,
uint32_t voice,
- float value)
+ uint32_t data_size,
+ const void* data)
{
- push_stamped(new SetPortValueEvent(_engine, _responder, now(), voice, port_path, value));
+ push_queued(new SetPortValueQueuedEvent(_engine, _responder, now(), voice, port_path, data_size, data));
}
void
-QueuedEngineInterface::set_port_value_queued(const string& port_path,
- float value)
+QueuedEngineInterface::set_port_value_immediate(const string& port_path,
+ uint32_t data_size,
+ const void* data)
{
- push_queued(new SetPortValueQueuedEvent(_engine, _responder, now(), port_path, value));
+ push_stamped(new SetPortValueEvent(_engine, _responder, now(), port_path, data_size, data));
+}
+
+
+void
+QueuedEngineInterface::set_port_value_immediate(const string& port_path,
+ uint32_t voice,
+ uint32_t data_size,
+ const void* data)
+{
+ push_stamped(new SetPortValueEvent(_engine, _responder, now(), voice, port_path, data_size, data));
}
diff --git a/src/libs/engine/QueuedEngineInterface.hpp b/src/libs/engine/QueuedEngineInterface.hpp
index 396615c0..06583186 100644
--- a/src/libs/engine/QueuedEngineInterface.hpp
+++ b/src/libs/engine/QueuedEngineInterface.hpp
@@ -119,14 +119,22 @@ public:
virtual void disconnect_all(const string& node_path);
virtual void set_port_value(const string& port_path,
- float val);
-
+ uint32_t data_size,
+ const void* data);
+
virtual void set_port_value(const string& port_path,
uint32_t voice,
- float val);
-
- virtual void set_port_value_queued(const string& port_path,
- float val);
+ uint32_t data_size,
+ const void* data);
+
+ virtual void set_port_value_immediate(const string& port_path,
+ uint32_t data_size,
+ const void* data);
+
+ virtual void set_port_value_immediate(const string& port_path,
+ uint32_t voice,
+ uint32_t data_size,
+ const void* data);
virtual void set_program(const string& node_path,
uint32_t bank,
diff --git a/src/libs/engine/events/SetPortValueEvent.cpp b/src/libs/engine/events/SetPortValueEvent.cpp
index 581defa6..fa2238e2 100644
--- a/src/libs/engine/events/SetPortValueEvent.cpp
+++ b/src/libs/engine/events/SetPortValueEvent.cpp
@@ -15,6 +15,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <sstream>
#include "Responder.hpp"
#include "SetPortValueEvent.hpp"
#include "Engine.hpp"
@@ -23,31 +24,57 @@
#include "Node.hpp"
#include "ObjectStore.hpp"
#include "AudioBuffer.hpp"
+#include "MidiBuffer.hpp"
+
+using namespace std;
namespace Ingen {
-/** Voice-specific control setting
- */
-SetPortValueEvent::SetPortValueEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, size_t voice_num, const string& port_path, Sample val)
+/** Omni (all voices) control setting */
+SetPortValueEvent::SetPortValueEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ const string& port_path,
+ uint32_t data_size,
+ const void* data)
: Event(engine, responder, timestamp),
- _voice_num(voice_num),
+ _omni(true),
+ _voice_num(0),
_port_path(port_path),
- _val(val),
+ _data_size(data_size),
+ _data(malloc(data_size)),
_port(NULL),
_error(NO_ERROR)
{
+ memcpy(_data, data, data_size);
}
-SetPortValueEvent::SetPortValueEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path, Sample val)
+/** Voice-specific control setting */
+SetPortValueEvent::SetPortValueEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ uint32_t voice_num,
+ const string& port_path,
+ uint32_t data_size,
+ const void* data)
: Event(engine, responder, timestamp),
- _voice_num(-1),
+ _omni(false),
+ _voice_num(voice_num),
_port_path(port_path),
- _val(val),
+ _data_size(data_size),
+ _data(malloc(data_size)),
_port(NULL),
_error(NO_ERROR)
{
+ memcpy(_data, data, data_size);
+}
+
+
+SetPortValueEvent::~SetPortValueEvent()
+{
+ free(_data);
}
@@ -62,16 +89,28 @@ SetPortValueEvent::execute(SampleCount nframes, FrameTime start, FrameTime end)
if (_port == NULL) {
_error = PORT_NOT_FOUND;
- } else if (!(_port->type() == DataType::FLOAT)) {
- _error = TYPE_MISMATCH;
+/* } else if (_port->buffer(0)->size() < _data_size) {
+ _error = NO_SPACE;*/
} else {
- AudioBuffer* const buf = (AudioBuffer*)_port->buffer(0);
- const size_t offset = (buf->size() == 1) ? 0 : _time - start;
- if (_voice_num == -1)
- for (uint32_t i=0; i < _port->poly(); ++i)
- ((AudioBuffer*)_port->buffer(i))->set(_val, offset);
- else
- ((AudioBuffer*)_port->buffer(_voice_num))->set(_val, offset);
+ Buffer* const buf = _port->buffer(0);
+ AudioBuffer* const abuf = dynamic_cast<AudioBuffer*>(buf);
+ if (abuf) {
+ const size_t offset = (buf->size() == 1) ? 0 : _time - start;
+
+ if (_omni)
+ for (uint32_t i=0; i < _port->poly(); ++i)
+ ((AudioBuffer*)_port->buffer(i))->set(*(float*)_data, offset);
+ else
+ ((AudioBuffer*)_port->buffer(_voice_num))->set(*(float*)_data, offset);
+
+ return;
+ }
+
+ MidiBuffer* const mbuf = dynamic_cast<MidiBuffer*>(buf);
+ if (mbuf) {
+ const double stamp = std::max((double)_time, mbuf->latest_stamp());
+ mbuf->append(stamp, _data_size, (const unsigned char*)_data);
+ }
}
}
@@ -83,17 +122,18 @@ SetPortValueEvent::post_process()
assert(_port != NULL);
_responder->respond_ok();
- _engine.broadcaster()->send_control_change(_port_path, _val);
+ _engine.broadcaster()->send_control_change(_port_path, *(float*)_data);
} else if (_error == PORT_NOT_FOUND) {
string msg = "Unable to find port ";
msg.append(_port_path).append(" for set_port_value");
_responder->respond_error(msg);
- } else if (_error == TYPE_MISMATCH) {
- string msg = "Attempt to set ";
- msg.append(_port_path).append(" to incompatible type");
- _responder->respond_error(msg);
+ } else if (_error == NO_SPACE) {
+ std::ostringstream msg("Attempt to write ");
+ msg << _data_size << " bytes to " << _port_path << ", with capacity "
+ << _port->buffer_size() << endl;
+ _responder->respond_error(msg.str());
}
}
diff --git a/src/libs/engine/events/SetPortValueEvent.hpp b/src/libs/engine/events/SetPortValueEvent.hpp
index da378347..4b6e8d92 100644
--- a/src/libs/engine/events/SetPortValueEvent.hpp
+++ b/src/libs/engine/events/SetPortValueEvent.hpp
@@ -35,18 +35,34 @@ class Port;
class SetPortValueEvent : public Event
{
public:
- SetPortValueEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path, Sample val);
- SetPortValueEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, size_t voice_num, const string& port_path, Sample val);
+ SetPortValueEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ const string& port_path,
+ uint32_t data_size,
+ const void* data);
+
+ SetPortValueEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ uint32_t voice_num,
+ const string& port_path,
+ uint32_t data_size,
+ const void* data);
+
+ ~SetPortValueEvent();
void execute(SampleCount nframes, FrameTime start, FrameTime end);
void post_process();
private:
- enum ErrorType { NO_ERROR, PORT_NOT_FOUND, TYPE_MISMATCH };
+ enum ErrorType { NO_ERROR, PORT_NOT_FOUND, NO_SPACE };
- int _voice_num;
+ bool _omni;
+ uint32_t _voice_num;
string _port_path;
- float _val;
+ uint32_t _data_size;
+ void* _data;
Port* _port;
ErrorType _error;
};
diff --git a/src/libs/engine/events/SetPortValueQueuedEvent.cpp b/src/libs/engine/events/SetPortValueQueuedEvent.cpp
index 35c2f270..8940d4c5 100644
--- a/src/libs/engine/events/SetPortValueQueuedEvent.cpp
+++ b/src/libs/engine/events/SetPortValueQueuedEvent.cpp
@@ -15,6 +15,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <sstream>
#include "SetPortValueQueuedEvent.hpp"
#include "Responder.hpp"
#include "Engine.hpp"
@@ -28,27 +29,44 @@
namespace Ingen {
-/** Voice-specific control setting
- */
-SetPortValueQueuedEvent::SetPortValueQueuedEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, size_t voice_num, const string& port_path, Sample val)
+/** Omni (all voices) control setting */
+SetPortValueQueuedEvent::SetPortValueQueuedEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ const string& port_path,
+ uint32_t data_size,
+ const void* data)
: QueuedEvent(engine, responder, timestamp),
- _voice_num(voice_num),
+ _omni(true),
+ _voice_num(0),
_port_path(port_path),
- _val(val),
+ _data_size(data_size),
+ _data(malloc(data_size)),
_port(NULL),
_error(NO_ERROR)
{
+ memcpy(_data, data, data_size);
}
-SetPortValueQueuedEvent::SetPortValueQueuedEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path, Sample val)
+/** Voice-specific control setting */
+SetPortValueQueuedEvent::SetPortValueQueuedEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ uint32_t voice_num,
+ const string& port_path,
+ uint32_t data_size,
+ const void* data)
: QueuedEvent(engine, responder, timestamp),
- _voice_num(-1),
+ _omni(false),
+ _voice_num(voice_num),
_port_path(port_path),
- _val(val),
+ _data_size(data_size),
+ _data(malloc(data_size)),
_port(NULL),
_error(NO_ERROR)
{
+ memcpy(_data, data, data_size);
}
@@ -60,8 +78,8 @@ SetPortValueQueuedEvent::pre_process()
if (_port == NULL) {
_error = PORT_NOT_FOUND;
- } else if ( !(_port->type() == DataType::FLOAT) ) {
- _error = TYPE_MISMATCH;
+/* } else if (_port->buffer_size() < _data_size) {
+ _error = NO_SPACE;*/
}
QueuedEvent::pre_process();
@@ -78,11 +96,12 @@ SetPortValueQueuedEvent::execute(SampleCount nframes, FrameTime start, FrameTime
assert(_port);
AudioBuffer* const buf = (AudioBuffer*)_port->buffer(0);
const size_t offset = (buf->size() == 1) ? 0 : _time - start;
- if (_voice_num == -1)
+
+ if (_omni)
for (uint32_t i=0; i < _port->poly(); ++i)
- ((AudioBuffer*)_port->buffer(i))->set(_val, offset);
+ ((AudioBuffer*)_port->buffer(i))->set(*(float*)_data, offset);
else
- ((AudioBuffer*)_port->buffer(_voice_num))->set(_val, offset);
+ ((AudioBuffer*)_port->buffer(_voice_num))->set(*(float*)_data, offset);
}
}
@@ -94,7 +113,7 @@ SetPortValueQueuedEvent::post_process()
assert(_port != NULL);
_responder->respond_ok();
- _engine.broadcaster()->send_control_change(_port_path, _val);
+ _engine.broadcaster()->send_control_change(_port_path, *(float*)_data);
// Send patch port control change, if this is a bridge port
/*Port* parent_port = _port->parent_node()->as_port();
@@ -108,10 +127,11 @@ SetPortValueQueuedEvent::post_process()
msg.append(_port_path).append(" for set_port_value_slow");
_responder->respond_error(msg);
- } else if (_error == TYPE_MISMATCH) {
- string msg = "Attempt to set ";
- msg.append(_port_path).append(" to incompatible type");
- _responder->respond_error(msg);
+ } else if (_error == NO_SPACE) {
+ std::ostringstream msg("Attempt to write ");
+ msg << _data_size << " bytes to " << _port_path << ", with capacity "
+ << _port->buffer_size() << endl;
+ _responder->respond_error(msg.str());
}
}
diff --git a/src/libs/engine/events/SetPortValueQueuedEvent.hpp b/src/libs/engine/events/SetPortValueQueuedEvent.hpp
index 43e3d0f8..b64cf903 100644
--- a/src/libs/engine/events/SetPortValueQueuedEvent.hpp
+++ b/src/libs/engine/events/SetPortValueQueuedEvent.hpp
@@ -35,19 +35,33 @@ class Port;
class SetPortValueQueuedEvent : public QueuedEvent
{
public:
- SetPortValueQueuedEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path, Sample val);
- SetPortValueQueuedEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, size_t voice_num, const string& port_path, Sample val);
-
+ SetPortValueQueuedEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ const string& port_path,
+ uint32_t data_size,
+ const void* data);
+
+ SetPortValueQueuedEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ uint32_t voice_num,
+ const string& port_path,
+ uint32_t data_size,
+ const void* data);
+
void pre_process();
void execute(SampleCount nframes, FrameTime start, FrameTime end);
void post_process();
private:
- enum ErrorType { NO_ERROR, PORT_NOT_FOUND, TYPE_MISMATCH };
+ enum ErrorType { NO_ERROR, PORT_NOT_FOUND, NO_SPACE };
- int _voice_num;
+ bool _omni;
+ uint32_t _voice_num;
string _port_path;
- float _val;
+ uint32_t _data_size;
+ void* _data;
Port* _port;
ErrorType _error;
};
diff --git a/src/libs/gui/ControlPanel.cpp b/src/libs/gui/ControlPanel.cpp
index be524814..b12a21f5 100644
--- a/src/libs/gui/ControlPanel.cpp
+++ b/src/libs/gui/ControlPanel.cpp
@@ -237,11 +237,11 @@ ControlPanel::value_changed(SharedPtr<PortModel> port, float val)
* setting right away (so the value doesn't need to be echoed back) */
if (_all_voices_radio->get_active()) {
- App::instance().engine()->set_port_value(port->path(), val);
+ App::instance().engine()->set_port_value_immediate(port->path(), sizeof(float), &val);
port->value(val);
} else {
int voice = _voice_spinbutton->get_value_as_int();
- App::instance().engine()->set_port_value(port->path(), voice, val);
+ App::instance().engine()->set_port_value_immediate(port->path(), voice, sizeof(float), &val);
port->value(val);
}
diff --git a/src/libs/gui/Port.cpp b/src/libs/gui/Port.cpp
index 5eae70c7..8ba43d56 100644
--- a/src/libs/gui/Port.cpp
+++ b/src/libs/gui/Port.cpp
@@ -90,7 +90,7 @@ void
Port::set_control(float value, bool signal)
{
if (signal)
- App::instance().engine()->set_port_value(_port_model->path(), value);
+ App::instance().engine()->set_port_value_immediate(_port_model->path(), sizeof(float), &value);
FlowCanvas::Port::set_control(value);
}
diff --git a/src/libs/serialisation/Loader.cpp b/src/libs/serialisation/Loader.cpp
index 9438583a..ec60225d 100644
--- a/src/libs/serialisation/Loader.cpp
+++ b/src/libs/serialisation/Loader.cpp
@@ -205,7 +205,7 @@ Loader::load(SharedPtr<EngineInterface> engine,
const Path port_path = patch_path.base() + node_name +"/"+ port_name;
- engine->set_port_value(port_path, val);
+ engine->set_port_value(port_path, sizeof(float), &val);
}
@@ -240,8 +240,10 @@ Loader::load(SharedPtr<EngineInterface> engine,
}
RDF::Node val_node = (*i)["portval"];
- if (val_node.is_float())
- engine->set_port_value(patch_path.base() + name, val_node.to_float());
+ if (val_node.is_float()) {
+ const float val = val_node.to_float();
+ engine->set_port_value(patch_path.base() + name, sizeof(float), &val);
+ }
string floatkey = rdf_world->qualify((*i)["floatkey"].to_string());
val_node = (*i)["floatval"];