Reaper-Tools

Audiokinetic Reaper Tools Repository
Log | Files | Refs

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)