-- Version 1.0
--
-- This script toggles FX online/offline, FX bypass, and track lock on
-- all selected tracks.
--
-- SWS cycle actions can be used for toggling only online and lock, but
-- not if you also want to include FX bypass.

-- SWS is required (http://www.sws-extension.org/)
--
-- Released to the public domain.

-- Select (1) or unselect (0) the given tracks.
function setSelected(tracks, selected)
    for i, track in ipairs(tracks) do
        reaper.SetMediaTrackInfo_Value(track, "I_SELECTED", selected)
    end
end

function main()
    -- Determine which tracks need to be unlocked and brought online.
    -- Any track with FX bypassed qualifies.
    numSelected = reaper.CountSelectedTracks(0)
    needUnlock = {}
    for idx = 0, numSelected - 1 do
        track = reaper.GetSelectedTrack(0, idx)
        if reaper.GetMediaTrackInfo_Value(track, "I_FXEN") <= 0 then
            needUnlock[#needUnlock+1] = track
        end
    end

    reaper.Undo_BeginBlock2(0)
    -- Unlock all tracks initially.
    -- Track: Unlock track controls
    reaper.Main_OnCommandEx(41313, 0, 0)
    -- Track: Toggle all FX online/offline for selected tracks
    reaper.Main_OnCommandEx(reaper.NamedCommandLookup('_S&M_FXOFFALL'), 0, 0)
    -- Track: Toggle FX bypass for selected tracks    
    reaper.Main_OnCommandEx(8, 0, 0)    

    -- Now we need to lock the tracks that have been offlined.  Unfortunately
    -- there is no API for doing this on individual tracks.  The best we can do
    -- is invoke an existing action.  So, here we unselect all tracks that need
    -- to stay unlocked, invoke the "lock track controls" action, and then reselect
    -- the temporarily unselected tracks.
    if #needUnlock < numSelected then
        setSelected(needUnlock, 0)
        -- Track: Lock track controls
        reaper.Main_OnCommandEx(41312, 0, 0)    
        setSelected(needUnlock, 1)
    end
    reaper.Undo_EndBlock2(0, "Toggle FX online/bypass/lock for selected tracks", -1)    
end

main()
