/*
This file is part of Ingen.
Copyright 2007-2015 David Robillard
Ingen is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or 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 Affero General Public License for details.
You should have received a copy of the GNU Affero General Public License
along with Ingen. If not, see .
*/
#ifndef INGEN_ENGINE_CONTROLBINDINGS_HPP
#define INGEN_ENGINE_CONTROLBINDINGS_HPP
#include "BufferRef.hpp"
#include "lv2/atom/forge.h"
#include "raul/Maid.hpp"
#include
#include
#include
#include
#include
#include
#include
namespace raul {
class Path;
} // namespace raul
namespace ingen {
class Atom;
namespace server {
class Buffer;
class Engine;
class RunContext;
class PortImpl;
class ControlBindings
{
public:
enum class Type : uint16_t {
NULL_CONTROL,
MIDI_BENDER,
MIDI_CC,
MIDI_RPN,
MIDI_NRPN,
MIDI_CHANNEL_PRESSURE,
MIDI_NOTE
};
struct Key {
Key(Type t, int16_t n) noexcept : type{t}, num{n} {}
Key() noexcept : Key{Type::NULL_CONTROL, 0U} {}
bool operator<(const Key& other) const {
return ((type < other.type) ||
(type == other.type && num < other.num));
}
bool operator==(const Key& other) const {
return type == other.type && num == other.num;
}
bool operator!() const { return type == Type::NULL_CONTROL; }
Type type;
int16_t num;
};
/** One binding of a controller to a port. */
struct Binding : public boost::intrusive::set_base_hook<>,
public raul::Maid::Disposable {
Binding(Key k, PortImpl* p) noexcept : key{k}, port{p} {}
Binding() noexcept : Binding{Key{}, nullptr} {}
bool operator<(const Binding& rhs) const { return key < rhs.key; }
Key key;
PortImpl* port;
};
/** Comparator for bindings by key. */
struct BindingLess {
bool operator()(const Binding& lhs, const Binding& rhs) const {
return lhs.key < rhs.key;
}
};
explicit ControlBindings(Engine& engine);
~ControlBindings();
Key port_binding(PortImpl* port) const;
Key binding_key(const Atom& binding) const;
void start_learn(PortImpl* port);
/** Set the binding for `port` to `binding` and take ownership of it. */
bool set_port_binding(RunContext& ctx,
PortImpl* port,
Binding* binding,
const Atom& value);
void port_value_changed(RunContext& ctx,
PortImpl* port,
Key key,
const Atom& value_atom);
void pre_process(RunContext& ctx, Buffer* buffer);
void post_process(RunContext& ctx, Buffer* buffer);
/** Get all bindings for `path` or children of `path`. */
void get_all(const raul::Path& path, std::vector& bindings);
/** Remove a set of bindings from an earlier call to get_all(). */
void remove(RunContext& ctx, const std::vector& bindings);
private:
using Bindings =
boost::intrusive::multiset>;
static Key
midi_event_key(const uint8_t* buf, uint16_t& value);
void set_port_value(RunContext& ctx,
PortImpl* port,
Type type,
int16_t value) const;
bool finish_learn(RunContext& ctx, Key key);
static float control_to_port_value(RunContext& ctx,
const PortImpl* port,
Type type,
int16_t value);
static int16_t port_value_to_control(RunContext& ctx,
PortImpl* port,
Type type,
const Atom& value_atom);
Engine& _engine;
std::atomic _learn_binding;
std::shared_ptr _bindings;
BufferRef _feedback;
LV2_Atom_Forge _forge;
};
} // namespace server
} // namespace ingen
#endif // INGEN_ENGINE_CONTROLBINDINGS_HPP