#! /usr/bin/python import sys from subprocess import Popen, PIPE from org.diplodocus.util import run_or_die from flac_archive.tags import Tags class SubprocessError(Exception): def __init__(self, status, command=None, stderr=None): if command is None: command_msg = None else: command_msg = ': ' + ' '.join(command) if status < 0: msg = 'exited due to signal %d%s' else: msg = 'exit status %d%s' Exception.__init__(self, msg % (abs(status), command_msg)) self.status = status self.command = command self.stderr = stderr def get_tags(fn): tags = Tags() command = ['metaflac', '--no-utf8-convert', '--export-tags-to=-', fn] p = Popen(command, stdout=PIPE) tags.load(p.stdout) status = p.wait() if status != 0: raise SubprocessError(status, command=command, stderr=p.stderr) return tags def do_read(filenames): # Use this mapping of tag names to sets of tag values to detect global tags. all_tags = {} # Build the collated result in this Tags object. coll_tags = Tags() # XXX The Tags interface is horrible. It's gotta be almost 10 years since # I wrote it, so not surprising... for fn in filenames: tags = get_tags(fn) track_tags = tags.get('TRACKNUMBER') if len(track_tags) != 1: raise Exception('bogus TRACKNUMBER %s for %s' % (track_tags, fn)) track = int(track_tags[0]) for tag, values in tags._global.iteritems(): for value in values: if tag in all_tags: all_tags[tag].add(value) else: all_tags[tag] = set([value]) coll_tags.set(tag, value, track) for tag, values in all_tags.iteritems(): if len(values) == 1: # Only one value for this tag, so add it to global tags. coll_tags.set(tag, list(values)[0]) # And now remove it from each track tags. for track, tags in coll_tags._tracks.iteritems(): del tags[tag] print '\n'.join(coll_tags.all()) return 0 def main(args): if len(args) < 3: return usage() if args[1] == 'read': return do_read(args[2:]) if args[1] == 'write': return do_write(args[2:]) return usage() def usage(): return 2 if __name__ == '__main__': sys.exit(main(sys.argv))