I am trying to write CC automation data to a MIDI region via a Lua script with full undo support. I was looking into the midi_cc_to_automation.lua and lfo_automation.lua scripts bundled with Ardour for guidance. I am already able to delete stuff from an existing midi region’s cc parameters via midi_region:control (EvoralParameter (...)): list() and its methods, but I struggle to add undo support for the script (the Control type’s list() doesn’t have a get_state() method).
The scripts linked above use the plugin_automation() utility function of the track the region in question belongs to to get access to an AutomationControl type which offers undo/redo functionality via the get_state() method, but I struggle to find an equivalent for generic MIDI CC automation.
but this only results in a shared_ptr is nil error.
I guess that I might have not yet fully grasped the scripting interface, and guess that I am likely poking at the wrong end. Can anybody tell me what to do in order to achieve what I want?
Ardour’s GUI shows MIDI CC events in a similar way as parameter automation, even though these are MIDI events in a MIDI region.
There is no automatable control port for MIDI. To add/remove CCs, you have to edit the MIDI region of the given track, using the control-list of the MIDI region.
local sel = Editor:get_selection ()
for r in sel.regions:regionlist ():iter () do
local mr = r:to_midiregion ()
if mr:isnil () then goto next end
local midi_channel = 0 -- MIDI channel [0 .. 15]
local cc_param = 1 -- CC-1 (modulation) [0 .. 127]
local ec = mr:control (Evoral.Parameter (ARDOUR.AutomationType.MidiCCAutomation, midi_channel, cc_param), true)
if ec:isnil () then goto next end
local cl = ec:list (); -- get control list for control
-- specify time in samples, here two points at 0, at 48000, converting them to MIDI beat-unit:
local bfc = ARDOUR.DoubleBeatsSamplesConverter (Session:tempo_map (), r:start ())
cl:editor_add (bfc:from (0 + r:start ()), 1, false)
cl:editor_add (bfc:from (48000 + r:start ()), 127, false)
::next::
end
At this point in time it is not possible to save an undo command, I’ve just git pushed a call to cast the ControlList into an AutomationList so that this will be possible staring with the next relase like this:
local al = cl:to_automationlist();
local before = al:get_state() -- save previous state (for undo)
-- ...
cl:editor_add (bfc:from (0 + r:start ()), 1, false)
-- ...
Session:begin_reversible_command ("Edit CC")
Session:add_command (al:memento_command(before, al:get_state()))
Session:commit_reversible_command(nil)
Thank you very much, Robin, for adding adding the cast to AutomationList! I’m looking forward to the next release. Until then I can live without undo when altering MIDI regions via Lua scripting.