diff options
author | David Robillard <d@drobilla.net> | 2010-02-03 04:46:56 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2010-02-03 04:46:56 +0000 |
commit | 87597f85c5a69a9accd3ce2ed88f2a006173e885 (patch) | |
tree | a3ffa393e9aecbc55dae64bad3bd45ee317e6d26 /src/engine/ControlBindings.cpp | |
parent | a645d2b8be4d7d31f6eef1649156b166a01e0c31 (diff) | |
download | ingen-87597f85c5a69a9accd3ce2ed88f2a006173e885.tar.gz ingen-87597f85c5a69a9accd3ce2ed88f2a006173e885.tar.bz2 ingen-87597f85c5a69a9accd3ce2ed88f2a006173e885.zip |
Comprehensive use of cached URIs and more advanced Value (Atom) system.
Atoms (e.g. property values or port values) can now be an Atom::DICT, which
maps directly to/from an RDF resource. This is now used to store control
bindings as a port property, eliminating the special API.
Full interned URIs used everywhere, instead of CURIEs pretending to be URIs.
Avoid converting string literals to URIs all over the place.
Support for binding MIDI pitch bender and MIDI channel pressure.
Saving/restoring of MIDI bindings as a free side-effect of the above.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2409 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine/ControlBindings.cpp')
-rw-r--r-- | src/engine/ControlBindings.cpp | 106 |
1 files changed, 86 insertions, 20 deletions
diff --git a/src/engine/ControlBindings.cpp b/src/engine/ControlBindings.cpp index 43e30338..2144aba7 100644 --- a/src/engine/ControlBindings.cpp +++ b/src/engine/ControlBindings.cpp @@ -20,6 +20,7 @@ #include "events/SendPortValue.hpp" #include "events/SendBinding.hpp" #include "ControlBindings.hpp" +#include "Engine.hpp" #include "EventBuffer.hpp" #include "PortImpl.hpp" #include "ProcessContext.hpp" @@ -34,6 +35,29 @@ namespace Ingen { void +ControlBindings::update_port(ProcessContext& context, PortImpl* port) +{ + const Shared::LV2URIMap& uris = Shared::LV2URIMap::instance(); + const Raul::Atom& binding = port->get_property(uris.ingen_controlBinding); + if (binding.type() == Atom::DICT) { + Atom::DictValue::const_iterator t = binding.get_dict().find(uris.rdf_type); + Atom::DictValue::const_iterator n = binding.get_dict().find(uris.midi_controllerNumber); + if (t != binding.get_dict().end() && n != binding.get_dict().end()) { + if (t->second == uris.midi_Controller) { + _bindings->insert(make_pair(Key(MIDI_CC, n->second.get_int32()), port)); + } else if (t->second == uris.midi_Bender) { + _bindings->insert(make_pair(Key(MIDI_BENDER), port)); + } else if (t->second == uris.midi_ChannelPressure) { + _bindings->insert(make_pair(Key(MIDI_CHANNEL_PRESSURE), port)); + } else { + error << "Unknown binding type " << t->second << endl; + } + } + } +} + + +void ControlBindings::learn(PortImpl* port) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); @@ -42,28 +66,40 @@ ControlBindings::learn(PortImpl* port) void -ControlBindings::set_port_value(ProcessContext& context, PortImpl* port, int8_t cc_value) +ControlBindings::set_port_value(ProcessContext& context, PortImpl* port, Type type, int16_t value) { // TODO: cache these to avoid the lookup - float min = port->get_property("lv2:minimum").get_float(); - float max = port->get_property("lv2:maximum").get_float(); + float min = port->get_property(Shared::LV2URIMap::instance().lv2_minimum).get_float(); + float max = port->get_property(Shared::LV2URIMap::instance().lv2_maximum).get_float(); + + float normal; + switch (type) { + case MIDI_CC: + case MIDI_CHANNEL_PRESSURE: + normal = (float)value / 127.0; + break; + case MIDI_BENDER: + normal = (float)value / 16383.0; + default: + break; + } - Raul::Atom value(static_cast<float>(((float)cc_value / 127.0) * (max - min) + min)); - port->set_value(value); + Raul::Atom atom(static_cast<float>(normal * (max - min) + min)); + port->set_value(atom); const Events::SendPortValue ev(context.engine(), context.start(), port, true, 0, - value.get_float()); + atom.get_float()); context.event_sink().write(sizeof(ev), &ev); } void -ControlBindings::bind(ProcessContext& context, int8_t cc_num) +ControlBindings::bind(ProcessContext& context, Type type, int16_t num) { - _bindings->insert(make_pair(cc_num, _learn_port)); + assert(_learn_port); + _bindings->insert(make_pair(Key(type, num), _learn_port)); - const Events::SendBinding ev(context.engine(), context.start(), _learn_port, - MessageType(MessageType::MIDI_CC, cc_num)); + const Events::SendBinding ev(context.engine(), context.start(), _learn_port, type, num); context.event_sink().write(sizeof(ev), &ev); _learn_port = NULL; @@ -106,12 +142,26 @@ ControlBindings::process(ProcessContext& context, EventBuffer* buffer) if (_learn_port) { buffer->rewind(); + int16_t num; while (buffer->get_event(&frames, &subframes, &type, &size, &buf)) { - if (type == _map->midi_event.id && (buf[0] & 0xF0) == MIDI_CMD_CONTROL) { - const int8_t controller = static_cast<const int8_t>(buf[1]); - bind(context, controller); - break; + if (type == _map->midi_event.id) { + switch (buf[0] & 0xF0) { + case MIDI_CMD_CONTROL: + num = static_cast<const int8_t>(buf[1]); + bind(context, MIDI_CC, num); + break; + case MIDI_CMD_BENDER: + bind(context, MIDI_BENDER); + break; + case MIDI_CMD_CHANNEL_PRESSURE: + bind(context, MIDI_CHANNEL_PRESSURE); + break; + default: + break; + } } + if (!_learn_port) + break; buffer->increment(); } } @@ -119,12 +169,28 @@ ControlBindings::process(ProcessContext& context, EventBuffer* buffer) if (!bindings->empty()) { buffer->rewind(); while (buffer->get_event(&frames, &subframes, &type, &size, &buf)) { - if (type == _map->midi_event.id && (buf[0] & 0xF0) == MIDI_CMD_CONTROL) { - const int8_t controller = static_cast<const int8_t>(buf[1]); - const int8_t value = static_cast<const int8_t>(buf[2]); - Bindings::const_iterator i = bindings->find(controller); - if (i != bindings->end()) { - set_port_value(context, i->second, value); + if (type == _map->midi_event.id) { + if ((buf[0] & 0xF0) == MIDI_CMD_CONTROL) { + const int8_t controller = static_cast<const int8_t>(buf[1]); + Bindings::const_iterator i = bindings->find(Key(MIDI_CC, controller)); + if (i != bindings->end()) { + const int8_t value = static_cast<const int8_t>(buf[2]); + set_port_value(context, i->second, MIDI_CC, value); + } + } else if ((buf[0] & 0xF0) == MIDI_CMD_BENDER) { + Bindings::const_iterator i = bindings->find(Key(MIDI_BENDER)); + if (i != bindings->end()) { + const int8_t lsb = static_cast<const int8_t>(buf[1]); + const int8_t msb = static_cast<const int8_t>(buf[2]); + const int16_t value = (msb << 7) + lsb; + set_port_value(context, i->second, MIDI_BENDER, value); + } + } else if ((buf[0] & 0xF0) == MIDI_CMD_CHANNEL_PRESSURE) { + Bindings::const_iterator i = bindings->find(Key(MIDI_CHANNEL_PRESSURE)); + if (i != bindings->end()) { + const int8_t value = static_cast<const int8_t>(buf[1]); + set_port_value(context, i->second, MIDI_CHANNEL_PRESSURE, value); + } } } buffer->increment(); |