Advertisement
Guest User

Untitled

a guest
May 20th, 2012
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.30 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. import optparse
  4. import string
  5. import re
  6. import glob
  7.  
  8. class StringEntry:
  9.     def __init__(self, string):
  10.     self.entry = string
  11.     def toString(self, dic):
  12.     return self.entry
  13.  
  14. class DicEntry(StringEntry):
  15.     def toString(self, dic):
  16.     return dic.get(self.entry, "")
  17.  
  18. class If:
  19.     def __init__(self, string, true, false):
  20.     self.entry = string
  21.     self.true = true
  22.     self.false = false
  23.     def toString(self, dic):
  24.     if self.entry in dic:
  25.         return "".join([x.toString(dic) for x in self.true])
  26.     else:
  27.         return "".join([x.toString(dic) for x in self.false])
  28.  
  29. _NORMAL_ = 0
  30. _VARIABLE_ = 1
  31. _POST_VARIABLE_ = 2
  32.  
  33. trans = {'0':'path', '1':'filename', '2':'songtitle', '3':'title',
  34.     '4':'composer', '5':'artist', '6':'date', '9':'track', 'a':'ripper',
  35.     'e':'tagger'}
  36.  
  37. class Format:
  38.     def __init__(self, string):
  39.     self.parse(string)
  40.     def trans(self, string):
  41.     return trans.get(string, string)
  42.     def parse(self, string):
  43.     (end, parsed) = self.parseString(string)
  44.     self.parts = parsed
  45.     def parseString(self, s, pos = 0, returnOnBracket = False, returnOnPipe = False):
  46.     parts = []
  47.     end = len(s)
  48.     pos = pos
  49.     rob = returnOnBracket
  50.     rop = returnOnPipe
  51.     mark = pos
  52.     state = _NORMAL_
  53.     while pos < end:
  54.         if state == _POST_VARIABLE_:
  55.         if s[pos] == "[":
  56.             (npos, true) = self.parseString(s, pos+1, True, True)
  57.             if s[npos] == "|":
  58.             (npos, false) = self.parseString(s, npos+1, True, False)
  59.             else:
  60.             false = []
  61.             parts.append(If(self.trans(s[pos-1:pos]), true, false))
  62.             pos = npos+1
  63.         else:
  64.             parts.append(DicEntry(self.trans(s[pos-1:pos])))
  65.         mark = pos
  66.         state = _NORMAL_
  67.         elif state == _VARIABLE_:
  68.         if s[pos] in string.hexdigits:
  69.             state = _POST_VARIABLE_
  70.             mark = pos + 1
  71.         elif s[pos] in "[]|%":
  72.             state = _NORMAL_
  73.             parts.append(StringEntry(s[pos]))
  74.             mark = pos + 1
  75.         else:
  76.             state = _NORMAL_
  77.         pos += 1
  78.         elif state == _NORMAL_:
  79.         if s[pos] == "%":
  80.             state = _VARIABLE_
  81.             if mark < pos:
  82.             parts.append(StringEntry(s[mark:pos]))
  83.             mark = pos+1
  84.         elif rop and s[pos] == "|":
  85.             break
  86.         elif rob and s[pos] == "]":
  87.             break
  88.         pos += 1
  89.     if state == _POST_VARIABLE_:
  90.         parts.append(self.dicEntry(s[pos-1:pos]))
  91.     else:
  92.         parts.append(StringEntry(s[mark:pos]))
  93.     return (pos, parts)
  94.     def toString(self, dic):
  95.     return "".join([x.toString(dic) for x in self.parts])
  96.  
  97. recentTag = "title"
  98. tags = {}
  99. position = 0
  100.  
  101. def parseComment(l):
  102.     global recentTag
  103.     global tags
  104.     tag = None
  105.     value = None
  106.     l = l.lstrip(string.whitespace+"#")
  107.     if l[0] == "@":
  108.     try:
  109.             (tag, value) = [x.strip() for x in l[1:].expandtabs(1).split(" ",1)]
  110.         except:
  111.             return
  112.     else:
  113.     cutoff = l.find(":")
  114.     if cutoff > 0:
  115.         (tag,value) = [x.strip() for x in l.split(":", 1)]
  116.     else:
  117.         if recentTag == "title":
  118.         dateBeg = l.rfind("[")
  119.         dateEnd = l.rfind("]")
  120.         if dateBeg > 0 and dateEnd > 0:
  121.             tags["date"] = l[dateBeg+1:dateEnd]
  122.         artBeg = l.rfind("(")
  123.         artEnd = l.rfind(")")
  124.         if artBeg > 0 and artEnd > 0:
  125.             tags["artist"] = l[artBeg+1:artEnd]
  126.         if artBeg > 0 or dateBeg > 0:
  127.             value = l[:min(dateBeg%len(l), artBeg%len(l))].strip()
  128.         else:
  129.             value = l.strip()
  130.         else:
  131.         value = l.strip()
  132.     if tag:
  133.     recentTag = tag.lower()
  134.     if recentTag in tags and value:
  135.     tags[recentTag] = ", ".join([tags[recentTag], value])
  136.     else:
  137.     tags[recentTag] = value
  138.  
  139. def makeTitle(title, filename, number):
  140.     global tags
  141.     global formater
  142.     tags["songtitle"] = title
  143.     tags["filename"] = filename
  144.     tags["track"] = str(number).zfill(2)
  145.     return re.sub(r'([^\\]),', r'\1\\,', formater.toString(tags))
  146.  
  147. pattern = re.compile(r"(?P<filename>.*)::(?P<filetype>[^,]*),(?P<pos>[^,]*),(?P<title>(\\,|[^,])*),(?P<remainder>.*)")
  148.  
  149. def parseEntry(s):
  150.     global tags
  151.     global position
  152.     global pattern
  153.     m = pattern.match(s)
  154.     if m:
  155.     position += 1
  156.     pos = str(position).zfill(2)
  157.     title = makeTitle(m.group("title"), m.group("filename"), pos)
  158.     playlistEntry = m.group("filename") + "::"
  159.     playlistEntry += ",".join([m.group("filetype"), m.group("pos"), title, m.group("remainder")])
  160.     filename = "".join([pos, " ", re.sub(r'\\,', ",", m.group("title")), ".m3u"]).translate(None, "*:?/\\")
  161.     f = open(filename, "w")
  162.     f.write(playlistEntry)
  163.     f.close()
  164.  
  165. def processFile(s):
  166.     f = open(s, "rb")
  167.     res = f.read()
  168.     f.close()
  169.     lines = [x.strip() for x in res.split("\n")]
  170.     for l in lines:
  171.     if l and l[0] == "#":
  172.         parseComment(l)
  173.     else:
  174.         parseEntry(l)
  175.  
  176. if __name__ == "__main__":
  177.     parser = optparse.OptionParser("usage: %prog [options] filename")
  178.     parser.add_option("-g", "--globalpathexpansion", dest="g", action="store_true", help="perform UNIX-like global path expansion on Filename argument (for systems where this isn't done automatically)")
  179.     parser.add_option("-f", "--format", dest="f", action="store", default="%2[%2|?] - %4[%4|?] - %3[%3|?] - "+chr(0xA9)+"%6 %5[%5|?]", help="title field format for generated playlists (using SPCAmp notation)", metavar="FORMAT_STRING")
  180.     (opts, args) = parser.parse_args()
  181.     if len(args) == 0:
  182.     parser.print_help()
  183.     else:
  184.         formater = Format(opts.f)
  185.     if opts.g:
  186.         processFile(glob.glob(args[0])[0])
  187.     else:
  188.         processFile(args[0])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement