Strata_Copy selection to next project.lua (8680B)
1 --[[ 2 @description Strata_Copy selection to next project 3 @author Audiokinetic 4 @version 1.0.2 5 @changelog 6 SP-4763: Remove the alpha flag 7 @provides 8 [main=main] . https://raw.githubusercontent.com/audiokinetic/Reaper-Tools/$commit/Scripts/Strata_Copy%20selection%20to%20next%20project.lua 9 @about 10 # Copy selection to next project 11 This script will identify regions and clips within user's time selection, hide any tracks that are not parents and have NO items - or tracks that are purposefully muted. 12 Project content is then copied from the current project tab to the next open project tab to the immediate right. 13 14 ## Setup 15 User should have a Strata (or other) collection project open and the desired project they would like to copy strata takes/regions etc. into. The destination project should be the NEXT tab to the right 16 of the source/Strata project. Make a selection in the source project timeline and run the script. 17 18 ## Contributing 19 The repository is not open to pull request but in the case of a bug report, bugfix or a suggestions, please feel free to contact us 20 via the [feature request section](http://www.audiokinetic.com/qa/feature-requests/) of Audiokinetic's Community Q&A. 21 22 ## Legal 23 Copyright (c) 2024 [Audiokinetic Inc.](https://audiokinetic.com) All rights reserved. 24 25 ## License 26 Copyright (c) 2024 AUDIOKINETIC Inc. 27 28 The script in this file is licensed to use under the license available at: 29 https://raw.githubusercontent.com/audiokinetic/Reaper-Tools/main/License.txt (the "License"). 30 You may not use this file except in compliance with the License. 31 32 Unless required by applicable law or agreed to in writing, software distributed 33 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 34 CONDITIONS OF ANY KIND, either express or implied. See the License for the 35 specific language governing permissions and limitations under the License. 36 @license 37 Copyright (c) 2024 AUDIOKINETIC Inc. 38 39 The script in this file is licensed to use under the license available at: 40 https://raw.githubusercontent.com/audiokinetic/Reaper-Tools/main/License.txt (the "License"). 41 You may not use this file except in compliance with the License. 42 43 Unless required by applicable law or agreed to in writing, software distributed 44 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 45 CONDITIONS OF ANY KIND, either express or implied. See the License for the 46 specific language governing permissions and limitations under the License. 47 ]]-- 48 49 -- Command IDs used for reaper.Main_OnCommand() 50 local EDIT_UNDO = 40029 -- Edit: Undo 51 local SELECT_ALL_ITEMS = 40182 -- Item: Select all items 52 local COPY_TRACKS = 40210 -- Track: Copy tracks 53 local PASTE_TRACKS = 42398 -- Item: Paste items/tracks (Ctrl-V) 54 local NEW_PROJECT_TAB = 40859 -- New project tab 55 local ACTIVATE_NEXT_PROJECT_TAB = 40861 -- Next project tab 56 local ACTIVATE_PREVIOUS_PROJECT_TAB = 40862 -- Previous project tab 57 58 local currentProj = reaper.EnumProjects(-1) 59 local nbProjectTabs = 0 60 if currentProj then 61 repeat 62 reaper.Main_OnCommand(ACTIVATE_NEXT_PROJECT_TAB, 0) 63 local proj = reaper.EnumProjects(-1) 64 nbProjectTabs = nbProjectTabs + 1 65 until proj == currentProj 66 67 local lastProject = reaper.EnumProjects(nbProjectTabs-1) 68 if lastProject == currentProj then 69 reaper.Main_OnCommand(NEW_PROJECT_TAB, 0) 70 reaper.Main_OnCommand(ACTIVATE_PREVIOUS_PROJECT_TAB, 0) 71 end 72 end 73 74 local time_sel_start, time_sel_end = reaper.GetSet_LoopTimeRange2(currentProj, false, false, 0, 0, false) 75 if time_sel_start == time_sel_end then 76 reaper.ShowMessageBox("There is nothing to copy. Please make a time selection!", "Strata Copy Script Error", 0) 77 return 78 end 79 80 -- No point continuing script if there are no tracks selected! 81 if reaper.CountSelectedTracks(currentProj) == 0 then 82 reaper.ShowMessageBox("No selected tracks to copy!", "Strata Copy Script Error", 0) 83 return 84 end 85 86 local all_tracks = {} 87 local track_children = {} 88 89 -- Collect all tracks AND identify items that are within the time selection 90 local item_buffer = {} 91 local track_count = reaper.CountTracks(currentProj) 92 local firstItemPos = 9999999 93 for i = 0, track_count - 1 do 94 local track = reaper.GetTrack(currentProj, i) 95 table.insert(all_tracks, track) 96 97 local parent_track = reaper.GetParentTrack(track) 98 if parent_track then 99 if not track_children[parent_track] then 100 track_children[parent_track] = {} 101 end 102 table.insert(track_children[parent_track], track) 103 end 104 105 local item_count = reaper.CountTrackMediaItems(track) 106 for j = 0, item_count - 1 do 107 local item = reaper.GetTrackMediaItem(track, j) 108 local item_pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION") 109 110 if item_pos < time_sel_start or item_pos > time_sel_end then 111 table.insert(item_buffer, {track = track, item = item}) 112 elseif item_pos < firstItemPos then 113 firstItemPos = item_pos 114 end 115 end 116 end 117 118 -- Safety first 119 if firstItemPos == 9999999 then 120 firstItemPos = 0 121 end 122 123 -- Begin Undo Block 124 reaper.Undo_BeginBlock() 125 126 -- Delete items outside time selection 127 for _, data in ipairs(item_buffer) do 128 reaper.DeleteTrackMediaItem(data.track, data.item) 129 end 130 131 -- This recursive function returns true for tracks that should be copied 132 local function should_copy_track(track) 133 if reaper.CountTrackMediaItems(track) > 0 then 134 return true 135 elseif reaper.GetMediaTrackInfo_Value(track, "B_MUTE") == 1 then 136 return false 137 end 138 139 local children = track_children[track] 140 if children then 141 for _, child_track in ipairs(children) do 142 if should_copy_track(child_track) then 143 return true 144 end 145 end 146 end 147 end 148 149 -- Hide tracks that are muted or have no items or only have children that must be hidden 150 for _, track in ipairs(all_tracks) do 151 if not should_copy_track(track) then 152 reaper.SetMediaTrackInfo_Value(track, "B_SHOWINMIXER", 0) 153 reaper.SetMediaTrackInfo_Value(track, "B_SHOWINTCP", 0) 154 end 155 end 156 157 -- Open next project to get the destination position offset 158 reaper.Main_OnCommand(ACTIVATE_NEXT_PROJECT_TAB, 0) 159 local cursorPosition = reaper.GetCursorPosition() 160 local itemPositionOffset = 0 - firstItemPos + cursorPosition 161 162 -- Go back to previous project tab and move all items 163 reaper.Main_OnCommand(ACTIVATE_PREVIOUS_PROJECT_TAB, 0) 164 for _, track in ipairs(all_tracks) do 165 if should_copy_track(track) then 166 167 local item_count = reaper.CountTrackMediaItems(track) 168 local track_items = {} 169 for j = 0, item_count - 1 do 170 local item = reaper.GetTrackMediaItem(track, j) 171 local item_pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION") 172 table.insert(track_items, {item = item, item_pos = item_pos}) 173 end 174 for _, data in ipairs(track_items) do 175 reaper.SetMediaItemPosition(data.item, data.item_pos + itemPositionOffset, false) 176 end 177 end 178 end 179 180 -- Select and copy items and tracks 181 reaper.Main_OnCommand(SELECT_ALL_ITEMS, 0) 182 -- Only copies selected tracks 183 reaper.Main_OnCommand(COPY_TRACKS, 0) 184 185 -- No media in region to be copied 186 if reaper.CountSelectedMediaItems(currentProj) == 0 then 187 reaper.Undo_EndBlock("No media in region to be copied", -1) 188 reaper.Main_OnCommand(EDIT_UNDO, 0) 189 reaper.ShowMessageBox("No media in region to be copied!", "Strata Copy Script Error", 0) 190 return 191 end 192 193 -- Collect regions inside the time selection 194 local regions_to_copy = {} 195 local num_markers_and_regions = reaper.CountProjectMarkers(currentProj) 196 for i = 0, num_markers_and_regions - 1 do 197 local _, is_rgn, pos, rgn_end, name, id, color = reaper.EnumProjectMarkers3(currentProj, i) 198 if is_rgn and pos >= time_sel_start and rgn_end <= time_sel_end then 199 table.insert(regions_to_copy, {pos = pos, rgn_end = rgn_end, name = name, id = id, color = color}) 200 end 201 end 202 203 reaper.TrackList_AdjustWindows(false) 204 reaper.UpdateArrange() 205 206 207 -- End Undo Block 208 reaper.Undo_EndBlock("Remove contents outside time sel", -1) 209 reaper.Main_OnCommand(EDIT_UNDO, 0) 210 211 212 -- Activate the other open project window and paste tracks and regions 213 reaper.Main_OnCommand(ACTIVATE_NEXT_PROJECT_TAB, 0) 214 215 -- Begin Undo Block 216 reaper.Undo_BeginBlock() 217 218 reaper.Main_OnCommand(PASTE_TRACKS, 0) 219 for _, region in ipairs(regions_to_copy) do 220 reaper.AddProjectMarker2(0, true, region.pos + itemPositionOffset, region.rgn_end + itemPositionOffset, region.name, -1, region.color) 221 end 222 223 -- End Undo Block 224 reaper.Undo_EndBlock("Pasted tracks and items", 0) 225 226 -- Uncomment the next line to go back to the previous tab after script execution 227 --reaper.Main_OnCommand(ACTIVATE_PREVIOUS_PROJECT_TAB, 0)