From 4c299323440923891b9c583a354116000eb143cc Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 11 Mar 2012 05:22:08 +0000 Subject: Implement cv:CVPort (fix #790). Not well-tested, but at least works somewhat. Use new style LV2 URI defines (and fix invalid atom URIs). git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4050 a436a847-0d15-0410-975c-d299462d15a1 --- src/server/AudioBuffer.cpp | 2 +- src/server/BufferFactory.cpp | 7 ++++--- src/server/BufferFactory.hpp | 3 ++- src/server/ConnectionImpl.cpp | 8 ++++---- src/server/InputPort.cpp | 2 +- src/server/LV2Info.cpp | 16 ++++++++-------- src/server/LV2Info.hpp | 1 + src/server/LV2Node.cpp | 7 +++++-- src/server/NodeImpl.cpp | 2 +- src/server/ObjectBuffer.cpp | 32 ++++++++++++++++++-------------- src/server/ObjectSender.cpp | 2 +- src/server/PatchImpl.cpp | 2 +- src/server/PortImpl.cpp | 19 ++++++++++++++----- src/server/PortType.hpp | 11 ++++++++--- src/server/events/CreatePort.cpp | 2 ++ src/server/events/Disconnect.cpp | 5 +++-- src/server/events/SetMetadata.cpp | 2 +- src/server/mix.hpp | 9 ++++----- 18 files changed, 79 insertions(+), 53 deletions(-) (limited to 'src/server') diff --git a/src/server/AudioBuffer.cpp b/src/server/AudioBuffer.cpp index 0a0c6a79..fc73f9d7 100644 --- a/src/server/AudioBuffer.cpp +++ b/src/server/AudioBuffer.cpp @@ -52,7 +52,7 @@ AudioBuffer::AudioBuffer(BufferFactory& bufs, PortType type, size_t size) // Audio port / Vector of float } else { - assert(type == PortType::AUDIO); + assert(type == PortType::AUDIO || type == PortType::CV); atom()->type = 0;//map->vector_type; LV2_Atom_Vector* body = (LV2_Atom_Vector*)atom(); body->body.child_size = sizeof(Sample); diff --git a/src/server/BufferFactory.cpp b/src/server/BufferFactory.cpp index 88e417cd..a26b0361 100644 --- a/src/server/BufferFactory.cpp +++ b/src/server/BufferFactory.cpp @@ -78,6 +78,7 @@ BufferFactory::default_buffer_size(PortType type) { switch (type.symbol()) { case PortType::AUDIO: + case PortType::CV: return audio_buffer_size(_engine.driver()->block_length()); case PortType::CONTROL: return sizeof(LV2_Atom) + sizeof(float); @@ -136,12 +137,12 @@ BufferFactory::create(PortType type, size_t size) if (type.is_control()) { AudioBuffer* ret = new AudioBuffer(*this, type, audio_buffer_size(size)); - ret->atom()->type = _uris->atom_Float32.id; + ret->atom()->type = _uris->atom_Float.id; buffer = ret; - } else if (type.is_audio()) { + } else if (type.is_audio() || type.is_cv()) { AudioBuffer* ret = new AudioBuffer(*this, type, audio_buffer_size(size)); ret->atom()->type = _uris->atom_Vector.id; - ((LV2_Atom_Vector*)ret->atom())->body.child_type = _uris->atom_Float32.id; + ((LV2_Atom_Vector*)ret->atom())->body.child_type = _uris->atom_Float.id; buffer = ret; } else if (type.is_events()) { buffer = new EventBuffer(*this, size); diff --git a/src/server/BufferFactory.hpp b/src/server/BufferFactory.hpp index 1cd10c3c..a1634c86 100644 --- a/src/server/BufferFactory.hpp +++ b/src/server/BufferFactory.hpp @@ -69,7 +69,8 @@ private: inline Raul::AtomicPtr& free_list(PortType type) { switch (type.symbol()) { - case PortType::AUDIO: return _free_audio; + case PortType::AUDIO: + case PortType::CV: return _free_audio; case PortType::CONTROL: return _free_control; case PortType::EVENTS: return _free_event; case PortType::VALUE: diff --git a/src/server/ConnectionImpl.cpp b/src/server/ConnectionImpl.cpp index a6838b49..a0205627 100644 --- a/src/server/ConnectionImpl.cpp +++ b/src/server/ConnectionImpl.cpp @@ -174,14 +174,14 @@ ConnectionImpl::can_connect(const OutputPort* src, const InputPort* dst) || ( (src->is_a(PortType::MESSAGE) || src->is_a(PortType::VALUE)) && (dst->is_a(PortType::MESSAGE) || dst->is_a(PortType::VALUE))) - // Control => atom:Float32 Value - || (src->is_a(PortType::CONTROL) && dst->supports(uris.atom_Float32)) + // Control => atom:Float Value + || (src->is_a(PortType::CONTROL) && dst->supports(uris.atom_Float)) // Audio => atom:Vector Value || (src->is_a(PortType::AUDIO) && dst->supports(uris.atom_Vector)) - // atom:Float32 Value => Control - || (src->supports(uris.atom_Float32) && dst->is_a(PortType::CONTROL)) + // atom:Float Value => Control + || (src->supports(uris.atom_Float) && dst->is_a(PortType::CONTROL)) // atom:Vector Value => Audio || (src->supports(uris.atom_Vector) && dst->is_a(PortType::AUDIO))); diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index 6a959ce9..ce0c6263 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -56,7 +56,7 @@ InputPort::InputPort(BufferFactory& bufs, add_property(uris.rdf_type, uris.lv2_InputPort); // Set default control range - if (type == PortType::CONTROL) { + if (type == PortType::CONTROL || type == PortType::CV) { set_property(uris.lv2_minimum, 0.0f); set_property(uris.lv2_maximum, 1.0f); } diff --git a/src/server/LV2Info.cpp b/src/server/LV2Info.cpp index 6b94f72f..4fff9647 100644 --- a/src/server/LV2Info.cpp +++ b/src/server/LV2Info.cpp @@ -37,15 +37,14 @@ namespace Ingen { namespace Server { LV2Info::LV2Info(Ingen::Shared::World* world) - : input_class(lilv_new_uri(world->lilv_world(), LILV_URI_INPUT_PORT)) - , output_class(lilv_new_uri(world->lilv_world(), LILV_URI_OUTPUT_PORT)) - , control_class(lilv_new_uri(world->lilv_world(), LILV_URI_CONTROL_PORT)) - , audio_class(lilv_new_uri(world->lilv_world(), LILV_URI_AUDIO_PORT)) + : input_class(lilv_new_uri(world->lilv_world(), LV2_CORE__InputPort)) + , output_class(lilv_new_uri(world->lilv_world(), LV2_CORE__OutputPort)) + , control_class(lilv_new_uri(world->lilv_world(), LV2_CORE__ControlPort)) + , cv_class(lilv_new_uri(world->lilv_world(), "http://lv2plug.in/ns/ext/cv-port#CVPort")) + , audio_class(lilv_new_uri(world->lilv_world(), LV2_CORE__AudioPort)) , event_class(lilv_new_uri(world->lilv_world(), LILV_URI_EVENT_PORT)) - , value_port_class(lilv_new_uri(world->lilv_world(), - "http://lv2plug.in/ns/ext/atom#ValuePort")) - , message_port_class(lilv_new_uri(world->lilv_world(), - "http://lv2plug.in/ns/ext/atom#MessagePort")) + , value_port_class(lilv_new_uri(world->lilv_world(), LV2_ATOM__ValuePort)) + , message_port_class(lilv_new_uri(world->lilv_world(), LV2_ATOM__MessagePort)) , _world(world) { assert(world); @@ -61,6 +60,7 @@ LV2Info::~LV2Info() lilv_node_free(input_class); lilv_node_free(output_class); lilv_node_free(control_class); + lilv_node_free(cv_class); lilv_node_free(audio_class); lilv_node_free(event_class); lilv_node_free(value_port_class); diff --git a/src/server/LV2Info.hpp b/src/server/LV2Info.hpp index b32eb594..297f3742 100644 --- a/src/server/LV2Info.hpp +++ b/src/server/LV2Info.hpp @@ -40,6 +40,7 @@ public: LilvNode* input_class; LilvNode* output_class; LilvNode* control_class; + LilvNode* cv_class; LilvNode* audio_class; LilvNode* event_class; LilvNode* value_port_class; diff --git a/src/server/LV2Node.cpp b/src/server/LV2Node.cpp index 91226c7b..2ff24538 100644 --- a/src/server/LV2Node.cpp +++ b/src/server/LV2Node.cpp @@ -96,7 +96,7 @@ LV2Node::prepare_poly(BufferFactory& bufs, uint32_t poly) PortImpl* const port = _ports->at(j); Buffer* const buffer = port->prepared_buffer(i).get(); if (buffer) { - if (port->is_a(PortType::CONTROL)) { + if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CONTROL)) { ((AudioBuffer*)buffer)->set_value(port->value().get_float(), 0, 0); } else { buffer->clear(); @@ -229,6 +229,8 @@ LV2Node::instantiate(BufferFactory& bufs) PortType data_type = PortType::UNKNOWN; if (lilv_port_is_a(plug, id, info->control_class)) { data_type = PortType::CONTROL; + } else if (lilv_port_is_a(plug, id, info->cv_class)) { + data_type = PortType::CV; } else if (lilv_port_is_a(plug, id, info->audio_class)) { data_type = PortType::AUDIO; } else if (lilv_port_is_a(plug, id, info->event_class)) { @@ -287,7 +289,8 @@ LV2Node::instantiate(BufferFactory& bufs) else port = new OutputPort(bufs, this, port_name, j, _polyphony, data_type, val); - if (direction == INPUT && data_type == PortType::CONTROL) { + if (direction == INPUT && (data_type == PortType::CONTROL + || data_type == PortType::CV)) { port->set_value(val); if (!isnan(min_values[j])) { port->set_property(uris.lv2_minimum, min_values[j]); diff --git a/src/server/NodeImpl.cpp b/src/server/NodeImpl.cpp index b64524a3..cee1cc0a 100644 --- a/src/server/NodeImpl.cpp +++ b/src/server/NodeImpl.cpp @@ -95,7 +95,7 @@ NodeImpl::activate(BufferFactory& bufs) for (uint32_t v = 0; v < _polyphony; ++v) { Buffer* const buf = port->buffer(v).get(); if (buf) { - if (port->is_a(PortType::CONTROL)) { + if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CV)) { ((AudioBuffer*)buf)->set_value( port->value().get_float(), 0, 0); } else { diff --git a/src/server/ObjectBuffer.cpp b/src/server/ObjectBuffer.cpp index b5a96dbd..407333d3 100644 --- a/src/server/ObjectBuffer.cpp +++ b/src/server/ObjectBuffer.cpp @@ -99,15 +99,17 @@ ObjectBuffer::port_data(PortType port_type, SampleCount offset) { switch (port_type.symbol()) { case PortType::CONTROL: + case PortType::CV: case PortType::AUDIO: switch (_type.symbol()) { - case PortType::CONTROL: - return (float*)LV2_ATOM_BODY(atom()); - case PortType::AUDIO: - return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom()) + offset; - default: - warn << "Audio data requested from non-audio buffer" << endl; - return NULL; + case PortType::CONTROL: + return (float*)LV2_ATOM_BODY(atom()); + case PortType::CV: + case PortType::AUDIO: + return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom()) + offset; + default: + warn << "Audio data requested from non-audio buffer" << endl; + return NULL; } break; default: @@ -120,15 +122,17 @@ ObjectBuffer::port_data(PortType port_type, SampleCount offset) const { switch (port_type.symbol()) { case PortType::CONTROL: + case PortType::CV: case PortType::AUDIO: switch (_type.symbol()) { - case PortType::CONTROL: - return (float*)LV2_ATOM_BODY(atom()); - case PortType::AUDIO: - return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom()) + offset; - default: - warn << "Audio data requested from non-audio buffer" << endl; - return NULL; + case PortType::CONTROL: + return (float*)LV2_ATOM_BODY(atom()); + case PortType::CV: + case PortType::AUDIO: + return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom()) + offset; + default: + warn << "Audio data requested from non-audio buffer" << endl; + return NULL; } break; default: diff --git a/src/server/ObjectSender.cpp b/src/server/ObjectSender.cpp index 8381a4db..746e7642 100644 --- a/src/server/ObjectSender.cpp +++ b/src/server/ObjectSender.cpp @@ -134,7 +134,7 @@ ObjectSender::send_port(ClientInterface* client, const PortImpl* port, bool bund if (bundle) client->bundle_begin(); - if (port->is_a(PortType::CONTROL)) { + if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CV)) { Resource::Properties props = port->properties(); props.erase(port->bufs().uris().ingen_value); props.insert(make_pair(port->bufs().uris().ingen_value, diff --git a/src/server/PatchImpl.cpp b/src/server/PatchImpl.cpp index 7dd960c4..b6956baa 100644 --- a/src/server/PatchImpl.cpp +++ b/src/server/PatchImpl.cpp @@ -355,7 +355,7 @@ PatchImpl::create_port(BufferFactory& bufs, } Raul::Atom value; - if (type == PortType::CONTROL) + if (type == PortType::CONTROL || type == PortType::CV) value = 0.0f; return new DuplexPort(bufs, this, name, num_ports(), polyphonic, _polyphony, diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp index 2aef6f5e..ac4eb21f 100644 --- a/src/server/PortImpl.cpp +++ b/src/server/PortImpl.cpp @@ -107,11 +107,15 @@ bool PortImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - if (buffer_type() != PortType::CONTROL && buffer_type() != PortType::AUDIO) + if (buffer_type() != PortType::CONTROL && + buffer_type() != PortType::CV && + buffer_type() != PortType::AUDIO) { return false; + } - if (_poly == poly) + if (_poly == poly) { return true; + } if (_prepared_buffers && _prepared_buffers->size() != poly) { delete _prepared_buffers; @@ -135,11 +139,15 @@ bool PortImpl::apply_poly(Maid& maid, uint32_t poly) { ThreadManager::assert_thread(THREAD_PROCESS); - if (buffer_type() != PortType::CONTROL && buffer_type() != PortType::AUDIO) + if (buffer_type() != PortType::CONTROL && + buffer_type() != PortType::CV && + buffer_type() != PortType::AUDIO) { return false; + } - if (!_prepared_buffers) + if (!_prepared_buffers) { return true; + } assert(poly == _prepared_buffers->size()); @@ -150,7 +158,7 @@ PortImpl::apply_poly(Maid& maid, uint32_t poly) assert(_buffers == _prepared_buffers); _prepared_buffers = NULL; - if (is_a(PortType::CONTROL)) + if (is_a(PortType::CONTROL) || is_a(PortType::CV)) for (uint32_t v = 0; v < _poly; ++v) if (_buffers->at(v)) boost::static_pointer_cast(_buffers->at(v))->set_value( @@ -211,6 +219,7 @@ PortImpl::broadcast_value(Context& context, bool force) } return; case PortType::CONTROL: + case PortType::CV: val = ((AudioBuffer*)buffer(0).get())->value_at(0); break; case PortType::EVENTS: diff --git a/src/server/PortType.hpp b/src/server/PortType.hpp index 1fc9f995..b8fd747e 100644 --- a/src/server/PortType.hpp +++ b/src/server/PortType.hpp @@ -34,9 +34,10 @@ public: UNKNOWN = 0, AUDIO = 1, CONTROL = 2, - EVENTS = 3, - VALUE = 4, - MESSAGE = 5, + CV = 3, + EVENTS = 4, + VALUE = 5, + MESSAGE = 6, }; PortType(const Raul::URI& uri) @@ -46,6 +47,8 @@ public: _symbol = AUDIO; } else if (uri == type_uri(CONTROL)) { _symbol = CONTROL; + } else if (uri == type_uri(CV)) { + _symbol = CV; } else if (uri == type_uri(EVENTS)) { _symbol = EVENTS; } else if (uri == type_uri(VALUE)) { @@ -70,6 +73,7 @@ public: inline bool is_audio() { return _symbol == AUDIO; } inline bool is_control() { return _symbol == CONTROL; } + inline bool is_cv() { return _symbol == CV; } inline bool is_events() { return _symbol == EVENTS; } inline bool is_value() { return _symbol == VALUE; } inline bool is_message() { return _symbol == MESSAGE; } @@ -81,6 +85,7 @@ private: "http://drobilla.net/ns/ingen#nil", "http://lv2plug.in/ns/lv2core#AudioPort", "http://lv2plug.in/ns/lv2core#ControlPort", + "http://lv2plug.in/ns/ext/cv-port#CVPort", "http://lv2plug.in/ns/ext/event#EventPort", "http://lv2plug.in/ns/ext/atom#ValuePort", "http://lv2plug.in/ns/ext/atom#MessagePort" diff --git a/src/server/events/CreatePort.cpp b/src/server/events/CreatePort.cpp index 1df393ca..9c519981 100644 --- a/src/server/events/CreatePort.cpp +++ b/src/server/events/CreatePort.cpp @@ -72,6 +72,8 @@ CreatePort::CreatePort(Engine& engine, _data_type = PortType::AUDIO; } else if (type == uris.lv2_ControlPort) { _data_type = PortType::CONTROL; + } else if (type == uris.cv_CVPort) { + _data_type = PortType::CV; } else if (type == uris.ev_EventPort) { _data_type = PortType::EVENTS; } else if (type == uris.atom_ValuePort) { diff --git a/src/server/events/Disconnect.cpp b/src/server/events/Disconnect.cpp index aa5c4edb..01313208 100644 --- a/src/server/events/Disconnect.cpp +++ b/src/server/events/Disconnect.cpp @@ -98,8 +98,9 @@ Disconnect::Impl::Impl(Engine& e, _dst_input_port->get_buffers(*_engine.buffer_factory(), _buffers, _dst_input_port->poly()); - const bool is_control = _dst_input_port->is_a(PortType::CONTROL); - const float value = is_control ? _dst_input_port->value().get_float() : 0; + const bool is_control = _dst_input_port->is_a(PortType::CONTROL) || + _dst_input_port->is_a(PortType::CV); + const float value = is_control ? _dst_input_port->value().get_float() : 0; for (uint32_t i = 0; i < _buffers->size(); ++i) { if (is_control) { PtrCast(_buffers->at(i))->set_value(value, 0, 0); diff --git a/src/server/events/SetMetadata.cpp b/src/server/events/SetMetadata.cpp index 4d6f6497..720cf3ba 100644 --- a/src/server/events/SetMetadata.cpp +++ b/src/server/events/SetMetadata.cpp @@ -195,7 +195,7 @@ SetMetadata::pre_process() ev->pre_process(); _set_events.push_back(ev); } else if (key == uris.ingen_controlBinding) { - if (port->is_a(PortType::CONTROL)) { + if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CV)) { if (value == uris.wildcard) { _engine.control_bindings()->learn(port); } else if (value.type() == Atom::DICT) { diff --git a/src/server/mix.hpp b/src/server/mix.hpp index c90c0e17..21040c52 100644 --- a/src/server/mix.hpp +++ b/src/server/mix.hpp @@ -38,17 +38,18 @@ mix(Context& context, Buffer* dst, const boost::intrusive_ptr* srcs, uin switch (dst->type().symbol()) { case PortType::AUDIO: case PortType::CONTROL: + case PortType::CV: // Copy the first source dst->copy(context, srcs[0].get()); // Mix in the rest for (uint32_t i = 1; i < num_srcs; ++i) { - assert(srcs[i]->type() == PortType::AUDIO || srcs[i]->type() == PortType::CONTROL); + assert(srcs[i]->type() == PortType::AUDIO || + srcs[i]->type() == PortType::CONTROL || + srcs[i]->type() == PortType::CV); ((AudioBuffer*)dst)->accumulate(context, (AudioBuffer*)srcs[i].get()); } - break; - case PortType::EVENTS: dst->clear(); for (uint32_t i = 0; i < num_srcs; ++i) { @@ -75,10 +76,8 @@ mix(Context& context, Buffer* dst, const boost::intrusive_ptr* srcs, uin break; } } - dst->rewind(); break; - default: if (num_srcs == 1) dst->copy(context, srcs[0].get()); -- cgit v1.2.1