Lua: How to get/set Playhead (among other beginner questions)

I do not intend to complain about the great possibilities Ardour offers! But getting started with Lua scripting is kinda strange IMHO… Maybe this thread can help other beginners too…

The https://manual.ardour.org/lua-scripting/class_reference/ is of course a great overview, but raises a lot of questions because the functions are not explained (or do I miss something?). Many things sound self-explanatory, but for many things I have no clue what they do…

So I think I wanna start easy, using Lua in a “macro”-fashion, kinda GUI-oriented, saving me a few clicks for repeated tasks… Therefore the list I found at http://mixbus.harrisonconsoles.com/forum/thread-4332.html seems very handy… But again, many functions have to be guessed…

Could you please help me with:

  • How do I get and set the position of the playhead to a certain position/sample?
  • What does the “alternate” mean in stuff like “Common/alternate-add-location-from-playhead”?
  • What is “Editor/edit-to-playhead”?
  • What is the edit-cursor, like in “Editor/edit-cursor-to-next-region-end”?

Thanks a lot for your kind support!
al

partial reply:

  • the edit cursor no longer exists
  • edit-to-playhead no longer does anything, since it used to move the edit cursor
  • ignore any actions with “alternate-” in their name

Querying the position is easy: local playhead_is_at = Session:transport_frame (), and
moving around is also relatively straight forward: In Ardour 5 it is simply:

Session:request_locate(target_position_in_samples)

However the API will change with Ardour 6!

Nomenclature has been changed throughout libardour. “Frame” now only refers to timecode and video frames. Audio position is indicated in “Samples”.

The transport position is local playhead_is_at = Session:transport_sample (), and the locate API has two two options: (1) what happens after the locate, and (2) the context that requests the change (relevant when timecode masters are used). e.g.

Session:request_locate (target_pos, ARDOUR.LocateTransportDisposition.MustStop, ARDOUR.TransportRequestSource.TRS_UI)

Editor actions are separate (also keep in mind that those are only available if there is an Editor. They have no effect for commandline scripts without):

The “-alternate” options were to allow many different key-bindings for the same action. As Paul already said, ignore them.

Mistake in my post. edit-to-playhead still exists, but replaces the removed concept of the “edit cursor” with something else. It will move the playhead to the first selected marker, if one exists.

In fact, in general if you come across the concept of “the edit cursor” in any documentation you can semantically replace it with “the first selected marker”.

I found the lua docs a little confusing at first too.
My tips are: Use the example scripts in the Ardour repo as a guide and get on the IRC chat and ask for help.

And be prepared to try things and have them not work and then report the bug and have it fixed in A6 :slight_smile:

Thank you very much for your kind help!

Next question: Why do I get different results when executing multiple commands from one script, compared to executing them one command per script, multiple scripts after another? Is there some kind of “flush” I miss…?

Example: I’ve got two overlapping regions, I wanna end up with the playhead set to where the first region ends. I thought straight forward: Select the second region, move playhead to beginning of this selected region, then move playhead to next region end. This should be the end result:

I do it something like this:

Session:request_locate(selected_region:position())
Editor:access_action(“Editor”,“playhead-to-next-region-end”)

It works perfectly well when executing the commands one by one (one command per script run), but done in one script together, the playhead ultimately ends up at the next region seen from where it was located before the script started (as if the first request_locate didn’t happen before).

What basic concept do I miss here?

is processed asynchronously.

The GUI asks the realtime thread to locate. A request is sent, and it is processed at a later time by the engine. It usually takes one process cycle to have effect.

A crude workaround would be to wait a bit after the request_locate call e.g.
ARDOUR.LuaAPI.usleep(500000) stalls half a second, and only then call ‘playhead-to-next-region-end’.

PS. Is there a reason why you don’t directly iterate over regions in the current playlist and locate to the region’s end?

I accept crude workarounds… :wink:

Honestly, thanks for your clarification. Of course you are right, I am new to real time asynchronous programming and didn’t think about that…

Well, but how do you do simple “macro”-like tasks then at all? You need reliable sequential execution for that…!?

My idea was to create crossfades at the click of a button: select overlapping region(s), and let the small script crossfade them for the length of the overlap:

from
grafik
to
grafik

The raw core of the script would be something like:

– move playhead to begin of selection (Ardour 5 command)
Session:request_locate(selected_region:position())

– move playhead to next region end
Editor:access_action(“Editor”,“playhead-to-next-region-end”)

– set-fade (to Edit Point)
Editor:access_action(“Region”,“set-fade-in-length”)

– move playhead to next region start
Editor:access_action(“Editor”,“playhead-to-next-region-start”)

Editor:access_action(“Region”,“set-fade-out-length”)

Of course this is brute-force and not at all bullet-proof and needs “optimal conditions” to work correctly, but does work well enough for my needs (apart from the asynchronicity problem).

Thank you so much for better suggestions!

Even after hours of playing around with this “GUI-based” approach, it is still a mess. I don’t quite get why, because the commands work perfectly well when executed one after another (one command per script run), but when put into one script run, “playhead-to-next-region-end” doesn’t seem to care about the previously repositioned playhead at all - no matter how much “sleep”-time used in between the commands. Even if I send it to sleep for five whole seconds after each and every command, it still doesn’t use the expected playhead positions… I give up here…

So anyways, I’ll have to try a more scripting-oriented approach (without goofing around with these GUI-functions). Next question arises: What would be the command to set the fade-ins/-outs of a region? The class reference only talks about using and showing the fades, but not setting their fade lengths…?

Thanks again!

I’ve only just added those bindings. So you’ll need Ardour 6 >= 6.0-pre0-3627.

We don’t just expose the API without writing an example script to exercise the Lua bindings. So this is an iterative process. Example: https://github.com/Ardour/ardour/blob/master/share/scripts/s_set_region_fades.lua

1 Like

That is amazing! I’ll wait for Ardour 6 stable though, because of limitations in my time budget… I’m really looking forward to it and will report back here with my solution then… :wink:

Thanks again for all your fantastic hard work, and the unbelievably kind way to treat even the most basic beginner questions with utmost dignity and patience!

@x42 : excuse me to ask this question here as I dont feel to open a new topic for it : is there a lua binding that open a plugin ( fx or instrument ) ui?

Thanks