+import re
+
+class Tags(object):
+ def __init__(self):
+ self._global = {}
+ self._tracks = {}
+
+ def __len__(self):
+ # All files have at least one track.
+ return max(1, len(self._tracks))
+
+ def set(self, key, value, track=None):
+ key = key.upper()
+ if track == None:
+ tags = self._global
+ else:
+ try:
+ tags = self._tracks[track]
+ except KeyError:
+ tags = self._tracks[track] = {}
+ if key not in tags:
+ tags[key] = []
+ tags[key].append(value)
+
+ def load(self, fp):
+ for line in (x.rstrip() for x in fp):
+ (tag, value) = line.split('=', 1)
+
+ m = re.search(r'\[([0-9]+)]$', tag)
+ if m != None:
+ tag = tag[:m.start()]
+ track = int(m.group(1))
+ else:
+ track = None
+
+ self.set(tag, value, track)
+
+ def get(self, key, track=None):
+ result = []
+ key = key.upper()
+ try:
+ result.extend(self._global[key])
+ except KeyError:
+ pass
+ try:
+ result.extend(self._tracks[track][key])
+ except KeyError:
+ pass
+ return result
+
+ def gets(self, key, track=None, separator='\n'):
+ value = self.get(key, track)
+ if len(value) == 0:
+ return None
+ return separator.join(value)
+
+ def all(self):
+ result = []
+ for (tag, values) in self._global.iteritems():
+ for value in values:
+ result.append('='.join([tag, value]))
+ for (track, tags) in self._tracks.iteritems():
+ for (tag, values) in tags.iteritems():
+ for value in values:
+ result.append('%s[%d]=%s' % (tag, track, value))
+ return result
+
+ def track(self, track):
+ result = ['TRACKNUMBER=%d' % (track,)]
+ for (tag, values) in self._global.iteritems():
+ for value in values:
+ result.append('='.join([tag, value]))
+ for (this_track, tags) in self._tracks.iteritems():
+ if this_track != track:
+ continue
+ for (tag, values) in tags.iteritems():
+ for value in values:
+ result.append('%s=%s' % (tag, value))
+ return result