|
|
|
01-08-2021, 05:23 PM
|
#1
|
Human being with feelings
Join Date: Sep 2016
Location: Toronto
Posts: 749
|
Req: MIDI Step Sequencer Pencil/Erase tool for arrange view (using JS_API)
Does REAPER need a step sequencer? No, it IS a step sequencer. Or at least, it will be one if we can get this script figured out.
Now that we have mouse intercept API thanks to the esteemed Julian Sader, it seems like it's possible for someone clever (or at least cleverer than me) to make a MIDI pencil/erase drag script for arrange view.
The script needs to intercept:
L Button: Clicking on a track in arrange inserts midi item on grid at mouse with single C4 note, both of which are the length of grid
L Drag: creates multiple of these items along the horizontal axis, unpooled (drag-to-draw)
R Button: deletes item under mouse
R Drag: deletes items horizontally along the same track, (drag-to-delete)
This is essentially the same mouse functionality as FL Studio's excellent step sequencer. If we could toggle this via toolbar button, I think it would eliminate the need for third-party step sequencers all together!
I did a mock-up of some of this functionality via two actions that works with L Button (armed action) and R Drag (using razor edit and a defer script that checks if there is a RE, then deletes any items in it and removes the RE).
But there are several obvious limitations and problems with this implementation, so I'm seeking help for someone to code a solution, for which I'll happily donate to support.
Here's the mockup:
|
|
|
01-10-2021, 09:36 AM
|
#2
|
Human being with feelings
Join Date: Jul 2009
Posts: 1,071
|
Hi Arthur McArthur,
Which scripts are you using so far for the mockup ?
I have had a hunt around thinking it would be nice if you could insert the currently selected item in media explorer as your source.
Wondering if there is a list of command to access the media explorer window and if so it would need a pointer to the copy command and then you could paste from there i guess ?
reaper.JS_WindowMessage_Send(media explorer, "WM_COMMAND", ??????, 0, 0, 0)
Is there a list anywhere or a way to get a value for the menu copy in ME ?
Last edited by J Reverb; 01-10-2021 at 09:56 AM.
|
|
|
01-10-2021, 01:39 PM
|
#3
|
Human being with feelings
Join Date: Sep 2016
Location: Toronto
Posts: 749
|
Here are the scripts I roughly hacked together for the mockup (please excuse my lackluster coding skills.) I think in general they would need to be largely written for this new script, as they can probably be approached and written much better using js_API.
This is the insert midi item with note at mouse (note that there is a bug where at higher grid settings the note is shorter than the length of the items):
Code:
Insert MIDI item with note at mouse cursor
local r=reaper
r.PreventUIRefresh(1)
r.Main_OnCommand(r.NamedCommandLookup('40514'), 0) --move edit cursor to mouse cursor (no snapping)
r.Main_OnCommand(r.NamedCommandLookup('40646'), 0) --move cursor left to grid division
r.Main_OnCommand(r.NamedCommandLookup('41110'), 0) --Select track under mouse
r.Main_OnCommand(r.NamedCommandLookup('40914'), 0) --Track: Set first selected track as last touched track
track = r.GetSelectedTrack(0, 0)
note = 60
r.Main_OnCommand(r.NamedCommandLookup('40635'), 0) -- remove time selection
reaper.Main_OnCommand(r.NamedCommandLookup('_SWS_MOVECURSELRIGHT'), 0) --move cursor right creating time selection
r.UpdateArrange()
r.UpdateTimeline()
starttime, endtime = r.GetSet_LoopTimeRange2(0, false, false, 0, 0, false)
qnotetime = 60 / r.Master_GetTempo()
length = (endtime - starttime)
midiItem = r.CreateNewMIDIItemInProj(track, starttime, starttime + qnotetime)
midiTake = r.GetActiveTake(midiItem)
r.SetMediaItemLength(midiItem, length, false)
r.MIDI_InsertNote(midiTake, false, false, 0, 500, 1, note, 127)
r.Main_OnCommand(r.NamedCommandLookup('40416'), 0) -- select and move to previous item
r.Main_OnCommand(r.NamedCommandLookup('40930'), 0) -- trim behind item
r.Main_OnCommand(r.NamedCommandLookup('40635'), 0) -- remove time selection
local x_l = reaper.GetSet_LoopTimeRange(0, 1, 0, 0, 0)
r.UpdateArrange()
r.UpdateTimeline()
r.Main_OnCommand(r.NamedCommandLookup('41174'), 0) -- move cursor to end of item
r.Main_OnCommand(r.NamedCommandLookup('_RS3b644da342aae75ce0a006e7d80c21ec2bb311c1'), 0) -- Script: cfillion_Set item end to cursor and resize trailing MIDI notes.lua
r.Main_OnCommand(r.NamedCommandLookup('_RSd91b900e46381ac49e82b8f980311182bf004a37'), 0) --Lokasenna_Item properties - Loop item source (on).lua
r.SetEditCurPos2(0, x_l, 0, 0)
r.PreventUIRefresh(-1)
::ending::
And the defer script for drag-to-delete with right click drag (most of the code is from Embass I believe in the razor edit thread in the prerelease forum)
Code:
local r = reaper
-- Set ToolBar Button State
function SetButtonState( set )
if not set then set = 0 end
local is_new_value, filename, sec, cmd, mode, resolution, val = reaper.get_action_context()
local state = reaper.GetToggleCommandStateEx( sec, cmd )
reaper.SetToggleCommandState( sec, cmd, set ) -- Set ON
reaper.RefreshToolbar2( sec, cmd )
end
local self = ({reaper.get_action_context()})[4]
reaper.SetToggleCommandState(0, self, 1)
function literalize(str)
return str:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", function(c) return "%" .. c end)
end
function GetItemsInRange(track, areaStart, areaEnd)
local items = {}
local itemCount = r.CountTrackMediaItems(track)
for k = 0, itemCount - 1 do
local item = r.GetTrackMediaItem(track, k)
local pos = r.GetMediaItemInfo_Value(item, "D_POSITION")
local length = r.GetMediaItemInfo_Value(item, "D_LENGTH")
local itemEndPos = pos+length
--check if item is in area bounds
if (itemEndPos > areaStart and itemEndPos <= areaEnd) or
(pos >= areaStart and pos < areaEnd) or
(pos <= areaStart and itemEndPos >= areaEnd) then
table.insert(items,item)
end
end
return items
end
function GetRazorEdits()
local trackCount = r.CountTracks(0)
local areaMap = {}
for i = 0, trackCount - 1 do
local track = r.GetTrack(0, i)
local ret, area = r.GetSetMediaTrackInfo_String(track, 'P_RAZOREDITS', '', false)
if area ~= '' then
--PARSE STRING
local str = {}
for j in string.gmatch(area, "%S+") do
table.insert(str, j)
end
--FILL AREA DATA
local j = 1
while j <= #str do
--area data
local areaStart = tonumber(str[j])
local areaEnd = tonumber(str[j+1])
local GUID = str[j+2]
local isEnvelope = GUID ~= '""'
--get item/envelope data
local items = {}
local envelopeName, envelope
local envelopePoints
if not isEnvelope then
items = GetItemsInRange(track, areaStart, areaEnd)
else
envelope = r.GetTrackEnvelopeByChunkName(track, GUID:sub(2, -2))
local ret, envName = r.GetEnvelopeName(envelope)
envelopeName = envName
envelopePoints = GetEnvelopePointsInRange(envelope, areaStart, areaEnd)
end
local areaData = {
areaStart = areaStart,
areaEnd = areaEnd,
track = track,
items = items,
--envelope data
isEnvelope = isEnvelope,
envelope = envelope,
envelopeName = envelopeName,
envelopePoints = envelopePoints,
GUID = GUID:sub(2, -2)
}
table.insert(areaMap, areaData)
j = j + 3
end
end
end
return areaMap
end
function RazorEditSelectionExists()
for i=0, r.CountTracks(0)-1 do
local retval, x = r.GetSetMediaTrackInfo_String(r.GetTrack(0,i), "P_RAZOREDITS", "string", false)
if x ~= "" then return true end
end--for
return false
end--RazorEditSelectionExists()
function Main()
if RazorEditSelectionExists() then
local selections = GetRazorEdits()
for i = 1, #selections do
local areaData = selections[i]
local items = areaData.items
r.Undo_BeginBlock();
for j = 1, #items do r.SetMediaItemSelected(items[j], true) end
r.UpdateTimeline()
r.PreventUIRefresh(1);
r.Main_OnCommand(42406, 0)--remove razor edit
r.Main_OnCommand(40006, 0)--remove items
r.PreventUIRefresh(-1);
r.Undo_EndBlock('Delete Item', -1)
end
end
r.defer(Main)
end
r.SetMouseModifier( 'MM_CTX_ARRANGE_RMOUSE', 0, 25)-- set right click drag to create razor edits
SetButtonState( 1 )
Main()
function exit ()
r.SetMouseModifier( 'MM_CTX_ARRANGE_RMOUSE', 0, 1)-- set right click drag back to marquee select items
reaper.SetToggleCommandState(0, self, 0)
end
reaper.atexit(exit)
reaper.atexit( SetButtonState )
|
|
|
01-10-2021, 01:49 PM
|
#4
|
Human being with feelings
Join Date: Sep 2016
Location: Toronto
Posts: 749
|
As far as creating new RS5K tracks with the selected item in the media explorer. I'm using a super hacky set of custom actions that works ok but I won't write out here as it will probably just be too confusing. But part of it is:
Code:
me = reaper.JS_Window_Find("Media Explorer", true)
reaper.JS_WindowMessage_Send(me, "WM_COMMAND", 40064, 0, 0, 0)--Options: Default action inserts media
reaper.JS_WindowMessage_Send(me, "WM_COMMAND", 40063, 0, 0, 0)--Options: Insert media on selected track
reaper.JS_WindowMessage_Send(me, "WM_COMMAND", 1013, 0, 0, 0)--Browser: Browse selected folder, or insert selected media file
|
|
|
01-10-2021, 01:51 PM
|
#5
|
Human being with feelings
Join Date: Jul 2009
Posts: 1,071
|
where do you get the codes from btw ?
reaper.JS_WindowMessage_Send(me, "WM_COMMAND", 40064, 0, 0, 0)--Options: Default action inserts media
|
|
|
01-10-2021, 01:54 PM
|
#6
|
Human being with feelings
Join Date: Dec 2020
Location: Miami, FL USA
Posts: 396
|
I feel like this would work well if you added the ability to tag tracks, so if a trackname was tagged with "[SEQ]" or something, then this behavior would kick in when clicking on those track lanes, but for other items it remains the same.
Manual toggle, or automatic mode based on track name.
This would allow you to skip manually toggling the sequencer mode.
So imagine having an arrangement like:
Code:
Voc_Hook_Main: XXXXXXXXXXXXXXXXX
Brass_Stabs : X X
---
[SEQ] Kick : X X X X X X X X X
[SEQ] Clap : X X X X
When you're editing the "regular" items up top, behavior is normal, but inside "sequenced" tracks you get this sort of step-sequencer behavior with clicks.
This would give you the ability to work with both patterns/sequences, and standard audio/MIDI clips in a single "work area" too, which is something I've not seen before.
My $0.02 at least ¯\_(ツ)_/¯
|
|
|
01-10-2021, 02:05 PM
|
#7
|
Human being with feelings
Join Date: Sep 2016
Location: Toronto
Posts: 749
|
Quote:
Originally Posted by J Reverb
where do you get the codes from btw ?
reaper.JS_WindowMessage_Send(me, "WM_COMMAND", 40064, 0, 0, 0)--Options: Default action inserts media
|
You can grab these in the Media Explorer context of the Actions window, right click on the action you want and "Copy selected action command ID"
|
|
|
01-10-2021, 02:25 PM
|
#8
|
Human being with feelings
Join Date: Jul 2009
Posts: 1,071
|
Oh sorry my bad I thought these were c++ things .. ok cool thanks !
So should this be armed ? makes sense ?
|
|
|
01-10-2021, 02:34 PM
|
#9
|
Human being with feelings
Join Date: Jul 2009
Posts: 1,071
|
@gxray
Yes ! I see that ... good idea !
|
|
|
01-10-2021, 02:35 PM
|
#10
|
Human being with feelings
Join Date: Sep 2016
Location: Toronto
Posts: 749
|
I think it should be a toolbar button that starts a defer script which intercepts the mouse clicks and runs the appropriate actions.
|
|
|
01-10-2021, 02:38 PM
|
#11
|
Human being with feelings
Join Date: Sep 2016
Location: Toronto
Posts: 749
|
Quote:
Originally Posted by gxray
I feel like this would work well if you added the ability to tag tracks, so if a trackname was tagged with "[SEQ]" or something, then this behavior would kick in when clicking on those track lanes, but for other items it remains the same.
|
Good idea, although the SEQ should come at the end of the track name, and the script to insert the selected sample into a new RS5K track should automatically add SEQ to the end.
|
|
|
01-12-2021, 01:08 PM
|
#12
|
Human being with feelings
Join Date: Jul 2009
Posts: 1,071
|
So I have had a play around with an idea for the painting side of things.
Instead of creating a midi item in the script insert one from the media explorer. This way you can paint midi items or audio items to the track.
In this test I have the items inserted using the current grid size. There seems to be a problem when zoomed out though where Reaper wants to replace audio source??, however if you zoom in a bit this doesn't happen. bug maybe, no idea yet. Anyway, please test and suggest.
And can we have a working example of mouse intercept? I kind of got it going but then gave up lol. I guess you have to free the mouse up somehow? I couldn't get it working. Here's code.... must be ARMED to work
Code:
function paint_items_from_media_explorer_to_grid()
reaper.PreventUIRefresh(1)
reaper.Undo_BeginBlock()
track, context, position = reaper.BR_TrackAtMouseCursor()
if context == 2 then
local cur_pos = reaper.GetCursorPosition()
local grid = reaper.SnapToGrid(0,cur_pos )
reaper.Main_OnCommand(reaper.NamedCommandLookup( "_SWS_XFDOFF" ),0) -- turn off autoxfade when editing
local me = reaper.JS_Window_Find("Media Explorer", true)
reaper.JS_WindowMessage_Send(me, "WM_COMMAND", 42082, 0, 0, 0)
reaper.Main_OnCommand(42398,0) -- Item: Paste items/tracks
local item = reaper.GetSelectedMediaItem(0,0)
if item then
reaper.SetMediaItemInfo_Value( item, "D_POSITION",cur_pos )
reaper.SetMediaItemSelected( item, 1 )
local retval, division, swingmode, swingamt = reaper.GetSetProjectGrid(0,0,0,0,0)
local division = division*2
reaper.SetMediaItemLength(item, division, false)
reaper.SetMediaItemInfo_Value( item, "D_FADEOUTLEN",0.001 )
local endgrid = reaper.BR_GetPrevGridDivision(division)
reaper.MoveEditCursor( endgrid, 0 )
reaper.UpdateItemInProject( item )
reaper.Main_OnCommand(reaper.NamedCommandLookup( "_SWS_XFDON" ),0)
end
end
end
reaper.UpdateTimeline()
reaper.UpdateArrange()
reaper.Undo_EndBlock("Paint item",1 )
paint_items_from_media_explorer_to_grid()
|
|
|
01-12-2021, 04:15 PM
|
#13
|
Human being with feelings
Join Date: Sep 2016
Location: Toronto
Posts: 749
|
Nice, big step in the right direction and I think it's great to have such an easy way of inserting audio items from the media explorer.
For the tracks marked SEQ at the end of their names I wish it would automatically insert midi items instead of having to select them in the media explorer. As my primary use case is the midi items on RS5K tracks and not audio items.
A couple of ideas:
It should select the tracks under mouse cursor first so you don't have to select the track manually you want to draw on, you just click where you want it to go.
If it deleted whatever item is under the mouse cursor first that would be handy and it may avoid the replace source problem.
If you click on empty space (not a track) it should create a new track and paste the item.
And for whatever reason the length of the items is longer than the grid on my system: https://imgur.com/a/zT4LtRu
For the mouse intercept question I would check out Julian Sader's Multi Tool script. There are several things he does with intercepts in that script so it might be simpler to ask it in the JS_API thread. But basically I think you have to intercept the keys and then free them up if there is an error or the script closes.
|
|
|
01-14-2021, 10:25 PM
|
#14
|
Human being with feelings
Join Date: Dec 2017
Posts: 152
|
|
|
|
01-17-2021, 01:21 PM
|
#15
|
Human being with feelings
Join Date: Jul 2009
Posts: 1,071
|
@Arthur McArthur
Had a play around with this again. Making progress with the erase side of things I think..
Add this code to the bottom of your midi item script to try it out.
There are a few different ways of doing this. I'm not sure which is better.
Anyway this just gets the item from point if right mouse button is down.
Still trying to figure out how to disable the marquee window but it can be useful if used to select items and then swipe to delete with a modifier key. In this case shift. Anyway here's code.
Code:
function rightclk()
click = reaper.JS_Mouse_GetState(1)
if click == 1 then return end
click = reaper.JS_Mouse_GetState(2)
shift = reaper.JS_Mouse_GetState(8)
if shift == 8 and click == 2 then
x, y = reaper.GetMousePosition()
take = reaper.GetItemFromPoint( x, y, 0 )
if take then
reaper.SetMediaItemSelected( take, 1)
reaper.GetSelectedMediaItem(0, 0)
reaper.Main_OnCommand(40006,0)
end
end
reaper.defer(rightclk)
end
rightclk()
@tufb
That's really cool btw ! Thanks v much
|
|
|
01-20-2021, 12:45 AM
|
#17
|
Human being with feelings
Join Date: Jul 2009
Posts: 1,071
|
WIP of SERA draw tools .. I guess that nails it !
Really good to learn the mouse stuff from this.
Thanks Lemerchand ! nice job !
|
|
|
01-21-2021, 10:41 AM
|
#18
|
Human being with feelings
Join Date: May 2018
Location: Sacramento, CA
Posts: 43
|
Quote:
Originally Posted by J Reverb
WIP of SERA draw tools .. I guess that nails it !
Really good to learn the mouse stuff from this.
Thanks Lemerchand ! nice job !
|
Thanks! I made some updates to it, so if you have installed the scripts you can update for a few new features.
I'll post more details in a dedicated thread, but for now you can toggle pattern visibility even in draw mode, and if you click-drag a pattern it will paste a new instance of the pattern where ever you release the mouse and the midi will be pooled so changes will be throughout the project unless you use Make Pattern Unique.
|
|
|
01-24-2021, 06:06 AM
|
#19
|
Human being with feelings
Join Date: Jul 2007
Location: Jazz City
Posts: 5,074
|
@lemerchand: How are the scripts supposed to be used? Could you add a short explanation/how-to?
Thanks!
__________________
Windows 10x64 | AMD Ryzen 3700X | ATI FirePro 2100 | Marian Seraph AD2, 4.3.8 | Yamaha Steinberg MR816x
"If I can hear well, then everything I do is right" (Allen Sides)
|
|
|
01-24-2021, 03:53 PM
|
#20
|
Human being with feelings
Join Date: May 2018
Location: Sacramento, CA
Posts: 43
|
Quote:
Originally Posted by beingmf
@lemerchand: How are the scripts supposed to be used? Could you add a short explanation/how-to?
Thanks!
|
Pretty soon @Arthur and I are going to make an official forum post with gifs, documentation, and maybe even a video.
Until then, the basic idea is to bind: - SERA - Draw Tool to a hotkey or toolbar button. With this script you can left click/right click to print/delete a dummy midi item onto the grid. This is just a C4 note to trigger a sampler (eg., rs5k) You can also left-drag/right-drag to draw quickly.
- SERA - Create Pattern Clip to a hotkey or toolbar button. After drawing your midi items, select everything you want in a 'Pattern Clip' and run this script. They will now be grouped to and inserted with a new parent track/item you can use to move it around when the children tracks are collapsed....which brings me to...
- SERA - Toggle Pattern Clip - to a hotkey, OR your double-click mouse modifier for items (don't worry, it still will perform the default double click actions on items). This script let's you toggle the visibility of the items within a pattern. It's sort of like opening or closing a step sequencer.
Another tip: Toggle Pattern Clip works even in draw mode.
And another: Left-click and drag the actual pattern clip to paste a pooled copy of the entire pattern.
I'm currently working on making it such that the user can drag and drop samples directly from the ME. It works but...it's too buggy to release. Hopefully soon!
|
|
|
01-26-2021, 09:33 PM
|
#21
|
Human being with feelings
Join Date: Feb 2015
Posts: 755
|
Awesome work, Arthur McArthur and lemerchand.
I've been actually considering such a workflow of using items with single notes to mimic a step sequencer. I think this is off to a great start.
Last edited by Ozman; 10-27-2023 at 10:27 AM.
|
|
|
10-27-2023, 10:18 AM
|
#22
|
Human being with feelings
Join Date: Feb 2015
Posts: 755
|
What's been up with this one?
Has it been still developed on?
|
|
|
10-27-2023, 12:49 PM
|
#23
|
Human being with feelings
Join Date: Jul 2007
Posts: 726
|
Quote:
Originally Posted by Ozman
What's been up with this one?
Has it been still developed on?
|
I can't express well enough the great fun and usefulness of Megababy NM. Try using that with a track template filled with ready routed RS5k's....
It's much better than drawing in the arrangement as you can switch patterns on the fly with midi notes.
Make a toolbar button to bring it up and it will feel like the step sequencer you were missing.
https://imgur.com/a/QAmyVhe
Edit: Imgur says the image might be unsuitable for under 18's and won't embed. I assure you it isn't!
Last edited by dna598; 10-27-2023 at 12:55 PM.
|
|
|
04-04-2024, 06:38 AM
|
#24
|
Human being with feelings
Join Date: Feb 2015
Posts: 755
|
One thing I'm noticing though, with most sequencer tools (even in other DAWs), is the absence of a note start offset parameter, per note. There's often times I'd prefer certain note not hit perfectly on the grid, and by a specific amount (not using a global swing).
I wish someone could resume development of MegaBaby and add more options.
|
|
|
04-04-2024, 06:58 AM
|
#25
|
Human being with feelings
Join Date: Mar 2007
Posts: 4,018
|
Quote:
Originally Posted by Ozman
One thing I'm noticing though, with most sequencer tools (even in other DAWs), is the absence of a note start offset parameter, per note. There's often times I'd prefer certain note not hit perfectly on the grid, and by a specific amount (not using a global swing).
I wish someone could resume development of MegaBaby and add more options.
|
The note start offset is present in Megababy sequencer
Shift + Left click/drag left/right: Adjust note start offset
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 01:31 PM.
|