# generate Station Playlist Cue Sheets, from Reaper project files
# Supply one argument. the RPP file, with .RPP extension
# creates a .CUE file for Station Playlist

# note: though we terminate strings with \n, the output file format is \r\n, and it seems to happen by magic

import sys

#*--*/ function FindTrack

def FindTrack (fin):
  '''
  Find the record for this track  
  provide file object.  updated to point to <track 
  returns 1 if found, 0 if not
  '''

#  sLine = fin.readline()
  i = 0
  done = 0
  while done == 0:
    try:
      sLine = fin.readline()
    except:
      return (0)

    if (len (sLine) == 0):
      return(0)

    if (sLine[0:8] == "  <TRACK"):
      return(1)
    #endif start of track
    i = i+1
    if (i > 1000):
      print "infinite loop in findTrack"
      return(0)
    #endif
  #endWhile
  print "never found <track"
  return(0)
#end of function FindTrack


#*--*/ function ProcessItem

def ProcessItem (fin):
  ''' provide file object,  updates file object.
  Leaves file pointed one line past end of item
  writes to itemDict
  '''
  itemLine = fin.readline()
  itemOpen = 1
  while itemOpen:
    if (itemLine.startswith("      POSITION")):
      iDot = itemLine.find(".") 
      itemTime = itemLine[15:iDot]
    elif (itemLine.startswith("      LENGTH")):
      iDot = itemLine.find(".") 
      itemLength = itemLine[13:iDot]
    elif (itemLine.startswith ("      NAME")):
      # the name may, or may not have a leading quote
      itemName = itemLine [10:]
      itemName = itemName.strip()
      #remove quotes
      startIndex = 0
      endIndex = len (itemName)
      if (itemName.startswith ("\"")):
        startIndex = 1
      if (itemName.endswith("\"")):
        endIndex = endIndex-1
      itemName = itemName[startIndex:endIndex]
    #endif found item name
    elif (itemLine.startswith ("      <SOURCE")):
      # where the source file is stored is in the next line
      itemLine = fin.readline()
      folderPath = itemLine[15:]
      pathList = folderPath.split("\\")
      if (len (pathList) > 2):
        folderName = pathList[2]
      else:
        folderName = "Unknown"
      #endif list too short
    elif (itemLine.startswith("    >")):
      # end of item
      itemOpen = 0
    #end of item
    if (itemOpen):
      itemLine = fin.readline()
    #endif
  #endWhile item open
  # print "item:", itemTime, itemName
  # collect this item, if large enough
  iLength = int(itemLength)
  if (iLength > 60):
    # longer than a minute
    itemTime = expandTo5Chars (itemTime)
    itemDict [itemTime] = itemName
    folderDict [itemTime] = folderName
  # end of item long enough
# end of function ProcessItem


#*--*/ function ProcessTrack (fin)

def ProcessTrack (fin):
  ''' supply file object, pointed at <track in a track definition
  Updates itemDict dictionary
  Returns:  Nothing
  '''
  trackOpen = 1
  sLine = fin.readline()
  while trackOpen:
    if (sLine.startswith ("    <ITEM")):
      # found an item
      ProcessItem (fin)
    #end found item
    sLine = fin.readline()
    if sLine.startswith ("  >"):
      trackOpen = 0
    #endif ; found end of track
  #endWhile track open
# end of function ProcessTrack


# *--*/

def expandTo5Chars (str):
  # makes sure all keys are 5 chars in length, blansk on the left
  curLen = len(str) 
  i = 5-curLen
  sResult = i * " " + str
  return sResult

# *--*/

def GenerateCueSheet (rppPath):
  iTrackIndex = 1
  outPath = rppPath[0:-3] + "cue"
  fOut = open (outPath, "w")
  sOut = "FILE \"" + rppPath[0:-4] + "\" WAVE\n"
  fOut.write (sOut)

  keyList = itemDict.keys()
  keyList.sort()
  for sSeconds in keyList:
    sSeconds.strip()  # remove blanks on left
    sProperties = itemDict [sSeconds]
    i = sProperties.find("-")
    if (i > 1):
      # dash separated artist and title
      sArtist = sProperties[0:i-1]
      # clean up the name
      sTitle = sProperties[i+2:]
      sTitle = sTitle.strip()
    else:
      # no dash
      # sArtist = "Unknown"
      sArtist = folderDict [sSeconds]
      sTitle = sProperties
    #endif  no dash
    # remove extensions
    i = sTitle.rfind(".")
    if (i > (len(sTitle)-5)):
      sTitle = sTitle [0:i]
    #endif

    # create the cue sheet entry
    sOut = "  TRACK %02d AUDIO\n" % iTrackIndex
    iTrackIndex = iTrackIndex+1
    fOut.write (sOut)

    sOut = "    TITLE \"%s\"\n" % sTitle
    fOut.write (sOut)

    sOut = "    PERFORMER \"%s\"\n" % sArtist
    fOut.write (sOut)

    # time in seconds converted to minutes
    iSeconds = int (sSeconds)
    iMinutes = iSeconds / 60
    iSeconds = iSeconds - (iMinutes * 60)
    sMinutes = "%02d:%02d:00" % (iMinutes, iSeconds)

    sOut = "    INDEX 01 %s\n" % sMinutes
    fOut.write(sOut)
  #end for each key
  fOut.close()
  return outPath

#*--*/ main

# filePath = "md5.rpp"
try:
  filePath = sys.argv[1]
except:
  print "missing parameter: supply the RPP reaper projedct file, including extension"
  sys.exit()

try:
  fin = open (filePath, "r")
except:
  print "file %s not found" % filePath
  sys.exit()

if (fin):
  # file opened
  itemDict = {}  # the dictionary, keys are in seconds
  folderDict = {} # parent folder names for each item
  while (FindTrack (fin)):
    ProcessTrack (fin)
  #end while

  outPath = GenerateCueSheet (filePath)
  del itemDict
  del folderDict
  print "file processed:",  filePath
  print "file %s created" % outPath
else:
  print "unable to open file " + filePath
# endif file not opened
  
