]> diplodocus.org Git - flac-archive/blob - rewrite-tags
Expand SubprocessError to report the failing command, and test it.
[flac-archive] / rewrite-tags
1 #! /usr/bin/python
2
3 import sys
4 from subprocess import Popen, PIPE
5
6 from org.diplodocus.util import run_or_die
7
8 from flac_archive.tags import Tags
9
10 class SubprocessError(Exception):
11 def __init__(self, status, command=None, stderr=None):
12 if command is None:
13 command_msg = None
14 else:
15 command_msg = ': ' + ' '.join(command)
16 if status < 0:
17 msg = 'exited due to signal %d%s'
18 else:
19 msg = 'exit status %d%s'
20 Exception.__init__(self, msg % (abs(status), command_msg))
21 self.status = status
22 self.command = command
23 self.stderr = stderr
24
25 def get_tags(fn):
26 tags = Tags()
27
28 command = ['metaflac', '--no-utf8-convert', '--export-tags-to=-', fn]
29 p = Popen(command, stdout=PIPE)
30 tags.load(p.stdout)
31
32 status = p.wait()
33 if status != 0:
34 raise SubprocessError(status, command=command, stderr=p.stderr)
35
36 return tags
37
38 def do_read(filenames):
39 # Use this mapping of tag names to sets of tag values to detect global tags.
40 all_tags = {}
41 # Build the collated result in this Tags object.
42 coll_tags = Tags()
43 # XXX The Tags interface is horrible. It's gotta be almost 10 years since
44 # I wrote it, so not surprising...
45 for fn in filenames:
46 tags = get_tags(fn)
47 track_tags = tags.get('TRACKNUMBER')
48 if len(track_tags) != 1:
49 raise Exception('bogus TRACKNUMBER %s for %s' % (track_tags, fn))
50 track = int(track_tags[0])
51 for tag, values in tags._global.iteritems():
52 for value in values:
53 if tag in all_tags:
54 all_tags[tag].add(value)
55 else:
56 all_tags[tag] = set([value])
57 coll_tags.set(tag, value, track)
58 for tag, values in all_tags.iteritems():
59 if len(values) == 1:
60 # Only one value for this tag, so add it to global tags.
61 coll_tags.set(tag, list(values)[0])
62 # And now remove it from each track tags.
63 for track, tags in coll_tags._tracks.iteritems():
64 del tags[tag]
65 print '\n'.join(coll_tags.all())
66 return 0
67
68 def main(args):
69 if len(args) < 3:
70 return usage()
71 if args[1] == 'read':
72 return do_read(args[2:])
73 if args[1] == 'write':
74 return do_write(args[2:])
75 return usage()
76
77 def usage():
78 return 2
79
80 if __name__ == '__main__':
81 sys.exit(main(sys.argv))
82