Dup Ver Goto 📝

SendSelectedTracksToNamedTracks

To
145 lines, 898 words, 5984 chars Page 'SendSelectedTracksToNamedTracks' does not exist.

1

I found this one at this reddit

There were some comments (copied below) on how it could be improved. One addition I make (mentioned below) is to default the send to -∞ dB, rather than the 0dB that is the default for sends (and I don't want to change that default since it's good for other sends).

local tr_cnt = reaper.CountSelectedTracks( 0 )
local fnd = 0
local sel_tr = {}
local store = {}

  -- add channel selector
  reaper.Undo_BeginBlock2( 0 )
  reaper.PreventUIRefresh( 1 )
  for i = 0, tr_cnt-1 do
    sel_tr[#sel_tr+1] = reaper.GetSelectedTrack( 0, i )
  end

  -- Finding track named Reverb
  for trackIndex = 0, reaper.CountTracks(0) - 1 do
    local tr = reaper.GetTrack(0, trackIndex)
    local _, trackName = reaper.GetSetMediaTrackInfo_String(tr, 'P_NAME', '', false)
    if string.match(trackName, "Reverb") ~= nil then -- Change Reverb for any other string you like
      store[#store+1] = tr
      fnd = fnd+1
    end
  end  
  if fnd == 0 then
    reaper.ShowMessageBox("No tracks with the name Reverb found!", "Error!", 0)
  end

  if fnd == 1 then
    for i = 1, #sel_tr do
      reaper.CreateTrackSend( sel_tr[i], store[fnd] )
    end
  end

  if fnd > 1 then
    local _, nmb = reaper.GetUserInputs("Multiple Reverb Tracks Found, input number:", 1, "number:", 0)
    nmb = tonumber(nmb)
    if _ == true and nmb ~= 0 and nmb <= fnd then
      for i = 1, #sel_tr do
        reaper.CreateTrackSend( sel_tr[i], store[nmb] )
      end
    end
  end

reaper.PreventUIRefresh( -1 )
reaper.Undo_EndBlock2( 0, "Route Selected Tracks to Reverb", 1)

To default send level to -∞ dB

      send_idx = reaper.CreateTrackSend( sel_tr[i], store[fnd] )
      reaper.SetTrackSendInfo_Value( sel_tr[i], 0, send_idx, "D_VOL", 0.0)

One could also put this in a function with the Reverb string a parameter. So we could use the same code to do sends to tracks named Delay.

Comments and Improvement

These comments were made by a [deleted] user on the Reddit linked above.

  1. You're counting how many time you find a track named "Reverb" via the variable fnd as you insert those tracks into an array (store). There's no need to maintain a separate count. That number is part of the array, accessed via #store. You're already using this fact to insert elements into the array; that's what the #store in store[#store+1] = str means. So the fnd variable is superfluous.

  2. string.match(trackName, "Reverb") can be written trackName:match("Reverb").

  3. if blah ~= nil then can be written if blah then. The ~= nil is implicit; that's what true means in Lua.

  4. Regarding _ == true: if _ is equal to true then _ and _ == true produce the same value, so the == true portion is unnecessary.

  5. _ is sometimes used if a value is being discarded, but here the value is actually being used and so should be named.

  6. You only use tr_cnt once, so it doesn't really need to even be stored (matter of taste).

  7. #store > 1 is a superset of #store == 1 and contains duplicate code. You can eliminate the duplication by folding these cases together.

  8. You have a comment indicating where someone can edit the code if they use a different reverb track name. It's easier for a user to find and edit that kind of configuration stuff if you put it to the top of the script.

  9. Naming a variable store is a lot like naming it variable. Yes, we know it stores something, but what does it store? The name should reflect its content. Given that your other variable for storing tracks is called sel_tr (presumably short for selected tracks), you could call this one rev_tr (to maintain the same level of terseness, though I'd probably just call them something like selected and reverb).

  10. There's no feedback for when no tracks are selected.

  11. When you prompt the user to choose which reverb track to send to, you give them a useless default and give no feedback if they type in an invalid option.

  12. If you're iterating through an array using a for i=1,N and you only use i to index the array, you can use the ipairs iterator instead and have a tidier loop body.

  13. If you wrap the body of your script in a function, you can

    1. use early returns to abort and
    2. nicely group the UI/undo handling stuff together.

Improved Version

local reverbTrackName = "Reverb" -- Change for any name you like

function main()
    local sel_tr = {}
    local reverb_tr = {}

    for i = 0, reaper.CountSelectedTracks(0)-1 do
        sel_tr[#sel_tr+1] = reaper.GetSelectedTrack(0,i)
    end

    if #sel_tr == 0 then
        reaper.ShowMessageBox("No tracks selected!", "Error!", 0)
        return
    end

    -- find all reverb tracks
    for trackIndex = 0, reaper.CountTracks(0) - 1 do
        local track = reaper.GetTrack(0, trackIndex)
        local _, trackName = reaper.GetSetMediaTrackInfo_String(track, 'P_NAME', '', false)
        if trackName:match(reverbTrackName) then
            reverb_tr[#reverb_tr+1] = track
        end
    end

    if #reverb_tr == 0 then
        reaper.ShowMessageBox("No tracks with the name " + reverbTrackName + " found!", "Error!", 0)
        return
    elseif #reverb_tr > 1 then
        local ok, nmb = reaper.GetUserInputs("Which reverb track should we send to?", 1, "number:", 1)
        if not ok then
            return
        end
        nmb = tonumber(nmb)
        if nmb < 1 or nmb > #reverb_tr then
            reaper.ShowMessageBox("That's not a valid reverb track.", "Error!", 0)
            return
        end
        reverb_tr[1] = reverb_tr[nmb]
    end

    for i,track in ipairs(sel_tr) do
        reaper.CreateTrackSend( track, reverb_tr[1] )
    end
end

reaper.Undo_BeginBlock2( 0 )
reaper.PreventUIRefresh( 1 )
main()
reaper.PreventUIRefresh( -1 )
reaper.Undo_EndBlock2( 0, "Route Selected Tracks to Reverb", 1)