diff --git a/example/playPreview.js b/example/playPreview.js new file mode 100644 index 0000000..1ac4d02 --- /dev/null +++ b/example/playPreview.js @@ -0,0 +1,37 @@ + +/** + * Example script that retrieves a preview of the specified Track through Spotify, + * then decodes the MP3 data through node-lame, and fianally plays the decoded PCM + * data through the speakers using node-speaker. + */ + +var Spotify = require('../'); +var login = require('../login'); +var lame = require('lame'); +var Speaker = require('speaker'); + +// determine the URI to play, ensure it's a "track" URI +var uri = process.argv[2] || 'spotify:track:6tdp8sdXrXlPV6AZZN2PE8'; +var type = Spotify.uriType(uri); +if ('track' != type) { + throw new Error('Must pass a "track" URI, got ' + JSON.stringify(type)); +} + +// initiate the Spotify session +Spotify.login(login.username, login.password, function (err, spotify) { + if (err) throw err; + + // first get a "Track" instance from the track URI + spotify.get(uri, function (err, track) { + if (err) throw err; + console.log('Playing 30 second preview of: %s - %s', track.artist[0].name, track.name); + + track.playPreview() + .pipe(new lame.Decoder()) + .pipe(new Speaker()) + .on('finish', function () { + spotify.disconnect(); + }); + + }); +}); diff --git a/lib/track.js b/lib/track.js index e56158d..71a8ac3 100644 --- a/lib/track.js +++ b/lib/track.js @@ -29,6 +29,18 @@ Object.defineProperty(Track.prototype, 'uri', { configurable: true }); +/** + * Track Preview URL getter + */ +Object.defineProperty(Track.prototype, 'previewUrl', { + get: function () { + var previewUrlBase = 'http://d318706lgtcm8e.cloudfront.net/mp3-preview/' + return this.preview.length && (previewUrlBase + util.gid2id(this.preview[0].fileId)); + }, + enumerable: true, + configurable: true +}) + /** * Loads all the metadata for this Track instance. Useful for when you get an only * partially filled Track instance from an Album instance for example. @@ -100,3 +112,41 @@ Track.prototype.play = function () { // return stream immediately so it can be .pipe()'d return stream; }; + +/** + * Begins playing a preview of the track, returns a Readable stream that outputs MP3 data. + * + * @api public + */ + +Track.prototype.playPreview = function () { + var spotify = this._spotify; + var stream = new PassThrough(); + var previewUrl = this.previewUrl; + + if (!previewUrl) { + process.nextTick(function() { + stream.emit('error', new Error('Track does not have preview available')); + }); + return stream; + } + + debug('GET %s', previewUrl); + var req = spotify.agent.get(previewUrl) + .set({ 'User-Agent': spotify.userAgent }) + .end() + .request(); + req.on('response', response); + + function response (res) { + debug('HTTP/%s %s', res.httpVersion, res.statusCode); + if (res.statusCode == 200) { + res.pipe(stream); + } else { + stream.emit('error', new Error('HTTP Status Code ' + res.statusCode)); + } + } + + // return stream immediately so it can be .pipe()'d + return stream; +};