|
-- @name Render tracks as MIDI Output (obeying time selection) |
|
-- @author Mads Thines Coello ([email protected]) |
|
-- @version 0.1.0 |
|
function saveSelectedTracks() |
|
local selectedTracks = {} |
|
|
|
for i = 0, reaper.CountSelectedTracks(0) - 1 do |
|
local selectedTrack = reaper.GetSelectedTrack(0, i) |
|
table.insert(selectedTracks, selectedTrack) |
|
end |
|
|
|
return selectedTracks |
|
end |
|
|
|
function setTracksAsSelected(tracks) |
|
-- Unselect all tracks |
|
reaper.Main_OnCommand(40297, 0) |
|
|
|
for _, track in ipairs(tracks) do |
|
reaper.SetTrackSelected(track, true) |
|
end |
|
|
|
reaper.UpdateArrange() |
|
end |
|
|
|
-- Insert empty MIDI item in the time selection and select it |
|
function insertEmptyMIDIItemsInTimeSelection() |
|
local startTime, endTime = reaper.GetSet_LoopTimeRange(false, false, 0, 0, false) |
|
|
|
if startTime == endTime then |
|
reaper.MB("Error: No time selection set.", "Error", 0) |
|
return |
|
end |
|
|
|
local numSelectedTracks = reaper.CountSelectedTracks(0) |
|
|
|
if numSelectedTracks == 0 then |
|
reaper.MB("Error: No tracks selected.", "Error", 0) |
|
return |
|
end |
|
|
|
local newItems = {} |
|
|
|
-- Loop through selected tracks |
|
for i = 0, numSelectedTracks - 1 do |
|
local track = reaper.GetSelectedTrack(0, i) |
|
|
|
-- Insert a new MIDI item within the time selection |
|
local newItem = reaper.CreateNewMIDIItemInProj(track, startTime, endTime, false) |
|
|
|
-- Select the new MIDI item |
|
reaper.SetMediaItemSelected(newItem, true) |
|
table.insert(newItems, newItem) |
|
end |
|
|
|
return newItems |
|
end |
|
|
|
-- Recursively select child tracks |
|
function selectAllChildTracks(track) |
|
local numChildTracks = reaper.CountTracks(0) |
|
|
|
for i = 0, numChildTracks - 1 do |
|
local childTrack = reaper.GetTrack(0, i) |
|
local parentTrack = reaper.GetParentTrack(childTrack) |
|
|
|
if parentTrack and parentTrack == track then |
|
reaper.SetTrackSelected(childTrack, true) |
|
selectAllChildTracks(childTrack) -- Recursively select child tracks of the current child track |
|
end |
|
end |
|
end |
|
|
|
function clearSelection() |
|
-- Unselect all items |
|
reaper.Main_OnCommand(40289, 0); |
|
-- Unselect all tracks |
|
reaper.Main_OnCommand(40297, 0); |
|
end |
|
|
|
function mergeMIDI() |
|
-- Item: Set item mix behavior to always mix |
|
reaper.Main_OnCommand(40919, 0); |
|
|
|
-- Item: Implode items across tracks into items on one track |
|
reaper.Main_OnCommand(40644, 0); |
|
|
|
-- Item: Glue items, ignoring time selection |
|
reaper.Main_OnCommand(40362, 0); |
|
|
|
-- Item: Set item mix behavior to project default |
|
reaper.Main_OnCommand(40922, 0); |
|
end |
|
|
|
function renderNestedMIDIToTrack(selectedTrack) |
|
-- Make sure the selected track is selected |
|
reaper.SetTrackSelected(selectedTrack, true) |
|
|
|
-- Recursively select all child tracks |
|
selectAllChildTracks(selectedTrack) |
|
|
|
-- Create new empty MIDI items for all tracks so we can apply the MIDI to them |
|
local newItems = insertEmptyMIDIItemsInTimeSelection(track) |
|
|
|
-- Apply track/take FX To MIDI items (MIDI Output) |
|
reaper.Main_OnCommand(40436, 0); |
|
|
|
-- Crop to Active Take |
|
reaper.Main_OnCommand(40131, 0); |
|
|
|
-- Merge the MIDI together into the first selected |
|
mergeMIDI() |
|
|
|
-- Rename the merged MIDI item to the name of the Track |
|
local selectedItem = reaper.GetSelectedMediaItem(0, 0) |
|
local track = reaper.GetMediaItem_Track(selectedItem) |
|
local _, trackName = reaper.GetSetMediaTrackInfo_String(track, "P_NAME", "", false) |
|
reaper.GetSetMediaItemTakeInfo_String(reaper.GetActiveTake(selectedItem), "P_NAME", trackName, true) |
|
|
|
-- Clear the selection |
|
clearSelection() |
|
end |
|
|
|
-- Run the main function |
|
function main() |
|
-- Begin a new undo block |
|
reaper.Undo_BeginBlock() |
|
|
|
-- Unselect all items |
|
reaper.Main_OnCommand(40289, 0); |
|
|
|
local numSelectedTracks = reaper.CountSelectedTracks(0) |
|
|
|
if numSelectedTracks == 0 then |
|
reaper.MB("Error: No tracks selected.", "Error", 0) |
|
return |
|
end |
|
|
|
-- Save selected tracks for iteration and restoration later |
|
local selectedTracks = saveSelectedTracks() |
|
|
|
-- Iterate over the selected tracks and render them individually to MIDI |
|
for _, selectedTrack in ipairs(selectedTracks) do |
|
renderNestedMIDIToTrack(selectedTrack); |
|
end |
|
|
|
-- Clear the selection |
|
clearSelection() |
|
|
|
-- Restore the initially selected tracks to the selection |
|
setTracksAsSelected(selectedTracks) |
|
|
|
-- End the undo block without registering any changes |
|
reaper.Undo_EndBlock("Render tracks as MIDI Output (obeying time selection)", -1) |
|
end |
|
|
|
-- Disable UI refresh to prevent flickering |
|
reaper.PreventUIRefresh(1) |
|
main(); |
|
-- Enable UI refresh |
|
reaper.PreventUIRefresh(-1) |
|
reaper.UpdateArrange() |