/*
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
#include
#include
#include
#include
#include "ingen/Atom.hpp"
#include "ingen/types.hpp"
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
#include "raul/Maid.hpp"
#include "raul/Path.hpp"
#include "BufferFactory.hpp"
namespace Ingen {
namespace Server {
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=Type::NULL_CONTROL, int16_t n=0) : type(t), num(n) {}
inline bool operator<(const Key& other) const {
return ((type < other.type) ||
(type == other.type && num < other.num));
}
inline bool operator==(const Key& other) const {
return type == other.type && num == other.num;
}
inline 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=Key(), PortImpl* p=nullptr) : key(std::move(k)), port(p) {}
inline 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:
typedef boost::intrusive::multiset<
Binding,
boost::intrusive::compare > Bindings;
Key midi_event_key(uint16_t size, const uint8_t* buf, uint16_t& value);
void set_port_value(RunContext& context,
PortImpl* port,
Type type,
int16_t value);
bool finish_learn(RunContext& context, Key key);
float control_to_port_value(RunContext& context,
const PortImpl* port,
Type type,
int16_t value) const;
int16_t port_value_to_control(RunContext& context,
PortImpl* port,
Type type,
const Atom& value_atom) const;
Engine& _engine;
std::atomic _learn_binding;
SPtr _bindings;
BufferRef _feedback;
LV2_Atom_Forge _forge;
};
} // namespace Server
} // namespace Ingen
#endif // INGEN_ENGINE_CONTROLBINDINGS_HPP