oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Controlling iTunes with Perl

by brian d foy

I created the Mac::iTunes Perl module to control iTunes from my scripts and from other machines. Everything that I present in this article comes with either the Mac::iTunes or Apache::iTunes distributions available on CPAN.

Once I have a back end, I can create almost any interface to iTunes that I like, and I do.

iTunes is AppleScriptable

Apple's MP3 player, iTunes, has been AppleScript-aware since version 2 (the latest version is 3.0.1). This gives me a lot of freedom to control how I use iTunes.

I can use Script Editor to create a script, but I can also use the osascript command-line tool from a Terminal window. I can use the -e switch to include a short script on the command line, or I can store the script in file. Once I liberate myself from Script Editor, I have more flexibility.

% osascript -e 'tell application "iTunes" activate'
-- iTunes script "quit_itunes"
-- run as "osascript quit_itunes"
tell application "iTunes"
end tell
% osascript quit_itunes

Scripts for iTunes can automate a lot of my common tasks. Apple has a collection of scripts, and Doug's AppleScripts for iTunes & SoundJam has several more good ones.

iTunes and Perl

Although I like AppleScript for very simple things, I think it gets tedious for complicated scripts. The language is verbose and does not have a good extension mechanism. Perl, on the other hand does, but at the moment it does not have good access to Aqua applications, even though it can control the usual Unix applications in Mac OS X, just like it can on other Unix platforms.

When I started to work with iTunes AppleScripts, I wanted it to be as easy to do as writing Perl scripts, even though it was not. After a while I decided to fix that by writing a Perl module to handle the AppleScript portions of iTunes. I already had a MacOSX::iTunes Perl module that I used to parse the binary format of the iTunes Music Library file. I needed to add AppleScript support to it.

On the suggestion of Chris Nandor, the caretaker of MacPerl and author of Mac::Carbon, I changed the name of my distribution to Mac::iTunes and added the Mac::iTunes::AppleScript module, which wrapped common AppleScripts in Perl functions. The meat of the module was the _osascript routine, which creates an AppleScript string and calls osascript just like I did earlier.

sub _osascript
	my $script = shift;
	require IPC::Open2;
	my( $read, $write );
	my $pid = IPC::Open2::open2( $read, $write, 'osascript' );
	print $write qq(tell application "iTunes"\n), $script,
			qq(\nend tell\n);
	close $write;
	my $data = do { local $/; <$read> };
	return $data;

The Mac::iTunes::AppleScript works much like the osascript command-line tool. Indeed, the first version simply created a script string (called osascript) with that script, and captured the output, if any, for parsing. About the same time I finished the first version, Nathan Torkington needed Perl access to AppleScript and convinced Dan Sugalski to write Mac::AppleScript. With that module, Perl could work with AppleScript without calling an external program. I replaced the _osascript routine with tell(), which uses the RunAppleScript function from Mac::AppleScript.

sub tell
	my $self    = shift;
	my $command = shift;
	my $script = 
		qq(tell application "iTunes"\n$command\nend tell);
	my $result = RunAppleScript( $script );
	if( $@ )
		carp $@;
	return 1 if( defined $result and $result eq '' );
	$result =~ s/^"|"$//g;
	return $result;

Once I have tell(), I simply feed it an AppleScript string, which it runs, and then returns the result. For example, iTunes can play Internet streams. The AppleScript way to say this uses open location.

tell application "iTunes"
	open location ""
end tell

In Mac::iTunes::AppleScript, I wrapped this little script in a method, named open_url(), which takes a URL as an argument and uses tell() to run it.

sub open_url
	my $self = shift;
	my $url  = shift;
	$self->tell( qq|open location "$url"| );

Most of the AppleScript commands for iTunes have a corresponding method in Mac::iTunes::AppleScript. Now I can use the full power of Perl, even though I am really using AppleScript behind the scenes.

iTunes, Perl, and Terminal

Just as I ran AppleScripts from the Terminal window with osascript, I can now run Perl programs that interact with iTunes. I want to play streaming media with very few keystrokes and without going to the iTunes Open Streaming... menu item -- it's just too much work when I do not want to switch applications. I created a simple program, named stream, using Mac::iTunes. I create an iTunes controller object, then call the open_url() method with the first command-line argument. Perl tells iTunes to play the MP3 stream, and even though iTunes starts to do something, it stays in the background while I continue whatever I am doing. I can even use this program from shell scripts.

use Mac::iTunes;
my $controller = Mac::iTunes->controller;
$controller->open_url( $ARGV[0] );
% stream

Small scripts do not have much of an advantage over the equivalent AppleScripts, but as things get more complex, Perl starts to shine.

Pages: 1, 2

Next Pagearrow