Dup Ver Goto 📝

ProjectNotes

PT2/music/daw/reaper/rpp-hacking does not exist
To
148 lines, 763 words, 5364 chars Page 'ProjectNotes' does not exist.

A .rpp file is a text file. At the start we see:

<REAPER_PROJECT 0.1 "7.03/win64" 1699444729
  TITLE "Mr Flibble"
  AUTHOR "Doctor Fox"
  <NOTES 0 2
    |Lorem ipsum dolor sit amet, consectetur adipiscing elit. In pharetra dui quis nunc congue lacinia. Aenean ligula risus, ultricies quis mattis at, feugiat nec sapien. Aenean ornare sapien non diam elementum, id suscipit mi cursus. Proin mattis vitae elit quis blandit. 
    |Pellentesque vel lectus magna. Proin sit amet eros id sapien sodales imperdiet. Vestibulum enim tortor, vehicula nec tincidunt id, aliquam a libero. Quisque molestie ultrices blandit. Duis faucibus diam eget mi aliquam, at iaculis lectus posuere. Curabitur nec velit ligula. Sed feugiat tortor ac viverra sollicitudin. 
    |
    |Proin ultrices feugiat felis vitae volutpat. Morbi libero magna, scelerisque nec fermentum eget, aliquet quis quam. Vivamus ligula velit, pretium in nisl ac, volutpat hendrerit nunc.
  >
  RIPPLE 0
  GROUPOVERRIDE 0 0 0
  AUTOXFADE 1
  ENVATTACH 3

or

<REAPER_PROJECT 0.1 "7.03/win64" 1699444571
  TITLE "Mr Flibble"
  AUTHOR "Doctor Fox"
  <NOTES 0 2
    |Mr Turnip
  >
  RIPPLE 0
  GROUPOVERRIDE 0 0 0
  AUTOXFADE 1
  ENVATTACH 3

So we can easily edit these notes and move them from project to project using a text editor.

Simple Python Scripts

These are mainly to illustrate how it's done. These are not guaranteed to be robust, nor would I actually use them. But here is a quick demo of all it takes to extract and insert notes. This is most useful if you want to batch export project notes, or perhaps batch insert them.

These are command line apps that work best with Linux or Macos, or if you have Cygwin or WSL under Windows. (I daily drive cygwin bash as my default command shell when running Windows.)

extract notes

#!/usr/bin/env python3
import sys
import json
args = sys.argv[1:]
if len(args) == 0:
  print(f"{sys.argv[0]} <rpp file>")
  exit(1)

rpp_fn = args[0]
rpp = open(rpp_fn).read()
lines = rpp.splitlines()
data = {}
in_notes = False
notes = []
data['notes'] = notes
for line in lines:
  if not in_notes:
    if line.startswith("  TITLE"):
      a,b = line.split(" TITLE ")
      data['title'] = b
      continue
    if line.startswith("  AUTHOR"):
      a,b = line.split(" AUTHOR ")
      data['author'] = b
      continue
    if line.startswith("  <NOTES"):
      in_notes = True
      continue
  else:
    if line.startswith("  >"):
      in_notes = False
      continue
    if line.startswith("    |"):
      a,b = line.split("|",1)
      notes.append(b)

json.dump(data,sys.stdout)

This dumps the following JSON to stdout, which you can then save to a file via

extract_rpp_notes myproject.rpp > myproject_notes.json

and the contents of this file will look like

{"notes": ["Lorem ipsum dolor sit amet, consectetur adipiscing elit. In pharetra dui quis nunc congue lacinia. Aenean ligula risus, ultricies quis mattis at, feugiat nec sapien. Aenean ornare sapien non diam elementum, id suscipit mi cursus. Proin mattis vitae elit quis blandit. ", "Pellentesque vel lectus magna. Proin sit amet eros id sapien sodales imperdiet. Vestibulum enim tortor, vehicula nec tincidunt id, aliquam a libero. Quisque molestie ultrices blandit. Duis faucibus diam eget mi aliquam, at iaculis lectus posuere. Curabitur nec velit ligula. Sed feugiat tortor ac viverra sollicitudin. ", "", "Proin ultrices feugiat felis vitae volutpat. Morbi libero magna, scelerisque nec fermentum eget, aliquet quis quam. Vivamus ligula velit, pretium in nisl ac, volutpat hendrerit nunc."], "title": "'Mr Flibble'", "author": "'Doctor Fox'"}

which can be edited in a text editor, or converted to/from a more readable format, and re-inserted via

insert_rpp_notes myproject.rpp myproject_with_new_notes.rpp

Note that the quotes in the title and author field are necessary. I found it easier to preserve them than to worry about how Reaper quotes stuff containing notes. (After experimenting, it appears Reaper uses " unless double quotes appear, then falls back to ', and if necessary using a backquote to delimit the string, and if necessary turning backquotes to straight quotes.)

The insert script is this:

#!/usr/bin/env python3
import sys
import json
args = sys.argv[1:]
if len(args) == 0:
  print(f"{sys.argv[0]} <rpp in file> <rpp out file>")
  print("Send notes as JSON to stdin")
  exit(1)

data = json.load(sys.stdin)
rpp_fn = args[0]
rpp_ofn = args[1]
rpp = open(rpp_fn).read()
lines = rpp.splitlines()
outlines = [lines[0]]
lines = lines[1:]
if 'title' in data:
  outlines.append(f"  TITLE {data['title']}")
if 'author' in data:
  outlines.append(f"  AUTHOR {data['author']}")
if 'notes' in data:
  outlines.append(f"  <NOTES 0 2")
  for line in data['notes']:
    outlines.append("    |"+line)
  outlines.append(f"  >")

in_notes = False
for line in lines:
  if not in_notes:
    if line.startswith("  TITLE"):
      continue
    if line.startswith("  AUTHOR"):
      continue
    if line.startswith("  <NOTES"):
      in_notes = True
      continue
    outlines.append(line)
  else:
    if line.startswith("  >"):
      in_notes = False
      continue
    # else drop lines

outlines.append("")
out_rpp = "\r\n".join(outlines)
with open(rpp_ofn,"wt") as f:
  f.write(out_rpp)
  print(f"Written {rpp_ofn}")