From d5a514148bec58cd7e97d032259362b2e19c0e95 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 29 Jan 2010 01:43:54 +0000 Subject: Magic MIDI binding via special ingen_control port. Always set lv2:minimum and lv2:maximum properties for control ports so they show up in properties dialog (and can be used for MIDI binding). git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2391 a436a847-0d15-0410-975c-d299462d15a1 --- src/engine/ControlBindings.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/engine/ControlBindings.cpp (limited to 'src/engine/ControlBindings.cpp') diff --git a/src/engine/ControlBindings.cpp b/src/engine/ControlBindings.cpp new file mode 100644 index 00000000..00241b54 --- /dev/null +++ b/src/engine/ControlBindings.cpp @@ -0,0 +1,96 @@ +/* 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 + */ + +#include "raul/log.hpp" +#include "raul/midi_events.h" +#include "events/SendPortValue.hpp" +#include "ControlBindings.hpp" +#include "EventBuffer.hpp" +#include "PortImpl.hpp" +#include "ProcessContext.hpp" +#include "ThreadManager.hpp" + +#define LOG(s) s << "[ControlBindings] " + +using namespace std; +using namespace Raul; + +namespace Ingen { + + +void +ControlBindings::learn(PortImpl* port) +{ + ThreadManager::assert_thread(THREAD_PRE_PROCESS); + _learn_port = port; +} + + +void +ControlBindings::set_port_value(ProcessContext& context, PortImpl* port, int8_t value) +{ + float min = port->get_property("lv2:minimum").get_float(); + float max = port->get_property("lv2:maximum").get_float(); + + Raul::Atom scaled_value(static_cast(((float)value / 127.0) * (max - min) + min)); + port->set_value(scaled_value); + + const Events::SendPortValue ev(context.engine(), context.start(), port, true, 0, + scaled_value.get_float()); + context.event_sink().write(sizeof(ev), &ev); +} + + +void +ControlBindings::process(ProcessContext& context, EventBuffer* buffer) +{ + uint32_t frames = 0; + uint32_t subframes = 0; + uint16_t type = 0; + uint16_t size = 0; + uint8_t* buf = NULL; + + if (_learn_port) { + buffer->rewind(); + while (buffer->get_event(&frames, &subframes, &type, &size, &buf)) { + if (type == _map->midi_event && (buf[0] & 0xF0) == MIDI_CMD_CONTROL) { + const int8_t controller = static_cast(buf[1]); + _bindings.insert(make_pair(controller, _learn_port)); + _learn_port = NULL; + break; + } + buffer->increment(); + } + } + + if (!_bindings.empty()) { + buffer->rewind(); + while (buffer->get_event(&frames, &subframes, &type, &size, &buf)) { + if (type == _map->midi_event && (buf[0] & 0xF0) == MIDI_CMD_CONTROL) { + const int8_t controller = static_cast(buf[1]); + const int8_t value = static_cast(buf[2]); + Bindings::const_iterator i = _bindings.find(controller); + if (i != _bindings.end()) { + set_port_value(context, i->second, value); + } + } + buffer->increment(); + } + } +} + +} -- cgit v1.2.1