summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-06-05 14:44:54 +0200
committerRobin Gareus <robin@gareus.org>2016-06-05 14:44:54 +0200
commit37b90c2a9eecbb97e4bbe16634272849be6b4e9f (patch)
treed9296aacda80147a008776d1d6e8399f35d4d665 /libs/ardour
parentb4a020cdf57107d44fabd983b6c4074da2eb519e (diff)
refine self-automating plugin interface
* thin automation at end * allow plugins to disable its internal write state (ctrl port) * Debug messages
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/debug.h1
-rw-r--r--libs/ardour/ardour/lv2_extensions.h1
-rw-r--r--libs/ardour/ardour/lv2_plugin.h3
-rw-r--r--libs/ardour/debug.cc1
-rw-r--r--libs/ardour/lv2_plugin.cc52
5 files changed, 54 insertions, 4 deletions
diff --git a/libs/ardour/ardour/debug.h b/libs/ardour/ardour/debug.h
index f8e8bfa5e0..41935087bd 100644
--- a/libs/ardour/ardour/debug.h
+++ b/libs/ardour/ardour/debug.h
@@ -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;
diff --git a/libs/ardour/ardour/lv2_extensions.h b/libs/ardour/ardour/lv2_extensions.h
index d49846c8fd..e299b0864a 100644
--- a/libs/ardour/ardour/lv2_extensions.h
+++ b/libs/ardour/ardour/lv2_extensions.h
@@ -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"
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h
index 34e68fdc7f..6552e40ac3 100644
--- a/libs/ardour/ardour/lv2_plugin.h
+++ b/libs/ardour/ardour/lv2_plugin.h
@@ -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;
diff --git a/libs/ardour/debug.cc b/libs/ardour/debug.cc
index 4f204f9a2b..4dd7714812 100644
--- a/libs/ardour/debug.cc
+++ b/libs/ardour/debug.cc
@@ -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");
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index ca0a5b45e3..1244d29366 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -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, &parameter,
+ _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);