Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
from collections import defaultdict
import plistlib
# I copied files locally.
# NEW is what gets written.
# CURRENT is the current "iTunes Library.xml" file (or rather, my copy).
# OLD is an old backup with lots of good ratings.
OLD = 'itunes.xml'
CURRENT = 'itunes_2012.xml'
NEW = 'updated.xml'
# I match based on filenames. IDs are different, sigh.
# But I needed to compensate for a new iTunes folder structure.
OLD_PREFIX = 'file://localhost/Users/reinout/Music/iTunes/iTunes%20Music/'
CURRENT_PREFIX = 'file://localhost/Users/reinout/Music/iTunes/iTunes%20Media/Music/'
def main():
# Read in the old tracks and grab the ratings.
old = plistlib.readPlist(OLD)
old_tracks = old['Tracks']
print "Found {} old tracks".format(len(old_tracks))
old_ratings = {}
for track in old_tracks.values():
filename = track['Location'].replace(OLD_PREFIX, '')
rating = track.get('Rating')
if rating is None:
old_ratings[filename] = rating
print "Found {} old ratings".format(len(old_ratings))
# Same with the current ratings. If we've rated something, we want to
# keep that rating.
current = plistlib.readPlist(CURRENT)
current_tracks = current['Tracks']
print "Found {} current tracks".format(len(current_tracks))
current_ratings = {}
for track in current_tracks.values():
filename = track['Location'].replace(CURRENT_PREFIX, '')
rating = track.get('Rating')
if rating is None:
current_ratings[filename] = rating
print "Found {} current ratings".format(len(current_ratings))
# Figure out which old ratings we want to move over.
new_ratings = {}
for filename in old_ratings:
if filename not in current_ratings:
new_ratings[filename]= old_ratings[filename]
print "This means {} new ratings".format(len(new_ratings))
# Create a dict {rating: tracks} for the new ratings I want to set.
new_playlists = defaultdict(list)
for track in current_tracks.values():
filename = track['Location'].replace(CURRENT_PREFIX, '')
new_rating = new_ratings.get(filename)
if new_rating is None:
track_id = track['Track ID']
# Create a playlist per rating. You can set the playlist's items to
# the correct rating in iTunes just fine.
playlists = []
for rating, track_ids in new_playlists.items():
print rating, len(track_ids)
new_playlist = {}
new_playlist['Name'] = str(rating) + ' points'
new_playlist['Visible'] = True
new_playlist['Playlist ID'] = 8000 + rating
new_playlist['All Items'] = True
new_playlist['Playlist Items'] = [{'Track ID': track_id}
for track_id in track_ids]
# Zap the existing ones, otherwise you end up with double items.
current['Playlists'] = playlists
plistlib.writePlist(current, NEW)
if __name__ == '__main__':
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.