Skip to content

Instantly share code, notes, and snippets.

@scoffey
Created November 25, 2010 04:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scoffey/714923 to your computer and use it in GitHub Desktop.
Save scoffey/714923 to your computer and use it in GitHub Desktop.
Sorts a given iTunes playlist according to the least played tracks in each album
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This script implements an algorithm for sorting a given iTunes playlist
according to the least played tracks in each album.
It aims to identify the tracks that were played the least and to show
how many times they should be played in order to reach the same playcount
as the most played track in the album they belong to.
The program input is the name of the playlist where tracks should be
taken from and the name of the new playlist to create or replace. The
output, apart from the new iTunes playlist, is a table showing the
candidate tracks and the playcount difference used for sorting them.
"""
__author__ = 'Santiago Coffey'
__email__ = 'scoffey@alu.itba.edu.ar'
__version__ = '0.1'
__license__ = 'GNU General Public License 3'
__docformat__ = 'restructuredtext en'
import sys
import appscript
iTunes = appscript.app('itunes')
def make_catalog(tracks):
""" Makes a music catalog dict by artist+album with track playcounts """
catalog = dict()
for track in tracks:
artist = track.album_artist() or track.artist()
album = track.album()
album_list = catalog.get((artist, album), {})
album_list[track] = track.played_count()
catalog[(artist, album)] = album_list
return catalog
def make_tracks_tuples(album_list, artist, album):
""" Returns tuples with artist name, album name, track object and
playcount difference """
max_playcount = max(album_list.values())
return [(artist, album, track, max_playcount - n) for track, n \
in album_list.iteritems() if n < max_playcount]
def get_candidates(playlist):
""" Returns candidate tracks data sorted by playcount difference """
candidates = []
catalog = make_catalog(playlist.file_tracks())
for artist_album, album_list in catalog.iteritems():
tuples = make_tracks_tuples(album_list, *artist_album)
candidates.extend(tuples)
candidates.sort(key=lambda x: x[3], reverse=True)
return candidates
def show_candidates(candidates):
""" Prints candidate tracks data as a table """
template = '\t | '.join(['%s'] * 4)
for artist, album, track, count in candidates:
print template % (count, artist, album, track.name())
def replace_playlist(name, tracks):
""" Creates or replaces an iTunes playlist with given tracks """
playlist = iTunes.user_playlists[name]
if iTunes.exists(playlist): # empty existing playlist
if len(playlist.tracks()):
iTunes.delete(playlist.tracks)
else: # create playlist
iTunes.make(new=appscript.k.playlist, \
with_properties={appscript.k.name: name})
for track in tracks:
iTunes.duplicate(track, to=playlist)
def main(program, *args):
""" Main program: Computes and creates new playlist according to input """
source = raw_input('Enter your source playlist name: ')
playlist = iTunes.user_playlists[source]
if iTunes.exists(playlist):
destination = raw_input('Enter your destination playlist name: ')
candidates = get_candidates(playlist)
show_candidates(candidates)
replace_playlist(destination, [i[2] for i in candidates])
else:
print 'Error: No such iTunes playlist: %s' % source
if __name__ == '__main__':
main(*sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment