Last active
May 26, 2020 15:27
-
-
Save jtackaberry/379d7da05b2a696620e0 to your computer and use it in GitHub Desktop.
REAPER script: Toggle visibility of disabled instrument tracks (i.e. tracks with a VSTi that have FX bypassed).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Version 1.2 | |
-- | |
-- This script toggles visibility of all tracks that have a VSTi FX. | |
-- It requires that the FX be prefixed with "VSTi:" (which Reaper | |
-- does do by default). Care is taken to preserve existing TCP/MCP | |
-- visibility when the filter is toggled off. | |
-- | |
-- SWS is required (http://www.sws-extension.org/) | |
-- | |
-- Released to the public domain. | |
SCRIPT_NAME = "toggle_disabled_instrument_tracks" | |
-- If true, ensures all parents (and ancestors) of unfiltered child tracks | |
-- are not filtered. Set this to false if you want to hide parent tracks | |
-- with no MIDI items. | |
PRESERVE_PARENT_FOLDERS = true | |
function isVSTi(track, fxidx) | |
_, name = reaper.TrackFX_GetFXName(track, fxidx, "") | |
return string.sub(name, 0, 5) == "VSTi:" or string.sub(name, 0, 6) == "VST3i:" | |
end | |
function isInstrumentTrack(track) | |
-- Iterate over all FX and look for FX names prefixed with | |
-- "VSTi:" or "VST3i:". We can't use TrackFX_GetInstrument because it skips | |
-- offlined instruments. | |
for fxidx = 0, reaper.TrackFX_GetCount(track) - 1 do | |
if isVSTi(track, fxidx) then | |
return true | |
end | |
end | |
return false | |
end | |
function setTrackVisibility(track, tcp, mcp) | |
if tcp == 0 then | |
-- Unselect the track if it's being hidden | |
reaper.SetTrackSelected(track, false) | |
end | |
reaper.SetMediaTrackInfo_Value(track, "B_SHOWINTCP", tcp) | |
reaper.SetMediaTrackInfo_Value(track, "B_SHOWINMIXER", mcp) | |
end | |
function setTrackFiltering(track, filtered) | |
local guid = reaper.GetTrackGUID(track) | |
local tcp, mcp | |
if filterOn then | |
-- Filter is being enabled. Store current track setting. | |
tcp = reaper.GetMediaTrackInfo_Value(track, "B_SHOWINTCP") | |
mcp = reaper.GetMediaTrackInfo_Value(track, "B_SHOWINMIXER") | |
reaper.SetProjExtState(0, SCRIPT_NAME, guid, math.floor(tcp) .. math.floor(mcp)) | |
if filtered then | |
setTrackVisibility(track, 0, 0) | |
end | |
else | |
-- Filter is being turned off. Restore tcp/mcp setting. | |
exists, state = reaper.GetProjExtState(0, SCRIPT_NAME, guid) | |
--reaper.ShowConsoleMsg(guid .. exists .. " " .. state .. "\n") | |
reaper.SetProjExtState(0, SCRIPT_NAME, guid, "") | |
if exists == 1 then | |
tcp = tonumber(string.sub(state, 1, 1)) | |
mcp = tonumber(string.sub(state, 2, 2)) | |
setTrackVisibility(track, tcp, mcp) | |
else | |
setTrackVisibility(track, 1, 1) | |
end | |
end | |
end | |
function markParents(parents, track, hasVisibleChildren) | |
local parent = reaper.GetParentTrack(track) | |
while parent ~= nil do | |
-- Small optimization: if parent is already known to have | |
-- visible children then there's no need to traverse up the | |
-- parent hierarchy. | |
if parents[parent] == 1 then | |
break | |
end | |
parents[parent] = (parents[parent] or 0) | hasVisibleChildren | |
parent = reaper.GetParentTrack(parent) | |
end | |
end | |
function updateView() | |
reaper.TrackList_AdjustWindows(0) | |
reaper.UpdateArrange() | |
reaper.UpdateTimeline() | |
if reaper.CountSelectedTracks(0) == 0 then | |
-- There are no selected tracks. Scroll to the top now that we have filtered | |
-- the view. | |
cmd = reaper.NamedCommandLookup('_XENAKIOS_TVPAGEHOME') | |
reaper.Main_OnCommandEx(cmd, 0, 0) | |
else | |
-- Track: Vertical scroll selected tracks into view. | |
reaper.Main_OnCommandEx(40913, 0, 0) | |
end | |
end | |
function main() | |
local parents = {} | |
_, _, section, cmd, _, _, _ = reaper.get_action_context() | |
exists, filterOn = reaper.GetProjExtState(0, SCRIPT_NAME, "filter_on") | |
-- Toggle filter | |
if filterOn == "1" then | |
filterOn = false | |
else | |
filterOn = true | |
end | |
reaper.Undo_BeginBlock2(0) | |
for trackIdx = 0, reaper.CountTracks(0) - 1 do | |
track = reaper.GetTrack(0, trackIdx) | |
if isInstrumentTrack(track) then | |
if not filterOn then | |
-- disabling filter | |
setTrackFiltering(track, false) | |
markParents(parents, track, 1) | |
else | |
if reaper.GetMediaTrackInfo_Value(track, "I_FXEN") > 0 then | |
setTrackFiltering(track, false) | |
markParents(parents, track, 1) | |
else | |
markParents(parents, track, 0) | |
setTrackFiltering(track, true) | |
end | |
end | |
end | |
end | |
for track, hasVisibleChildren in pairs(parents) do | |
if hasVisibleChildren == 1 and PRESERVE_PARENT_FOLDERS then | |
setTrackFiltering(track, false) | |
else | |
setTrackFiltering(track, true) | |
end | |
end | |
filterOn = filterOn and "1" or "0" | |
reaper.SetProjExtState(0, SCRIPT_NAME, "filter_on", filterOn) | |
reaper.SetToggleCommandState(section, cmd, filterOn) | |
reaper.RefreshToolbar2(section, cmd) | |
updateView() | |
reaper.Undo_EndBlock2(0, "Toggle visibility of disabled instrument tracks", -1) | |
end | |
reaper.defer(main) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment