I recently posted a Lua script which automates bouncing MIDI Instrument tracks to audio tracks (MIDI Track freeze), which - so far - worked fine for me, but I’m trying to enhance some points and make it more flexible. On my way, tried to encapsulate the two main processes (“freeze” and “unfreeze”) inside functions.
Now I get the following issue:
Inside the freeze()
function, there’s a line, that creates a new audio track and a second one, that gets the playlist for that audio track to put in the bounced audio region.
-- Create new audio track for bounced audio
local freezeTrack = Session:new_audio_track (output_count, output_count, nil, 1, audioTrackname, order, ARDOUR.TrackMode.Normal, true)
-- Get playlist for new audio track
local playlist = freezeTrack:front():playlist()
This worked fine in my old script, but encapsuled inside a function I get an error message regarding shared pointer is nil
whenever I …
- freeze a track
- unfreeze the same track again
- select the SAME track again, and.
- …try to freeze it once again
Here’s a gif, to demonstrate, what I mean:
Okay, I know, that this is not a usual process, but it should work though.
Any hints on, how to solve that?
PS:
Here’s the full script:
ardour {
["type"] = "EditorAction",
name = "MIDI Track Freeze | Unfreeze 3 TEST",
author = "Toxonic",
license = "MIT",
description = [[This script is supposed to provide a "Track Freeze" function for MIDI Tracks, as you can find in severeal well-known DAWs. The goal is, to save CPU ressources in projects with many MIDI instrument tracks, while they don't need to be edited. The contents of these tracks can be "frozen" (bounced) to an Audio track with a special Prefix ('*** ') In a next step, the 'source' MIDI Track gets deactivated and hidden in the track view. If you need to edit it again, you can 'unfreeze' the track again by selecting the Audio-Freeze-Track and run the script again. The Audio-Freeze-Track will then be removed and the MIDI Track will be re-activated and unhidden.]]
}
function factory (unused_params)
return function ()
-- Set up variables
local selCount = Editor:get_selection().tracks:routelist():size() -- Number of selected routes
local get_route = Session:route_by_selected_count(0) -- Get the (first) selected route
local track = get_route:to_track() -- Cast the selected route to a track
local groups = Session:route_groups() -- Variable containing all route groups
-- INFO MESSAGES FUNCTION
function dialog (text)
LuaDialog.Message ("Information", text, LuaDialog.MessageType.Info, LuaDialog.ButtonType.Close):run ()
end
-- FREEZE FUNCTION
function freeze ()
-- Set up necessary variables to go on
local order = get_route:presentation_info_ptr():order() -- Get order number of MIDI track
local output_count = get_route:n_outputs():n_audio() -- Get audio output channels # of MIDI Track to freeze
local audioTrackname = "*** ".. get_route:name() -- Audio trackname with "*** "-prefix
-- Bounce full MIDI track to audio
track:bounce(ARDOUR.InterThreadInfo (),audioTrackname)
-- Deactivate MIDI track
get_route:set_active (false, nil)
-- Hide MIDI track
local rtav = Editor:rtav_from_route(get_route)
Editor:hide_track_in_display (rtav:to_timeaxisview(), false)
-- Create new audio track for bounced audio
local freezeTrack = Session:new_audio_track (output_count, output_count, nil, 1, audioTrackname, order, ARDOUR.TrackMode.Normal, true)
-- Get playlist for new audio track
local playlist = freezeTrack:front():playlist()
-- Get regions of this session to import "frozen" audio region
local rl = ARDOUR.RegionFactory.regions()
local reg_at = 0
local reg_id
-- Iterate over them
for id, region in rl:iter() do
-- Check regions for a specific name...
if region:name() == audioTrackname then
-- ... if it's a match, save ID of the region until the most current version of the frozen" audio region
if math.max(reg_at, tonumber(id:to_s())) == tonumber(id:to_s()) then
reg_at = tonumber(id:to_s())
reg_id = id
end
end
end
-- ..add the corresponding region to the playlist...
playlist:add_region (rl:at(reg_id), Temporal.timepos_t(0), 1, false)
--[[ If a Multiout-Instrument-Track selected, connect all outputs of the new Freeze-Audio-Track to the inputs of the group-tracks
local m_route = Session:route_by_name(audioTrackname)
local m_track = m_route:to_track()
local groups = Session:route_groups()
local i = 0
for x,y in groups:iter() do
if x:name() == get_route:name() then
print("Multitrack")
for a,b in x:route_list():iter() do
m_track:output():connect(m_track:output():nth(i), a:to_track():input():nth(0):name(), nil)
print(a:to_track():input():nth(0):name())
i = i+1
end
end
end --]]
end
-- END OF FREEZE FUNCTION
-- UNFREEZE FUNCTION
function unfreeze()
-- Set up necessary variables
local midiTrackname = string.gsub(get_route:name(),"*** ","")
local midiTrack = Session:route_by_name(midiTrackname)
-- Remove the freeze-Audio track
Editor:access_action("Editor", "remove-track")
-- Activate the MIDI source track ...
midiTrack:set_active (true, nil)
-- ...and make it visible again
local rtav = Editor:rtav_from_route(midiTrack)
Editor:show_track_in_display (rtav:to_timeaxisview(), false)
end
--END OF UNFREEZE FUNCTION
--[[*********** MAIN ************]]--
-- Stop playback
if Session:transport_stopped() == false then Session:request_stop(false, false, 0)
end
-- Check if selection is valid for "freezing"
if selCount < 1 then dialog("No track selected.\n\nPlease select a MIDI track to freeze or a valid Audio-Freeze-Track to unfreeze (Prefix '*** ').")
do return end
elseif selCount > 1 then
dialog("Multiple tracks selected.\n\nPlease select a MIDI track to freeze or a valid Audio-Freeze-Track to unfreeze (Prefix '*** ').")
do return end
-- Check if selection is valid for "unfreezing""
elseif selCount == 1 and get_route:data_type():to_string() == "audio" then
if string.sub(get_route:name(),1,4) ~= "*** " then
dialog("This Audio track is not a valid Audio-Freeze-Track.\n\nPlease select an Audio-Freeze-Track with the prefix '*** ' to proceed with unfreezing")
do return end
end
end
--[[*********** unfreeze action ************]]--
if selCount == 1 and get_route:data_type():to_string() == "audio" and string.sub(get_route:name(),1,4) == "*** " then
unfreeze() -- If selection is valid, call unfreeze() function
--[[*********** freeze action ************]]--
elseif selCount == 1 and get_route:data_type():to_string() == "midi" then
freeze() -- If selection is valid, call freeze() function
end
end
end