Switching to a Mac

A friend of mine bought a new MacBook Pro (the aluminum uni-body style) and he let me play around with it a bit and I got hooked.  So recently bought one of my own and have begun the transition from windows to OS X.

I don’t think of myself as a typical user.  I am computer programmer and use linux at work so I am very comfortable at the command prompt and in unix like environments.  That’s the first thing that I liked about Mac OS X, it’s all just unix underneath … makes a lot more sense to me than windows.  Also, the programming frameworks that Apple provides are phenominal.  They are well thought out, elegant, and a pleasure to use.  Contrast that to the mess that is windows.  I think that i am quickly becoming an apple fan boy 🙂

Anyway one of the problems I ran into while pulling my files over from windows was getting my music ratings out of the windows itunes into my mac itunes.  All the files transferred over fine but I was left without any ratings.  This is a problem for me as I have taken the time to rate most of my library and i rely on those ratings to create smart playlists.  After searching the web there did not appear to be any simple way to get the ratings over.  But after about an hour of hacking around with apple script (which I have never used in my life before now) and a bit of python I was able to parse the XML file that itunes produces and set the ratings on my new itunes library.  It was pretty cool.  I thought I would post what I did in case any one in the future might find it useful.  Mind you this code is posted AS IS, with no warranty either express or implied.  It worked on my itunes library with no problem but if it nukes your itunes don’t come crying to me.

Ok, so how did I do it?

  1. Goto your old library and find the ITunes folder.  On my windows box this was in the Music folder.  There should be a file in there called “ITunes Music Library.xml”
  2. Transfer the aforementioned file to your mac computer
  3. Open up the terminal on your mac (you can do this by going to finder and typing ‘terminal’) and navigate to the folder where you saved the xml file.
  4. type emacs make_db.py
  5. in the make_db.py file paste the following text:

    import xml.sax.handler
    import sys

    class ITunesHandler(xml.sax.handler.ContentHandler):
        def __init__(self):
            self.parsing_tag = False
            self.tag = ”
            self.value = ”
            self.tracks = []
            self.track = None

        def startElement(self, name, attributes):
            if name == ‘key’:
                self.parsing_tag = True

        def characters(self, data):
            if self.parsing_tag:
                self.tag = data
                self.value = ”
            else:
                # could be multiple lines, so append data.
                self.value = self.value + data
               
        def endElement(self,name):
            if name == ‘key’:
                self.parsing_tag = False
            else:
                if self.tag == ‘Track ID’:
                    # start of a new track, so a new object
                    # is needed.
                    self.track = Track()
                elif self.tag == ‘Name’ and self.track:
                    self.track.track = self.value
                elif self.tag == ‘Rating’ and self.track:
                    self.track.rating = self.value
                    self.tracks.append(self.track)
                    self.track = None
                elif self.tag == ‘Size’ and self.track:
                    self.track.size = self.value
                elif self.tag == ‘Artist’ and self.track:
                    self.track.artist = self.value

    class Track:
        def __init__(self):
            self.track = ”
            self.artist = ”
            self.size = ”
            self.rating = ”

        def __str__(self):
            return “Track = %s\nArtist = %s\nRating = %s\nSize = %s” % (self.track, self.artist, self.rating, self.size)

    parser = xml.sax.make_parser()
    handler = ITunesHandler()
    parser.setContentHandler(handler)
    parser.parse(‘FULL PATH YOUR XML FILE’)

    my_tracks = []
    for track in handler.tracks:
        my_tracks.append(track)

    import pickle
    f = open(‘data’, ‘w’)
    pickle.dump(my_tracks, f)
    f.close()

  6. Run that program by typing python make_db.py at the terminal
  7. Now open get_rating.py and fill it with the following commands:

    import pickle, sys

    class Track:
        def __init__(self):
            self.track = ”
            self.artist = ”
            self.size = ”
            self.rating = ”

        def __str__(self):
            return “Track = %s\nArtist = %s\nRating = %s\nSize = %s” % (self.track, self.artist, self.rating, self.size)

    search_name = sys.argv[1]
    search_size = sys.argv[2]
    f = open(‘FULL PATH TO DATA FILE’, ‘r’)
    my_tracks = pickle.load(f)
    f.close()

    for track in my_tracks:
        try:
            if search_name == track.track and search_size == track.size:
                print track.rating
        except Exception, e:
            print e

  8. Now open up ‘Script Editor’ (again, you can use the finder to get to this and enter the following applescript program:

    tell application “iTunes”
        set currentList to view of front window
        repeat with currTrack in (get every track of currentList)
            set trackName to name
    of currTrack
            set trackSize to size of currTrack
            set newRating to (do shell script “python ~/Downloads/get_rating.py \”” & trackName & “\” ” & trackSize)
            set rating of currTrack to newRating
        end repeat
    end tell

  9. That’s it, now all your ratings should be loaded into itunes!

I apologize that the instructions require some comfortability with your mac.