From c1160ffc8a5dfb38891b0faa6373c9eecdd8e4c9 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 22 Sep 2007 23:51:00 +0000 Subject: Type oblivious set_port_value interface. git-svn-id: http://svn.drobilla.net/lad/ingen@765 a436a847-0d15-0410-975c-d299462d15a1 --- src/common/interface/EngineInterface.hpp | 18 +++-- src/libs/client/DeprecatedLoader.cpp | 3 +- src/libs/client/OSCClientReceiver.cpp | 2 +- src/libs/client/OSCEngineSender.cpp | 43 ++++++++--- src/libs/client/OSCEngineSender.hpp | 18 +++-- src/libs/client/PluginModel.cpp | 13 ++-- src/libs/engine/MidiBuffer.cpp | 5 +- src/libs/engine/MidiBuffer.hpp | 3 + src/libs/engine/OSCEngineReceiver.cpp | 63 ++++++++++++---- src/libs/engine/OSCEngineReceiver.hpp | 3 +- src/libs/engine/QueuedEngineInterface.cpp | 27 +++++-- src/libs/engine/QueuedEngineInterface.hpp | 20 ++++-- src/libs/engine/events/SetPortValueEvent.cpp | 84 ++++++++++++++++------ src/libs/engine/events/SetPortValueEvent.hpp | 26 +++++-- src/libs/engine/events/SetPortValueQueuedEvent.cpp | 56 ++++++++++----- src/libs/engine/events/SetPortValueQueuedEvent.hpp | 26 +++++-- src/libs/gui/ControlPanel.cpp | 4 +- src/libs/gui/Port.cpp | 2 +- src/libs/serialisation/Loader.cpp | 8 ++- 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::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 -#include "OSCEngineSender.hpp" #include -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 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 - *

\b /ingen/set_port_value - Sets the value of a port for all voices (both AR and CR) + *

\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

\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 - *

\b /ingen/set_port_value - Sets the value of a port for a specific voice (both AR and CR) + *

\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

\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 - *

\b /ingen/set_port_value_queued - Sets the value of a port for all voices (as a QueuedEvent) + *

\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).

\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.

\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 + *

\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.

\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 #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, SampleCount timestamp, size_t voice_num, const string& port_path, Sample val) +/** Omni (all voices) control setting */ +SetPortValueEvent::SetPortValueEvent(Engine& engine, + SharedPtr 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, SampleCount timestamp, const string& port_path, Sample val) +/** Voice-specific control setting */ +SetPortValueEvent::SetPortValueEvent(Engine& engine, + SharedPtr 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(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(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, SampleCount timestamp, const string& port_path, Sample val); - SetPortValueEvent(Engine& engine, SharedPtr responder, SampleCount timestamp, size_t voice_num, const string& port_path, Sample val); + SetPortValueEvent(Engine& engine, + SharedPtr responder, + SampleCount timestamp, + const string& port_path, + uint32_t data_size, + const void* data); + + SetPortValueEvent(Engine& engine, + SharedPtr 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 #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, SampleCount timestamp, size_t voice_num, const string& port_path, Sample val) +/** Omni (all voices) control setting */ +SetPortValueQueuedEvent::SetPortValueQueuedEvent(Engine& engine, + SharedPtr 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, SampleCount timestamp, const string& port_path, Sample val) +/** Voice-specific control setting */ +SetPortValueQueuedEvent::SetPortValueQueuedEvent(Engine& engine, + SharedPtr 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, SampleCount timestamp, const string& port_path, Sample val); - SetPortValueQueuedEvent(Engine& engine, SharedPtr responder, SampleCount timestamp, size_t voice_num, const string& port_path, Sample val); - + SetPortValueQueuedEvent(Engine& engine, + SharedPtr responder, + SampleCount timestamp, + const string& port_path, + uint32_t data_size, + const void* data); + + SetPortValueQueuedEvent(Engine& engine, + SharedPtr 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 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 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 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"]; -- cgit v1.2.1