]> diplodocus.org Git - flac-archive/blob - rewrite-tags
Don't save TRACKNUMBER.
[flac-archive] / rewrite-tags
1 #! /usr/bin/python
2
3 import sys
4 from subprocess import Popen, PIPE
5
6 from flac_archive.tags import Tags
7
8 class SubprocessError(Exception):
9 def __init__(self, status, command=None, stderr=None):
10 if command is None:
11 command_msg = None
12 else:
13 command_msg = ': ' + ' '.join(command)
14 if status < 0:
15 msg = 'exited due to signal %d%s'
16 else:
17 msg = 'exit status %d%s'
18 Exception.__init__(self, msg % (abs(status), command_msg))
19 self.status = status
20 self.command = command
21 self.stderr = stderr
22
23 def get_tags(fn):
24 tags = Tags()
25
26 command = ['metaflac', '--no-utf8-convert', '--export-tags-to=-', fn]
27 p = Popen(command, stdout=PIPE)
28 tags.load(p.stdout)
29
30 status = p.wait()
31 if status != 0:
32 raise SubprocessError(status, command=command, stderr=p.stderr)
33
34 return tags
35
36 def do_read(filenames):
37 # Use this mapping of tag names to sets of tag values to detect global tags.
38 all_tags = {}
39 # Build the collated result in this Tags object.
40 coll_tags = Tags()
41 # XXX The Tags interface is horrible. It's gotta be almost 10 years since
42 # I wrote it, so not surprising...
43 for fn in filenames:
44 tags = get_tags(fn)
45 track_tags = tags.get('TRACKNUMBER')
46 # this check belongs in Tags
47 if len(track_tags) != 1:
48 sys.stderr.write('bogus TRACKNUMBER %s: %s\n' % (track_tags, fn))
49 return 3
50 track = int(track_tags[0])
51 for tag, values in tags._global.iteritems():
52 # Makes no sense to save TRACKNUMBER in coll_tags.
53 if tag == 'TRACKNUMBER':
54 continue
55 for value in values:
56 if tag in all_tags:
57 all_tags[tag].add(value)
58 else:
59 all_tags[tag] = set([value])
60 coll_tags.set(tag, value, track)
61 for tag, values in all_tags.iteritems():
62 if len(values) == 1:
63 # Only one value for this tag, so add it to global tags.
64 coll_tags.set(tag, list(values)[0])
65 # And now remove it from each track tags.
66 for track, tags in coll_tags._tracks.iteritems():
67 del tags[tag]
68 print '\n'.join(coll_tags.all())
69 return 0
70
71 def do_write(args):
72 tags = Tags()
73 tags.load(open(args.pop(0)))
74 if len(args) != len(tags):
75 sys.stderr.write('expected %d flac files, got %d\n'
76 % (len(tags), len(args)))
77 return 4
78 artist = tags.get_path_safe('ARTIST')
79 album = tags.get_path_safe('ALBUM'),
80 try:
81 os.mkdir(artist)
82 except OSError, e:
83 if e.errno != EEXIST:
84 raise
85 album_path = artist + '/' + album
86 try:
87 os.mkdir(album_path)
88 except OSError, e:
89 if e.errno != EEXIST:
90 raise
91 for i, old_fn in enumerate(args):
92 track = i + 1
93 fn = '%s/%s/%s.flac' % (artist, album, tags.make_filename(track))
94 if fn != old_fn:
95 #os.rename(old_fn, fn)
96 pass
97
98 def main(args):
99 if len(args) < 3:
100 return usage()
101 if args[1] == 'read':
102 return do_read(args[2:])
103 if args[1] == 'write':
104 return do_write(args[2:])
105 return usage()
106
107 def usage():
108 return 2
109
110 if __name__ == '__main__':
111 sys.exit(main(sys.argv))
112