annotate itunes2mp3.py @ 1:0ca90a90e723

Complete rework to make MP3 CDs from iTunes plist (XML) playlists. Use ffmpeg as it doesn't barf on long file names or some m4as (like faad) nor does it display unwanted album images and hang wasting CPU (mplayer). Shuffle now creates a directory and fills it with hardlinks in random order.
author Daniel O'Connor <darius@dons.net.au>
date Thu, 13 Jun 2013 00:16:23 +0930
parents 7ca49dff763a
children 1681a628ceb4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
1 #!/usr/bin/env python
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
2
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
3 import errno
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
4 import glob
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
5 import os
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
6 import plistlib
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
7 import random
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
8 import shutil
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
9 import subprocess
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
10 import sys
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
11 import urllib2
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
12
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
13 def compress(srcfile, destdir):
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
14 plist = plistlib.readPlist(srcfile)
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
15 playlist = plist['Playlists'][0]
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
16
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
17 failures = []
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
18 for item in playlist['Playlist Items']:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
19 track = plist['Tracks'][str(item['Track ID'])]
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
20 if 'Location' not in track:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
21 print "No location for " + track['Name']
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
22 continue
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
23
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
24 location = track['Location']
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
25
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
26 path = urllib2.unquote(urllib2.urlparse.urlparse(location).path)
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
27 print "Path is " + path
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
28
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
29 destmp3 = destdir + '/' + path.split('/')[-1][:-3] + 'mp3'
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
30 if os.path.isfile(destmp3):
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
31 print "Already done"
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
32 continue
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
33
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
34 devnull = file('/dev/null', 'w')
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
35 if path.lower().endswith('.mp3'):
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
36 shutil.copy(path, destmp3)
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
37 elif path.lower().endswith('.m4a'):
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
38 ffmpeg = subprocess.Popen(['ffmpeg', '-y', '-v', 'quiet', '-b', '160', '-i', path, destmp3])
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
39 rtn = ffmpeg.wait()
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
40
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
41 if rtn != 0:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
42 print "Failed to convert %s, return code %d" % (path, rtn)
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
43 failures.append(path)
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
44 try:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
45 os.unlink(destmp3)
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
46 except OSError, e:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
47 if e.errno != 2:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
48 raise e
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
49 else:
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
50 print "Don't know how to convert " + path
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
51 if len(failures) > 0:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
52 print
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
53 print "Failures:"
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
54 for f in failures:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
55 print f
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
56
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
57 def shuffle(srcdir):
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
58 try:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
59 os.mkdir(srcdir + '/burn')
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
60 except OSError, e:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
61 if e.errno != 17:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
62 raise e
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
63 files = glob.glob(srcdir + '/*.mp3')
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
64 random.shuffle(files)
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
65
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
66 i = 0
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
67 for f in files:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
68 dest = srcdir + '/burn/%03d - %s' % (i, f.split('/')[-1])
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
69 i += 1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
70 os.link(f, dest)
0
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
71
7ca49dff763a Initial commit
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
72 if __name__ == "__main__":
1
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
73 if len(sys.argv) != 2:
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
74 print "Bad usage"
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
75 print "%s playlist.xml destdir"
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
76 sys.exit(1)
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
77
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
78 compress(sys.argv[1], sys.argv[2])
0ca90a90e723 Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Daniel O'Connor <darius@dons.net.au>
parents: 0
diff changeset
79 shuffle(sys.argv[2])