Set Loop In / Set Loop Out using the current playhead position

Created with the help of Claude…

Summary

“Set Loop In/Out” (Transport → Looping → Set Loop In/Out) always opens a dialog requiring both the loop-in and loop-out times to be typed in manually. There’s no way to set either value to the current playhead/cursor position without reading the time off the transport clock and re-entering it digit by digit.

Current behavior

PlaybackController::setLoopRegionInOut() pre-fills both dialog fields from the existing loop region, not the playhead:

// src/playback/internal/playbackcontroller.cpp
void PlaybackController::setLoopRegionInOut()
{
    PlaybackRegion region = player()->loopRegion();

    muse::UriQuery loopRegionInOutUri("audacity://playback/loop_region_in_out");
    loopRegionInOutUri.addParam("title", muse::Val(muse::trc("trackedit", "Set looping region in/out")));
    loopRegionInOutUri.addParam("start", muse::Val(static_cast<double>(region.start)));
    loopRegionInOutUri.addParam("end", muse::Val(static_cast<double>(region.end)));
    ...
}

The dialog itself (LoopRegionInOut.qml) uses the same segmented, digit-by-digit Timecode/NumericView widget used elsewhere in the app for timecode entry. That widget has no clipboard paste handling, so there’s also no quick copy-from-elsewhere-and-paste workaround - each field has to be typed by hand.

Desired behavior

A way to set the loop-in and/or loop-out point to wherever the playhead currently is, without manually reading and re-typing a timecode. For example:

  • A “Set Loop In to Playhead” / “Set Loop Out to Playhead” pair of commands (bindable to their own keyboard shortcuts, since neither has a default shortcut today), that set one edge of the loop region to playbackState()->playbackPosition() immediately, leaving the other edge untouched - similar in spirit to how a punch-in/punch-out point is set in most DAWs.
  • Alternatively/additionally, a button or field-level action inside the existing Set Loop In/Out dialog that fills the focused field from the current playhead position, for people who prefer the dialog workflow.

Why this matters

Looping a specific stretch of a long recording to review it repeatedly (e.g. while doing accuracy/QA passes on transcription or diarization output) is much easier when you can just park the playhead where you want a boundary and hit one key, rather than pausing, reading the transport clock, opening a dialog, and typing the exact time into a segmented field twice (once for in, once for out).

Precedent already in the codebase

The capability to read the live playhead value directly already exists and is used elsewhere - it just isn’t wired up for the loop-in/out dialog. TrackeditActionsController::selectLeftOfPlaybackPos() / selectRightOfPlaybackPos() (src/trackedit/internal/trackeditactionscontroller.cpp) both call playbackState()->playbackPosition() directly to set one edge of a selection to the current playhead. The same pattern would work for the loop region.

Suggested implementation sketch

Add two new dispatcher actions (e.g. set-loop-in-to-playhead, set-loop-out-to-playhead) alongside the existing set-loop-region-in-out action in trackeditactionscontroller.cpp / playbackcontroller.cpp, each reading playbackState()->playbackPosition() and calling player()->setLoopRegion({...}) with only the relevant edge replaced - no dialog involved. Register them in shortcuts.xml (currently unbound, like set-loop-region-in-out itself) and add corresponding menu items under Transport → Looping.

Environment

  • Audacity version: 3.7.8
  • OS: Windows

Entering digits not necessary : select a region to loop, then press L …

“Click Loop, or it’s shortcut L, to set a looping region. When you use it the first time, it’ll set your current selection to the looping region”.

https://manual.audacityteam.org/man/playing_and_recording.html

The issue is I’d like to set the start/end loop points independently…