refine self-automating plugin interface
* thin automation at end * allow plugins to disable its internal write state (ctrl port) * Debug messages
This commit is contained in:
parent
b4a020cdf5
commit
37b90c2a9e
@ -54,6 +54,7 @@ namespace PBD {
|
||||
LIBARDOUR_API extern DebugBits AudioPlayback;
|
||||
LIBARDOUR_API extern DebugBits Panning;
|
||||
LIBARDOUR_API extern DebugBits LV2;
|
||||
LIBARDOUR_API extern DebugBits LV2Automate;
|
||||
LIBARDOUR_API extern DebugBits CaptureAlignment;
|
||||
LIBARDOUR_API extern DebugBits PluginManager;
|
||||
LIBARDOUR_API extern DebugBits AudioUnits;
|
||||
|
@ -94,6 +94,7 @@ typedef struct {
|
||||
#define LV2_AUTOMATE_URI__control LV2_AUTOMATE_URI_PREFIX "automationControl"
|
||||
/** lv2:portProperty */
|
||||
#define LV2_AUTOMATE_URI__controlled LV2_AUTOMATE_URI_PREFIX "automationControlled"
|
||||
#define LV2_AUTOMATE_URI__controller LV2_AUTOMATE_URI_PREFIX "automationController"
|
||||
|
||||
/** atom messages */
|
||||
#define LV2_AUTOMATE_URI__event LV2_AUTOMATE_URI_PREFIX "event"
|
||||
|
@ -210,7 +210,8 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
|
||||
PORT_POSITION = 1 << 7, ///< Event port understands position
|
||||
PORT_PATCHMSG = 1 << 8, ///< Event port supports patch:Message
|
||||
PORT_AUTOCTRL = 1 << 9, ///< Event port supports auto:AutomationControl
|
||||
PORT_CTRLED = 1 << 10 ///< Port prop auto:AutomationControlled (can be self controlled)
|
||||
PORT_CTRLED = 1 << 10, ///< Port prop auto:AutomationControlled (can be self controlled)
|
||||
PORT_CTRLER = 1 << 11 ///< Port prop auto:AutomationController (can be self set)
|
||||
} PortFlag;
|
||||
|
||||
typedef unsigned PortFlags;
|
||||
|
@ -50,6 +50,7 @@ PBD::DebugBits PBD::DEBUG::Solo = PBD::new_debug_bit ("solo");
|
||||
PBD::DebugBits PBD::DEBUG::AudioPlayback = PBD::new_debug_bit ("audioplayback");
|
||||
PBD::DebugBits PBD::DEBUG::Panning = PBD::new_debug_bit ("panning");
|
||||
PBD::DebugBits PBD::DEBUG::LV2 = PBD::new_debug_bit ("lv2");
|
||||
PBD::DebugBits PBD::DEBUG::LV2Automate = PBD::new_debug_bit ("lv2automate");
|
||||
PBD::DebugBits PBD::DEBUG::CaptureAlignment = PBD::new_debug_bit ("capturealignment");
|
||||
PBD::DebugBits PBD::DEBUG::PluginManager = PBD::new_debug_bit ("pluginmanager");
|
||||
PBD::DebugBits PBD::DEBUG::AudioUnits = PBD::new_debug_bit ("audiounits");
|
||||
|
@ -174,6 +174,7 @@ public:
|
||||
LilvNode* auto_can_write_automatation; // lv2:optionalFeature
|
||||
LilvNode* auto_automation_control; // atom:supports
|
||||
LilvNode* auto_automation_controlled; // lv2:portProperty
|
||||
LilvNode* auto_automation_controller; // lv2:portProperty
|
||||
#endif
|
||||
|
||||
private:
|
||||
@ -639,6 +640,11 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
|
||||
flags |= PORT_CTRLED;
|
||||
}
|
||||
}
|
||||
if (lilv_port_has_property(_impl->plugin, port, _world.auto_automation_controller)) {
|
||||
if ((flags & PORT_INPUT) && (flags & PORT_CONTROL)) {
|
||||
flags |= PORT_CTRLER;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_port_flags.push_back(flags);
|
||||
@ -2063,7 +2069,8 @@ LV2Plugin::automatable() const
|
||||
void
|
||||
LV2Plugin::set_automation_control (uint32_t i, boost::shared_ptr<AutomationControl> c)
|
||||
{
|
||||
if ((_port_flags[i] & PORT_CTRLED)) {
|
||||
if ((_port_flags[i] & (PORT_CTRLED | PORT_CTRLER))) {
|
||||
DEBUG_TRACE(DEBUG::LV2Automate, string_compose ("Ctrl Port %1\n", i));
|
||||
_ctrl_map [i] = AutomationCtrlPtr (new AutomationCtrl(c));
|
||||
}
|
||||
}
|
||||
@ -2470,8 +2477,12 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
|
||||
const uint32_t p = ((const LV2_Atom_Int*)parameter)->body;
|
||||
const float v = ((const LV2_Atom_Float*)value)->body;
|
||||
// -> add automation event..
|
||||
DEBUG_TRACE(DEBUG::LV2Automate,
|
||||
string_compose ("Event p: %1 t: %2 v: %3\n", p, frames, v));
|
||||
AutomationCtrlPtr c = get_automation_control (p);
|
||||
if (c && c->ac->automation_state() == Touch) {
|
||||
if (c &&
|
||||
(c->ac->automation_state() == Touch || c->ac->automation_state() == Write)
|
||||
) {
|
||||
framepos_t when = std::max ((framepos_t) 0, _session.transport_frame() + frames - _current_latency);
|
||||
assert (_session.transport_frame() + frames - _current_latency >= 0);
|
||||
if (c->guard) {
|
||||
@ -2488,11 +2499,42 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
|
||||
// writes automation for its own inputs
|
||||
// -> put them in "touch" mode (preferably "exclusive plugin touch(TM)"
|
||||
for (AutomationCtrlMap::iterator i = _ctrl_map.begin(); i != _ctrl_map.end(); ++i) {
|
||||
i->second->ac->set_automation_state (Touch);
|
||||
if (_port_flags[i->first] & PORT_CTRLED) {
|
||||
DEBUG_TRACE(DEBUG::LV2Automate,
|
||||
string_compose ("Setup p: %1\n", i->first));
|
||||
i->second->ac->set_automation_state (Touch);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (obj->body.otype == _uri_map.urids.auto_finalize) {
|
||||
// set [touched] parameters to "play" ??
|
||||
// allow plugin to change its mode (from analyze to apply)
|
||||
const LV2_Atom* parameter = NULL;
|
||||
const LV2_Atom* value = NULL;
|
||||
lv2_atom_object_get(obj,
|
||||
_uri_map.urids.auto_parameter, ¶meter,
|
||||
_uri_map.urids.auto_value, &value,
|
||||
0);
|
||||
if (parameter && value) {
|
||||
const uint32_t p = ((const LV2_Atom_Int*)parameter)->body;
|
||||
const float v = ((const LV2_Atom_Float*)value)->body;
|
||||
AutomationCtrlPtr c = get_automation_control (p);
|
||||
DEBUG_TRACE(DEBUG::LV2Automate,
|
||||
string_compose ("Finalize p: %1 v: %2\n", p, v));
|
||||
if (c && _port_flags[p] & PORT_CTRLER) {
|
||||
c->ac->set_value(v, Controllable::NoGroup);
|
||||
}
|
||||
} else {
|
||||
DEBUG_TRACE(DEBUG::LV2Automate, "Finalize\n");
|
||||
}
|
||||
for (AutomationCtrlMap::iterator i = _ctrl_map.begin(); i != _ctrl_map.end(); ++i) {
|
||||
// guard will be false if an event was written
|
||||
if ((_port_flags[i->first] & PORT_CTRLED) && !i->second->guard) {
|
||||
DEBUG_TRACE(DEBUG::LV2Automate,
|
||||
string_compose ("Thin p: %1\n", i->first));
|
||||
i->second->ac->alist ()->thin (20);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (obj->body.otype == _uri_map.urids.auto_start) {
|
||||
const LV2_Atom* parameter = NULL;
|
||||
@ -2502,6 +2544,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
|
||||
if (parameter) {
|
||||
const uint32_t p = ((const LV2_Atom_Int*)parameter)->body;
|
||||
AutomationCtrlPtr c = get_automation_control (p);
|
||||
DEBUG_TRACE(DEBUG::LV2Automate, string_compose ("Start Touch p: %1\n", p));
|
||||
if (c) {
|
||||
c->ac->start_touch (std::max ((framepos_t)0, _session.transport_frame() - _current_latency));
|
||||
c->guard = true;
|
||||
@ -2516,6 +2559,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
|
||||
if (parameter) {
|
||||
const uint32_t p = ((const LV2_Atom_Int*)parameter)->body;
|
||||
AutomationCtrlPtr c = get_automation_control (p);
|
||||
DEBUG_TRACE(DEBUG::LV2Automate, string_compose ("End Touch p: %1\n", p));
|
||||
if (c) {
|
||||
c->ac->stop_touch (true, std::max ((framepos_t)0, _session.transport_frame() - _current_latency));
|
||||
}
|
||||
@ -2792,6 +2836,7 @@ LV2World::LV2World()
|
||||
auto_can_write_automatation = lilv_new_uri(world, LV2_AUTOMATE_URI__can_write);
|
||||
auto_automation_control = lilv_new_uri(world, LV2_AUTOMATE_URI__control);
|
||||
auto_automation_controlled = lilv_new_uri(world, LV2_AUTOMATE_URI__controlled);
|
||||
auto_automation_controller = lilv_new_uri(world, LV2_AUTOMATE_URI__controller);
|
||||
#endif
|
||||
#ifdef HAVE_LV2_1_2_0
|
||||
bufz_powerOf2BlockLength = lilv_new_uri(world, LV2_BUF_SIZE__powerOf2BlockLength);
|
||||
@ -2816,6 +2861,7 @@ LV2World::~LV2World()
|
||||
lilv_node_free(auto_can_write_automatation);
|
||||
lilv_node_free(auto_automation_control);
|
||||
lilv_node_free(auto_automation_controlled);
|
||||
lilv_node_free(auto_automation_controller);
|
||||
#endif
|
||||
lilv_node_free(patch_Message);
|
||||
lilv_node_free(patch_writable);
|
||||
|
Loading…
Reference in New Issue
Block a user