Old 09-08-2018, 05:10 AM   #1
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman 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: 5,151
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: The vast, frozen wasteland of western Canadia.
Posts: 5,552
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.
__________________
Currently enrolled in a coding bootcamp; don't expect timely responses from me.
Default 5.0 Nitpicky Edition / GUI tutorial for Lua / GUI library for Lua scripts / Theory Helper / Radial Menu / Donate / ReaPack
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: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman 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: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman 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: The vast, frozen wasteland of western Canadia.
Posts: 5,552
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.
__________________
Currently enrolled in a coding bootcamp; don't expect timely responses from me.
Default 5.0 Nitpicky Edition / GUI tutorial for Lua / GUI library for Lua scripts / Theory Helper / Radial Menu / Donate / ReaPack

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: 2,135
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()
__________________
SoundCloud | MPL Scripts discussion | ReaPack | Donate
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: The vast, frozen wasteland of western Canadia.
Posts: 5,552
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.
__________________
Currently enrolled in a coding bootcamp; don't expect timely responses from me.
Default 5.0 Nitpicky Edition / GUI tutorial for Lua / GUI library for Lua scripts / Theory Helper / Radial Menu / Donate / ReaPack
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,486
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: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman 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: 299
Default

Made a poll at Feature Request:

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

Lets go and vote!
__________________
ToDoList Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 09-14-2018, 06:22 AM   #12
mespotine
Human being with feelings
 
mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig, Germany
Posts: 513
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
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: 299
Default

There are a lot of references to Pickle in LBX Stripper
__________________
REAPER-OSC-panels
erthoide
ThrashJazzAssassin is online now   Reply With Quote
Old 09-15-2018, 04:19 AM   #14
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman 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: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 09-16-2018, 12:56 PM   #16
mespotine
Human being with feelings
 
mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig, Germany
Posts: 513
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
mespotine is offline   Reply With Quote
Old 09-17-2018, 04:26 PM   #17
lb0
Human being with feelings
 
Join Date: Apr 2014
Posts: 2,691
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:
LBX Stripper | LBX Chaos Engine | LBX Floating FX Positioner | LBX SRD Smart Knobs
Donate via Paypal
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: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman 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: 2,691
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:
LBX Stripper | LBX Chaos Engine | LBX Floating FX Positioner | LBX SRD Smart Knobs
Donate via Paypal
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: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 09-20-2018, 09:27 AM   #21
mespotine
Human being with feelings
 
mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig, Germany
Posts: 513
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 mespotine; 11-12-2018 at 03:06 AM.
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: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman 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: 299
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 Donate Mark4Celest: Frid (i ditt hjärta) Eve & the Fisherman on Spotify

Last edited by tompad; 09-29-2018 at 07:05 AM.
tompad 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 02:09 PM.


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