Simple PHP Code To Get last.fm Last Played Tracks

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.
    You can see in the example above that I have selected the small image size in the array by using $track->image[0].
  • 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-&gt;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.

Permalink

Simple PHP code, though I got it mixed up with the one I'm working on now. Haha. But thanks for this! *bookmarks*

Permalink

Works like a charm, unlike all the WordPress plugins I've tried

Permalink
Great code! Is there any way to implement this to a group on last.fm? Lets say display all users from the group and what there last track was? Cheers, Danyo
Permalink
Thanks :) The only comparable feed available for groups is the journal feed (eg. http://ws.audioscrobbler.com/1.0/group/Women+in+Extreme+Metal/journals.rss). The alternative here is to use the Last.fm API to extract the data you need from the system. This requires the use of an API key, which you have to apply for. Using that you can then either get a list of the most listened tracks that week with the getWeeklyTrackChart method (http://www.last.fm/api/show/group.getWeeklyTrackChart) or via getting members of the group through getMembers (http://www.last.fm/api/show/group.getMembers) and then looping through each member to find their latest tracks. Of course, the simplest way to go might be to have a list of users and loop through them to collate their track listings. You'll need to compare the date and time of each entry to put them in order, but it shouldn't be that hard :)
Name
Philip Norton
Permalink
Thanks for the reply. I have managed to do it! With you above code is there anyway to limit the amount of tracks being pulled in from each user? Currently its 10, i would only like 1 track to be pulled in. Cheers, Dan
Permalink
I found this script very useful... the simplicity of the code loads quite fast. Like a previous post, I would like to display only one track. I have implemented your solution, it works like a charm. I was curious... when I'm listening to music, Last.fm will apply a 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, Scott
Permalink
You'll probably want something like:foreach ($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.
Name
Philip Norton
Permalink
Hi, is there a way to make it like showing 2 songs instead of 11 songs? Greets, Jerry
Permalink
Or is there a way, to make it like this? 1st song (now playing) 2nd song, last played | 3th song - 4th song | 5th song | 6th song So you can echo the 5th song which has played, and so forth..? Its kinda neat for Wordpress in the footer area :) Greets, Jerry
Permalink
really its likely content
Permalink
thanks youre saved my live
Permalink

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
11 + 4 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.