Simple PHP Code To Get last.fm Last Played Tracks

Thursday, December 1, 2011 - 09:52

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$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 width="28" height="28" class="cover" src="' . $track->image[0] . '" /></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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?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 width="28" height="28" class="cover" src="' . $track->image[0] . '" /></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.

Category: 
philipnorton42's picture

Philip Norton

Phil is the founder and administrator of #! code and is an IT professional working in the North West of the UK.
Google+ | Twitter

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*

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

philipnorton42's picture
Submitted by philipnorton42 on Wed, 06/05/2013 - 16:09

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 :)

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

philipnorton42's picture
Submitted by philipnorton42 on Thu, 06/06/2013 - 10:32

Yes. You can do that by appending the 'limit' argument. For example:
http://ws.audioscrobbler.com/2.0/user/philipnorton42/recenttracks?limit=1

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 <track nowplaying="true"> to the XML feed. When this occurs, the script displays two tracks. Is it possible to disregard the <track nowplaying="true"> so that the script displays only one track, regardless of playing music or not?

Thanks,
Scott

philipnorton42's picture
Submitted by philipnorton42 on Thu, 04/03/2014 - 19:02

You'll probably want something like:
1
2
3
4
5
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.

Add new comment