#!/usr/bin/env python # -*- coding: utf-8 -*- # # Martin Tournoij # # Use this code as you see fit. There are no restrictions. # import cgi import codecs import operator import os import re import subprocess import sys import time from mutagen.mp3 import MP3 # Header for the HTML page head = u''' Martin's Music
[To top] | [Hide all] | [Show all] | [Generator source]
[Last upd %(now)s] | [Artists: %(artistcount)i] | [Albums: %(albumcount)i] | [Tracks: %(trackcount)i] | [Avg album/artist: %(avg).1f] | [Size: %(totalsize)s]

Clicking on an artist or album title will get you to the corresponding MusicBrainz page.
Clicking on the [+] will show you the albums. If you want to expand all the fields, then (re)load this page with Javascript disabled.
Note that most release dates are the release date of this specific release, not the original release date of the album.

''' # Used once at the top of each artist hdr = u''' ''' # Used for each album item = u''' ''' # Used once at the bottom of each artist ftr = u''' ''' # Used once at the bottom of the HTML page footer = u'''
[+] %(artist)s (Permalink | Wikipedia)
%(album)s %(year)s %(type)s, %(status)s %(bitrate)i Kbps
''' def GetTags(mp3file): f = MP3(mp3file) info = { 'bitrate': f.info.bitrate / 1000, 'artist': cgi.escape(f.tags.get('TPE1')[0]), 'name': cgi.escape(f.tags.get('TALB')[0]), 'year': '9999', 'type': None, 'status': None, 'albumid': None, 'artistid': None, } for t in f.tags.getall('TXXX'): if t.desc == 'MusicBrainz Album Type': info['type'] = t.text[0] elif t.desc == 'MusicBrainz Album Status': info['status'] = t.text[0] elif t.desc == 'MusicBrainz Album Id': info['albumid'] = t.text[0] elif t.desc == 'MusicBrainz Album Artist Id': info['artistid'] = t.text[0] if f.tags.get('TDOR'): info['year'] = f.tags.get('TDOR').__str__()[:4] elif f.tags.get('TDRL'): info['year'] = f.tags.get('TDRL').__str__()[:4] elif f.tags.get('TDRC'): info['year'] = f.tags.get('TDRC').__str__()[:4] # XXX hack if info['albumid'] == '95b6db4a-8ce8-43a6-918c-d3b540179c0f': info['artist'] = 'Biosphere & Deathprod' return info artistcount = 0.0 albumcount = 0.0 music = [] for artist in os.listdir(u'.'): if not os.path.isdir(artist) or artist == 'new': continue # XXX commandline switch #if artistcount >= 5: break artistcount += 1 thisartist = [{'year': '0000'}] for album in os.listdir(artist): if not os.path.isdir(u'%s/%s' % (artist, album)): continue track = os.listdir(u'%s/%s' % (artist, album))[0] albumcount += 1 try: # XXX commandline switch #print >> sys.stdout, u'Fetching tags for %s/%s/%s' % (artist, album, track) album = GetTags(u'%s/%s/%s' % (artist, album, track)) except: print >> sys.stderr, ' Error, skipping %s/%s/%s' % (artist, album, track) print >> sys.stderr, sys.exc_info()[1] #sys.exit(42) continue thisartist.append(album) # Sort by release year thisartist.sort(key=operator.itemgetter('year')) if len(thisartist) == 1: continue thisartist[0] = [ thisartist[1]['artist'], thisartist[1]['artistid'] ] music.append(thisartist) music.sort() totalsize = subprocess.Popen(['du', '-hc', '.'], stdout=subprocess.PIPE).communicate()[0] totalsize = totalsize.split('\n')[-2:][0].replace('total', '').strip() trackcount_p1 = subprocess.Popen(['find', '.', '-name', '*\.mp3'], stdout=subprocess.PIPE) trackcount_p2 = subprocess.Popen(['wc', '-l'], stdin=trackcount_p1.stdout, stdout=subprocess.PIPE) trackcount = int(trackcount_p2.communicate()[0].strip()) fp = codecs.open(sys.argv[1], 'w', 'utf-8') fp.write(head % ({ 'now': time.strftime('%d %b %Y'), 'artistcount': artistcount, 'albumcount': albumcount, 'trackcount': trackcount, 'avg': float(albumcount / artistcount), 'totalsize': totalsize, })) # Make sure we don't have invalid characters in the ID attribute. replace = { '': '[^a-zA-Z0-9_-]', 'one-': '1', 'two-': '2', 'three-': '3', 'four-': '4', 'five-': '5', 'six-': '6', 'seven-': '7', 'eight-': '8', 'nine-': '9', 'zero-': '0', '-': '--' } for lst in music: first = True for album in lst: # First entry in list is always the artist name if first: first = False # Make 100% valid HTML idlink idlink = album[0].lower() idlink = idlink.replace(' ', '-').strip('-') for (subst, repl) in replace.iteritems(): idlink = re.sub(repl, subst, idlink) wplink = 'http://en.wikipedia.org/wiki/%s' % album[0] mblink = 'http://musicbrainz.org/artist/%s' % album[1] fp.write(hdr % ({ 'idlink': idlink, 'wplink': wplink, 'artist': album[0], 'artistid': album[1], 'mblink': mblink, })) continue wplink = 'http://en.wikipedia.org/wiki/%s' % album['name'] mblink = 'http://musicbrainz.org/release/%s.html' % album['albumid'] if album['bitrate'] < 128: clss = ' red' elif album['bitrate'] < 180: clss = ' yellow' else: clss = '' if album['year'] == '9999': album['year'] = 'None' fp.write(item % ({ 'wplink': wplink, 'album': album['name'], 'year': album['year'], 'bitrate': album['bitrate'], 'type': album['type'], 'status': album['status'], 'mblink': mblink, 'albumid': album['albumid'], 'class': clss, 'idlink': idlink, })) fp.write(ftr % ({ 'idlink': idlink, })) fp.write(footer + u'\n') fp.close()