Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- import optparse
- import string
- import re
- import glob
- class StringEntry:
- def __init__(self, string):
- self.entry = string
- def toString(self, dic):
- return self.entry
- class DicEntry(StringEntry):
- def toString(self, dic):
- return dic.get(self.entry, "")
- class If:
- def __init__(self, string, true, false):
- self.entry = string
- self.true = true
- self.false = false
- def toString(self, dic):
- if self.entry in dic:
- return "".join([x.toString(dic) for x in self.true])
- else:
- return "".join([x.toString(dic) for x in self.false])
- _NORMAL_ = 0
- _VARIABLE_ = 1
- _POST_VARIABLE_ = 2
- trans = {'0':'path', '1':'filename', '2':'songtitle', '3':'title',
- '4':'composer', '5':'artist', '6':'date', '9':'track', 'a':'ripper',
- 'e':'tagger'}
- class Format:
- def __init__(self, string):
- self.parse(string)
- def trans(self, string):
- return trans.get(string, string)
- def parse(self, string):
- (end, parsed) = self.parseString(string)
- self.parts = parsed
- def parseString(self, s, pos = 0, returnOnBracket = False, returnOnPipe = False):
- parts = []
- end = len(s)
- pos = pos
- rob = returnOnBracket
- rop = returnOnPipe
- mark = pos
- state = _NORMAL_
- while pos < end:
- if state == _POST_VARIABLE_:
- if s[pos] == "[":
- (npos, true) = self.parseString(s, pos+1, True, True)
- if s[npos] == "|":
- (npos, false) = self.parseString(s, npos+1, True, False)
- else:
- false = []
- parts.append(If(self.trans(s[pos-1:pos]), true, false))
- pos = npos+1
- else:
- parts.append(DicEntry(self.trans(s[pos-1:pos])))
- mark = pos
- state = _NORMAL_
- elif state == _VARIABLE_:
- if s[pos] in string.hexdigits:
- state = _POST_VARIABLE_
- mark = pos + 1
- elif s[pos] in "[]|%":
- state = _NORMAL_
- parts.append(StringEntry(s[pos]))
- mark = pos + 1
- else:
- state = _NORMAL_
- pos += 1
- elif state == _NORMAL_:
- if s[pos] == "%":
- state = _VARIABLE_
- if mark < pos:
- parts.append(StringEntry(s[mark:pos]))
- mark = pos+1
- elif rop and s[pos] == "|":
- break
- elif rob and s[pos] == "]":
- break
- pos += 1
- if state == _POST_VARIABLE_:
- parts.append(self.dicEntry(s[pos-1:pos]))
- else:
- parts.append(StringEntry(s[mark:pos]))
- return (pos, parts)
- def toString(self, dic):
- return "".join([x.toString(dic) for x in self.parts])
- recentTag = "title"
- tags = {}
- position = 0
- def parseComment(l):
- global recentTag
- global tags
- tag = None
- value = None
- l = l.lstrip(string.whitespace+"#")
- if l[0] == "@":
- try:
- (tag, value) = [x.strip() for x in l[1:].expandtabs(1).split(" ",1)]
- except:
- return
- else:
- cutoff = l.find(":")
- if cutoff > 0:
- (tag,value) = [x.strip() for x in l.split(":", 1)]
- else:
- if recentTag == "title":
- dateBeg = l.rfind("[")
- dateEnd = l.rfind("]")
- if dateBeg > 0 and dateEnd > 0:
- tags["date"] = l[dateBeg+1:dateEnd]
- artBeg = l.rfind("(")
- artEnd = l.rfind(")")
- if artBeg > 0 and artEnd > 0:
- tags["artist"] = l[artBeg+1:artEnd]
- if artBeg > 0 or dateBeg > 0:
- value = l[:min(dateBeg%len(l), artBeg%len(l))].strip()
- else:
- value = l.strip()
- else:
- value = l.strip()
- if tag:
- recentTag = tag.lower()
- if recentTag in tags and value:
- tags[recentTag] = ", ".join([tags[recentTag], value])
- else:
- tags[recentTag] = value
- def makeTitle(title, filename, number):
- global tags
- global formater
- tags["songtitle"] = title
- tags["filename"] = filename
- tags["track"] = str(number).zfill(2)
- return re.sub(r'([^\\]),', r'\1\\,', formater.toString(tags))
- pattern = re.compile(r"(?P<filename>.*)::(?P<filetype>[^,]*),(?P<pos>[^,]*),(?P<title>(\\,|[^,])*),(?P<remainder>.*)")
- def parseEntry(s):
- global tags
- global position
- global pattern
- m = pattern.match(s)
- if m:
- position += 1
- pos = str(position).zfill(2)
- title = makeTitle(m.group("title"), m.group("filename"), pos)
- playlistEntry = m.group("filename") + "::"
- playlistEntry += ",".join([m.group("filetype"), m.group("pos"), title, m.group("remainder")])
- filename = "".join([pos, " ", re.sub(r'\\,', ",", m.group("title")), ".m3u"]).translate(None, "*:?/\\")
- f = open(filename, "w")
- f.write(playlistEntry)
- f.close()
- def processFile(s):
- f = open(s, "rb")
- res = f.read()
- f.close()
- lines = [x.strip() for x in res.split("\n")]
- for l in lines:
- if l and l[0] == "#":
- parseComment(l)
- else:
- parseEntry(l)
- if __name__ == "__main__":
- parser = optparse.OptionParser("usage: %prog [options] filename")
- 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)")
- 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")
- (opts, args) = parser.parse_args()
- if len(args) == 0:
- parser.print_help()
- else:
- formater = Format(opts.f)
- if opts.g:
- processFile(glob.glob(args[0])[0])
- else:
- processFile(args[0])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement