Amarok: Record Labels from MusicBrainz

This code should* select all the albums in a MySQL Amarok database for which the release date is known, look each one up from MusicBrainz and associate a record label with the album's tracks using the addLabels DCOP call.

There's no ID3 tag for 'record label', so I was thinking of using the 'Genre' field, but Amarok's generic free-text 'Label' field seems to work well enough if you're not using it for anything else, although the record label metadata won't be written to the MP3 files.

Last.fm is hosting a UK mirror of MusicBrainz now, so this script uses that. Change the host to "musicbrainz.org" if you're elsewhere.

* NOTE: backup your database first


#! /usr/bin/env python
import sys, time, MySQLdb, os
from musicbrainz2.webservice import Query, ReleaseFilter, ReleaseIncludes, WebService
mb = WebService(host='www.uk.musicbrainz.org')
inc = ReleaseIncludes(releaseEvents=True, labels=True)
db = MySQLdb.connect(db="DB_NAME", user="DB_USER", passwd="DB_PASS", use_unicode=True, charset="utf8")
c = db.cursor()
c.execute("""SELECT a.name as 'artist', a.id as 'artist_id', b.name as 'album', b.id as 'album_id' FROM `artist` a INNER JOIN `tags` t ON a.id = t.artist INNER JOIN `album` b ON t.album = b.id  WHERE t.sampler = 0 AND t.year > 1 GROUP BY a.id, b.id ORDER BY a.name ASC""")
print "%d rows" % c.rowcount
albums = c.fetchall()
for (artist, artist_id, album, album_id) in albums:  
  if (artist and album):
    time.sleep(1)
    
    q = Query(mb)
    print "Looking up: %s - %s" % (artist, album)
    f = ReleaseFilter(artistName=artist, title=album, limit=1)
    search_results = q.getReleases(f)
    
    if search_results:
      release = search_results[0].release
      
      print "Found: %s - %s" % (release.artist.name, release.title)
      
      release_result = q.getReleaseById(release.id, inc)
      if (release_result and release_result.releaseEvents):      
        if release_result.releaseEvents[0].label:
          label = release_result.releaseEvents[0].label
          print label.name
          c.execute("""SELECT CONCAT_WS('/', d.lastmountpoint, t.url) AS track_url FROM `tags` t LEFT JOIN `devices` d ON t.deviceid = d.id WHERE artist = %s AND album = %s ORDER by track_url ASC""", (artist_id, album_id))
          tracks = c.fetchall()
          for track_url in tracks:
            url = track_url[0].replace('"', r'\"')
            name = label.name.replace('"', r'\"')
            print 'addLabels "%s" [ "%s" ]' % (url, name)
            os.system('dcop amarok collection addLabels "%s" [ "%s" ]' %  (url, name))
        else:
          print "No label"  
      else:
        print "No release results"
        
    else:
      print "No results"
  print
c.close()
db.close()
You can use something like this to display them:

<?php
$link = mysql_connect('localhost', 'DB_USER', 'DB_PASS');
mysql_select_db('DB_NAME');
$result = mysql_query("SELECT l.name, COUNT(l.id) as c FROM tags_labels tl LEFT JOIN labels l ON tl.labelid = l.id GROUP BY l.id ORDER BY c DESC");
$items = array();
while($label = mysql_fetch_object($result)){
  $items[] = "<tr><td><a href='http://musicbrainz.org/search/oldsearch.html?type=label&order=date&handlearguments=1&query={$label->name}'>{$label->name}</a></td><td>{$label->c}</td></td>";
}
print "<table><tr><th>Label</th><th>Tracks</th></tr>" . implode("\n", $items) . "</table>";