diff --git a/binding.gyp b/binding.gyp index f6caa2e..41f916e 100644 --- a/binding.gyp +++ b/binding.gyp @@ -4,6 +4,7 @@ "target_name": "libspotify", "sources": [ "src/album.cc", + "src/albumbrowse.cc", "src/artist.cc", "src/audio.cc", "src/binding.cc", diff --git a/lib/Album.js b/lib/Album.js index 29834ee..c8af14c 100644 --- a/lib/Album.js +++ b/lib/Album.js @@ -83,4 +83,17 @@ Album.prototype.smallCoverImage = function (cb) { this.coverImage(this.IMAGE_SIZ Album.prototype.normalCoverImage = function (cb) { this.coverImage(this.IMAGE_SIZE_NORMAL, cb); } Album.prototype.largeCoverImage = function (cb) { this.coverImage(this.IMAGE_SIZE_LARGE, cb); } +Album.prototype.getTracks = function (cb) { + var browser = b.albumbrowse_create(this.getSession()._sp_session, this._sp_object, function () { + tracks = new Array(b.albumbrowse_num_tracks(browser)); + + for(var i = 0; i callback = static_cast(userdata); + + callback->Call(callback, 0, NULL); + callback.Dispose(); +} + +static Handle AlbumBrowse_Create(const Arguments& args) { + HandleScope scope; + + // test arguments sanity + assert(args.Length() == 3); + assert(args[0]->IsObject()); // sp_session + assert(args[1]->IsObject()); // sp_album + assert(args[2]->IsFunction()); // callback + + ObjectHandle *session = ObjectHandle::Unwrap(args[0]); + ObjectHandle *album = ObjectHandle::Unwrap(args[1]); + Handle callback = Persistent::New(Handle::Cast(args[2])); + + ObjectHandle* albumbrowse = new ObjectHandle("sp_albumbrowse"); + albumbrowse->pointer = sp_albumbrowse_create(session->pointer, album->pointer, cb_albumbrowse_complete, *callback); + + return scope.Close(albumbrowse->object); +} + +static Handle AlbumBrowse_Num_Tracks(const Arguments& args) { + HandleScope scope; + + // test arguments sanity + assert(args.Length() == 1); + assert(args[0]->IsObject()); // sp_albumbrowse + + ObjectHandle *albumbrowse = ObjectHandle::Unwrap(args[0]); + const int num = sp_albumbrowse_num_tracks(albumbrowse->pointer); + + return scope.Close(Number::New(num)); +} + +static Handle AlbumBrowse_Track(const Arguments& args) { + HandleScope scope; + + // test arguments sanity + assert(args.Length() == 2); + assert(args[0]->IsObject()); // sp_albumbrowse + assert(args[1]->IsNumber()); // index + + // input + ObjectHandle *albumbrowse = ObjectHandle::Unwrap(args[0]); + int index = args[1]->ToNumber()->Int32Value(); + + // output + sp_track* sptrack = sp_albumbrowse_track(albumbrowse->pointer, index); + ObjectHandle* track = new ObjectHandle("sp_track"); + track->pointer = sptrack; + + return scope.Close(track->object); +} + +static Handle AlbumBrowse_Release(const Arguments& args) { + HandleScope scope; + + // test arguments sanity + assert(args.Length() == 1); + assert(args[0]->IsObject()); // sp_albumbrowse + + ObjectHandle *albumbrowse = ObjectHandle::Unwrap(args[0]); + sp_error error = sp_albumbrowse_release(albumbrowse->pointer); + NSP_THROW_IF_ERROR(error); + + return scope.Close(Undefined()); +} + +void nsp::init_albumbrowse(Handle target) { + NODE_SET_METHOD(target, "albumbrowse_create", AlbumBrowse_Create); + NODE_SET_METHOD(target, "albumbrowse_num_tracks", AlbumBrowse_Num_Tracks); + NODE_SET_METHOD(target, "albumbrowse_track", AlbumBrowse_Track); + NODE_SET_METHOD(target, "albumbrowse_release", AlbumBrowse_Release); +} diff --git a/src/binding.cc b/src/binding.cc index f1484bf..9b8ab90 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -27,6 +27,7 @@ extern "C" { // initializing all modules nsp::init_album(target); + nsp::init_albumbrowse(target); nsp::init_artist(target); nsp::init_link(target); nsp::init_player(target); diff --git a/src/common.h b/src/common.h index 79b8e53..3ed9df9 100644 --- a/src/common.h +++ b/src/common.h @@ -140,6 +140,7 @@ namespace nsp { * init the album related functions to the target module exports */ void init_album(v8::Handle target); + void init_albumbrowse(v8::Handle target); /** * init the artist related functions to the target module exports */ @@ -156,7 +157,7 @@ namespace nsp { * init the playlist related functions to the target module exports */ void init_playlist(v8::Handle target); - + /** * This utility class allows to keep track of a C pointer that we attached * to a JS object. It differs from node's ObjectWrap in the fact that it @@ -191,7 +192,7 @@ namespace nsp { * We do create this one */ v8::Persistent object; - + /** * Get the name of the ObjectHandle that we gave it during instanciation */ @@ -229,7 +230,7 @@ namespace nsp { object->SetPointerInInternalField(0, this); } - + template ObjectHandle* ObjectHandle::Unwrap(v8::Handle obj) { assert(obj->IsObject()); diff --git a/test/test-032-albumbrowse.js b/test/test-032-albumbrowse.js new file mode 100644 index 0000000..bb451fd --- /dev/null +++ b/test/test-032-albumbrowse.js @@ -0,0 +1,37 @@ +var sp = require('../lib/libspotify'); +var testutil = require('./util'); + +var getAlbum = function(test, cb) { + var search = new sp.Search('artist:"Hurts" album:"Exile"'); + search.trackCount = 1; + search.execute(function() { + test.ok(search.tracks.length > 0, 'the album was found'); + test.ok(search.tracks[0] instanceof sp.Track, 'track is an track'); + test.ok(search.tracks[0].album instanceof sp.Album, 'album is an album'); + cb(search.tracks[0].album); + }); +}; + +var session = null; + +exports.albumbrowse = { + setUp: function(cb) { + testutil.getDefaultTestSession(function(s) { + session = s; + cb(); + }); + }, + 'get tracks from album': function(test) { + getAlbum(test, function(album) { + album.getTracks(function(err, tracks) { + test.ifError(err); + test.equal(tracks.length, 14, 'the album has 14 tracks'); + test.equal(tracks.map(function(e) {return e instanceof sp.Track;}).indexOf(false), -1, 'It should only contain tracks'); + test.equal(tracks.reduce(function(prev, current) { + return prev && current.isReady(); + }, true), true, 'All tracks should be loaded'); + test.done(); + }); + }); + } +}