Lua: get IDs from Editor selection

I noticed in the XML that is saved in the project directory that Regions and Locations have an ID associated with them. In poking around the Lua bindings, it looks like you can get the ID of a Region from a Map of all regions, something like:

selectedRegions = Editor:get_selection().regions:regionlist()

for id, region in ARDOUR.RegionFactory:regions():iter() do
    for selected in selectedRegions:iter() do
        if selected:name() == region:name() then
            print(id:to_s() .. " => " .. selected:name())

but the mapping is dependent upon the name – is there a way to get the ID from the selected region more directly instead?

Likewise, if you were doing something similar for location markers:

for location in Session:locations():list():iter() do
    for marker in Editor:get_selection().markers:iter() do
        -- whatever

in this case, I can see looping through the session locations as being necessary because the markers in selection may include both sides of a single range (i.e., and map to a single ID, presumably).

So what’s the right way to get the IDs from these types? (I.e., the same ID that ends up in the XML.)

Yes: :to_stateful():id()

local selectedRegions = Editor:get_selection().regions:regionlist()

for selected in selectedRegions:iter() do
    print(selected:to_stateful():id():to_s() .. " => " .. selected:name())

Not sure about locations/markers. According to the Class Reference, ARDOUR:Location (Session:locations()) has an id() method but I can’t see any way to get an ID from an ArdourUI:ArdourMarker (Editor:get_selection().markers).


That’s super helpful.

Re: markers – I think it makes sense, actually, because as I understand it, a marker is not the same as a location, in the sense that it could represent one side of a range. I’m not at my computer, but my recollection is that locations always have a start and end, even if it’s the same instant.

So there must be a way to map the selected marker to one of the Session:locations() that is more reliable than the start/end instants. I’m saying this because it seems to me that you could have locations/ranges that overlap. So perhaps the locations have a way to provide access to their current markers, and then those could be matched up?

I didn’t realize there was a class reference in the documentation! I’ve been digging through the source :frowning:

Ignoring location/mark selection for a moment, I am noticing that the id from the Location interface is not producing the same id I see in the .ardour XML, which I assume is the “database” (what persists the state of the project). What the Lua script editor displays is:

local iter = Session:locations():list():iter()

for l in iter do
    print(l:id():to_s() .. " => " .. l:name() .. " => " .. l:start())
94154273062912 => session => 0
94154273062912 => 20230514x => 9261145
5703716569088 => mark1 => 15058645

whereas the XML looks like this

    <Location id="11646" name="session" start="0" end="22330609" flags="IsSessionRange" locked="0" position-lock-style="AudioTime" timestamp="1684000014"/>
    <Location id="12895" name="20230514x" start="9261145" end="9261145" flags="IsMark" locked="0" position-lock-style="AudioTime" timestamp="1684073651"/>
    <Location id="16078" name="mark1" start="15058645" end="15058645" flags="IsMark" locked="0" position-lock-style="AudioTime" timestamp="1684093954"/>

First, the first two ids coming from the Lua script are the same – even though they are different in every way. But regardless the ids are not the same as the ids that end up in the XML. What id is this, and how do I get the same id as what’s in the XML (so that I can map between them)?