Skip to content

Commit a0d982a

Browse files
committed
cleanup next item function
1 parent 0ad538d commit a0d982a

File tree

4 files changed

+119
-141
lines changed

4 files changed

+119
-141
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,58 @@
11
local runner = require('command.runner')
22
local state_interface = require('state_machine.state_interface')
33
local config = require 'definitions.config'.general
4-
local unselectAllButLastTouchedTrack = require('custom_actions.utils').unselectAllButLastTouchedTrack
4+
5+
local function normalTrackMotion(track_operator, track_motion)
6+
runner.runAction("SaveTrackSelection")
7+
runner.makeSelectionFromTrackMotion(track_motion, 1)
8+
runner.runAction(track_operator)
9+
if type(track_operator) ~= 'table' or not track_operator['setTrackSelection'] then
10+
runner.runAction("RestoreTrackSelection")
11+
end
12+
end
13+
14+
local function normalTrackSelector(track_operator, track_selector)
15+
runner.runAction("SaveTrackSelection")
16+
runner.runAction(track_selector)
17+
runner.runAction(track_operator)
18+
if type(track_operator) ~= 'table' or not track_operator['setTrackSelection'] then
19+
runner.runAction("RestoreTrackSelection")
20+
end
21+
end
22+
23+
local function visualTrackTrackOperator(track_operator)
24+
runner.runAction(track_operator)
25+
state_interface.setModeToNormal()
26+
if not config.persist_visual_track_selection and (type(track_operator) ~= 'table' or not track_operator['setTrackSelection']) then
27+
local track = reaper.GetLastTouchedTrack()
28+
if track then reaper.SetOnlyTrackSelected(track) end
29+
end
30+
end
31+
32+
local function visualTrackTrackMotion(track_motion)
33+
local args = { track_motion, 1 }
34+
local sel_function = runner.makeSelectionFromTrackMotion
35+
runner.extendTrackSelection(sel_function, args)
36+
end
37+
38+
local function visualTrackTimelineMotion(timeline_motion)
39+
if config.allow_timeline_movement_in_visual_mode then
40+
runner.runAction(timeline_motion)
41+
end
42+
end
543

644
---@type ActionModes
745
return {
8-
all_modes = {
9-
{ { 'track_motion' }, runner.runAction }
10-
},
46+
all_modes = { { { 'track_motion' }, runner.runAction } },
1147
normal = {
12-
{
13-
{ 'track_operator', 'track_motion' },
14-
function(track_operator, track_motion)
15-
runner.runAction("SaveTrackSelection")
16-
runner.makeSelectionFromTrackMotion(track_motion, 1)
17-
runner.runAction(track_operator)
18-
if type(track_operator) ~= 'table' or not track_operator['setTrackSelection'] then
19-
runner.runAction("RestoreTrackSelection")
20-
end
21-
end
22-
},
23-
{
24-
{ 'track_operator', 'track_selector' },
25-
function(track_operator, track_selector)
26-
runner.runAction("SaveTrackSelection")
27-
runner.runAction(track_selector)
28-
runner.runAction(track_operator)
29-
if type(track_operator) ~= 'table' or not track_operator['setTrackSelection'] then
30-
runner.runAction("RestoreTrackSelection")
31-
end
32-
end
33-
},
48+
{ { 'track_operator', 'track_motion' }, normalTrackMotion },
49+
{ { 'track_operator', 'track_selector' }, normalTrackSelector },
3450
},
3551
visual_track = {
3652
{ { 'visual_track_command' }, runner.runAction },
37-
{
38-
{ 'track_operator' },
39-
function(track_operator)
40-
runner.runAction(track_operator)
41-
state_interface.setModeToNormal()
42-
if not config.persist_visual_track_selection and (type(track_operator) ~= 'table' or not track_operator['setTrackSelection']) then
43-
unselectAllButLastTouchedTrack()
44-
end
45-
end
46-
},
53+
{ { 'track_operator' }, visualTrackTrackOperator },
4754
{ { 'track_selector' }, runner.runAction },
48-
{
49-
{ 'track_motion' },
50-
function(track_motion)
51-
local args = { track_motion, 1 }
52-
local sel_function = runner.makeSelectionFromTrackMotion
53-
runner.extendTrackSelection(sel_function, args)
54-
end
55-
},
56-
{
57-
{ 'timeline_motion' },
58-
function(timeline_motion)
59-
if config.allow_timeline_movement_in_visual_mode then
60-
runner.runAction(timeline_motion)
61-
end
62-
end
63-
},
55+
{ { 'track_motion' }, visualTrackTrackMotion },
56+
{ { 'timeline_motion' }, visualTrackTimelineMotion },
6457
}
6558
}

internal/custom_actions/custom_actions.lua

+71-67
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,78 @@ local actions = {}
33

44
function actions.projectStart() reaper.SetEditCurPos(0, true, false) end
55

6-
function actions.projectEnd()
7-
reaper.SetEditCurPos(reaper.GetProjectLength(0), true, false)
8-
end
6+
function actions.projectEnd() reaper.SetEditCurPos(reaper.GetProjectLength(0), true, false) end
97

108
function actions.firstItemStart()
11-
local start = nil
9+
local len = reaper.GetProjectLength(0)
10+
local start = len
1211
for i = 0, reaper.CountSelectedTracks() - 1 do
1312
local track = reaper.GetSelectedTrack(0, i)
1413
if reaper.GetTrackNumMediaItems(track) > 0 then
1514
local item = reaper.GetTrackMediaItem(track, 0)
1615
local pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION")
17-
if not start or pos < start then start = pos end
16+
if pos < start then start = pos end
1817
end
1918
end
20-
if start then reaper.SetEditCurPos(start, true, false) end
19+
if start < len then reaper.SetEditCurPos(start, true, false) end
2120
end
2221

23-
-- This won't work if last item on track is not the "last" one, imagine [long----[short]--],
24-
-- short is last but ends sooner. However, this is a reasonable limitation as otherwise we
25-
-- need to scan at most all items on all selected tracks
22+
-- This won't work if last item on track is not the one with latest start, imagine [long----[short]--],
23+
-- This is a reasonable limitation as otherwise we need to scan all items on all selected tracks
2624
function actions.lastItemEnd()
27-
local last_end = nil
25+
local last_end = 0
2826
for i = 0, reaper.CountSelectedTracks() - 1 do
2927
local track = reaper.GetSelectedTrack(0, i)
3028
local items = reaper.GetTrackNumMediaItems(track)
31-
if items > 0 then
32-
local item = reaper.GetTrackMediaItem(track, items - 1)
29+
if items == 0 then goto next_track end
30+
local item = reaper.GetTrackMediaItem(track, items - 1)
31+
local pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION")
32+
+ reaper.GetMediaItemInfo_Value(item, "D_LENGTH")
33+
if pos > last_end then last_end = pos end
34+
::next_track::
35+
end
36+
if last_end > 0 then reaper.SetEditCurPos(last_end, true, false) end
37+
end
38+
39+
function actions.prevItemStart()
40+
local cur, start = reaper.GetCursorPosition(), -1
41+
for i = 0, reaper.CountSelectedTracks() - 1 do
42+
local track = reaper.GetSelectedTrack(0, i)
43+
for j = 0, reaper.GetTrackNumMediaItems(track) - 1 do
44+
local item = reaper.GetTrackMediaItem(track, j)
3345
local pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION")
34-
+ reaper.GetMediaItemInfo_Value(item, "D_LENGTH")
35-
if not last_end or pos > last_end then last_end = pos end
46+
if pos >= cur then goto next_track elseif pos > start then start = pos end
3647
end
48+
::next_track::
3749
end
38-
if last_end then reaper.SetEditCurPos(last_end, true, false) end
50+
if start > -1 then reaper.SetEditCurPos(start, true, false) end
3951
end
4052

41-
local function moveToPrevItemStart(item_positions)
53+
local function nextItem(add_length)
54+
local cur = reaper.GetCursorPosition()
55+
local len = reaper.GetProjectLength(0)
56+
local start = len
57+
local item = nil
58+
for i = 0, reaper.CountSelectedTracks() - 1 do
59+
local track = reaper.GetSelectedTrack(0, i)
60+
for j = 0, reaper.GetTrackNumMediaItems(track) - 1 do
61+
item = reaper.GetTrackMediaItem(track, j)
62+
local pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION")
63+
if pos > cur and pos < start then start = pos end
64+
if pos > cur then goto next_track end
65+
end
66+
::next_track::
67+
end
68+
if add_length then start = start + reaper.GetMediaItemInfo_Value(item, "D_LENGTH") end
69+
if start < len then reaper.SetEditCurPos(start, true, false) end
70+
end
71+
72+
function actions.nextItemStart() nextItem(false) end
73+
74+
function actions.nextItemEnd() nextItem(true) end
75+
76+
function actions.prevBigItemStart()
77+
local item_positions = utils.getBigItemPositionsOnSelectedTracks()
4278
local pos = reaper.GetCursorPosition()
4379
local next_position = nil
4480
for i, item in pairs(item_positions) do
@@ -60,15 +96,8 @@ local function moveToPrevItemStart(item_positions)
6096
if next_position then reaper.SetEditCurPos(next_position, true, false) end
6197
end
6298

63-
function actions.prevBigItemStart()
64-
moveToPrevItemStart(utils.getBigItemPositionsOnSelectedTracks())
65-
end
66-
67-
function actions.prevItemStart()
68-
moveToPrevItemStart(utils.getItemPositionsOnSelectedTracks())
69-
end
70-
71-
local function moveToNextItemStart(item_positions)
99+
function actions.nextBigItemStart()
100+
local item_positions = utils.getBigItemPositionsOnSelectedTracks()
72101
local pos = reaper.GetCursorPosition()
73102
local next_position = nil
74103
for _, item_position in pairs(item_positions) do
@@ -82,15 +111,8 @@ local function moveToNextItemStart(item_positions)
82111
if next_position then reaper.SetEditCurPos(next_position, true, false) end
83112
end
84113

85-
function actions.nextBigItemStart()
86-
moveToNextItemStart(utils.getBigItemPositionsOnSelectedTracks())
87-
end
88-
89-
function actions.nextItemStart()
90-
moveToNextItemStart(utils.getItemPositionsOnSelectedTracks())
91-
end
92-
93-
local function moveToNextItemEnd(item_positions)
114+
function actions.nextBigItemEnd()
115+
local item_positions = utils.getBigItemPositionsOnSelectedTracks()
94116
local current_position = reaper.GetCursorPosition()
95117
local next_position = nil
96118
local tolerance = .002
@@ -106,31 +128,20 @@ local function moveToNextItemEnd(item_positions)
106128
end
107129
end
108130

109-
function actions.nextBigItemEnd()
110-
moveToNextItemEnd(utils.getBigItemPositionsOnSelectedTracks())
111-
end
112-
113-
function actions.nextItemEnd()
114-
moveToNextItemEnd(utils.getItemPositionsOnSelectedTracks())
115-
end
116-
117131
function actions.firstTrack()
118132
local track = reaper.GetTrack(0, 0)
119133
if track then reaper.SetOnlyTrackSelected(track) end
120134
end
121135

122136
function actions.lastTrack()
123137
local num = reaper.GetNumTracks()
124-
if num == 0 then return end
125-
local track = reaper.GetTrack(0, num - 1)
126-
reaper.SetOnlyTrackSelected(track)
138+
if num ~= 0 then reaper.SetOnlyTrackSelected(reaper.GetTrack(0, num - 1)) end
127139
end
128140

129141
function actions.trackWithNumber()
130-
local _, number = reaper.GetUserInputs("Match Forward", 1, "Track Number", "")
131-
if type(number) ~= 'number' then return end
132-
133-
local track = reaper.GetTrack(0, number - 1)
142+
local ok, num = reaper.GetUserInputs("Match Forward", 1, "Track Number", "")
143+
if not ok or type(num) ~= 'number' then return end
144+
local track = reaper.GetTrack(0, num - 1)
134145
if track then reaper.SetOnlyTrackSelected(track) end
135146
end
136147

@@ -152,8 +163,8 @@ function actions.snap()
152163
end
153164

154165
function actions.innerProjectTimeline()
155-
local project_end = reaper.GetProjectLength(0)
156-
reaper.GetSet_LoopTimeRange(true, false, 0, project_end, false)
166+
local len = reaper.GetProjectLength(0)
167+
reaper.GetSet_LoopTimeRange(true, false, 0, len, false)
157168
end
158169

159170
function actions.innerItem()
@@ -182,15 +193,13 @@ end
182193

183194
function actions.onlyCurrentTrack()
184195
local track = reaper.GetSelectedTrack(0, 0)
185-
if track then
186-
reaper.SetOnlyTrackSelected(track)
187-
end
196+
if track then reaper.SetOnlyTrackSelected(track) end
188197
end
189198

190199
function actions.innerRegion()
191-
local pos = reaper.GetCursorPosition()
192-
local _, region_id = reaper.GetLastMarkerAndCurRegion(0, pos)
193-
utils.selectRegion(region_id)
200+
local _, region_id = reaper.GetLastMarkerAndCurRegion(0, reaper.GetCursorPosition())
201+
local ok, is_region, start_pos, end_pos, _, _ = reaper.EnumProjectMarkers(region_id)
202+
if ok and is_region then reaper.GetSet_LoopTimeRange(true, false, start_pos, end_pos, false) end
194203
end
195204

196205
function actions.clearTimeSelection()
@@ -203,14 +212,10 @@ local function getUserGridDivisionInput()
203212
if not ok then return end
204213
local division = str:match("[0-9.]+")
205214
local fraction = str:match("/([0-9.]+)")
206-
if division and fraction then
207-
return division / fraction
208-
elseif division then
209-
return division
210-
else
211-
reaper.MB("Could not parse specified grid division", "Error", 0)
212-
return nil
213-
end
215+
if division and fraction then return division / fraction end
216+
if division then return division end
217+
reaper.MB("Could not parse specified grid division " .. str, "Error", 0)
218+
return nil
214219
end
215220

216221
function actions.setMidiGridDivision()
@@ -231,8 +236,7 @@ end
231236
-- this one avoids splitting all items across tracks in time selection, if no items are selected
232237
function actions.splitItemsAtTimeSelection()
233238
if reaper.CountSelectedMediaItems(0) == 0 then return end
234-
local SplitAtTimeSelection = 40061
235-
reaper.Main_OnCommand(SplitAtTimeSelection, 0)
239+
reaper.Main_OnCommand(40061, 0) -- split at time selection
236240
end
237241

238242
return actions

internal/custom_actions/utils.lua

-19
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,6 @@ function utils.getBigItemPositionsOnSelectedTracks()
8686
return big_item_positions
8787
end
8888

89-
function utils.selectRegion(id)
90-
local ok, is_region, start_pos, end_pos, _, got_id = reaper.EnumProjectMarkers(id)
91-
if ok and is_region then
92-
reaper.GetSet_LoopTimeRange(true, false, start_pos, end_pos, false)
93-
return true
94-
end
95-
return false
96-
end
97-
9889
function utils.getMatchedTrack(search_name, forward)
9990
if not search_name then
10091
return nil
@@ -191,16 +182,6 @@ function utils.setCurrentTrack(index)
191182
end
192183
end
193184

194-
function utils.unselectAllButLastTouchedTrack()
195-
local last_touched_i = utils.getTrackPosition()
196-
if last_touched_i then
197-
local track = reaper.GetTrack(0, last_touched_i)
198-
if track then
199-
reaper.SetOnlyTrackSelected(track)
200-
end
201-
end
202-
end
203-
204185
function utils.getSelectedTrackIndices()
205186
local selected_tracks = utils.getSelectedTracks()
206187
local selected_track_indices = {}

internal/definitions/bindings.lua

+3-3
Original file line numberDiff line numberDiff line change
@@ -497,10 +497,10 @@ local main = {
497497
["B"] = "PrevBigItemStart",
498498
["E"] = "NextBigItemEnd",
499499
["W"] = "NextBigItemStart",
500-
["b"] = "PrevItemStart",
501500
["<M-b>"] = "PrevEnvelopePoint",
502-
["e"] = "NextItemEnd",
503-
["w"] = "NextItemStart",
501+
w = "NextItemStart",
502+
e = "NextItemEnd",
503+
b = "PrevItemStart",
504504
["<M-w>"] = "NextEnvelopePoint",
505505
["$"] = "LastItemEnd",
506506
["("] = "TimeSelectionStart",

0 commit comments

Comments
 (0)