-
Notifications
You must be signed in to change notification settings - Fork 148
RPP Parser
This script (Development/RPP-Parser/ReaTeam_RPP-Parser.lua
) is about the most advanced third-party REAPER .rpp project file parser.
It is a Lua port of the parser used by mrlimbic on its acclaimed Vordio v6 software. It could be ported to other languages as well.
It is shared and updated right on Reateam/ReaScripts
reapack compatible and widely distributed repository to make it easily accessible by scripters.
It doesn't rely on REAPER API so it can be used outside REAPER (using Lua Binaries and call from shell/terminal for eg).
With this script, you can parse .rpp files or rpp text chunks, manipulate them extensively (any nodes, any value etc), stringify them and write them back to .rpp files. You can even create them from scratch.
In practice, this means you can build things like these examples:
- a script to list all media sources used as active take in all .rpp files in a directory
- a script to merge projects tracks from different .rpp into one
- a script to create a project with tracks and items already in place, based on a CSV
- an advanced diff checker for .rpp for advanced collaboration
- a .rpp to converter toward other format
- etc...
Because it works with rpp format definition (data as written in the .rpp file definition), a good knowledge on this and State Chunk formatting are required. Meo-Ada Mespotine various State Chunk Documentations may be the more advanced doc available. Other State Chunk definitions can be found on ReaTeam/Doc repository.
The parser is very generic, object based, and so, flexible. The parser filer only have function for raw data manipulation (adding, delete, remove, updating, find etc), as shown on Definitions below. It is up to the user to write custom functions to actually do actual reaper stuff with it, and do the data sanitization. Extra files could be added to the Parser folder to pack some user made functions by category (items, tracks etc).
If you do project generation from scratch, here is a key feature that will help you: you can write only the data you need, as REAPER doesn't need .rpp to be completed to be readable. Any missing data will be filled with default ones, based on user default project template.
-
RChunk: Main RPP State Chunks. It starts with
<
and ends with>
. It is a type of RNode. -
RNode: RNode are all kind of line or block structure in the RPP. A node is made of a line (arbitrary data), or RToken tokens (value sepatated by spaces). If both tokens and line are present on a RNode at stringification tokens will have priority. RNode can have parent and children nodes, accesisble with
RNode.parent
andRNode.children
. -
RToken: Value of a certain RNode. When you parse a rpp to string, values are just stored in
node.line
, and are only Tokenized to one or ``several tokens if needed (this allows to save CPU). First token is usually RNode main tag, like TRACK, ITEM... for RChunks, or NAME, POSITION.. for an item chunk RNodes childs. Some helpers functions are associated with RToken. Tokens can be accessed withnode.tokens
.
List of all functions and method right in the Reateam_RPP-Parser.lua source code for now.
This give something like this:
<RCHUNK -- This is a RChunk type of RNode. "RCHUNK" string itself is a RToken, the first and only of this RNode.
RToken1 RToken2 RToken3 -- All these tokens are linked to an RNode
> -- End of RChunk
See Reateam_RPP-Parser-test.lua
file for more demo.
More complete examples in the Reateam_RPP-Parser_test.lua
file.
dofile(reaper.GetResourcePath() .. "\\Scripts\\Reateam Scripts\\Development\\RPP-Parser\\Reateam_RPP-Parser.lua") -- Import the parser
-- INPUT
path = "TEST.rpp" -- Path to your initial .rpp
root = ReadRPP(path) -- Parse the RPP
-- Do what you want
tracks = root:findAllChunksByName("TRACK") -- Find chunks and manipulate them
-- OUTPUT
outputpath = "output.RPP"
output_retval, output_message = WriteRPP(outputpath, root) -- Write to .rpp file
dofile(reaper.GetResourcePath() .. "\\Scripts\\Reateam Scripts\\Development\\RPP-Parser\\Reateam_RPP-Parser.lua") -- Import the parser
root = StringifyRPPChunk(str) -- Parse the RPP text chunk
-- Do what you want
-- OUTPUT
outputpath = "output.RPP"
output_retval, output_message = WriteRPP(outputpath, root) -- Write to .rpp file
dofile(reaper.GetResourcePath() .. "\\Scripts\\Reateam Scripts\\Development\\RPP-Parser\\Reateam_RPP-Parser.lua") -- Import the parser
root = CreateRPP() -- Create the root
local index = 0
tracks={}
for j = 1, 5 do
local track = AddRChunk(root, {"TRACK"}) -- Add track
table.insert(tracks, track)
local name = AddRNode(track, {"NAME", j}) -- Add track name
for i = 1, 1 do
index = index + 1
local item = AddRChunk(track, {"ITEM"}) -- Add item
local position = AddRNode(item, {"POSITION", i-1}) -- Add item position
local length = AddRNode(item, {"LENGTH", "1"}) -- Add length
local notes = AddRChunk(item, {"NOTES"}) -- Add notes
notes:setTextNotes("This is a multiline text.\nOr is it?")
local notes_text = notes:getTextNotes()
end
end
output_path = script_folder .. "OUTPUT.rpp"
output_retval, output_message = WriteRPP(output_path, root)
Here is list of main functions provided by the parser. Other functions can be found in the parser file code directly.
ReadRPPChunk(input)
CreateRPP(version, system, time)
CreateRTokens(tab)
CreateRChunk(tab) -- Table of string
CreateRNode(var) -- Table or String
AddRChunk(parent, tab)
AddRNode(parent, tab)
AddRToken(node, tab)
TableRPPNode(node, indent, tab)
StringifyRPPNode(node)
WriteRPP(filename, root)
RNode:new(o)
RNode:getTokens()
RNode:getToken(index)
RNode:getName()
RNode:getParam(index)
RNode:getTokensAsLine()
RNode:remove()
RChunk:findFirstNodeByName(name, start_index, end_index)
RChunk:findFirstChunkByName(name, start_index, end_index)
RChunk:findAllNodesByFilter(filter, start_index, end_index)
RChunk:findAllChunksByFilter(filter, out, start_index, end_index)
RChunk:findAllNodesByName(name, start_index, end_index)
RChunk:findAllChunksByName(name, start_index, end_index)
RChunk:indexOf(node)
RChunk:getTextNotes()
RChunk:setTextNotes(str)
RChunk:addNode(node)
RChunk:removeNode(node)
RChunk:StripGUID()
-
RChunk:copy(parent)
- Don't forget to delete any GUID ReadRPP(filename)
RToken:new(o)
RToken:getString()
RToken:getNumber()
RToken:getBoolean()
RToken:setString(token)
RToken:setNumber(token)
RToken:setBoolean(b)
RToken:toSafeString(s)
Tokenize(line)
Written by X-Raym