Go Back   Cockos Incorporated Forums > REAPER Forums > REAPER Bug Reports

Reply
 
Thread Tools Display Modes
Old 11-12-2022, 12:27 AM   #1
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,878
Default Undo doesn't actually undo for various stuff (FIXED)

In the persistent script I`m doing something like

reaper.Undo_BeginBlock2( 0)
-- do LOT of stuff including linking parameters, replacing RS5k samples, setting FX parameters, etc
reaper.Undo_EndBlock2( 0, 'do various stuff', 0xFFFFFFFF )

What is expected:
- print project state at Undo_BeginBlock2
- prevent any ReaScript or triggered Action write undo history
- print project state again (or print only defined stuff if I set flags)
- further undo return me back to firstly printed project state

What happed:
- on some actions it shows undo entry is shon in top menu lane, but it doesn`t actually trigger undo history entry.



Specifically I came from here: https://github.com/MichaelPilyavskiy...ipts/issues/29, https://github.com/MichaelPilyavskiy...ipts/issues/30

Last edited by mpl; 11-25-2022 at 10:10 PM.
mpl is offline   Reply With Quote
Old 11-12-2022, 08:18 AM   #2
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,346
Default

When debugging undo related things, set "debug=1" in reaper.ini, restart REAPER, and you'll see an added column in the undo history which lets you see a summary of what changed.

Anyway, looks like perhaps those new param.X.* APIs need to mark the FX dirty for undo purposes, fixing that (if there are other places let me know).
Justin is offline   Reply With Quote
Old 11-17-2022, 07:52 AM   #3
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,878
Default

Thanks for debug tip!
The issue on the github started from no undo when changing rs5k sample via SetNamedConfigParam / FILE0. So it seems this function should produce undo step (i guess I should use fx flag for undo in this case or it is ok to sell all flags on?)
mpl is offline   Reply With Quote
Old 11-24-2022, 11:46 AM   #4
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,878
Default

In clean RS5k manager drop sample on pad:
- write ext state data to parent (mark it parent)

Code:
 <TRACK {8B695594-C8A9-4BBE-977F-131439A76CAB}
...
     VOLPAN 1 0 -1 -1 1
     MUTESOLO 0 0 0
     IPHASE 0
     PLAYOFFS 0 1
-    ISBUS 0 0
-    BUSCOMP 0 0 0 0 0
+    ISBUS 1 1
+    BUSCOMP 1 0 0 0 0
     SHOWINMIX 1 0.6667 0.5 1 0.5 -1 -1 -1
     REC 0 0 1 0 0 0 0 0
     VU 2
...
     NCHAN 2
     FX 1
     TRACKID {8B695594-C8A9-4BBE-977F-131439A76CAB}
     PERF 0
+    <EXT
+    <BIN MPLRS5KMAN
+    UEFSRU5UX0RSUkFDS1NISUZUIDM2ClBBUkVOVF9MQVNUQUNUSVZFTk9URSA0OApQQVJFTlRfVEFCU1RBVEVGTEFHUyAxMwpQQVJFTlRfTUFDUk9DTlQgMTYKUEFSRU5UX0xBU1RBQ1RJVkVNQUNSTyAtMQpQQVJFTlRfREFUQUJBU0VNQVAg
+    >
+    MPLRS5KMAN_VERSION 3.0
+    >
     UNDO_HAS_TRACKENV
     MIDIOUT -1
     MAINSEND 1 0
- insert child track / add rs5k instance

Code:
+<TRACK {F584DC3B-82AC-421C-8A0D-08CF261F721A}
+NAME "1 F1"
+PEAKCOL 16576
+BEAT -1
+AUTOMODE 0
+VOLPAN 1 0 -1 -1 1
+MUTESOLO 0 0 0
+IPHASE 0
+PLAYOFFS 0 1
+ISBUS 0 0
+BUSCOMP 0 0 0 0 0
+SHOWINMIX 1 0.6667 0.5 1 0.5 -1 -1 -1
+REC 0 0 1 0 0 0 0 0
+VU 2
+TRACKHEIGHT 0 0 0 0 0 0
+INQ 0 0 0 0.5 100 0 0 100
+NCHAN 2
+FX 1
+TRACKID {F584DC3B-82AC-421C-8A0D-08CF261F721A}
+PERF 0
+<EXT
+MPLRS5KMAN_CHILD_INSTR_FXGUID {1733F22E-715B-40A0-8EBB-883FCE3C820A}
+MPLRS5KMAN_CHILD_ISRS5K 1
+MPLRS5KMAN_CHILD_PARENTGUID {8B695594-C8A9-4BBE-977F-131439A76CAB}
+MPLRS5KMAN_NOTE 48
+MPLRS5KMAN_SAMPLELEN 0.85705215419501
+MPLRS5KMAN_TYPE_REGCHILD 1
+MPLRS5KMAN_VERSION 3.0
+>
+UNDO_HAS_TRACKENV
+AUXRECV 2 0 1 0 0 0 0 -1 0 -1:U 0 -1 ''
+MIDIOUT -1
+<MIDINOTENAMES
+-1 48 "1 F1" 0 48
+>
+MAINSEND 1 0
+>
Code:
+SHOW 0
+LASTSEL 0
+DOCKED 0
+BYPASS 0 0 0
+FXID_NEXT {1733F22E-715B-40A0-8EBB-883FCE3C820A}
+<VST "VSTi: ReaSamplOmatic5000 (Cockos)" reasamplomatic.dll 0 "" 1920167789<56535472736F6D72656173616D706C6F> ""
+bW9zcu5e7f4AAAAAAgAAAAEAAAAAAAAAAgAAAAAAAAANAQAAAQAAAAAAEAA=
+AAAAAAAAAPA/AAAAAAAA4D8AAAAAAADwPwAAAAAAAAAAAAAAAAAA8D+amZmZmZmxP83MzMzMzOs/AAAAAAAAAAAcx3Ecx3HcP/yp8dJNYkA//Knx0k1iQD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwPwAAAAAAAOA/AQAAAAAAAAAAAAAAAAAAAAAA8D9AAAAAVVVVVVVVxT//////CAQCgUAggD8AAAAAAADwPwAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAADOpCEhGmWQPwAAAAAAAPA//Knx0k1iMD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
+AAAQAAAA
+>
+FLOATPOS 0 0 0 0
+WAK 0 0
- set sample
Code:
[nothing]
- create midi bus (extstate mark it bus) and send to child track


Code:
+<TRACK {BA201625-B764-4BC4-9EC4-9C910E3528B0}
+NAME "MIDI bus"
+PEAKCOL 16576
+BEAT -1
+AUTOMODE 0
+VOLPAN 1 0 -1 -1 1
+MUTESOLO 0 0 0
+IPHASE 0
+PLAYOFFS 0 1
+ISBUS 2 -1
+BUSCOMP 0 0 0 0 0
+SHOWINMIX 1 0.6667 0.5 1 0.5 -1 -1 -1
+REC 1 5088 1 0 0 0 0 0
+VU 2
+TRACKHEIGHT 0 0 0 0 0 0
+INQ 0 0 0 0.5 100 0 0 100
+NCHAN 2
+FX 1
+TRACKID {BA201625-B764-4BC4-9EC4-9C910E3528B0}
+PERF 0
+<EXT
+MPLRS5KMAN_CHILD_PARENTGUID {8B695594-C8A9-4BBE-977F-131439A76CAB}
+MPLRS5KMAN_CHOKE_GUID {0BE51E6B-533E-4D97-B88B-83BC83E13127}
+MPLRS5KMAN_MIDIBUS 1
+MPLRS5KMAN_VERSION 3.0
+>
+UNDO_HAS_TRACKENV
+MIDIOUT -1
+<MIDINOTENAMES
+-1 48 "1 F1" 0 48
+>
+MAINSEND 1 0
+>
- add jsfx to midi bus
Code:
+SHOW 0
+LASTSEL 0
+DOCKED 0
+BYPASS 0 0 0
+FXID_NEXT {0BE51E6B-533E-4D97-B88B-83BC83E13127}
+<JS "MPL Scripts\FX specific\mpl_RS5K_manager_MIDIBUS_choke.jsfx" ""
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+>
+FLOATPOS 0 0 0 0
+WAK 0 0
SetNamedConfig does NOT mark FX dirty:
mpl is offline   Reply With Quote
Old 11-24-2022, 11:52 AM   #5
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,346
Default

Can you give me a minimal example script to test with
Justin is offline   Reply With Quote
Old 11-24-2022, 12:20 PM   #6
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,878
Default

new project - add new track - selecting this track:
Code:
track = reaper.GetTrack(0,0)
if track then reaper.TrackFX_AddByName( track, 'ReaSamplOmatic5000 (Cockos)', false, 1 )end
then

Code:
track = reaper.GetTrack(0,0)
reaper.Undo_BeginBlock2( 0 ) reaper.TrackFX_SetNamedConfigParm( track, 0, 'FILE', 'C:/01-180324_1122.wav' ) reaper.Undo_EndBlock2( 0, 'test', -1 )
undoing this remove rs5k from track instead reverting empty sampler (or previous sample if it was set)

EDIT:
damn nevermind, I forgot reaper.TrackFX_SetNamedConfigParm( track, 0, 'DONE', '' ) let me test it with confirming like that
edit2:
nope I had this in the code, it seems I need to dig it further https://github.com/MichaelPilyavskiy...und).lua#L3217
mpl is offline   Reply With Quote
Old 11-24-2022, 12:26 PM   #7
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,878
Default

The issue is there are lot of things happened when dropping sample on pad, thats why I supposed I can just bound, say some_function() with the undo/endblock and expect it just roughly print project (or track or FX completely or FX state) state before and after

shortly it is:
Code:
                               onmousefiledrop = function() 
                                                    reaper.Undo_BeginBlock2( 0)
                                                    DATA2:Actions_PadOnFileDrop(note) 
                                                    reaper.Undo_EndBlock2( 0, 'RS5k manager / Pad / Drop file', 0xFFFFFFFF )--                                          reaper.Undo_BeginBlock2( 0)
                                                  end,
->

Code:
  -----------------------------------------------------------------------
  function DATA2:Actions_PadOnFileDrop(note, layer, filepath0) 
    if not DATA2.tr_valid then return end
    
    -- validate additional stuff
    DATA2:TrackDataRead_ValidateMIDIbus()
    SetMediaTrackInfo_Value( DATA2.tr_ptr, 'I_FOLDERCOMPACT',1 ) -- folder compacted state (only valid on folders), 0=normal, 1=small, 2=tiny children
    DATA2:TrackDataRead(DATA2.tr_ptr)
    -- get fp
      if filepath0 then 
        DATA2:Actions_PadOnFileDrop_Sub(note, layer, filepath0)
       else
        for i =1, #DATA.GUI.droppedfiles.files+1 do
          local filepath = DATA.GUI.droppedfiles.files[i-1]
          DATA2:Actions_PadOnFileDrop_Sub(note+i-1, layer, filepath)
        end
      end
      
    -- refresh data
      DATA2:TrackDataRead(DATA2.tr_ptr)
      DATA2.PARENT_LASTACTIVENOTE = note
      DATA2.PARENT_LASTACTIVENOTE_layer = layer
      DATA2:TrackDataWrite(_,{master_upd=true})
      DATA_RESERVED_ONPROJCHANGE(DATA)
  end

->

Code:
  -----------------------------------------------------------------------
  function DATA2:Actions_PadOnFileDrop_Sub(note, layer, filepath)
    if not DATA2.tr_valid == true then return end

    if not layer then layer =1 end
    DATA2:TrackDataWrite(_,{master_set=true})  -- make sure folder is parent
    DATA2:TrackDataRead_ValidateMIDIbus()
    
      -- add new non-device child
    if not DATA2.notes[note] then
      SetMediaTrackInfo_Value( DATA2.tr_ptr, 'I_FOLDERDEPTH', 1 ) -- make sure parent folder get parent ono adding first child
      local new_tr = DATA2:Actions_PadOnFileDrop_AddChildTrack()  -- set_currentparentforchild / setchild
      DATA2:Actions_PadOnFileDrop_ExportToRS5k(new_tr, filepath,note) 
      DATA2:Actions_PadOnFileDrop_AddMIDISend(new_tr)
      DATA2:TrackDataWrite(new_tr, {setnote_ID=note})
      DATA2:TrackDataRead_GetChildrens() 
      DATA_RESERVED_ONPROJCHANGE(DATA)
      local filepath_sh = GetShortSmplName(filepath) if filepath_sh:match('(.*)%.[%a]+') then filepath_sh = filepath_sh:match('(.*)%.[%a]+') end 
        SetTrackMIDINoteNameEx( 0,DATA2.MIDIbus.ptr, note, -1, filepath_sh) 
        SetTrackMIDINoteNameEx( 0,new_tr, note, -1, filepath_sh)
      return
    end
    
    -- replace existing sample into 1st layer 
    if DATA2.notes[note] and not DATA2.notes[note].TYPE_DEVICE and DATA2.notes[note].layers[1] and layer == 1 then
      DATA2:Actions_PadOnFileDrop_ReplaceRS5kSample(note, 1, filepath) 
      DATA2:TrackDataRead_GetChildrens() 
      DATA_RESERVED_ONPROJCHANGE(DATA)
      local filepath_sh = GetShortSmplName(filepath) if filepath_sh:match('(.*)%.[%a]+') then filepath_sh = filepath_sh:match('(.*)%.[%a]+') end SetTrackMIDINoteNameEx( 0,DATA2.MIDIbus.ptr, note, -1, filepath_sh)  
      return 
    end
    
    -- create device / move first layer to a device
    if DATA2.notes[note] and not DATA2.notes[note].TYPE_DEVICE and layer ~= 1 then
      DATA2:Actions_PadOnFileDrop_ConvertChildToDevice(note)  
      SetTrackMIDINoteNameEx( 0,DATA2.MIDIbus.ptr, note, -1, 'Note '..note)  
      local new_tr = DATA2:Actions_PadOnFileDrop_AddChildTrack(DATA2.notes[note].devicetr_ID) 
      if new_tr then 
        DATA2:Actions_PadOnFileDrop_ExportToRS5k(new_tr, filepath, note) 
        DATA2:Actions_PadOnFileDrop_AddMIDISend(new_tr)
        DATA2:TrackDataWrite(new_tr, {set_devicechild_deviceGUID=DATA2.notes[note].tr_GUID})
        DATA2:TrackDataWrite(new_tr, {setnote_ID=note})
      end
      DATA2:TrackDataRead_GetChildrens() 
      DATA_RESERVED_ONPROJCHANGE(DATA)
      return
    end
    
    -- replace device existing sample in specific layer
    if DATA2.notes[note] and DATA2.notes[note].TYPE_DEVICE == true and DATA2.notes[note].layers and DATA2.notes[note].layers[layer] then 
      DATA2:Actions_PadOnFileDrop_ReplaceRS5kSample(note,layer,filepath)
      DATA2:TrackDataRead_GetChildrens() 
      DATA_RESERVED_ONPROJCHANGE(DATA)
      return
    end      
    
    -- add  new layer to device
    if DATA2.notes[note] and DATA2.notes[note].TYPE_DEVICE == true and DATA2.notes[note].layers and not DATA2.notes[note].layers[layer] then  
      local devicetr_ID = DATA2.notes[note].devicetr_ID
      local new_tr = DATA2:Actions_PadOnFileDrop_AddChildTrack(devicetr_ID) 
      if new_tr then
        DATA2:Actions_PadOnFileDrop_ExportToRS5k(new_tr, filepath,note) 
        DATA2:Actions_PadOnFileDrop_AddMIDISend(new_tr)
        DATA2:TrackDataWrite(new_tr, {set_devicechild_deviceGUID=DATA2.notes[note].tr_GUID})
      end
      if layer == 1 and #DATA2.notes[note].layers == 0 then
        SetMediaTrackInfo_Value( DATA2.notes[note].tr_ptr, 'I_FOLDERDEPTH',1 )
        SetMediaTrackInfo_Value( new_tr, 'I_FOLDERDEPTH',-1 )
      end
    end
    
  end
->

Code:
  -----------------------------------------------------------------------  
  function DATA2:Actions_PadOnFileDrop_ExportToRS5k(new_tr, filepath,note)
    if not filepath then return end
    if filepath:match('@fx') then 
      --reaper.Undo_BeginBlock2( 0)
      DATA2:Actions_PadOnFileDrop_ExportFXasDeviceInstrument(new_tr, filepath,note)
      --reaper.Undo_EndBlock2( 0, 'RS5k manager: add FX instrument', 0xFFFFFFFF )
      return
    end
    
    --reaper.Undo_BeginBlock2( 0)
    local instrument_pos = TrackFX_AddByName( new_tr, 'ReaSamplomatic5000', false, 0 ) 
    if instrument_pos == -1 then instrument_pos = TrackFX_AddByName( new_tr, 'ReaSamplomatic5000', false, -1000 ) end 
    if DATA.extstate.CONF_onadd_float == 0 then TrackFX_SetOpen( new_tr, instrument_pos, false ) end
    if DATA.extstate.CONF_onadd_copytoprojectpath == 1 then 
      filepath = DATA2:Actions_PadOnFileDrop_ExportToRS5k_CopySrc(filepath)
    end 
    TrackFX_SetNamedConfigParm( new_tr, instrument_pos, 'FILE0', filepath)
    TrackFX_SetNamedConfigParm( new_tr, instrument_pos, 'DONE', '')      
    TrackFX_SetParamNormalized( new_tr, instrument_pos, 2, 0) -- gain for min vel
    TrackFX_SetParamNormalized( new_tr, instrument_pos, 5, 0.5 ) -- pitch for start
    TrackFX_SetParamNormalized( new_tr, instrument_pos, 6, 0.5 ) -- pitch for end
    TrackFX_SetParamNormalized( new_tr, instrument_pos, 8, 0 ) -- max voices = 0
    TrackFX_SetParamNormalized( new_tr, instrument_pos, 9, 0 ) -- attack
    TrackFX_SetParamNormalized( new_tr, instrument_pos, 11, DATA.extstate.CONF_onadd_obeynoteoff) -- obey note offs
    DATA2:Actions_PadOnFileDrop_setnote_ID(new_tr, instrument_pos, note)
    
    
    -- store external data
    local src = PCM_Source_CreateFromFile( filepath )
    if src then 
      local it_len =  GetMediaSourceLength( src )
      GetSetMediaTrackInfo_String( new_tr, 'P_EXT:MPLRS5KMAN_SAMPLELEN', it_len, true)
      local instrumentGUID = TrackFX_GetFXGUID( new_tr, instrument_pos)
      DATA2:TrackDataWrite(new_tr, {setinstr_FXGUID = instrumentGUID})
      DATA2:TrackDataWrite(new_tr, {setnote_ID=note})
      DATA2:TrackDataWrite(new_tr, {is_rs5k=true})
    end 
    
    
    -- handle track name 
      filepath_sh = GetShortSmplName(filepath)
      if filepath_sh:match('(.*)%.[%a]+') then filepath_sh = filepath_sh:match('(.*)%.[%a]+') end
      if DATA.extstate.CONF_onadd_renametrack==1 then GetSetMediaTrackInfo_String( new_tr, 'P_NAME', filepath_sh, true ) end
      
    --reaper.Undo_EndBlock2( 0, 'RS5k manager: add instrument', 0xFFFFFFFF ) -- reaper.Undo_BeginBlock2( 0)
  end

I double checked I use TrackFX_SetNamedConfigParm/DONE when I replace sample

Last edited by mpl; 11-24-2022 at 12:34 PM.
mpl is offline   Reply With Quote
Old 11-24-2022, 01:36 PM   #8
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,346
Default

so the minimal example…
Justin is offline   Reply With Quote
Old 11-24-2022, 10:30 PM   #9
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,878
Default

Sorry, took me 2 hours to catch it but I cant.
There are lot of stuff happenes. Can I somehow say to REAPER API 'Do not write anything to undo history' inside the code without using defer() tricks BUT at the same time allow to manually bound needed blocks of code with Undo_BeginBlock/Undo_EndBlock? If there was a way, I can test every step with somethings like this:

Code:
function dostuff()
 dostuff_sub1()
 
 reaper.Undo_BeginBlock()
 dostuff_sub2
 reaper.Undo_EndBlock

 reaper.Undo_BeginBlock()
 dostuff_sub3
 reaper.Undo_EndBlock
end


reaper.DisableUndo()
dostuff()
reaper.EnableUndo()
mpl is offline   Reply With Quote
Old 11-25-2022, 06:58 AM   #10
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,346
Default

Thanks -- I think I figured this one out, fixing!
Justin is offline   Reply With Quote
Old 11-29-2022, 01:27 PM   #11
Buy One
Human being with feelings
 
Buy One's Avatar
 
Join Date: Sep 2019
Posts: 925
Default

Wonder if the fix has any bearing on using Undo blocks for general purposes, if there's anything worth knowing
__________________
https://github.com/Buy-One/REAPER-scripts
REAPER is a DAW whose user guide file is larger than its installation file
Buy One is online now   Reply With Quote
Old 11-30-2022, 10:29 AM   #12
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,233
Default

Quote:
Originally Posted by Justin View Post
When debugging undo related things, set "debug=1" in reaper.ini, restart REAPER, and you'll see an added column in the undo history which lets you see a summary of what changed.
Very helpful tip! Is there an official list of Reaper ini flags on the web somewhere?
MonkeyBars is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 07:58 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2023, vBulletin Solutions Inc.