Controlling iTunes from Python

July 12, 2011

django-tunesBack in 2008 I stumbled on then new API on Mac OS X called Scripting Bridge that enables easy controlling of Cocoa apps (like iTunes) from scripting languages like Python.

I wrote simple proof-of-concept Django app that turned my iPod touch into a remote control. It was cool, even though it didn’t do very much. Now there’s of course native iOS apps for this but I was somewhat surprised that there are still not much code for controlling iTunes via Web. I misplaced my original code so I decided to write it again – just for fun.

So here’s a working class for controlling iTunes, in 58 lines of Python:

# -*- coding: utf-8 -*-
from Foundation import *
from ScriptingBridge import *

class iTunes(object):
    """
    A helper class for interacting with iTunes on Mac OS X via Scripting 
    Bridge framework.

    To use this, launch iTunes and make sure a playlist or an album is ready.

    Usage:

    >>> player = iTunes()
    >>> player.status
    'playing'
    >>> player.current_track
    u'Maison Rilax'
    >>> player.current_album
    u'Maison Rilax'
    >>> player.current_artist
    u'Lemonator'
    >>> player.pause()
    >>> player.status
    'paused'
    >>> player.play()
    >>> player.next()
    >>> player.current_track
    u'Not Your Game'

    """

    def __init__(self):
        self.app = SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes")

    def _get_status(self):
        if self.app.playerState() == 1800426320:
            return "playing"
        elif self.app.playerState() == 1800426352:
            return "paused"
        else:
            return "unknown"
    status = property(_get_status)

    def _get_current_track(self):
        return self.app.currentTrack().name()
    current_track = property(_get_current_track)

    def _get_current_artist(self):
        return self.app.currentTrack().artist()
    current_artist = property(_get_current_artist)

    def _get_current_album(self):
        return self.app.currentTrack().album()
    current_album = property(_get_current_album)

    def _set_volume(self, level):
        """
        level should be an integer between 0-100.
        """
        self.app.setSoundVolume_(level)

    def _get_volume(self):
        return self.app.soundVolume()
    volume = property(_get_volume, _set_volume)

    def pause(self):
        self.app.pause()

    def play(self):
        # According to AppleScript documentatin there should be a .play() 
        # method, but apparently there isn't. So we fake it :)
        if self.status == "paused":
            self.app.playpause()

    def next(self):
        self.app.nextTrack()

    def previous(self):
        self.app.previousTrack()

This could be easily refined into something potentially interesting like a native REST API for iTunes. The downside, of course, is that it only works on a Mac. (The code is available also on BitBucket.)

A somewhat related is a project called Mopidy, which is a Python powered MPD music server for the awesome Spotify music service (that is suposed to finally be launching in US very soon, I hear.). I’m not at all familiar with MPD but I think it wouldn’t be very difficult to build a Django frontend to a server like Mopidy to get a very slick Web-based interface to your music. Now that would be cool.

Tagged with , , ,
Proudly Powered by Django
Unessa.net © 2000-2018 Ville Säävuori. All lefts reversed.