Lua: removing a region from the sources

How can I remove all regions with a specific name from the sources with Lua?
I found the method remove_region() but it seems that I can’t apply that when iterating through ARDOUR.RegionFactory.regions() .
Actually I have the following lines:

local trackname = Session:route_by_selected_count(0):name()
local regionName = "*** "..trackname

-- Get regions of this session 
local rl = ARDOUR.RegionFactory.regions()

-- Iterate over the regionlist
for _, r in rl:iter() do  
  
      -- Check each region if it matches a specific name...
      if r:name() == regionName then 

      -- ...and delete it, if condoition is true
      -- HERE SHOULD HAPPEN THE REMOVAL OF 'r'

      end
end

Any ideas would be appreciated! :slight_smile:

What exactly do you mean by removing a region from “the sources”? Maybe describe it as what you would do manually in the gui.

Hey and thank you for your reply! :slight_smile:
I mean the “Sources” tab in the Editor List on the right side of the main window, when “View” → “Show Editor List” is enabled.

Generally speaking you cannot do that. Ardour is non-destructive. Once a file is on disk it will not be modified or deleted.

It is possible to “cleanup unused sources”, but that requires user interaction and cannot be done directly from a script. You can however initiate this from Lua by calling

Editor:access_action ("Main", "CleanupUnusedSources")
1 Like

Hmm… when i overthink it all, there could be a workaround for my problem.

In the code, i postet above, i use a generic for-loop. If i wanted to add the last region with a specific name in the regionlist to a new track, a numeric for-loop would be the way to go i guess )so i could iterate in reverse direction over the list), but i don’t know how to index the regionlist…!?
I thought of something like this:

local rl = ARDOUR.RegionFactory.regions()

for i=rl:size(),1,-1 do 
-- check if element 'i' in 'rl' matches a predefined string and add to playlist of a track
end

How can I index element ‘i’ in ‘rl’?
Okay, i’m afraid, i expressed myself very awkwardly… hope you got me though! :wink:

Where “r” is the route in question…

local rl = r:to_track():playlist():region_list()
local lastRegion = rl:table()[rl:size()]

--test
print(lastRegion:name())

:table() gets the regions as a table. It seems that they are ordered in that table by their start location, so the last table element will be the latest start region, which I guess is “last region” in that sense, but not necessarily the latest-ending region if there are overlapping regions in there.

That script isn’t checking things like: is this a track (not a bus) and does it even have any regions?

Hey and thank you for your reply! :slight_smile:
Indeed, this works, as long, as I apply this for the regions of a track, but i want apply this on the regions inside the Sources tab. The table() method is available for ARDOUR.RegionFactory:regions() too, but for some reason it won’t work like expected there. I guess, this has got something to do with the fact, that ARDOUR.RegionFactory:regions() returns a RegionMap, but I don’t exactly know what that is.
For example, while this here works on a selected track…

local r = Session:route_by_selected_count(0)
local rl = r:to_track():playlist():region_list()

for i=rl:size(),1,-1 do
local region_by_index = rl:table()[i]
print(region_by_index:name()) 
end

… this code doesn’t work for the RegionsFactory:

local rl = ARDOUR.RegionFactory:regions() 

for i=rl:size(),1,-1 do
local region_by_index = rl:table()[i]
print(lastRegion:name()) 
end

I can’t seem to figure out, how to do that for the RegionFactory. :frowning:

EDIT: I tried the following code…

local rl = ARDOUR.RegionFactory:regions()

local tablek = rl:table()
for x,i in pairs(tablek) do print(i:name())
end

which somehow works, but this is again a generic for-loop, so i have no option to invert the loop direction. But what is strange at that code is, that the order of the printed elements change in an odd random behavior each time I run that code.

Looking at the source code, the keys in ARDOUR.RegionFactory:regions():table() are PBD:ID objects (the id of the region, presumably) not table indexes (numbers). So no, something like rl:table()[i] won’t work if i is an index number.

The following is iterating the RegionFactory regions, if that’s of any help.

local rl = ARDOUR.RegionFactory:regions()
for id, region in rl:iter() do
  print(id:to_s(), " --> ", region:name())
end

It’s basically the same as iterating the :table() instead…

local rl = ARDOUR.RegionFactory:regions():table()
for id, region in pairs(rl) do
  print(id:to_s(), " --> ", region:name())
end

…but pairs() can’t be relied upon for any kind of sorted order. ipairs() can but only works for tables that have numbers for its keys, which this doesn’t.

The first script seems to be iterating in ascending order of the ID. The second way is pretty much random, as is often the case with pairs().

“If i wanted to add the last region with a specific name in the regionlist …”

What exactly do you mean by “last region”? Most recently created? Latest start on the timeline?

Thank you for your reply! :slight_smile:
Yeah, I mean the most recently created version, which seems to be the last occurance of it, when iterating over the regions, but also the one with the highest ID. I didn’t even know about the to_s()method, which helps to find the highest ID.
I tried to save the highest ID to a variable (reg_at) in the following code, which works fine as long as I run it inside Ardours scripting window:

		            -- Get regions of this session to import "frozen" audio region
                    local rl = ARDOUR.RegionFactory.regions()

			        -- 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:to_s(), id:to_s()) == id:to_s() then reg_at = id  end  

				        end

			        end

For some reason, the script doesn’t work anymore, when i assigned it to a button inside Ardour,… (EDIT: However, after restarting the test project it seems now to work fine) … so I remained on using the last occurance of the region in the for-loop, which also works fine, when assigned to a button so far:

-- Get regions of this session to import "frozen" audio region
                    local rl = ARDOUR.RegionFactory.regions()

			        -- 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
                            reg_at = id  

				        end

			        end

Do you have an idea, why the first code doesn’t work, after assigning the script to a button?

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.