Old 11-17-2015, 06:05 PM   #1
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default Lua: converting "userdata" variables into strings or numbers..?

How can this be done?

gfx.printf will display them formatted, but tostring, tonumber and string.format don't convert userdata variables correctly or result in an error, and there is no sprintf function in Lua.

I've been reading up on userdata types, but it's not meaning much and I need a solution to this to compare takes with stored takes in ExtState.



>
planetnine is offline   Reply With Quote
Old 11-17-2015, 09:29 PM   #2
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 2,487
Default

Quote:
... to compare takes with stored takes in ExtState
Maybe you should use ItemTake GUIDs?
I guess Reaper userdata used for Reaper objects (items, tracks, projects, accessors, etc) internally only.
__________________
SoundCloud | MPL Scripts discussion | ReaPack | Donate

Last edited by mpl; 11-17-2015 at 09:40 PM.
mpl is offline   Reply With Quote
Old 11-17-2015, 09:59 PM   #3
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,171
Default

I don't know what userdata is but is there an issue or trick with getting MediaItem item out of a table? I was getting something but it was throwing an error. "...Media item expected." New to Lua. Is that what you mean? Use GUID instead of that? Maybe dumb error on my part. Python made no trouble ever.
FnA is offline   Reply With Quote
Old 11-17-2015, 10:05 PM   #4
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 2,487
Default

afaik userdata is type of variable in Lua.

Quote:
Media item expected
You should check is item exists before do something with it.

PHP Code:
item reaper.GetSelectedMediaItem(0,0)
if 
item ~= nil then
  reaper
.SetMediaItemInfo_Value(item'B_MUTE'1)
end 
Here item variable is like temporary userdata [reaper object 0xsomehexstuff], so if you move it, this variable could be changed. But its GUID looks like {A9C706BF-645C-0C44-AD45-E5D60D2B96F0} will be the same.
__________________
SoundCloud | MPL Scripts discussion | ReaPack | Donate

Last edited by mpl; 11-17-2015 at 10:11 PM.
mpl is offline   Reply With Quote
Old 11-17-2015, 10:17 PM   #5
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,171
Default

it was this script from heda's thread. It was where I ended up using 1 or 0 in table instead.

Code:
--Transpose all active takes in selected items v1.lua (requires SWS)
skip_str = "NO_TRP" -- change phrase inside quotes to desired ignore flag for take names

function Fn_Transpose_MIDI()
  local FNG_Take = reaper.FNG_AllocMidiTake(GAT)
  local NoteCount = reaper.FNG_CountMidiNotes(FNG_Take)
  for nc = 1, NoteCount do
    local note = reaper.FNG_GetMidiNote(FNG_Take, nc - 1)
    local pitch = reaper.FNG_GetMidiNoteIntProperty(note, "PITCH")
    reaper.FNG_SetMidiNoteIntProperty(note, "PITCH", pitch + TRP)
  end
  reaper.FNG_FreeMidiTake(FNG_Take)
end

function Fn_Pitch_NonMIDI()
  local w = TRP
  local neg = false
  if w < 0 then
    w = w * (-1)
    neg = true
  end
  while w > 0 do
    if w >= 12 then
      if neg then
        reaper.Main_OnCommand(40516, 0) -- Pitch down octave
      else
        reaper.Main_OnCommand(40515, 0) -- Pitch up octave
      end
      w = w - 12
    else
      if neg then
        reaper.Main_OnCommand(40205, 0) -- Pitch down semitone
      else
        reaper.Main_OnCommand(40204, 0) -- Pitch up semitone
      end
      w = w -1
    end 
  end
end
  
function Fn_Reselect()
  for r = 1, CMI do
    if reselect_t[r] ~= 0 then
      reaper.SetMediaItemSelected(reaper.GetMediaItem(0, r - 1), true)
    end
  end
end

-----------------------------------------------

GUI, RCV = reaper.GetUserInputs("Transpose all active takes", 1, "number of semitones", "")
if RCV == "" or RCV == "0" then
  GUI = false
end

pool_str = ""
reselect_t = {}
  
if GUI then
  reaper.Undo_BeginBlock2(0)
  reaper.PreventUIRefresh(1)
  TRP = tonumber(RCV)
  CMI = reaper.CountMediaItems(0)
  for i = 1, CMI do
    item = reaper.GetMediaItem(0, i - 1)
    if reaper.IsMediaItemSelected(item) then
      GAT = reaper.GetActiveTake(item);
      local name_str = reaper.GetTakeName(GAT)
      local skip1, skip2 = string.find(name_str, skip_str)
      if skip1 then -- unselect NO_TRP
        reselect_t[i] = 1;
        reaper.SetMediaItemSelected(item, false)
      else
        if reaper.TakeIsMIDI(GAT) then
          reselect_t[i] = 1;
          reaper.SetMediaItemSelected(item, false)
          local BR, GUID_str = reaper.BR_GetMidiTakePoolGUID(GAT)          
          if BR then
            short_str = string.sub(GUID_str, 1, 9)
            s1, s2 = string.find(pool_str, short_str)
            if not s1 then
              pool_str = pool_str .. short_str
              Fn_Transpose_MIDI()
            end
          else -- normal MIDI
            Fn_Transpose_MIDI()
          end
        end -- if reaper.TakeIsMIDI(GAT) then
      end -- if skip1 then / else
    else -- not selected
      reselect_t[i] = 0;
    end --if reaper.IsMediaItemSelected(item) then / else
  end -- for r = 1, CMI do
  Fn_Pitch_NonMIDI()
  Fn_Reselect()
  reaper.PreventUIRefresh(-1)
  reaper.Undo_EndBlock2(0, "Transpose All Active Takes", 0)
else
  reaper.Undo_OnStateChange("Transposition Cancelled")
end -- if GUI then
(I don't know how to link to single post. lol)

edit- string was coming back, showing in IDE, but not working. Something to do with void maybe? Sorry, script was obviously shifted around a little and I threw that one out. I'll see how to do it sometime...

Last edited by FnA; 11-17-2015 at 10:37 PM.
FnA is offline   Reply With Quote
Old 11-17-2015, 10:59 PM   #6
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 2,487
Default

I can`t send you pm, so we are already offtop here.
I don`t know what happend above, but take a look at this:

PHP Code:
  -- Transpose all active takes in selected items
  
  
function Fn_Transpose_MIDI(take,user_ret)
    
local FNG_Take reaper.FNG_AllocMidiTake(take)
    
local NoteCount reaper.FNG_CountMidiNotes(FNG_Take)
    for 
nc 1NoteCount do
      
local note reaper.FNG_GetMidiNote(FNG_Takenc 1)
      
local pitch reaper.FNG_GetMidiNoteIntProperty(note"PITCH")
      
reaper.FNG_SetMidiNoteIntProperty(note"PITCH"pitch user_ret)
    
end
    reaper
.FNG_FreeMidiTake(FNG_Take)
  
end
  
  retval
ret reaper.GetUserInputs('Transpose'1'Semitone''')
  if 
retval ~= nil and ret ~= "" then
    
if tonumber(ret) ~= nil then
      reaper
.Undo_BeginBlock2(0)
      
reaper.PreventUIRefresh(1)
      
      
count_sel_items reaper.CountSelectedMediaItems(0)
      if 
count_sel_items ~= nil then
        
for 1count_sel_items do
          
item reaper.GetSelectedMediaItem(0,i-1)
          if 
item ~= nil then
            take 
reaper.GetActiveTake(item)
            if 
take ~= nil then
              
if reaper.TakeIsMIDI(takethen Fn_Transpose_MIDI(take,ret
               else 
                
takepitch reaper.GetMediaItemTakeInfo_Value(take'D_PITCH')
                
reaper.SetMediaItemTakeInfo_Value(take'D_PITCH',takepitch ret)
              
end
            end
          end
          reaper
.UpdateItemInProject(item)
        
end
      end
      
      reaper
.PreventUIRefresh(-1)
      
reaper.Undo_EndBlock2(0"Transpose All Active Takes"0)
    
end
  end 
Is this what you need?
__________________
SoundCloud | MPL Scripts discussion | ReaPack | Donate
mpl is offline   Reply With Quote
Old 11-17-2015, 11:17 PM   #7
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default

Quote:
Originally Posted by mpl View Post
Maybe you should use ItemTake GUIDs?
I guess Reaper userdata used for Reaper objects (items, tracks, projects, accessors, etc) internally only.

Heh, I don't need that kind of persistence!

I'm reading the take under the mouse cursor with Breeder's extensions for the next script to pick up and compare, and I wanted to turn it into a simple string of the number.

gfx.printf will display the take in the gfx window, but tostring outputs "userdata: hhhhhhhh", to number outputs nil, and string.format errors with "expected number, got lightuserdata".

Just want to store the take in ExtState to check if the mouse is still over the same take. Maybe have to mess with string matching, hoped there was a simple formatting trick.

Will look at GUIDs as a storage/comparison solution later on though, mpl, thank you...



>
planetnine is offline   Reply With Quote
Old 11-18-2015, 12:29 AM   #8
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 2,487
Default

Then you definitely should use BR_GetMediaItemTakeGUID
__________________
SoundCloud | MPL Scripts discussion | ReaPack | Donate
mpl is offline   Reply With Quote
Old 11-18-2015, 12:37 AM   #9
planetnine
Human being with feelings
 
planetnine's Avatar
 
Join Date: Oct 2007
Location: Lincoln, UK
Posts: 7,585
Default

Very quick test, it looks like it works, Reading the ExtState I have all the data in the correct format stored that I need

Thanks mpl...



>
planetnine is offline   Reply With Quote
Old 11-22-2015, 05:11 PM   #10
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,171
Default

Sorry for late reply, was away for a while. Thanks for checking out the script. It was actually working already. (it needs the Breeder function to stop pooled items from getting transposed more than once) I was/am just confused as to why I had to resort to getting numbers rather than just getting Media Item. In python you just put them in a list and take them out.

Maybe this is a better example...Edit. Figured it out. Bonehead mistake.

Last edited by FnA; 11-22-2015 at 07:34 PM.
FnA is offline   Reply With Quote
Old 08-06-2019, 02:51 AM   #11
lollo
Human being with feelings
 
Join Date: Jun 2017
Posts: 44
Default

I try to move up this thread.
Here my code
Code:
function msg(xxx)
  reaper.ShowConsoleMsg(xxx)
end
  
msg('')

gGUID = reaper.genGuid('hello!')
msg('I\'m the new GUID generated: ' .. gGUID) 


string = reaper.guidToString(gGUID, '')
-- from API Reference
--string destNeed64 = reaper.guidToString(string gGUID, string destNeed64)

msg('\nConversion: ' .. string)
Of course, without success.
destNeed64? What is it?
lollo is offline   Reply With Quote
Old 08-06-2019, 03:00 AM   #12
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 7,783
Default

Quote:
Originally Posted by lollo View Post
Of course, without success.
destNeed64? What is it?
The code works as expected here. What are you expecting to see or how does it fail for you?

With Lua ReaScript code, the destNeed64 can be just an empty string. And if you provide something else, it is ignored anyway.

Note that in Lua ReaScript, reaper.genGuid returns a string to begin with, so there is no need to do a further conversion of it.
__________________
For info on SWS Reaper extension plugin (including Xenakios' previous extension/actions) :
http://www.sws-extension.org/
https://github.com/Jeff0S/sws
--
Xenakios blog (about HourGlass, Paul(X)Stretch and λ) :
http://xenakios.wordpress.com/

Last edited by Xenakios; 08-06-2019 at 03:06 AM.
Xenakios is offline   Reply With Quote
Old 08-06-2019, 03:27 AM   #13
lollo
Human being with feelings
 
Join Date: Jun 2017
Posts: 44
Default

Thanks Xenakios.

The idea is to create custom GUIDs with some information on them.
These GUIDs will be uniques, of course.

From my previous code I would like to receive as final message, my "hello!"
lollo is offline   Reply With Quote
Old 08-06-2019, 03:40 AM   #14
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 7,783
Default

Quote:
Originally Posted by lollo View Post
The idea is to create custom GUIDs with some information on them.
GUIDs are 128 bit random numbers that don't have any other information. They are used to uniquely identify objects. The object itself has to be stored somewhere else together with its GUID.

The string you have to provide to reaper.genGuid is a "dummy" string like with guidToString, it can be empty and if it is something else, it is just ignored.
__________________
For info on SWS Reaper extension plugin (including Xenakios' previous extension/actions) :
http://www.sws-extension.org/
https://github.com/Jeff0S/sws
--
Xenakios blog (about HourGlass, Paul(X)Stretch and λ) :
http://xenakios.wordpress.com/

Last edited by Xenakios; 08-06-2019 at 03:48 AM.
Xenakios is offline   Reply With Quote
Old 08-06-2019, 04:00 AM   #15
lollo
Human being with feelings
 
Join Date: Jun 2017
Posts: 44
Default

Ok Xenakios! Thanks for your explanation. No custom info, no party!
lollo is offline   Reply With Quote
Old 08-06-2019, 04:01 AM   #16
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 7,783
Default

Quote:
Originally Posted by lollo View Post
No custom info, no party!
What are you actually trying to do?
__________________
For info on SWS Reaper extension plugin (including Xenakios' previous extension/actions) :
http://www.sws-extension.org/
https://github.com/Jeff0S/sws
--
Xenakios blog (about HourGlass, Paul(X)Stretch and λ) :
http://xenakios.wordpress.com/
Xenakios is offline   Reply With Quote
Old 08-06-2019, 06:04 AM   #17
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,078
Default

Sounds like they want to convert data --> randomish characters for storage --> back to data.

Whether or not this is possible depends on what kind of data you need to store. Any userdata references like MediaTracks, MediaItem_Takes, etc. can't be stored AFAIK because they're literally just a pointer to the object's current place in memory - when the project is reloaded, the pointers will all be different.
Lokasenna is offline   Reply With Quote
Old 08-06-2019, 06:13 AM   #18
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 7,783
Default

Quote:
Originally Posted by Lokasenna View Post
Any userdata references like MediaTracks, MediaItem_Takes, etc. can't be stored
The state text chunks could be stored and potentially restored, though...
__________________
For info on SWS Reaper extension plugin (including Xenakios' previous extension/actions) :
http://www.sws-extension.org/
https://github.com/Jeff0S/sws
--
Xenakios blog (about HourGlass, Paul(X)Stretch and λ) :
http://xenakios.wordpress.com/
Xenakios is offline   Reply With Quote
Old 08-06-2019, 06:27 AM   #19
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,078
Default

Quite true. I'm pretty sure that's how Sexan's Track Versions script works.
Lokasenna is offline   Reply With Quote
Old 08-07-2019, 01:55 AM   #20
lollo
Human being with feelings
 
Join Date: Jun 2017
Posts: 44
Default

I wanted to enter some information about the files. Type from which library it came from, the date of import and who imported that file in order that, by another script, to return the complete list of these information.
I tried to do it as test on the track
Code:
function msg(xxx)
  reaper.ShowConsoleMsg(xxx)
end

function TL(nametable)-- array length
  local count = 0
  for _ in pairs(nametable) do count = count + 1 end
  return count
end

track = reaper.GetTrack(0,0)

function GetTrackChunk(track)
  myInfo = {}
  ret, track_chunk = reaper.GetTrackStateChunk(track, "", false)
  for s in string.gmatch(track_chunk, "[^\n]+") do
      table.insert(myInfo, s)
  end
  output = ""
  for i = 1, TL(myInfo) do
      
      if i == 3 then
      -- insert my chunck on 3° place
      output = output .. "MY INFO\n"
      else 
      
      output = output.. myInfo[i]..'\n'
      end
  end
  
  -- set the new info
  reaper.SetTrackStateChunk(track, output, false)
  return output
end
  
msg('')
msg('-------------------------------------------------My list modified-------------------------------------------\n'.. GetTrackChunk(track))

-- read again the info
ret, info = reaper.GetTrackStateChunk(track, "", true)
msg('\n----------------------------------------------Read again ------------------------------------------\n'..info)
But the track doesn't store this cutom info

Last edited by lollo; 08-07-2019 at 03:32 AM.
lollo is offline   Reply With Quote
Old 08-07-2019, 07:39 AM   #21
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 8,915
Default

You can use GetSetMediaItemInfo_String() or GetSetMediaItemTakeInfo_String() with P_EXT to save / load custom info with media items / takes. The data is saved in project file.

Here's an example with an automation item, where it works basically the same.
https://forum.cockos.com/showpost.ph...05&postcount=3

edit:
Or for items you could also use P_NOTES to use the native item notes.

Last edited by nofish; 08-07-2019 at 07:45 AM.
nofish is offline   Reply With Quote
Old 08-07-2019, 09:00 AM   #22
lollo
Human being with feelings
 
Join Date: Jun 2017
Posts: 44
Default

Quote:
Originally Posted by nofish View Post
You can use GetSetMediaItemInfo_String() or GetSetMediaItemTakeInfo_String() with P_EXT to save / load custom info with media items / takes. The data is saved in project file.
Great nofish.
You gave me the info I needed. Many thanks
lollo 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 AM.


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