Old 09-08-2018, 05:10 AM   #1
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default Scripts using Pickle

Hola!

Can anyone hint/hit me with name on a reascript(lua) using Pickle?
I am trying Pickle out and want to look how others are using it.
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 09-08-2018, 08:22 AM   #2
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,900
Default

Never heard of that,


if you speak about pickle.lua table serialization module, maybe table.concat native function in Lua 5.3 is enough.


http://lua-users.org/wiki/TableLibraryTutorial
X-Raym is offline   Reply With Quote
Old 09-08-2018, 08:47 AM   #3
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
Default

@X-Raym: He needs to serialize a bunch of data for storing in an extstate and reloading.

I believe Sexan uses Pickle - have a look at his Track Versions script, maybe.
__________________
I'm no longer using Reaper or working on scripts for it. Sorry. :(
Default 5.0 Nitpicky Edition / GUI library for Lua scripts / Theory Helper / Radial Menu / Donate
Lokasenna is offline   Reply With Quote
Old 09-09-2018, 02:36 AM   #4
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Quote:
Originally Posted by Lokasenna View Post
@X-Raym: He needs to serialize a bunch of data for storing in an extstate and reloading.
Spot on Lokasenna! :-)

Quote:
I believe Sexan uses Pickle - have a look at his Track Versions script, maybe.
Thanks for tip - will check.

My plan A is to use pickle.lua but I got some errors in pickle code after
changing table.getn (deprecated) to #table so I thought I could check
some others scripts to see how they use pickle.lua.

My plan B is to use this:
Code:
 
 reaper.SetProjExtState(0,"ToDoList",1,tostring(GUI.table_list(items)))
Shouldn't that "tostring(GUI.table_list(items))" make a string with table content?

By the way - I watched some other examples with SetProjExtState that used "for k, v in pairs(s) do"
but if I want to save just ONE long string in SetProjExtState do I really need to do a for loop?
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 09-09-2018, 04:00 AM   #5
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

I got Pickle running (YEAJJ!!) - but as usual another thing shows up! ;-)

When closing project starting a new project my scriptwindow
stays open!? Shouldn't it close before project is closed?

Edit: I have used the following - none is closing my script window.

Code:
local function theEnd ()
  saveToProjExtState()
  --GUI.Window:close()
    gfx.exit()
  --GUI.exit()
  --GUI.quit = true

end


reaper.atexit(theEnd)
Maybe its a Linux-thing?
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify

Last edited by tompad; 09-09-2018 at 05:41 AM.
tompad is offline   Reply With Quote
Old 09-09-2018, 07:39 AM   #6
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
Default

Quote:
Originally Posted by tompad View Post
Code:
 
 reaper.SetProjExtState(0,"ToDoList",1,tostring(GUI.table_list(items)))
Shouldn't that "tostring(GUI.table_list(items))" make a string with table content?
Yes, GUI.table_list will do that. It also adds pretty indenting though, which might cause trouble.

However, the logic is pretty simple:

Code:
local settings = {
  flag1 = true,
  flag2 = false,
  param1 = 4,
  param2 = 5,
  param3 = "tompad"
}

local function settingsToStr()
  local strs = {}
  for k, v in pairs(settings) do
    strs[#strs+1] = k .. "=" .. tostring(v)
  end
  return table.concat(strs, ",")
end

Msg(settingsToStr())
--> flag1=true,param2=5,param1=4 ...etc...

-- Note that pairs() doesn't maintain any sort of order in the
-- table, but Lua doesn't either so it doesn't matter.

local function formatValue(v)
  if tonumber(v) then
    return tonumber(v)
  elseif (v == "true" or v == "false") then
    return v == "true"
  else
    return v
  end
end

local function settingsFromStr(str)
  for k, v in str:gmatch("([^,]+)=([^,]+)") do
    settings[k] = formatValue(v)
  end
end
Quote:
By the way - I watched some other examples with SetProjExtState that used "for k, v in pairs(s) do"
but if I want to save just ONE long string in SetProjExtState do I really need to do a for loop?
If you know it's one long string, then no - you should be able to plop it straight in there. Might need to replace any \ns with a placeholder and then swap them back on reload - I'm not sure.

Quote:
Originally Posted by tompad View Post
When closing project starting a new project my script window says open
Reaper doesn't send any events for the script to know that you've changed projects. AFAIK your best option would be to make use of the SWS Project Startup action or whatever it's called, but I don't think you'd be able to save into the previous project's ExtState that way.
__________________
I'm no longer using Reaper or working on scripts for it. Sorry. :(
Default 5.0 Nitpicky Edition / GUI library for Lua scripts / Theory Helper / Radial Menu / Donate

Last edited by Lokasenna; 09-09-2018 at 07:53 AM.
Lokasenna is offline   Reply With Quote
Old 09-09-2018, 07:50 AM   #7
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,984
Default

Quote:
Reaper doesn't send any events for the script to know that you've changed projects
in some cases this can be workarounded by tracking project name/path by EnumProjects() / GetProjectName()
mpl is offline   Reply With Quote
Old 09-09-2018, 07:52 AM   #8
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
Default

Quote:
Originally Posted by mpl View Post
in some cases this can be workarounded by tracking project name/path by EnumProjects() / GetProjectName()
I thought of that, but in this case you'd still be in the new project without having a chance to save your ExtState in the old one.
__________________
I'm no longer using Reaper or working on scripts for it. Sorry. :(
Default 5.0 Nitpicky Edition / GUI library for Lua scripts / Theory Helper / Radial Menu / Donate
Lokasenna is offline   Reply With Quote
Old 09-09-2018, 09:27 AM   #9
spk77
Human being with feelings
 
Join Date: Aug 2012
Location: Finland
Posts: 2,668
Default

Quote:
Originally Posted by mpl View Post
in some cases this can be workarounded by tracking project name/path by EnumProjects() / GetProjectName()
Quote:
Originally Posted by Lokasenna View Post
I thought of that, but in this case you'd still be in the new project without having a chance to save your ExtState in the old one.
That is really annoying...here's an API request: https://forum.cockos.com/showthread....91#post1968991

Quote:
Originally Posted by spk77 View Post
Two functions that would be nice to have:
  1. reaper.atprojectexit(ReaProject proj, function)
    • Similar to reaper.atexit(function), but "function" would be run when the project is closing
  2. reaper.SetProjExtState(string projectfilename, string extname, string key, string value)
    • SetProjExtState for offline project files
spk77 is offline   Reply With Quote
Old 09-10-2018, 04:23 AM   #10
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Quote:
Originally Posted by spk77 View Post
That is really annoying...here's an API request: https://forum.cockos.com/showthread....91#post1968991
+1! Please, please please!

Where can I vote for this!?


Edit:
Or maybe I need to get back to saving to external file instead of waiting for a new API.
I guess Reaper devs have more importent things to do with the upcoming Reaper 6.
Its a shame though - I just managed to use Pickle and save to ProjExtState ;-(
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify

Last edited by tompad; 09-11-2018 at 07:55 AM.
tompad is offline   Reply With Quote
Old 09-13-2018, 10:57 PM   #11
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Made a poll at Feature Request:

https://forum.cockos.com/showthread.php?t=211132

Lets go and vote!
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 09-14-2018, 06:22 AM   #12
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,630
Default

Quote:
Originally Posted by mpl View Post
in some cases this can be workarounded by tracking project name/path by EnumProjects() / GetProjectName()
Give me a few more weeks, I have some functions for tracking changed/added/deleted Projecttabs in my collection of helper-functions, that I'm going to release within the next few weeks.
Still finishing up the documentation for that...

The function in question will be:

Quote:
boolean retval, integer countUnorderedProj, array unorderedProj, integer countNewProj, array newProj, integer countClosedProj, array closedProj = ultraschall.CheckForChangedProjectTabs(boolean update)

Returns if projecttabs have been changed due reordering, new projects or closed projects, since last calling this function.
Set update=true to update Ultraschall's internal project-monitoring-list or it will only return the changes since starting the API in this script or since the last time you used this function with parameter update set to true!

Returns false, -1 in case of error.

Returnvalues:
boolean retval - true, no changes in the projecttabs at all; false, either order, newprojects or closed project-changes
integer countUnorderedProj - the number of unordered projects
array unorderedProj - the unordered projects as ReaProjects
integer countNewProj - the number of new projects
array newProj - the new projects as ReaProjects
integer countClosedProj - the number of closed projects
array closedProj - the closed projects as ReaProjects

Parameters:
boolean update - true, update Ultraschall's internal projecttab-monitoring-list to the current state of all tabs
- false, don't update the internal projecttab-monitoring-list, so it will keep the "old" project-tab-state as checking-reference
Meo-Ada Mespotine is offline   Reply With Quote
Old 09-14-2018, 06:57 AM   #13
ThrashJazzAssassin
Human being with feelings
 
ThrashJazzAssassin's Avatar
 
Join Date: Oct 2010
Location: Scotland
Posts: 422
Default

There are a lot of references to Pickle in LBX Stripper
__________________
TJA MIDI JSFX | REAPER-OSC-panels | erthoide
ThrashJazzAssassin is offline   Reply With Quote
Old 09-15-2018, 04:19 AM   #14
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Quote:
Originally Posted by ThrashJazzAssassin View Post
There are a lot of references to Pickle in LBX Stripper
Thanks TrashJazzAssassin! I have fixed to use Pickle in my ToDoList-script,
however there where some issues when using using ProjExtState and changing
(closing) projects...Mespotine maybe have a solution though....I will check
it out when its ready - meanwhile GO AND VOTE! ;-)

Made a poll at Feature Request:

https://forum.cockos.com/showthread.php?t=211132
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 09-15-2018, 04:21 AM   #15
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Quote:
Originally Posted by mespotine View Post
Give me a few more weeks, I have some functions for tracking changed/added/deleted Projecttabs in my collection of helper-functions, that I'm going to release within the next few weeks.
Sounds very interesting! Where is respotory? Github?
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 09-16-2018, 12:56 PM   #16
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,630
Default

It's not online yet, but I estimate I'll be ready mid-october. Just finishing docs and doing last bugfixes.
Will be worth the wait
Meo-Ada Mespotine is offline   Reply With Quote
Old 09-17-2018, 04:26 PM   #17
lb0
Human being with feelings
 
Join Date: Apr 2014
Posts: 4,175
Default

Quote:
Originally Posted by ThrashJazzAssassin View Post
There are a lot of references to Pickle in LBX Stripper
Yep - I use it for some things still - but moved away from it for large amounts of data to my own dedicated routines (saving in files rather than the project) as this worked much much faster for my needs. For backwards compatibility I still use it for loading very old strips.

Regarding issues with changing projects (and using project tabs) - I solved this by having the script detect that the project has changed and saving the data before resetting the script for the current active project.
__________________
Projects - Reascripts - Lua:
Smart Knobs 2 | LBX Stripper | LBX Floating FX Positioner
Donate via Paypal | LBX Tools Website
lb0 is offline   Reply With Quote
Old 09-19-2018, 09:58 AM   #18
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Quote:
Originally Posted by lb0 View Post
Regarding issues with changing projects (and using project tabs) - I solved this by having the script detect that the project has changed and saving the data before resetting the script for the current active project.
Could you explain more? How can I detect that the project has changed?
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 09-19-2018, 11:37 AM   #19
lb0
Human being with feelings
 
Join Date: Apr 2014
Posts: 4,175
Default

Quote:
Originally Posted by tompad View Post
Could you explain more? How can I detect that the project has changed?
I created a unique (random) project id for the active project.

If one doesn't exist I create it and then save it in the project state. Also storing it in a variable.

Then every iteration of the defer loop - I would check the variable against the project state one. If they are different then I can assume it's a different project - and save the data before resetting for the different project (creating a new projectid if one doesn't exist, or reloading any necessary variables for an existing project from the state).

That's the gist anyway... I might have missed something vital as I cannot remember exactly how it worked when storing all the data in the project state, that got too slow for me - so I use external files instead.


When using external files to store data -

Things get more complex as you need to detect if the Save As or Save As New has been called - as the projectid will remain the same - then you also need to look at the project name also. This is not required if you're storing all data in the project state - but is required if you choose to use external data files.
__________________
Projects - Reascripts - Lua:
Smart Knobs 2 | LBX Stripper | LBX Floating FX Positioner
Donate via Paypal | LBX Tools Website
lb0 is offline   Reply With Quote
Old 09-19-2018, 12:57 PM   #20
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Quote:
Originally Posted by lb0 View Post
I created a unique (random) project id for the active project.

If one doesn't exist I create it and then save it in the project state. Also storing it in a variable.

Then every iteration of the defer loop - I would check the variable against the project state one. If they are different then I can assume it's a different project - and save the data before resetting for the different project (creating a new projectid if one doesn't exist, or reloading any necessary variables for an existing project from the state).
Thanks for telling this - interesting. The defer loop is something new for
me, have to take a look at it.
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 09-20-2018, 09:27 AM   #21
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,630
Default

Some basics:
Defer-loops are an alternative to while/for-loops. While and for loops, when running too long, "block" the GUI of Reaper at some point.
To overcome this, you can use defer-loops.
It will end the script, when reaching the defer-function, so Reaper can do the other tasks(other running scripts, updating GUI, etc) and return to your script, restarting it at the function you gave to the defer-function.
e.g. reaper.defer(main) will restart executing the script the next time from the function main().

The following code updates a counter and displays it into Reaper-Console-window, by running main().

Code:
Counter=0

function main()
   reaper.ClearConsole()
   reaper.ShowConsoleMsg(Counter)
   Counter=Counter+1

  -- now, we do the defering/looping
   reaper.defer(main)
end

main()

Some additional things:
defer-scripts are run about 30 times a second, so the execution of the main-function is never more often than 30 times. If you want to execute the code in the main function more often, you need to put it into a for-loop:

Code:
Counter=0

function main()
  for i=0, 10 do -- now we add to variable Counter 10 times more often per 
                 -- second,
                 -- means 300 times, as opposed to 30 times in the example 
                 -- before
    reaper.ClearConsole()
    reaper.ShowConsoleMsg(Counter)
    Counter=Counter+1

    -- now, we do the deferring/looping
    reaper.defer(main)
  end
end

main()
You can also use while-loops to never run the loop longer than a specific time. Use reaper.time_precise() to define a starting and endtime.


Another thing is, the first time the script is executed, it will run completely, until the end. From the second time onward, it will run only the deferred function.

Code:
Counter=0

function main()
  for i=0, 10 do -- now we add to variable Counter 10 times more often per 
                 -- second,
                 -- means 300 times, as opposed to 30 times in the example 
                 -- before
    reaper.ClearConsole()
    reaper.ShowConsoleMsg(Counter)
    Counter=Counter+1

    -- now, we do the deferring/looping
    reaper.defer(main)
  end
end

main()

reaper.MB("This Messagebox is shown only in the first run of the script!","",0)
Last thing is:
With every defer-cycle, the variables and returned values by functions will be updated. So with every defer-cycle, reaper.GetPlayPosition() will return the updated position of the playcursor.
These will be updated once, before going into the deferred-function. So the values stay the same, until they are updated the next defer-cycle.

Code:
function main()
   reaper.ClearConsole()
   reaper.ShowConsoleMsg(reaper.GetPlayPosition().."\n")
   for i=0, 10000 do end  
   reaper.ShowConsoleMsg(reaper.GetPlayPosition()) -- shows the same playposition as the ShowConsoleMsg() before, 
                                                   -- even if playposition has changed during the for-loop.
   
   -- now, we do the deferring/looping
   reaper.defer(main)
end

main()
PS:
When you want to run the defer-script only a limited number of times, use an if in the defer-line

Code:
Counter=0

function main()
   reaper.ClearConsole()
   reaper.ShowConsoleMsg(Counter)
   Counter=Counter+1

  -- now, we do the defering/looping
   if Counter<100 then reaper.defer(main) end -- will defer, until Counter is 100
end

main()

Last edited by Meo-Ada Mespotine; 11-12-2018 at 03:06 AM.
Meo-Ada Mespotine is offline   Reply With Quote
Old 09-20-2018, 11:13 AM   #22
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Quote:
Originally Posted by mespotine View Post
Some basics:
Defer-loops are an alternative to while/for-loops. While and for loops, when running too long, "block" the GUI of Reaper at some point.
To overcome this, you can use defer-loops.
It will end the script, when reaching the defer-function, so Reaper can do the other tasks(other running scripts, updating GUI, etc) and return to your script, restarting it at the function you gave to the defer-function.
e.g. reaper.defer(main) will restart executing the script the next time from the function main().

Vooooo! That was a lot to digest! But thanks anyway! :-)
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 09-23-2018, 10:19 AM   #23
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

@mespotine: Must I place the defer code in main or can I make
another function with defer?

Edit:
I have already a GUI.Main in my code - can I add another Main() then
or will it mess everything up??


I am thinking on using lb0's method to make my script
save to projextstate if project changes (new proj) and
then close my script window and reset the values in script.

Edit: ...or I wait a while for your helper functions :-)
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify

Last edited by tompad; 09-29-2018 at 07:05 AM.
tompad is offline   Reply With Quote
Old 09-04-2020, 06:23 AM   #24
lexaproductions
Human being with feelings
 
Join Date: Jan 2013
Posts: 1,128
Default

Quote:
Originally Posted by mespotine View Post
Some additional things:
defer-scripts are run about 30 times a second, so the execution of the main-function is never more often than 30 times. If you want to execute the code in the main function more often, you need to put it into a for-loop:

Code:
Counter=0

function main()
  for i=0, 10 do -- now we add to variable Counter 10 times more often per 
                 -- second,
                 -- means 300 times, as opposed to 30 times in the example 
                 -- before
    reaper.ClearConsole()
    reaper.ShowConsoleMsg(Counter)
    Counter=Counter+1

    -- now, we do the deferring/looping
    reaper.defer(main)
  end
end

main()
...

Last thing is:
With every defer-cycle, the variables and returned values by functions will be updated. So with every defer-cycle, reaper.GetPlayPosition() will return the updated position of the playcursor.
These will be updated once, before going into the deferred-function. So the values stay the same, until they are updated the next defer-cycle.

Code:
function main()
   reaper.ClearConsole()
   reaper.ShowConsoleMsg(reaper.GetPlayPosition().."\n")
   for i=0, 10000 do end  
   reaper.ShowConsoleMsg(reaper.GetPlayPosition()) -- shows the same playposition as the ShowConsoleMsg() before, 
                                                   -- even if playposition has changed during the for-loop.
   
   -- now, we do the deferring/looping
   reaper.defer(main)
end

main()
[/code]

Hey Mespotine,
Thanks for this explanation. I'm trying to make myself a very precise "On Next Measure" function, will this work? I'm not sure it does:

Code:
function on_NextMeasure(outfunction, last_msr)
	for i = 1, 1 do
		local isStopped = reaper.GetPlayState() == 0
		if isStopped then return end
		local _, msr = reaper.TimeMap2_timeToBeats(0, reaper.GetPlayPosition()+0.1) -- added 0.1 as timing adjust
		if last_msr and last_msr ~= msr then      -- if the measure number changed we're in another measure
			outfunction()
			return
		end
		last_msr = msr
	end
	reaper.defer(function() on_NextMeasure(outfunction, last_msr) end)
end
I need my "msr" variable to be updated and polled as fast as I can to get sub-milliseconds precision. But right now, it seems to be a hit and miss.

Thanks for your time.
lexaproductions is offline   Reply With Quote
Old 10-05-2020, 06:31 PM   #25
lexaproductions
Human being with feelings
 
Join Date: Jan 2013
Posts: 1,128
Default

Bump

I hope Mespotine will see this...
lexaproductions 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 11:00 PM.


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