Old 11-19-2016, 06:02 PM   #1
Spacemen Tree
Human being with feelings
 
Spacemen Tree's Avatar
 
Join Date: Mar 2013
Posts: 501
Default Lua - How to insert FX Chain via script

Hi all.

I think a while back I saw a way to insert a .Rfx (FX Chain) via script but I can't for the life of me find it. Maybe I dreamed of it, dunno...

Is there any new API stuff to do this or a way to hack reaper.TrackFX_AddByName in order to do it?

Ideas?

Thanks
__________________
"After silence, that which comes nearest to expressing the inexpressible is music", Aldous Huxley
Spacemen Tree is offline   Reply With Quote
Old 11-21-2016, 05:27 PM   #2
me2beats
Human being with feelings
 
me2beats's Avatar
 
Join Date: Jul 2015
Location: Yekaterinburg, Russia
Posts: 400
Default

Hi

My idea is to find FX chain file by name, then read this file and use SetTrackStateChunk()

For example here's my script for importing tracks from track template
Code:
tp = 'test'

local r = reaper; local function nothing() end; local function bla() r.defer(nothing) end

function os_file_data (path, addstr)
--needs OS == r.GetOS()

  if path then
    if addstr then
      if OS == 'Win32' or 'Win64' then file = path:gsub([==[\]==], [==[\\]==])..[[\\]]..addstr
      else file = path..[[/]]..addstr end
    else
      if OS == 'Win32' or 'Win64' then file = path:gsub([==[\]==], [==[\\]==])
      else file = path end
    end
  end
  path, addstr = nil, nil
  if r.file_exists(file) then
    file_open = io.open(file, 'r'); data = file_open:read('*a'); file_open:close()
  return file, data
  else return file end
end


res_path = r.GetResourcePath()

OS = r.GetOS()


if OS == 'Win32' or 'Win64' then
  tp_path = res_path..[[\TrackTemplates]]
else tp_path = res_path..[[/TrackTemplates]] end


for i = 0, 1000 do
  fn = r.EnumerateFiles(tp_path, i)
  if not fn or fn == '' then break
  elseif fn == tp..[[.RTrackTemplate]] then
    _, tp_data = os_file_data(tp_path,fn)
    if tp_data then
      r.Undo_BeginBlock()

      for chunk in tp_data:gmatch'(<TRACK.->)' do
        tracks = r.CountTracks(0)
        r.InsertTrackAtIndex(tracks, 0)
        tr = r.GetTrack(0,tracks)
        r.SetTrackStateChunk(tr, chunk, 0)
      end
      
      r.TrackList_AdjustWindows(0)

      r.Undo_EndBlock('import tracks from track template', -1)

    end
  break end
end
https://github.com/me2beats/rea-me2/...ack%20template

this script needs some updates (for example this version don't check subfolders).
me2beats is offline   Reply With Quote
Old 11-21-2016, 09:35 PM   #3
Spacemen Tree
Human being with feelings
 
Spacemen Tree's Avatar
 
Join Date: Mar 2013
Posts: 501
Default

Hello.

Thank you for that piece of code. Already learned somethings about structure from that, just by reading it through. Very nice.

It pointed me in some direction, let's see if I'm able to adapt it for FX Chains.

One thing though, unless I misunderstand what you mean by "importing tracks from track template", here's the way I've been doing it, don't know if you are aware of it:

Code:
Track_Template = "My Track Template.RTrackTemplate"

path = reaper.GetResourcePath()

Track_Template_path = path .. "/" .. "TrackTemplates" .. "/" .. Track_Template

reaper.Main_openProject(Track_Template_path)
This adds My Track Template to your current project. It's imperative that you add the full path. At first I wasn't getting how to do it but once I defined the whole path to the track template in question it worked.

Anyway, if you were not aware of this...
__________________
"After silence, that which comes nearest to expressing the inexpressible is music", Aldous Huxley
Spacemen Tree is offline   Reply With Quote
Old 11-22-2016, 03:04 AM   #4
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 2,530
Default

Code:
  FX_chain_file_path = [[C:\001.RfxChain]]
  track_id = 1
  
  function ExtractBracketsBlock(str)
    local s = ''
    local count = 1
    count_lines = 0
    for line in str:gmatch('[^\n]+') do
      count_lines = count_lines + 1
      s = s..'\n'..line
      if line:find('<') then count = count +1 end
      if line:find('>') then count = count -1 end 
      if count == 1 then return s, count_lines end     
    end
  end  
  
  -- get some chain file, ex. from GetUserFileForRead()
    file = io.open(FX_chain_file_path)
    external_FX_chain_content = file:read('a')
    file:close()
  
  -- get track chunk
    track = reaper.GetTrack(0,track_id-1)
    _, chunk = reaper.GetTrackStateChunk(track, '', true)

  -- split chunk by lines into table
    local t = {} 
    for line in chunk:gmatch('[^\n]+') do       if line:find('<FXCHAIN') then fx_chain_id0 = #t end       t[#t+1] = line     end      

  --  find size of FX chain and where it placed
    _, cnt_lines = ExtractBracketsBlock(chunk:match('<FXCHAIN.*'))
    fx_chain_id1 = fx_chain_id0 + cnt_lines -1
  
  -- insert FX chain
    new_chunk = table.concat(t,'\n',  1, fx_chain_id1)..'\n'..
                external_FX_chain_content..
                table.concat(t,'\n',  fx_chain_id1)
  
  -- apply new chunk                
    reaper.SetTrackStateChunk(track, new_chunk, false) 
    reaper.UpdateArrange()

Last edited by mpl; 11-22-2016 at 12:00 PM.
mpl is offline   Reply With Quote
Old 11-22-2016, 01:41 PM   #5
Spacemen Tree
Human being with feelings
 
Spacemen Tree's Avatar
 
Join Date: Mar 2013
Posts: 501
Default

Thanks so much mpl!

I got success with a mod of me2beats code as far as tracks without any FX on it. When there was already a FX Chain in the track things got a bit trickier for my skills.

I see you accounted for that in your code. I was coming here to ask exactly help on that. Thank you.
__________________
"After silence, that which comes nearest to expressing the inexpressible is music", Aldous Huxley
Spacemen Tree is offline   Reply With Quote
Old 02-24-2017, 04:02 PM   #6
Spacemen Tree
Human being with feelings
 
Spacemen Tree's Avatar
 
Join Date: Mar 2013
Posts: 501
Default

Anyone knows if there's anything new on this API wise? Thanks.
__________________
"After silence, that which comes nearest to expressing the inexpressible is music", Aldous Huxley
Spacemen Tree is offline   Reply With Quote
Old 02-24-2017, 06:36 PM   #7
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,503
Default

Quote:
Originally Posted by mpl View Post
Code:
  FX_chain_file_path = [[C:\001.RfxChain]]
  track_id = 1
  
  function ExtractBracketsBlock(str)
    local s = ''
    local count = 1
    count_lines = 0
    for line in str:gmatch('[^\n]+') do
      count_lines = count_lines + 1
      s = s..'\n'..line
      if line:find('<') then count = count +1 end
      if line:find('>') then count = count -1 end 
      if count == 1 then return s, count_lines end     
    end
  end  
  
  -- get some chain file, ex. from GetUserFileForRead()
    file = io.open(FX_chain_file_path)
    external_FX_chain_content = file:read('a')
    file:close()
  
  -- get track chunk
    track = reaper.GetTrack(0,track_id-1)
    _, chunk = reaper.GetTrackStateChunk(track, '', true)

  -- split chunk by lines into table
    local t = {} 
    for line in chunk:gmatch('[^\n]+') do       if line:find('<FXCHAIN') then fx_chain_id0 = #t end       t[#t+1] = line     end      

  --  find size of FX chain and where it placed
    _, cnt_lines = ExtractBracketsBlock(chunk:match('<FXCHAIN.*'))
    fx_chain_id1 = fx_chain_id0 + cnt_lines -1
  
  -- insert FX chain
    new_chunk = table.concat(t,'\n',  1, fx_chain_id1)..'\n'..
                external_FX_chain_content..
                table.concat(t,'\n',  fx_chain_id1)
  
  -- apply new chunk                
    reaper.SetTrackStateChunk(track, new_chunk, false) 
    reaper.UpdateArrange()
Nice! Thank you! Could this get modified so that it would insert the FX Chain to the chain of the currently focused fx? (be it track or item fx)

If I substitute "track_id=1" for "retval, track_id, focused_item_fx, focused_fx_id = reaper.GetFocusedFX()", then it works for track fx..
amagalma is offline   Reply With Quote
Old 04-15-2019, 09:56 PM   #8
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

This is working great, but in my situation, I'd like to replace the existing fx chain.

Would that be difficult?

I'll try and parse what's going on here.... maybe I can figure it out.

Any tips welcome

EDIT: Well, not super elegant, but this works at the top of the function:
Code:
    commandID = reaper.NamedCommandLookup("_S&M_CLRFXCHAIN3") --remove track fx on selected track
__________________
eric moon
Very Stable Genius
https://gogolab.com/

Last edited by woodslanding; 04-16-2019 at 10:12 AM.
woodslanding is offline   Reply With Quote
Old 04-16-2019, 03:23 PM   #9
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,173
Default

Quote:
Originally Posted by Spacemen Tree View Post
Is there any new API stuff to do this or a way to hack reaper.TrackFX_AddByName in order to do it?
I guess you don't need chunks anymore. blabla is FXChain's name. It is in a sub-folder called bla. Seems to work here on Windows 7 x64.

Code:
reaper.PreventUIRefresh(1)
reaper.Undo_BeginBlock2(0)
for i = 0, reaper.CountSelectedTracks(0)-1 do
  local trk = reaper.GetSelectedTrack(0,i)
  for j = reaper.TrackFX_GetCount(trk)-1, 0, -1 do
    reaper.TrackFX_Delete(trk, j)
  end
  reaper.TrackFX_AddByName(trk, "bla/blabla.rfxchain", false, -1)
end
reaper.Undo_EndBlock2(0, "asdf", 2)
reaper.PreventUIRefresh(-1)
Quote:
Originally Posted by woodslanding View Post
I'd like to replace the existing fx chain.
Tried this with
reaper.Main_OnCommand(reaper.NamedCommandLookup("_ S&M_CLRFXCHAIN3"),0)
before for i,etc loop instead of
for j = reaper.TrackFX_GetCount(trk)-1, 0, -1 do
reaper.TrackFX_Delete(trk, j)
end
and the SWS action appears to be 5-10% slower than the TrackFX_Delete function loop in a couple tests of 15 or so tracks.
FnA is offline   Reply With Quote
Old 04-16-2019, 03:30 PM   #10
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

Well now that code is a lot simpler than parsing the track chunk!

As for the timing difference....good to know....

Although with multiple tracks I imagine the loading time of the new fx will dwarf the time required to delete the old ones....

EDIT: Well, this isn't working for me. The old fx are deleting, but the new ones aren't showing up. I used the same code to set the path that I used for the track chunk code, which loaded fine:

Code:
    local path =  reaper.GetResourcePath()..'\\FXChains\\'..chainname..'.RfxChain'
    --also doesn't work:
    local path = 'FXChains\\'..chainname..'.RfxChain'
    --you had a forward slash???  Well, this doesn't work either:
    local path = 'FXChains/'..chainname..'.RfxChain'
You did verify this works with a .RfxChain file? Wonder what I've got wrong...
__________________
eric moon
Very Stable Genius
https://gogolab.com/

Last edited by woodslanding; 04-16-2019 at 05:04 PM.
woodslanding is offline   Reply With Quote
Old 04-16-2019, 05:32 PM   #11
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,173
Default

bla/
in
bla/FX Chain Name.rfxchain
was only necessary when the chain was in a subfolder in Fx Chains folder. Other chains in top folder were just
FX Chain Name.rfxchain


edit. bla\\blabla.rfxchain seems to work too.

Last edited by FnA; 04-16-2019 at 05:39 PM.
FnA is offline   Reply With Quote
Old 04-16-2019, 07:23 PM   #12
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

I think maybe my version of Reaper on this computer was a little too old... got it working now, cool!!
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 04-21-2019, 08:01 PM   #13
Pinknoise
Human being with feelings
 
Pinknoise's Avatar
 
Join Date: Aug 2012
Location: Around Montréal
Posts: 877
Default

Thank you that works !
What can be added to float selected fx or fx chain ?
Pinknoise is online now   Reply With Quote
Old 04-22-2019, 10:36 AM   #14
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,173
Default

Hm, floating an fx based on an index is fairly easy with factory API function: TrackFX_Show

Determining which fx are selected is more obscure, if you mean whichever fx are highlighted on the left side of the fx chain window. I think it probably requires something like the js extension API functions. Amagalma has a script called
Script: amagalma_Toggle enclose selected or focused FX in visible chain with AB_LM Level Matching VST or JSFX.lua
which might be something to study.
FnA is offline   Reply With Quote
Old 05-13-2019, 04:05 PM   #15
Pinknoise
Human being with feelings
 
Pinknoise's Avatar
 
Join Date: Aug 2012
Location: Around Montréal
Posts: 877
Default

In this thread there is a discussion about it and maybe I'll be able to add to your script with my script copy paste knowledge
https://forum.cockos.com/showthread....+Name.rfxchain

Is there a track template add by name script somewhere ?
Pinknoise is online now   Reply With Quote
Old 05-13-2019, 04:36 PM   #16
Neutronic
Human being with feelings
 
Neutronic's Avatar
 
Join Date: Sep 2013
Posts: 382
Default

Quote:
Originally Posted by Pinknoise View Post
Is there a track template add by name script somewhere ?
Here.
Neutronic is offline   Reply With Quote
Old 05-13-2019, 05:50 PM   #17
Pinknoise
Human being with feelings
 
Pinknoise's Avatar
 
Join Date: Aug 2012
Location: Around Montréal
Posts: 877
Default

Quote:
Originally Posted by Neutronic View Post
Thanks more fun !

I copy the script afterwards and it worked ! Loads fx chain and floats !
For reacomp fxchain:
Code:
reaper.PreventUIRefresh(1)
reaper.Undo_BeginBlock2(0)
for i = 0, reaper.CountSelectedTracks(0)-1 do
  local trk = reaper.GetSelectedTrack(0,i)
  for j = reaper.TrackFX_GetCount(trk)-1, 0, -1 do
    reaper.TrackFX_Delete(trk, j)
  end
  reaper.TrackFX_AddByName(trk, "Reacomp.rfxchain", false, -1)
end
reaper.Undo_EndBlock2(0, "asdf", 2)
reaper.PreventUIRefresh(-1)


fx_name = 'VST: ReaComp (Cockos)'

local track = reaper.GetSelectedTrack(0,0)
if track then
  for fx = 0, reaper.TrackFX_GetCount(track)-1 do
    local _, name = reaper.TrackFX_GetFXName(track, fx, "")
    if name == fx_name then
      reaper.TrackFX_Show(track, fx, 3) -- 3 = show as floating.
      break 
    end
  end
end
Pinknoise is online now   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 09:57 AM.


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