[UPDATED - see below!]
Here’s some cool code I hacked together from the iTunes Windows COM SDK docs and some other sites - Dan Crevier’s Blog and ajc.
I had already posted how I did something like this in WinAmp, but I’ve been using iTunes a lot now and really like it. There are a few plugins and such out there to post the current track info to a file or site, but the main thing other scripts didn’t do was to post the stream info if iTunes was playing a stream.
Basically it’s some JavaScript that runs in the background listening for events from the iTunes applications. Currently I’m just using OnPlayerPlayEvent and OnQuittingEvent, but some of the other events might be cool to use. I just create a little XML and post it to the web server - this one’s real time, where my WinAmp one was polled.
I don’t know how good or efficient this code is, but it hasn’t crashed my box yet! I also am posting a simple cgi I hacked up in Perl to snag the bits of XML and output an HTML file that is included in my main page via SSI.
I just start iTunes, then run my script. When I exit iTunes, the JavaScript code exits as well - and it tells you it’s closing.
iTunes JavaScript code: (I think I got the html escaped - I need a better way to post code!)
var iTunesApp = WScript.CreateObject("iTunes.Application");
var iTunesIsRunning = true;
function ITEventTest_OnPlayerPlayEvent(iTrack) {
getCurrentTrackInfo();
}
function ITEventTest_OnPlayerPlayingTrackChangedEvent(iTrack) {
getCurrentTrackInfo();
}
function ITEventTest_OnQuittingEvent() {
iTunesIsRunning = false;
}
function getCurrentTrackInfo() {
var current = iTunesApp.CurrentTrack;
var stream = iTunesApp.CurrentStreamTitle;
var trackType = "";
var trackName = "";
var trackArtist = "";
var trackAlbum = "";
if (stream != "") {
streamURL = iTunesApp.CurrentStreamURL;
trackType="stream";
trackName=stream;
trackArtist=current.Name;
trackAlbum=streamURL;
} else {
trackType="file";
trackName=current.Name;
trackArtist=current.Artist;
trackAlbum=current.Album;
}
var response = postTrack(trackType, trackName, trackArtist, trackAlbum);
}
function postTrack(trackType, trackName, trackArtist, trackAlbum) {
var xmlTrack = new ActiveXObject("MSXML2.DOMDocument.4.0");
xmlTrack.loadXML(’<?xml version="1.0" ?><track/>’);
var root = xmlTrack.documentElement;
root.setAttribute("type", trackType);
var textNode = xmlTrack.createElement("name");
textNode.text = trackName;
root.appendChild(textNode);
var textNode = xmlTrack.createElement("artist");
textNode.text = trackArtist;
root.appendChild(textNode);
var textNode = xmlTrack.createElement("album");
textNode.text = trackAlbum;
root.appendChild(textNode);
var xmlhttp = new ActiveXObject("MSXML2.XMLHTTP.4.0");
xmlhttp.open("POST", "http://[cgi url]",false);
xmlhttp.send(xmlTrack);
if (xmlhttp.status != "200") {
WScript.Echo("Error posting to server. Code is: " + xmlhttp.status);
}
}
WScript.ConnectObject(iTunesApp, "ITEventTest_");
WScript.Echo("Waiting for changes…");
getCurrentTrackInfo();
while (iTunesIsRunning) {
WScript.Sleep(1000);
}
var response = postTrack("OFFLINE", "offline.", "", "");
WScript.DisconnectObject(iTunesApp);
WScript.Echo("iTunes was closed, iTunesListener exiting.");
Perl CGI on the server: (Beware: I’m not a great Perl coder!)
#!/usr/bin/perl
use XML::LibXML;
local $/;
my $parser = XML::LibXML->new();
my $request = <STDIN>;
my $xmlRequest = $parser->parse_string($request);
my $root = $xmlRequest->getDocumentElement;
my $type = $root->getAttribute("type");
my @nodes = $root->findnodes("name");
my $name = $nodes[0]->string_value();
@nodes = $root->findnodes("artist");
my $artist = $nodes[0]->string_value();
my @nodes = $root->findnodes("album");
my $album = $nodes[0]->string_value();
open(file,">[path writable by web server]/current_song.html");
print file $name;
print file "<br />";
print file $artist;
print file "<br />";
print file $album;
print file "\n";
close(file);
print "Content-type: text/html\n\n";
print "ok";
And the simple Server Side Include in my html:
<!–#include virtual=”../includes/iTunes/current_song.html” –>
Works for me and it’s pretty cool hack I think! I’m thinking about some other possiblities… If I can use iTunes to publish a stream, then I could have some playlist posting and even playlist manipulation - that could be cool.
Also I found a somewhat cool plugin for iTunes on Windows called “multi plugin”. I only really use the plugin for controlling iTunes with my laptop’s multimedia buttons when iTunes is minimized - iTunes should automatically do this like WinAmp did. I can’t figure out how to uninstall it though!
UPDATE:
Seems I deleted some code that is needed so that the getCurrentTrackInfo() function is called when listening to a stream. The “OnPlayerPlayEvent” event is not called when the track a stream is playing changes. You need to trap for “OnPlayerPlayingTrackChangedEvent”, so just add this:
function ITEventTest_OnPlayerPlayingTrackChangedEvent(iTrack) {
getCurrentTrackInfo();
}
I’ve updated my code above to reflect this. The full title of the stream sometimes isn’t present when you first connect - just reconnect if that bothers you.
Also, I need to add some more error trapping too. The script crashes if you start the script and iTunes isn’t playing anything - at least this happens to me!
Enjoy!