Connecting Spotify to your Windows lockscreen in 36 lines of code

In this tutorial we will make our Windows 8/8.1 lockscreen more dynamic and colorful, by displaying whatever track currently playing on Spotify on the lockscreen, using node.js and a couple of NodeRT & out of the box npm modules.

The full script & modules are available at: https://github.com/nadavbar/spotify-lockscreen/tree/blog
For the sake of brevity, all code samples below lack error handling of any kind, but the code in the github repository above, does not.

[Throughout this tutorial, the currently playing track will be Edward Sharpe and the Magnetic Zeros - 40 Day Dream (you should totally play it on the background while you're reading this...)]

In order to achieve our goal, we will need to do 3 things:
1. Get the track currently playing on Spotify.
2. Get album art for the track.
3. Put that album art on the lockscreen.

Ok then, let's get started:

1. Get the track currently playing on Spotify:

For this section, We will use the node-spotify-webhelper module that I wrote, which interacts with the Spotify Web Helper API. (more info on this method is available here)

So, getting the current track, comes down to:

var nsw = require('node-spotify-webhelper');  
var spotify = new nsw.SpotifyWebHelper();

spotify.getStatus(function (err, res) {  
  // do something with the result..
});

The result of the getStatus method is a JSON containing the current track information:

{ version: 9,
  client_version: '0.9.10.21.g22fbdb39',
  playing: false,
  shuffle: false,
  repeat: false,
  play_enabled: true,
  prev_enabled: true,
  next_enabled: true,
  track:
   { track_resource:
      { name: '40 Day Dream',
        uri: 'spotify:track:3WBWgjyg6ew1Bq2sehB4is',
        location: { og: 'http://open.spotify.com/track/3WBWgjyg6ew1Bq2sehB4is' }
 },
     artist_resource:
      { name: 'Edward Sharpe & The Magnetic Zeros',
        uri: 'spotify:artist:7giUHu5pv6YTZgSkxxCcgh',
        location: { og: 'http://open.spotify.com/artist/7giUHu5pv6YTZgSkxxCcgh'
} },
     album_resource:
      { name: 'Up From Below',
        uri: 'spotify:album:4EBtalKeisyblXwox9mMXf',
        location: { og: 'http://open.spotify.com/album/4EBtalKeisyblXwox9mMXf' }
 },
     length: 234,
     track_type: 'normal' },
  playing_position: 2.7900002,
  server_time: 1403897300,
  volume: 1,
  online: true,
  open_graph_state: { private_session: false, posting_disabled: true },
  running: true }

From the JSON above, we can easily retrieve the artist & name of the track, but furthermore - we can also retrieve the URL for the track's Spotify page, which is located in the track.track_resource.location.og field - we will use this URL in the next section.

2. Get album art for the track:

Browsing to the URL we got at the end of the previous section: http://open.spotify.com/track/3WBWgjyg6ew1Bq2sehB4is, a nice page will show up, displaying the name of the artist and track, and...a colorful image! Examining the page source, you will notice that the image element's id is "big-cover".
Ok, let's get that image now. Since we're working with node.js, this should be pretty easy - just a couple of lines of code using request and cheerio:

var fs = require('fs');  
var path = require('path');

var request = require('request')  
var cheerio = require('cheerio')  
var nsw = require('node-spotify-webhelper');

var spotify = new nsw.SpotifyWebHelper();

spotify.getStatus(function (err, res) {  
  var url = res.track.track_resource.location.og;
  // scrape the spotify website and get url to the track's image
  request(url, function (err, res, body) {

    // get the src url of the image 
    var $ = cheerio.load(body);
    var imageUrl = $('img[id=big-cover]')[0].attribs.src;

    var imageFilePath = path.join(__dirname, 'image.png');
    // download the image and set the lockscreen
    request(imageUrl).pipe(
      fs.createWriteStream(imageFilePath))
      .on('close', function (err) {
        // set the lock screen image now...
    });
  });
});

3. Put that album art on the lockscreen:

The simplest thing we could do in order to set the lock screen image in Windows 8/8.1, would be to use the LockScreen API, and the SetImageFileAsync method that does just that. This API is part of the Windows Store Apps API, but is also available for desktop apps.

At first this task may seem a bit tricky...we need to use native APIs here, maybe even write some C++ code to in order to interact with the API above...

Enter NodeRT, a WinRT-nodejs modules generator we recently released. NodeRT generates node.js native addons that bridge between node.js and WinRT APIs.

So, all we need in order to use the LockScreen API from node.js is to generate 2 NodeRT modules:

  • windows.system.userprofile - for using the lockscreen class
  • windows.storage - for creating a WinRT StorageFile object that will be passed to the SetImageFileAsync method.

Using the generated NodeRT modules, the following code snippet will do the trick:

var profile = require('windows.system.userprofile');  
var storage = require('windows.storage');

storage.StorageFile.getFileFromPathAsync(imageFilePath,  
  function (err, file) {
    profile.LockScreen.setImageFileAsync(file, function (err) {
      console.info('lock screen was set!');
    });
  });

Plugging it into the code from section 2, our final script for setting the image according to the currently playing Spotify track is:

var fs = require('fs');  
var path = require('path');

var request = require('request')  
var cheerio = require('cheerio')  
var nsw = require('node-spotify-webhelper');

var profile = require('windows.system.userprofile');  
var storage = require('windows.storage');

var spotify = new nsw.SpotifyWebHelper();

spotify.getStatus(function (err, res) {  
  var url = res.track.track_resource.location.og;
  // scrape the spotify website and get url to the track's image
  request(url, function (err, res, body) {

    // get the src url of the image 
    var $ = cheerio.load(body);
    var imageUrl = $('img[id=big-cover]')[0].attribs.src;

    var imageFilePath = path.join(__dirname, 'image.png');
    // download the image and set the lockscreen
    request(imageUrl).pipe(
      fs.createWriteStream(imageFilePath))
      .on('close', function (err) {
      // set the lock screen image
        storage.StorageFile.getFileFromPathAsync(
          imageFilePath, function (err, file) {
        profile.LockScreen.setImageFileAsync(file, function (err) {
          console.info('lock screen was set!');
        });
      });
    });
  });
});

And the result:

The full code, which is available here, goes a bit further and checks whether the currently playing song had changed every 15 seconds, and then sets the lock screen image using the code shown above.



[Big thanks go out to Guy & Chen for helping out with this post :)]



[Update: 10 Aug 2014 - Merged an awesome pull request by Steynno and Cariah that queries the Spotify API for an image with a better quality, parses JSON instead HTML and supports different images when playing is paused/image not available (see blog comments for more details). Updated Code is available on the master branch. Thanks guys!]