m1gin 1234

I use Ardour to create podcast. Most of the times I need to shift all the regions in all tracks next to the selected one. Even though Ardour give us the chance to shift all regions in the same track, it doesn't have an option for all the tracks.

I was using Wavelab before and it has two options for that called as "Track auto-grouping" and "Global auto-grouping".

I tried to find similar feature in Ardour for "Gloabl auto-grouping". I spend so much time but I couldn't find an easy option for that.

Here are the steps I do every time to change the positions of all the next regions of a point.

  1. I select a region
  2. Press Ctrl + Shift + E to select all regions after edit point. If there are selected overlapped regions in other tracks they will be also selected.
  3. I do Ctrl + Click to deselect the regions I don't want to move.
  4. I press mouse down and shift the selection to the desired point.

This is really so tiresome, specially if you have so many regions need to be moved.

Today I realized Ardour 6 is relaesed. With a big hope I wanted to look if they developed such a feature or not.
I installed Ardour 6 and started to examine it. But I couldn't find something for what I was hoping.

Since Ardour have the ability to use some LUA scripts, I started to think about it. I know nothing about Ardour LUA scripting. Maybe I can learn things and develop my own script for such feature.

And this page will hold my notes about what I will learn about Ardour scripting.


Get the names and positions in session and start sample in original source, full path of selected regions:

-- Region selection
-- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:RegionSelection

local sel = Editor:get_selection ()
for r in sel.regions:regionlist ():iter () do
-- each of the items is a
-- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:Region
print ("Region:", r:name (), r:position (), r:start ())

print( r:isnil(), r:to_stateful ():id (), r:source(0):ancestor_name ())
print( r:source(0):to_filesource ():path(), r:whole_file () )
end

Get selection range:

-- The total time extents of all selected regions and ranges
local ok, ext = Editor:get_selection_extents (0, 0)
if ok then
print ("Selection Extents:", ext[1], ext[2])
else
print ("No region or range is selected")
end


  • Session:get_tracks ()

After a couple hours, it looks like I succeeded to develop a script that does the job. Hurray!

I wonder if it is possible to assign a hotkey for this script to make it run. I will try to dig for that after taking some rest. :)

Assigning a hotkey to the script is also possible!
To be able to do that, load the script in Script Manager and assing a hotkey in Keyboard Shortcus window.

ardour {
["type"] = "EditorAction",
name = "mb_SelectAllNextRegions",
author = "mim.mbirgin.com",
description = [[Select all regions after selection.]]
}


function factory () return function ()
local ok, ext = Editor:get_selection_extents (0, 0)

local start_pos = 0;
if (ok) then
print(ok)
start_pos = ext[1]
--end_pos = ext[2]
-- print ("Selection Extents:", ext[1], ext[2])
end
print("start_pos:", start_pos)


local sl = ArdourUI.SelectionList () -- empty selection list

local sel = Editor:get_selection () -- get current selection
-- for each selected track/bus..
for route in Session:get_tracks ():iter () do
-- consider only tracks
local track = route:to_track ()
if track:isnil() then
goto continue
end


-- iterate over all regions of the given track
for region in track:playlist():region_list():iter() do
print(region:name(), region:position());
if (region:position () < start_pos) then
-- skip regions before the start point.
else
-- get RegionView (GUI object to be selected)
local rv = Editor:regionview_from_region (region)
-- add it to the list of Objects to be selected
sl:push_back (rv);
end
end
::continue::
end

-- set/replace current selection in the editor
Editor:set_selection (sl, ArdourUI.SelectionOp.Set);
end end

m1gin 0

Works for mono tracks. For stereo tracks only one channel will be used.

Export Selected Regions

ardour { ["type"] = "EditorAction", name = "mb:ExportSelectedRegions",
license = "MIT",
author = "mbirgin",
description = [[Export selected regions to be able to import in another session]]
}

function factory (params) return function ()
-- there is currently no direct way to find the track
-- corresponding to a [selected] region
function find_track_for_region (region_id)
for route in Session:get_tracks():iter() do
local track = route:to_track();
local pl = track:playlist ()
if not pl:region_by_id (region_id):isnil () then
return track
end
end
assert (0); -- can't happen, region must be in a playlist
end

-- get selection
-- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:Selection
local sel = Editor:get_selection ()

-- prepare undo operation
Session:begin_reversible_command ("Export Selected Regions")
local add_undo = false -- keep track if something has changed

local proc = ARDOUR.LuaAPI.nil_proc () -- bounce w/o processing -- mb

tmpfile="/tmp/mb_ardour.tsv"
file = io.open(tmpfile, "w")
-- Iterate over Regions part of the selection
-- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:RegionSelection
for r in sel.regions:regionlist ():iter () do

local track = find_track_for_region (r:to_stateful():id())
local playlist = track:playlist ()


file:write(r:position (), "\t", r:length (), "\t", r:source(0):to_filesource ():path (), "\n")

-- print(r:position(), r:length())
print ("Region:", r:name (), r:position ())
print( r:isnil(), r:to_stateful ():id (), r:source(0):ancestor_name ())
print( r:source(0):to_filesource ():path(), r:whole_file () )

end
file:close()


end end


Import to Selected Track:


ardour { ["type"] = "EditorAction", name = "mb:ImportRegions",
license = "MIT",
author = "mbirgin",
description = [[Import previously exported regions]]
}

function factory (params) return function ()


local tmpfile = '/tmp/mb_ardour.tsv'

-- 3. Parse the data to a key-value table (specify a key for each column):
local keyTable = {}
for line in io.lines(tmpfile) do
local a,b,c = line:match("(.-)\t(.-)\t(.*)")
print(a, b, c)
keyTable[#keyTable + 1] = { ["pos"] = a, ["len"] = b, ["path"] = c}
end
print(keyTable)


for idx, t in pairs(keyTable) do
local files = C.StringVector()

print(idx, t)
print(t.path)
files:push_back(t.path)
Editor:do_import (files, Editing.ImportDistinctFiles, Editing.ImportToTrack, ARDOUR.SrcQuality.SrcBest,
ARDOUR.MidiTrackNameSource.SMFTrackName, ARDOUR.MidiTempoMapDisposition.SMFTempoIgnore, t.pos, ARDOUR.PluginInfo())
end

-- files:push_back("/home/m1/sil/music/141018-133622.WAV")

-- Editing.ImportAsRegion
-- Editing.ImportToTrack
-- Editing.ImportAsTrack

-- local pos = Session:transport_sample ()
-- Editor:do_import (files,
-- Editing.ImportDistinctFiles, Editing.ImportToTrack, ARDOUR.SrcQuality.SrcBest,
-- ARDOUR.MidiTrackNameSource.SMFTrackName, ARDOUR.MidiTempoMapDisposition.SMFTempoIgnore,
-- pos, ARDOUR.PluginInfo())

-- set to clipboard
-- os.execute("echo say something | xclip -selection clipboard")

end end


It looks like it is possible to embed/link a file without copying it into the session..

Editor:do_embed (files, Editing.ImportDistinctFiles, Editing.ImportToTrack, t.pos, ARDOUR.PluginInfo())


m1gin 0

And finally I have created a python script to copy playlists between Ardour sessions. It works for mono and stereo regions. 

The code can be found on Github

m1gin 0

Get Track ID of all tracks in a session

objs = Session:get_routes ()
print(objs:size())

for it in objs:iter() do
print (it:to_track ():playlist():get_orig_track_id():to_s () )
end

Get Regions info

objs = Session:get_routes ()
print(objs:size())

for it in objs:iter() do
rl = it:to_track ():playlist():region_list ()

for r in rl:iter() do
print("--------")

for source in r:master_sources():iter() do
print(source)
end

print(r:name(), r:length ())
print ("Region:", r:name (), r:position (), r:start ())
print( r:isnil(), r:to_stateful ():id (), r:source(0):ancestor_name ())
print( r:source(0):to_filesource ():path(), r:whole_file () )
end
end

Add to: