The other day I was approached by a friend (Julie Cheung) and asked if I could create some code that would display a list of last played tracks from last.fm. Julie isn't a PHP developer and so the code I gave her had to be easily understandable so that she could edit it herself if needed. The following code is what I came up with.
$username = 'philipnorton42';
$scrobbler_url = "http://ws.audioscrobbler.com/2.0/user/" . $username . "/recenttracks";
if ($scrobbler_xml = file_get_contents($scrobbler_url)) {
$scrobbler_data = simplexml_load_string($scrobbler_xml);
echo '<ul>';
foreach ($scrobbler_data->track as $track) {
$string = '<li>';
$string .= '<div class="cover"><img class="cover" height="28" src="' . $track->image[0] . '" width="28" /></div>';
$string .= '<p><span class="title">' . $track->artist . '</span><br />' . $track->name . '</p>';
$string .= '<p>Played: ' . $track->date . '</p>'; $string .= '</li>';
echo $string;
}
echo '</ul>';
}
What this code does is to grab the XML feed containing the latest played songs from last.fm and convert them into a set of list elements containing some information about the tracks. This is done very simply by using the simple_xml_load_string() function, which works quite well for most situations and in this case only destroys a small amount of information that isn't really needed. Each track contains information about the artist and track that was played, including album artwork. Here is a breakdown of the information available in the feed, with the latest song in my own playlist as an example.
- artist : The name of the artist (e.g. "The Black Dahlia Murder").
- name : This is the name of the track (e.g. "Deathmask Divine").
- streamable : This is a boolean value (as a 1 or a 0) that states if the track can be streamed.
- mbid : The mbid is an ID of the song, but is lost when the XML feed is passed through the simplexml_load_string() function. This doesn't matter, however, as we probably won't need it when printing out the results.
- album : This is the name of the album that the track belongs to (e.g. "Nocturnal").
- url : This is a URL that links back to the track information on the last.fm site. For the example I gave above this is http://www.last.fm/music/The+Black+Dahlia+Murder/_/Deathmask+Divine.
- image : This is an array if different images for the album cover. Although the sizes are lost in the translation from XML the array translates to the following sizes:
- 0 : Small image size, 34px by 34px.
- 1 : Medium image size, 64px by 64px.
- 2 : Large image size, 128px by 128px.
- 3 : Extra large image size, 300px by 300px.
- date : This is the date and time that the track was played on (e.g. "21 Nov 2011, 15:28").
One addition to this code would be to stop it pulling in the entire feed on every page load, which isn't really needed. The addition of a small amount of caching code is ideal to keep page load times down (especially as we are relying on a third party service). We only need to store the data in a separate file for about 3 minutes or so (the average playtime of a song) so this time check is also added to the code.
<?php
$username = 'philipnorton42';
$scrobbler_url = "http://ws.audioscrobbler.com/2.0/user/" . $username . "/recenttracks";
$scrobbler_cache_file = 'scrobbler_' . $username . '_data.cache';
if (file_exists($scrobbler_cache_file)) {
if (time() - filemtime($scrobbler_cache_file) --> 180) {
// if the file was created more than 3 minutes ago then delete.
unlink($scrobbler_cache_file);
} else {
$scrobbler_url = realpath('./' . $scrobbler_cache_file);
}
}
if ($scrobbler_xml = file_get_contents($scrobbler_url)) {
$scrobbler_data = simplexml_load_string($scrobbler_xml);
if (!file_exists($scrobbler_cache_file)) {
file_put_contents($scrobbler_cache_file, $scrobbler_xml);
}
echo '<ul>';
foreach ($scrobbler_data->track as $track) {
$string = '<li>';
$string .= '<div class="cover"><img class="cover" height="28" src="' . $track->image[0] . '" width="28" /></div>';
$string .= '<p><span class="title">' . $track->artist . '</span><br />' . $track->name . '</p>';
$string .= '<p>Played: ' . $track->date . '</p>';
$string .= '</li>';
echo $string;
}
echo '</ul>';
}
You can see the code (or at least a variant) in action on Julie Cheung's site. If you want my to write something like to for your own blog then let me know, as long as I can create a blog post out of it (and perhaps a backlink) I'm happy to help.
Comments
Nice code, very easy to understand. You just taught me some cool things I have yet to learn about PHP and caching also.
Simple PHP code, though I got it mixed up with the one I'm working on now. Haha. But thanks for this! *bookmarks*
Works like a charm, unlike all the WordPress plugins I've tried
to the XML feed. When this occurs, the script displays two tracks. Is it possible to disregard the
so that the script displays only one track, regardless of playing music or not?
Thanks,
Scottforeach ($scrobbler_data->track as $track) { if ($track->nowplaying == 'true') { continue; }
...
Note that this is untested, but what what you said in your comment the track should have a 'nowplaying' property, which should contain a value of some sort. This is probably a string saying 'true', but it *might* get transformed into a boolean so it's worth checking.
Essentially, when the nowplaying property is true then the loop skips the track in question so you won't see it in the output.