]> diplodocus.org Git - flac-archive/blob - rewrite-tags
some write work
[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 if len(track_tags) != 1:
47 sys.stderr.write('bogus TRACKNUMBER %s: %s\n' % (track_tags, fn))
48 return 3
49 track = int(track_tags[0])
50 for tag, values in tags._global.iteritems():
51 for value in values:
52 if tag in all_tags:
53 all_tags[tag].add(value)
54 else:
55 all_tags[tag] = set([value])
56 coll_tags.set(tag, value, track)
57 for tag, values in all_tags.iteritems():
58 if len(values) == 1:
59 # Only one value for this tag, so add it to global tags.
60 coll_tags.set(tag, list(values)[0])
61 # And now remove it from each track tags.
62 for track, tags in coll_tags._tracks.iteritems():
63 del tags[tag]
64 print '\n'.join(coll_tags.all())
65 return 0
66
67 def do_write(args):
68 tags = Tags()
69 tags.load(open(args.pop(0)))
70 if len(args) != len(tags):
71 sys.stderr.write('expected %d flac files, got %d\n'
72 % (len(tags), len(args)))
73 return 4
74 artist = tags.get_path_safe('ARTIST')
75 album = tags.get_path_safe('ALBUM'),
76 try:
77 os.mkdir(artist)
78 except OSError, e:
79 if e.errno != EEXIST:
80 raise
81 album_path = artist + '/' + album
82 try:
83 os.mkdir(album_path)
84 except OSError, e:
85 if e.errno != EEXIST:
86 raise
87 for i, old_fn in enumerate(args):
88 track = i + 1
89 fn = '%s/%s/%s.flac' % (artist, album, tags.make_filename(track))
90 if fn != old_fn:
91 #os.rename(old_fn, fn)
92
93 def main(args):
94 if len(args) < 3:
95 return usage()
96 if args[1] == 'read':
97 return do_read(args[2:])
98 if args[1] == 'write':
99 return do_write(args[2:])
100 return usage()
101
102 def usage():
103 return 2
104
105 if __name__ == '__main__':
106 sys.exit(main(sys.argv))
107