From 64bd557e75113743f179086b365ea7d97b72ee3e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 12 Nov 2009 06:56:26 +0000 Subject: String port support. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2255 a436a847-0d15-0410-975c-d299462d15a1 --- src/engine/AudioBuffer.cpp | 1 - src/engine/AudioBuffer.hpp | 2 - src/engine/Buffer.cpp | 3 + src/engine/Buffer.hpp | 12 ++-- src/engine/EventBuffer.hpp | 15 ++--- src/engine/LV2Info.cpp | 3 + src/engine/LV2Info.hpp | 1 + src/engine/LV2Node.cpp | 70 +++++++++++++++----- src/engine/PortImpl.cpp | 29 ++++---- src/engine/PortImpl.hpp | 2 +- src/engine/StringBuffer.cpp | 121 ++++++++++++++++++++++++++++++++++ src/engine/StringBuffer.hpp | 59 +++++++++++++++++ src/engine/events/RequestMetadata.cpp | 13 ++-- src/engine/events/RequestMetadata.hpp | 10 +-- src/engine/events/SendPortValue.hpp | 21 +++--- src/engine/events/SetPortValue.cpp | 24 +++++-- src/engine/internals/Note.cpp | 6 +- src/engine/wscript | 1 + 18 files changed, 315 insertions(+), 78 deletions(-) create mode 100644 src/engine/StringBuffer.cpp create mode 100644 src/engine/StringBuffer.hpp (limited to 'src/engine') diff --git a/src/engine/AudioBuffer.cpp b/src/engine/AudioBuffer.cpp index dc7efee5..02ebea57 100644 --- a/src/engine/AudioBuffer.cpp +++ b/src/engine/AudioBuffer.cpp @@ -35,7 +35,6 @@ AudioBuffer::AudioBuffer(size_t size) : Buffer((size == 1) ? DataType::CONTROL : DataType::AUDIO, size) , _data(NULL) , _local_data(NULL) - , _size(size) , _filled_size(0) , _state(OK) , _set_value(0) diff --git a/src/engine/AudioBuffer.hpp b/src/engine/AudioBuffer.hpp index 732ff0db..aff990ec 100644 --- a/src/engine/AudioBuffer.hpp +++ b/src/engine/AudioBuffer.hpp @@ -56,7 +56,6 @@ public: void prepare_read(FrameTime start, SampleCount nframes); void prepare_write(FrameTime start, SampleCount nframes) {} - void rewind() const {} void resize(size_t size); void filled_size(size_t size) { _filled_size = size; } @@ -72,7 +71,6 @@ private: Sample* _data; ///< Used data pointer (probably same as _local_data) Sample* _local_data; ///< Locally allocated buffer (possibly unused if joined or set_data used) - size_t _size; ///< Allocated buffer size size_t _filled_size; ///< Usable buffer size (for MIDI ports etc) State _state; ///< State of buffer for setting values next cycle Sample _set_value; ///< Value set by set_value (for completing the set next cycle) diff --git a/src/engine/Buffer.cpp b/src/engine/Buffer.cpp index a8b091e0..14d97314 100644 --- a/src/engine/Buffer.cpp +++ b/src/engine/Buffer.cpp @@ -17,6 +17,7 @@ #include "AudioBuffer.hpp" #include "EventBuffer.hpp" +#include "StringBuffer.hpp" namespace Ingen { @@ -31,6 +32,8 @@ Buffer::create(DataType type, size_t size) return new AudioBuffer(size); else if (type.is_event()) return new EventBuffer(size); + else if (type.is_string()) + return new StringBuffer(size); else throw; } diff --git a/src/engine/Buffer.hpp b/src/engine/Buffer.hpp index c6b6dd1b..a1a56725 100644 --- a/src/engine/Buffer.hpp +++ b/src/engine/Buffer.hpp @@ -44,25 +44,25 @@ public: /** Clear contents and reset state */ virtual void clear() = 0; + virtual void resize(size_t size) { _size = size; } + virtual void* raw_data() = 0; virtual const void* raw_data() const = 0; /** Rewind (ie reset read pointer), but leave contents unchanged */ - virtual void rewind() const = 0; + virtual void rewind() const {} + + virtual void copy(const Buffer* src, size_t start_sample, size_t end_sample) = 0; virtual void prepare_read(FrameTime start, SampleCount nframes) = 0; virtual void prepare_write(FrameTime start, SampleCount nframes) = 0; - bool is_joined() const { return (_joined_buf != NULL); } + bool is_joined() const { return (_joined_buf != NULL); } Buffer* joined_buffer() const { return _joined_buf; } virtual bool join(Buffer* buf) = 0; virtual void unjoin() = 0; - virtual void copy(const Buffer* src, size_t start_sample, size_t end_sample) = 0; - - virtual void resize(size_t size) { _size = size; } - Shared::DataType type() const { return _type; } size_t size() const { return _size; } diff --git a/src/engine/EventBuffer.hpp b/src/engine/EventBuffer.hpp index b35fb13e..f89705b0 100644 --- a/src/engine/EventBuffer.hpp +++ b/src/engine/EventBuffer.hpp @@ -31,17 +31,20 @@ class EventBuffer : public Buffer { public: EventBuffer(size_t capacity); - void prepare_read(FrameTime start, SampleCount nframes); - void prepare_write(FrameTime start, SampleCount nframes); - bool join(Buffer* buf); void unjoin(); + void clear() { reset(_this_nframes); } + void* raw_data() { return _buf; } const void* raw_data() const { return _buf; } - void copy(const Buffer* src, size_t start_sample, size_t end_sample); + void rewind() const { _buf->rewind(); } + void prepare_read(FrameTime start, SampleCount nframes); + void prepare_write(FrameTime start, SampleCount nframes); + + void copy(const Buffer* src, size_t start_sample, size_t end_sample); bool merge(const EventBuffer& a, const EventBuffer& b); bool increment() const { return _buf->increment(); } @@ -52,10 +55,6 @@ public: inline uint32_t this_nframes() const { return _this_nframes; } inline uint32_t event_count() const { return _buf->event_count(); } - inline void rewind() const { _buf->rewind(); } - - inline void clear() { reset(_this_nframes); } - inline void reset(SampleCount nframes) { _this_nframes = nframes; _buf->reset(); diff --git a/src/engine/LV2Info.cpp b/src/engine/LV2Info.cpp index 91db3e7b..10541d0c 100644 --- a/src/engine/LV2Info.cpp +++ b/src/engine/LV2Info.cpp @@ -32,6 +32,8 @@ LV2Info::LV2Info(Ingen::Shared::World* world) , control_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_CONTROL)) , audio_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_AUDIO)) , event_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_EVENT)) + , string_class(slv2_value_new_uri(world->slv2_world, + "http://lv2plug.in/ns/dev/string-port#StringPort")) , _world(world) { assert(world); @@ -55,6 +57,7 @@ LV2Info::~LV2Info() slv2_value_free(control_class); slv2_value_free(audio_class); slv2_value_free(event_class); + slv2_value_free(string_class); } diff --git a/src/engine/LV2Info.hpp b/src/engine/LV2Info.hpp index 2486efca..6f34dc57 100644 --- a/src/engine/LV2Info.hpp +++ b/src/engine/LV2Info.hpp @@ -47,6 +47,7 @@ public: SLV2Value control_class; SLV2Value audio_class; SLV2Value event_class; + SLV2Value string_class; Ingen::Shared::World& world() { return *_world; } SLV2World lv2_world() { return _world->slv2_world; } diff --git a/src/engine/LV2Node.cpp b/src/engine/LV2Node.cpp index df2ccbb2..70ee2e08 100644 --- a/src/engine/LV2Node.cpp +++ b/src/engine/LV2Node.cpp @@ -43,11 +43,11 @@ using namespace Shared; * (It _will_ crash!) */ LV2Node::LV2Node(LV2Plugin* plugin, - const string& name, - bool polyphonic, - PatchImpl* parent, - SampleRate srate, - size_t buffer_size) + const string& name, + bool polyphonic, + PatchImpl* parent, + SampleRate srate, + size_t buffer_size) : NodeBase(plugin, name, polyphonic, parent, srate, buffer_size) , _lv2_plugin(plugin) , _instances(NULL) @@ -168,7 +168,7 @@ LV2Node::instantiate() (*_instances)[i], LV2_CONTEXT_MESSAGE); if (i == 0 && ctx_ext) { - cerr << "HAS CONTEXT EXTENSION" << endl; + cerr << _lv2_plugin->uri() << " has message context" << endl; assert(!_message_funcs); _message_funcs = (LV2MessageContext*)ctx_ext; } @@ -184,9 +184,17 @@ LV2Node::instantiate() float* def_values = new float[num_ports]; slv2_plugin_get_port_ranges_float(plug, 0, 0, def_values); - SLV2Value pred = slv2_value_new_uri(info->lv2_world(), + SLV2Value context_pred = slv2_value_new_uri(info->lv2_world(), "http://lv2plug.in/ns/dev/contexts#context"); + // FIXME: Why doesn't this just use lv2:default? + SLV2Value default_pred = slv2_value_new_uri(info->lv2_world(), + "http://lv2plug.in/ns/dev/string-port#default"); + + // FIXME: Make this a separate extension + SLV2Value size_pred = slv2_value_new_uri(info->lv2_world(), + "http://lv2plug.in/ns/dev/string-port#requiredSpace"); + for (uint32_t j=0; j < num_ports; ++j) { SLV2Port id = slv2_plugin_get_port_by_index(plug, j); @@ -196,6 +204,7 @@ LV2Node::instantiate() port_path = path().child(port_name); + Raul::Atom val; DataType data_type = DataType::UNKNOWN; if (slv2_port_is_a(plug, id, info->control_class)) { data_type = DataType::CONTROL; @@ -206,6 +215,34 @@ LV2Node::instantiate() } else if (slv2_port_is_a(plug, id, info->event_class)) { data_type = DataType::EVENT; port_buffer_size = _buffer_size; + } else if (slv2_port_is_a(plug, id, info->string_class)) { + data_type = DataType::STRING; + port_buffer_size = 0; + + // Get default value, and its length + SLV2Values defaults = slv2_port_get_value(plug, id, default_pred); + for (uint32_t i = 0; i < slv2_values_size(defaults); ++i) { + SLV2Value d = slv2_values_get_at(defaults, i); + if (slv2_value_is_string(d)) { + const char* str_val = slv2_value_as_string(d); + const size_t str_val_len = strlen(str_val); + if (str_val_len >= port_buffer_size) { + val = str_val; + port_buffer_size = str_val_len; + } + } + } + + // Get minimum size, if set in data + SLV2Values sizes = slv2_port_get_value(plug, id, size_pred); + for (uint32_t i = 0; i < slv2_values_size(sizes); ++i) { + SLV2Value d = slv2_values_get_at(sizes, i); + if (slv2_value_is_int(d)) { + size_t size_val = slv2_value_as_int(d); + if (size_val > port_buffer_size) + port_buffer_size = size_val; + } + } } enum { UNKNOWN, INPUT, OUTPUT } direction = UNKNOWN; @@ -223,31 +260,30 @@ LV2Node::instantiate() return false; } - // FIXME: need nice type preserving SLV2Value -> Raul::Atom conversion - const float def = isnan(def_values[j]) ? 0.0f : def_values[j]; - const Raul::Atom defatm = def; + if (val.type() == Atom::NIL) + val = isnan(def_values[j]) ? 0.0f : def_values[j]; if (direction == INPUT) - port = new InputPort(this, port_name, j, _polyphony, data_type, defatm, port_buffer_size); + port = new InputPort(this, port_name, j, _polyphony, data_type, val, port_buffer_size); else - port = new OutputPort(this, port_name, j, _polyphony, data_type, defatm, port_buffer_size); + port = new OutputPort(this, port_name, j, _polyphony, data_type, val, port_buffer_size); if (direction == INPUT && data_type == DataType::CONTROL) - ((AudioBuffer*)port->buffer(0))->set_value(def, 0, 0); + ((AudioBuffer*)port->buffer(0))->set_value(val.get_float(), 0, 0); - SLV2Values contexts = slv2_port_get_value(plug, id, pred); + SLV2Values contexts = slv2_port_get_value(plug, id, context_pred); for (uint32_t i = 0; i < slv2_values_size(contexts); ++i) { SLV2Value c = slv2_values_get_at(contexts, i); const char* context = slv2_value_as_string(c); if (!strcmp("http://lv2plug.in/ns/dev/contexts#MessageContext", context)) { - cout << "MESSAGE CONTEXT!" << endl; + cerr << _lv2_plugin->uri() << " port " << i << " has message context" << endl; if (!_message_funcs) { - cerr << "Plugin " << _lv2_plugin->uri() + cerr << _lv2_plugin->uri() << " has a message port, but no context extension data." << endl; } port->set_context(Context::MESSAGE); } else { - cout << "UNKNOWN CONTEXT: " + cout << _lv2_plugin->uri() << " port " << i << " has unknown context " << slv2_value_as_string(slv2_values_get_at(contexts, i)) << endl; } diff --git a/src/engine/PortImpl.cpp b/src/engine/PortImpl.cpp index 05fcfe67..7559ae02 100644 --- a/src/engine/PortImpl.cpp +++ b/src/engine/PortImpl.cpp @@ -18,14 +18,15 @@ #include #include "raul/Array.hpp" #include "raul/Maid.hpp" -#include "PortImpl.hpp" -#include "NodeImpl.hpp" #include "interface/DataType.hpp" +#include "events/SendPortValue.hpp" +#include "events/SendPortActivity.hpp" #include "AudioBuffer.hpp" #include "EventBuffer.hpp" +#include "NodeImpl.hpp" +#include "PortImpl.hpp" #include "ProcessContext.hpp" -#include "events/SendPortValue.hpp" -#include "events/SendPortActivity.hpp" +#include "StringBuffer.hpp" using namespace std; using namespace Raul; @@ -177,19 +178,13 @@ PortImpl::clear_buffers() void PortImpl::broadcast_value(ProcessContext& context, bool force) { + Raul::Atom val; switch (_type.symbol()) { case DataType::UNKNOWN: break; case DataType::AUDIO: case DataType::CONTROL: - { - const Sample val = ((AudioBuffer*)buffer(0))->value_at(0); - if (force || val != _last_broadcasted_value) { - _last_broadcasted_value = val; - const Events::SendPortValue ev(context.engine(), context.start(), this, false, 0, val); - context.event_sink().write(sizeof(ev), &ev); - } - } + val = ((AudioBuffer*)buffer(0))->value_at(0); break; case DataType::EVENT: if (((EventBuffer*)buffer(0))->event_count() > 0) { @@ -197,7 +192,17 @@ PortImpl::broadcast_value(ProcessContext& context, bool force) context.event_sink().write(sizeof(ev), &ev); } break; + case DataType::STRING: + val = Raul::Atom(((StringBuffer*)buffer(0))->data()); + break; } + + if (val.type() == Atom::FLOAT && (force || val != _last_broadcasted_value)) { + _last_broadcasted_value = val; + const Events::SendPortValue ev(context.engine(), context.start(), this, false, 0, val); + context.event_sink().write(sizeof(ev), &ev); + } + } diff --git a/src/engine/PortImpl.hpp b/src/engine/PortImpl.hpp index 986e8233..7d587165 100644 --- a/src/engine/PortImpl.hpp +++ b/src/engine/PortImpl.hpp @@ -139,7 +139,7 @@ protected: bool _fixed_buffers; bool _broadcast; bool _set_by_user; - Sample _last_broadcasted_value; + Raul::Atom _last_broadcasted_value; Context::ID _context; Raul::Array* _buffers; diff --git a/src/engine/StringBuffer.cpp b/src/engine/StringBuffer.cpp new file mode 100644 index 00000000..a6cec9f1 --- /dev/null +++ b/src/engine/StringBuffer.cpp @@ -0,0 +1,121 @@ +/* This file is part of Ingen. + * Copyright (C) 2009 Dave Robillard + * + * 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 + */ + +#define __STDC_LIMIT_MACROS 1 +#include +#include +#include +#include "ingen-config.h" +#include "StringBuffer.hpp" + +using namespace std; + +namespace Ingen { + +using namespace Shared; + +/** Allocate a new string buffer. + * \a capacity is in bytes. + */ +StringBuffer::StringBuffer(size_t capacity) + : Buffer(DataType(DataType::EVENT), capacity) +{ + memset(&_local_buf, '\0', sizeof(LV2_String_Data)); + _local_buf.data = (char*)malloc(capacity); + _local_buf.storage = capacity; + + _buf = &_local_buf; + clear(); + + cerr << "Creating String Buffer " << _buf << ", capacity = " << capacity << endl; +} + + +void +StringBuffer::clear() +{ + static const string default_val("2\n0 1\n1 1\n"); + if (_buf && _buf->data && _buf->storage > default_val.length()) + strncpy(_buf->data, default_val.c_str(), default_val.length()); +} + + +/** Use another buffer's data instead of the local one. + * + * This buffer will essentially be identical to @a buf after this call. + */ +bool +StringBuffer::join(Buffer* buf) +{ + assert(buf != this); + StringBuffer* sbuf = dynamic_cast(buf); + if (!sbuf) + return false; + + _buf = &sbuf->_local_buf; + _joined_buf = sbuf; + + return true; +} + + +void +StringBuffer::unjoin() +{ + _joined_buf = NULL; + _buf = &_local_buf; +} + + +void +StringBuffer::prepare_read(FrameTime start, SampleCount nframes) +{ + _this_nframes = nframes; +} + + +void +StringBuffer::prepare_write(FrameTime start, SampleCount nframes) +{ +} + + +void +StringBuffer::copy(const Buffer* src_buf, size_t start_sample, size_t end_sample) +{ + const StringBuffer* src = dynamic_cast(src_buf); + assert(src); + assert(src != this); + assert(src->_buf != _buf); + assert(src->_buf->data != _buf->data); + + strncpy(_buf->data, src->_buf->data, std::min(_buf->len, src->_buf->len)); + _this_nframes = end_sample - start_sample; +} + + +void +StringBuffer::resize(size_t size) +{ + _buf->data = (char*)realloc(_buf->data, size); + _buf->storage = size; + _size = size; +} + + +} // namespace Ingen + diff --git a/src/engine/StringBuffer.hpp b/src/engine/StringBuffer.hpp new file mode 100644 index 00000000..79d83f7a --- /dev/null +++ b/src/engine/StringBuffer.hpp @@ -0,0 +1,59 @@ +/* This file is part of Ingen. + * Copyright (C) 2009 Dave Robillard + * + * 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 STRINGBUFFER_H +#define STRINGBUFFER_H + +#include "string-port.lv2/string-port.h" +#include "interface/DataType.hpp" +#include "Buffer.hpp" + +namespace Ingen { + + +class StringBuffer : public Buffer { +public: + StringBuffer(size_t capacity); + + void clear(); + + void* raw_data() { return (void*)&_buf; } + const void* raw_data() const { return (void*)&_buf; } + + char* data() { return _buf->data; } + const char* data() const { return _buf->data; } + + void prepare_read(FrameTime start, SampleCount nframes); + void prepare_write(FrameTime start, SampleCount nframes); + + bool join(Buffer* buf); + void unjoin(); + + void copy(const Buffer* src, size_t start_sample, size_t end_sample); + + void resize(size_t size); + +private: + LV2_String_Data* _buf; ///< Contents (_local_buf or belongs to _joined_buf) + LV2_String_Data _local_buf; ///< Local contents + uint32_t _this_nframes; ///< Current cycle nframes +}; + + +} // namespace Ingen + +#endif // STRINGBUFFER_H diff --git a/src/engine/events/RequestMetadata.cpp b/src/engine/events/RequestMetadata.cpp index 145260ef..e633ca10 100644 --- a/src/engine/events/RequestMetadata.cpp +++ b/src/engine/events/RequestMetadata.cpp @@ -25,6 +25,7 @@ #include "PortImpl.hpp" #include "PluginImpl.hpp" #include "AudioBuffer.hpp" +#include "StringBuffer.hpp" using namespace std; using namespace Raul; @@ -36,11 +37,11 @@ using namespace Shared; RequestMetadata::RequestMetadata(Engine& engine, - SharedPtr responder, - SampleCount timestamp, - bool is_meta, - const URI& subject, - const URI& key) + SharedPtr responder, + SampleCount timestamp, + bool is_meta, + const URI& subject, + const URI& key) : QueuedEvent(engine, responder, timestamp) , _error(NO_ERROR) , _special_type(NONE) @@ -93,6 +94,8 @@ RequestMetadata::execute(ProcessContext& context) if (port) { if (port->type() == DataType::CONTROL || port->type() == DataType::AUDIO) _value = ((AudioBuffer*)port->buffer(0))->value_at(0); // TODO: offset + else if (port->type() == DataType::STRING) + _value = (char*)((StringBuffer*)port->buffer(0))->data(); } else { _resource = 0; } diff --git a/src/engine/events/RequestMetadata.hpp b/src/engine/events/RequestMetadata.hpp index ba860aaf..0777c79a 100644 --- a/src/engine/events/RequestMetadata.hpp +++ b/src/engine/events/RequestMetadata.hpp @@ -45,11 +45,11 @@ class RequestMetadata : public QueuedEvent { public: RequestMetadata(Engine& engine, - SharedPtr responder, - SampleCount timestamp, - bool meta, - const Raul::URI& subject, - const Raul::URI& key); + SharedPtr responder, + SampleCount timestamp, + bool meta, + const Raul::URI& subject, + const Raul::URI& key); void pre_process(); void execute(ProcessContext& context); diff --git a/src/engine/events/SendPortValue.hpp b/src/engine/events/SendPortValue.hpp index d3ac61f7..b942398c 100644 --- a/src/engine/events/SendPortValue.hpp +++ b/src/engine/events/SendPortValue.hpp @@ -18,6 +18,7 @@ #ifndef SENDPORTVALUEEVENT_H #define SENDPORTVALUEEVENT_H +#include "raul/Atom.hpp" #include "engine/Event.hpp" #include "engine/types.hpp" @@ -43,12 +44,12 @@ class SendPortValue : public Event { public: inline SendPortValue( - Engine& engine, - SampleCount timestamp, - PortImpl* port, - bool omni, - uint32_t voice_num, - Sample value) + Engine& engine, + SampleCount timestamp, + PortImpl* port, + bool omni, + uint32_t voice_num, + const Raul::Atom& value) : Event(engine, SharedPtr(), timestamp) , _port(port) , _omni(omni) @@ -67,10 +68,10 @@ public: void post_process(); private: - PortImpl* _port; - bool _omni; - uint32_t _voice_num; - Sample _value; + PortImpl* _port; + bool _omni; + uint32_t _voice_num; + Raul::Atom _value; }; diff --git a/src/engine/events/SetPortValue.cpp b/src/engine/events/SetPortValue.cpp index eacf172b..1964880d 100644 --- a/src/engine/events/SetPortValue.cpp +++ b/src/engine/events/SetPortValue.cpp @@ -31,6 +31,7 @@ #include "ProcessContext.hpp" #include "Responder.hpp" #include "SetPortValue.hpp" +#include "StringBuffer.hpp" using namespace std; using namespace Raul; @@ -169,21 +170,18 @@ SetPortValue::apply(uint32_t start, uint32_t nframes) return; } - EventBuffer* const ebuf = dynamic_cast(buf); - const LV2Features::Feature* f = _engine.world()->lv2_features->feature(LV2_URI_MAP_URI); LV2URIMap* map = (LV2URIMap*)f->controller; - // FIXME: eliminate lookups - // FIXME: need a proper prefix system - if (ebuf && _value.type() == Atom::BLOB) { + // TODO: eliminate lookups + EventBuffer* const ebuf = dynamic_cast(buf); + if (ebuf) { const uint32_t frames = std::max( - (uint32_t)(_time - start), + uint32_t(_time - start), ebuf->latest_frames()); // Size 0 event, pass it along to the plugin as a typed but empty event if (_value.data_size() == 0) { - cout << "BANG!" << endl; const uint32_t type_id = map->uri_to_id(NULL, _value.get_blob_type()); ebuf->append(frames, 0, type_id, 0, NULL); _port->raise_set_by_user_flag(); @@ -202,6 +200,18 @@ SetPortValue::apply(uint32_t start, uint32_t nframes) } } + StringBuffer* const sbuf = dynamic_cast(buf); + if (sbuf) { + if (_value.type() != Atom::STRING) { + _error = TYPE_MISMATCH; + return; + } + strncpy(sbuf->data(), _value.get_string(), + std::min(sbuf->size(), strlen(_value.get_string()))); + return; + } + + if (_value.type() == Atom::BLOB) cerr << "WARNING: Unknown value blob type " << _value.get_blob_type() << endl; else diff --git a/src/engine/internals/Note.cpp b/src/engine/internals/Note.cpp index 4b42807b..1a7d3f5e 100644 --- a/src/engine/internals/Note.cpp +++ b/src/engine/internals/Note.cpp @@ -131,7 +131,8 @@ NoteNode::process(ProcessContext& context) midi_in->rewind(); if (midi_in->event_count() > 0) - while (midi_in->get_event(&frames, &subframes, &type, &size, &buf)) { + for (midi_in->rewind(); midi_in->get_event(&frames, &subframes, &type, &size, &buf); + midi_in->increment()) { /*cout << "EVENT TYPE " << type << " @ " << frames << "." << subframes << ": "; for (uint16_t i = 0; i < size; ++i) @@ -178,9 +179,6 @@ NoteNode::process(ProcessContext& context) } else { //fprintf(stderr, "Unknown (size %d) MIDI event %X\n", size, buf[0]); } - - if (midi_in->increment() == midi_in->this_nframes()) - break; } NodeBase::post_process(context); diff --git a/src/engine/wscript b/src/engine/wscript index b4d0dc7a..0b3888f0 100644 --- a/src/engine/wscript +++ b/src/engine/wscript @@ -28,6 +28,7 @@ def build(bld): PostProcessor.cpp ProcessSlave.cpp QueuedEvent.cpp + StringBuffer.cpp events/SendPortActivity.cpp events/SendPortValue.cpp ingen_engine.cpp -- cgit v1.2.1