Last active
October 1, 2022 20:40
-
-
Save adammw/4285451 to your computer and use it in GitHub Desktop.
Spotify
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* https://spapps.spotify.edgekey.net/api/12e172c/scripts/main.js | |
* | |
* 15/12/2012 | |
*/ | |
function SpotifyApi() { | |
this._modules = {}; | |
this._requested = {}; | |
this._moduleQueue = []; | |
this._delayedFns = []; | |
this._parallelReqs = 4; | |
this._contextStack = []; | |
this._deferredFlush = !1; | |
this._patchRequestOpen() | |
} | |
SpotifyApi.AnalyticsContext = function (a) { | |
this.name = a; | |
this.id = SpotifyApi.AnalyticsContext._nextId++; | |
this.references = 0; | |
this._begin() | |
}; | |
SpotifyApi.AnalyticsContext._nextId = 1; | |
SpotifyApi.AnalyticsContext.prototype.addReference = function () { | |
this.references++ | |
}; | |
SpotifyApi.AnalyticsContext.prototype.removeReference = function () { | |
this.references--; | |
this.references === 0 && this._end() | |
}; | |
SpotifyApi.AnalyticsContext.prototype._begin = function () { | |
SpotifyApi.api.request("core_context_begin", [this.id, this.name], this) | |
}; | |
SpotifyApi.AnalyticsContext.prototype._end = function () { | |
SpotifyApi.api.request("core_context_end", [this.id], this) | |
}; | |
SpotifyApi.prototype.analyticsContext = function (a, f) { | |
var g = new SpotifyApi.AnalyticsContext(a); | |
g.addReference(); | |
this._contextStack.push(g); | |
try { | |
f() | |
} finally { | |
this._contextStack.pop(), g.removeReference() | |
} | |
}; | |
SpotifyApi.Callback = function (a, f) { | |
this._func = a; | |
this._setContextStack(f || SpotifyApi.api._contextStack) | |
}; | |
SpotifyApi.Callback.prototype.apply = function (a, f) { | |
try { | |
var g = SpotifyApi.api._contextStack; | |
SpotifyApi.api._contextStack = this._contextStack; | |
this._func.apply(a, f) | |
} catch (b) { | |
setTimeout(function () { | |
throw b; | |
}, 0) | |
} finally { | |
SpotifyApi.api._contextStack = g, this.clear() | |
} | |
}; | |
SpotifyApi.Callback.prototype.call = function (a, f) { | |
this.apply(a, Array.prototype.slice.call(arguments, 1)) | |
}; | |
SpotifyApi.Callback.prototype.copy = function () { | |
return new this.constructor(this._func, this._contextStack) | |
}; | |
SpotifyApi.Callback.prototype.clear = function () { | |
this._releaseContextStack(); | |
delete this._func; | |
delete this._contextStack | |
}; | |
SpotifyApi.Callback.prototype._setContextStack = function (a) { | |
for (var f = 0, g = a.length; f < g; ++f) a[f].addReference(); | |
this._contextStack = a.slice(0) | |
}; | |
SpotifyApi.Callback.prototype._releaseContextStack = function () { | |
for (var a = this._contextStack, f = 0, g = a.length; f < g; ++f) a[g - f - 1].removeReference() | |
}; | |
SpotifyApi.prototype.callback = function (a) { | |
return new SpotifyApi.Callback(a) | |
}; | |
SpotifyApi.prototype._getContextIdForRequest = function () { | |
var a = this._contextStack; | |
return a.length ? a[a.length - 1].id : 0 | |
}; | |
window.addEventListener("message", function (a) { | |
if (a.source == window && a.data == "api-delay") { | |
a.stopPropagation(); | |
for (var a = SpotifyApi.api._delayedFns.splice(0), f = 0, g = a.length; f < g; f++) a[f].call() | |
} | |
}); | |
SpotifyApi.prototype._prepareFlush = function () { | |
if (!this._deferredFlush) this._deferredFlush = !0, this.defer(this, this._flushRequests) | |
}; | |
SpotifyApi.prototype._flushRequests = function () { | |
this.request("core_flush", []); | |
this._deferredFlush = !1 | |
}; | |
SpotifyApi.prototype.defer = function (a, f) { | |
this._delayedFns.push(this.bind(this.callback(f), a)) == 1 && window.postMessage("api-delay", "*") | |
}; | |
SpotifyApi.prototype._evalModule = function (a, f, g, b) { | |
return !/\.lang$/.test(g) ? this._evalJSModule(a, f, g, b) : this._evalLangModule(g, b) | |
}; | |
SpotifyApi.prototype._evalJSModule = function (a, f, g, b) { | |
var c = this, | |
d = { | |
__name: g | |
}; | |
try { | |
return (new Function("require", "exports", "SP", "_code", "eval(_code)")).call({}, function (b, h) { | |
d.__waiting = !0; | |
var k = function () { | |
d.__waiting = !1; | |
return h.apply(this, arguments) | |
}; | |
k.__native = !0; | |
return c._require(g, a, f, b, k) | |
}, d, this, "'use strict';" + b + "\n//@ sourceURL=" + g), d | |
} catch (h) { | |
throw h.message += " in " + g, h; | |
} | |
}; | |
SpotifyApi.LangModule = function (a, f) { | |
this.__name = a; | |
this.strings = f | |
}; | |
SpotifyApi.LangModule.prototype.get = function (a, f) { | |
for (var g = this.strings.hasOwnProperty(a) ? this.strings[a] : a, b = "", c = 0, d, h; | |
(d = g.indexOf("{", c)) > -1;) { | |
h = g.indexOf("}", d + 1); | |
if (h == -1) break; | |
var i = arguments[parseInt(g.substring(d + 1, h)) + 1]; | |
b += i !== void 0 ? g.substring(c, d) + i : g.substring(c, h + 1); | |
c = h + 1 | |
} | |
return c ? b + g.substring(c) : g | |
}; | |
SpotifyApi.prototype._evalLangModule = function (a, f) { | |
try { | |
return new SpotifyApi.LangModule(a, JSON.parse(f)) | |
} catch (g) { | |
throw Error('Cannot import language file "' + a + '": ' + g.message); | |
} | |
}; | |
SpotifyApi.prototype._fireCallbacks = function (a) { | |
for (; a;) { | |
a.waiting--; | |
if (a.waiting) break; | |
a.unpacked.forEach(function (f) { | |
var g = f.position, | |
b = a.args[g], | |
f = f.property; | |
if (!(f in b)) throw Error('No "' + f + '" exported in module "' + b.__name + '"'); | |
a.args[g] = b[f] | |
}); | |
a.callback.apply({}, a.args); | |
a.waiting = 1 / 0; | |
a = a.parent | |
} | |
}; | |
SpotifyApi.prototype._createRequest = function (a, f) { | |
var g = new XMLHttpRequest; | |
g.open("GET", a, !0); | |
g.onreadystatechange = function () { | |
if (g.readyState == 4) { | |
if (g.status != 200 && g.status != 0) throw Error('Could not load module "' + a + '"; Not found.'); | |
f(g.responseText) | |
} | |
}; | |
g.send(null) | |
}; | |
SpotifyApi.prototype._loadModule = function (a, f, g, b, c) { | |
var d = this, | |
h = this._modules[g]; | |
h && !h.__waiting ? (a.args[b] = this._modules[g], c && a.unpacked.push({ | |
property: c, | |
position: b | |
}), this._fireCallbacks(a)) : this._requested[g] || !this._parallelReqs ? this.defer(this, function () { | |
this._loadModule(a, f, g, b, c) | |
}) : (this._requested[g] = !0, this._parallelReqs--, this._createRequest(g, function (h) { | |
d._parallelReqs++; | |
h = d._modules[g] = d._evalModule(a, f, g, h); | |
a.args[b] = h; | |
c && a.unpacked.push({ | |
property: c, | |
position: b | |
}); | |
d._fireCallbacks(a) | |
})) | |
}; | |
SpotifyApi.prototype._resolveModule = function (a) { | |
if (!/\.lang$/.test(a)) { | |
var f = a.match(/^(\$(?:[^\/]+)\/)(?!scripts)(.*)/); | |
f && (a = f[1] + "scripts/" + f[2]); | |
a += ".js" | |
} | |
return a | |
}; | |
SpotifyApi.prototype._require = function (a, f, g, b, c) { | |
typeof b == "string" && (b = [b]); | |
if (!b || !b.length) throw Error("Missing modules argument to require()."); | |
if (!c || typeof c != "function") throw Error("Missing callback function argument to require()."); | |
var d = b.length; | |
if (!c.__native && d != c.length) throw Error("Module-parameter mismatch! Imported " + d + " but only declared " + c.length + " in callback."); | |
a = { | |
name: a, | |
parent: f, | |
waiting: d, | |
callback: c, | |
args: Array(d), | |
unpacked: [] | |
}; | |
f.waiting++; | |
for (f = 0; f < d; f++) { | |
c = b[f]; | |
if (!c) throw Error("Empty module name in require."); | |
var h = c.split("#"), | |
c = this._resolveModule(h[0]), | |
h = h[1], | |
i = g.slice(0), | |
j = g.indexOf(c); | |
i.push(c); | |
if (j != -1) throw i = i.slice(j).join(" -> "), Error('Circular Dependency on Module "' + c + '": ' + i); | |
this._loadModule(a, i, c, f, h) | |
} | |
}; | |
SpotifyApi.prototype.varargs = function (a, f, g) { | |
f || (f = 0); | |
if (Array.isArray(a[f])) { | |
if (a.length > f + 1) throw Error("Ambiguous use of varargs"); | |
a = a[f]; | |
f = 0 | |
} | |
return f || g ? Array.prototype.slice.call(a, f) : a | |
}; | |
SpotifyApi.prototype.uris = function (a, f) { | |
for (var g = this.varargs(a, f), b = [], c = 0, d = g.length; c < d; c++) b.push(g[c].uri); | |
return b | |
}; | |
SpotifyApi.prototype.bind = function (a, f, g) { | |
if (arguments.length > 2) { | |
var b = Array.prototype.slice, | |
c = Function.prototype.bind; | |
if (c && a.bind === c) return c.apply(a, b.call(arguments, 1)); | |
var d = b.call(arguments, 2); | |
return function () { | |
return a.apply(f, arguments.length ? d.concat(b.call(arguments)) : d) | |
} | |
} else return function () { | |
return a.apply(f, arguments) | |
} | |
}; | |
SpotifyApi.prototype.inherit = function (a, f) { | |
var g = function () {}; | |
g.prototype = a._superClass = f.prototype; | |
a.prototype = new g; | |
return a.prototype.constructor = a | |
}; | |
SpotifyApi.prototype._patchRequestOpen = function () { | |
var a = XMLHttpRequest.prototype.open, | |
f = document.createElement("a"), | |
g = window.location; | |
XMLHttpRequest.prototype.open = function (b, c) { | |
var d = a.apply(this, arguments); | |
f.href = c; | |
f.protocol == g.protocol && f.hostname == g.hostname && this.setRequestHeader("X-Spotify-Requested-With", "XMLHttpRequest"); | |
return d | |
} | |
}; | |
function require(a, f) { | |
return SpotifyApi.api._require("__main__", { | |
callback: function () {}, | |
waiting: 1 / 0 | |
}, [], a, f) | |
} | |
String.prototype.decodeForText = function () { | |
return this.toString() | |
}; | |
String.prototype.decodeForHtml = function () { | |
var a = { | |
"&": "&", | |
"<": "<", | |
">": ">" | |
}, f = function (g) { | |
return a[g] | |
}; | |
return function () { | |
return this.replace(/[&<>]/g, f) | |
} | |
}(); | |
String.prototype.decodeForLink = function () { | |
return encodeURI(this) | |
}; | |
SpotifyApi.Bases = { | |
uri: "spotify", | |
url: "http://open.spotify.com" | |
}; | |
SpotifyApi.Exps = { | |
spotify: /^spotify:(.+)$/, | |
http: /^https?:\/\/open\.spotify\.com\/(.+)$/ | |
}; | |
String.prototype.toSpotifyURL = function () { | |
var a = this.match(SpotifyApi.Exps.spotify); | |
if (!a) return this; | |
var a = a.pop().replace(/:$/, "").split(/:/), | |
f = a.shift(); | |
f == "search" && (a = [a.join(":")]); | |
a.unshift(SpotifyApi.Bases.url, f); | |
return a.join("/") | |
}; | |
String.prototype.toSpotifyURI = function () { | |
var a = this.match(SpotifyApi.Exps.http); | |
if (!a) return this; | |
a = a.pop().replace(/\/$/, "").split(/\//); | |
a.unshift(SpotifyApi.Bases.uri); | |
return a.join(":") | |
}; | |
String.prototype.toSpotifyLink = function () { | |
return this.toSpotifyURI() | |
}; | |
(function () { | |
var a = 0, | |
f = {}; | |
SpotifyApi.prototype._throwError = !0; | |
var g = window.dependencies, | |
b = g["static"], | |
c = b.replace(/\/([^\/]*)$/, ""), | |
d = c + "/", | |
h = SpotifyApi.prototype._resolveModule; | |
SpotifyApi.prototype._resolveModule = function (a) { | |
var a = h(a), | |
d = a.match(/^\$([a-z\-\_]+)(\/.*)/), | |
f = !1, | |
j, l = !1; | |
d ? (f = d[1], j = d[2]) : /^\//.exec(a) && (l = !0); | |
d = !1; | |
/\.lang$/.exec(a) && (d = "en.loc", a = f ? "$" + f + "/" + (j = "/" + d + j) : (l ? "/" + d : d + "/") + a); | |
f && g[f] ? a = g[f] + j : (f ? a = "/" + f + j : l || (a = "/" + a), a = (f ? c : b) + a); | |
return a | |
}; | |
var i = window.MutationObserver || window.WebKitMutationObserver; | |
i ? (new i(function (a) { | |
for (var c = 0, f = a.length; c < f; c++) { | |
var g = a[c].addedNodes; | |
if (!g.length) return this; | |
for (var h = b + "/$", j = 0, l = g.length; j < l; j++) { | |
var i = g[j]; | |
if (i.tagName.toLowerCase() == "link" && /^\$/.test(i.getAttribute("href"))) i.href = i.href.replace(h, d) | |
} | |
} | |
})).observe(document.head, { | |
childList: !0 | |
}) : document.head.addEventListener("DOMSubtreeModified", function (a) { | |
if (a.target === document.head) for (var a = document.head.querySelectorAll('link[href^="$"]'), c = b + "/$", f = 0, g = a.length; f < g; f++) { | |
var h = a[f]; | |
if (/^\$/.test(h.getAttribute("href"))) h.href = h.href.replace(c, d) | |
} | |
}); | |
if ("XDomainRequest" in window) { | |
var j = SpotifyApi.prototype._createRequest; | |
SpotifyApi.prototype._createRequest = function (a, c) { | |
if (!/^http/.test(a)) return j(a, c); | |
var b = new XDomainRequest; | |
b.onprogress = function () {}; | |
b.onerror = function () { | |
throw Error('Could not load module "' + a + '"; Not found.'); | |
}; | |
b.onload = function () { | |
c(b.responseText) | |
}; | |
b.open("GET", a); | |
b.send(null) | |
} | |
} | |
var k = { | |
hermes_register_schema: 1 | |
}; | |
SpotifyApi.prototype.request = function (b, c, d, h, j) { | |
var l = window.top; | |
if (l === window) return this; | |
c = { | |
id: a++, | |
name: b, | |
args: c | |
}; | |
if (k[b]) c.deps = g; | |
l.postMessage(JSON.stringify(c), "*"); | |
if (!h) return this; | |
f[c.id] = { | |
success: h, | |
failed: j, | |
caller: d | |
}; | |
this._prepareFlush() | |
}; | |
SpotifyApi.prototype._requestReply = function (a) { | |
a = a.data; | |
if (typeof a == "string") try { | |
a = JSON.parse(a) | |
} catch (c) { | |
return this | |
} | |
var b = f[a.id]; | |
if (!b) return this; | |
a.success && b.success ? b.success.call(b.caller, a.payload) : !a.success && b.failed && b.failed.call(b.caller, a.payload) | |
}; | |
SpotifyApi.api = new SpotifyApi; | |
window.addEventListener("message", SpotifyApi.api._requestReply, !1); | |
SpotifyApi.Bases.url = "https://play.spotify.com"; | |
SpotifyApi.Exps.http = /^https?:\/\/(play|open)\.spotify\.com\/(.+)$/; | |
String.prototype.toSpotifyLink = function () { | |
return this.toSpotifyURL() | |
}; | |
document.documentElement.addEventListener("click", function (a) { | |
var b = a.target; | |
if (b.tagName.toLowerCase() === "a") { | |
var b = b.href, | |
c = null; | |
SpotifyApi.Exps.http.test(b) ? c = b.toSpotifyURI() : SpotifyApi.Exps.spotify.test(b) && (c = b); | |
c && (a.preventDefault(), SpotifyApi.api.request("application_open_uri", [c, null])) | |
} | |
}); | |
var l = Array.prototype.slice; | |
if (!Array.prototype.indexOf) Array.prototype.indexOf = function (a, b) { | |
for (var c = this.length >>> 0, d = b < 0 ? Math.max(0, c + b) : b || 0; d < c; d++) if (this[d] === a) return d; | |
return -1 | |
}; | |
if (!String.prototype.trim) String.prototype.trim = function () { | |
return String(this).replace(/^\s+|\s+$/g, "") | |
}; | |
if (!Function.prototype.bind) Function.prototype.bind = function (a) { | |
var b = this, | |
c = arguments.length > 1 ? l.call(arguments, 1) : null, | |
d = function () {}, f = function () { | |
var h = a, | |
g = arguments.length; | |
if (this instanceof | |
f) d.prototype = b.prototype, h = new d; | |
g = !c && !g ? b.call(h) : b.apply(h, c && g ? c.concat(l.call(arguments)) : c || arguments); | |
return h == a ? g : h | |
}; | |
return f | |
}; | |
({ | |
_modifiers: {}, | |
_keymap: {}, | |
_ignore: {}, | |
_bindings: {}, | |
_empty: function () {}, | |
init: function () { | |
SpotifyApi.api.request("keyboard_get_bindings", [], this, function (a) { | |
for (var b in a) a.hasOwnProperty(b) && (this[b] = a[b]) | |
}.bind(this), this._empty); | |
window.addEventListener("keydown", this.handleOwn.bind(this, !1)); | |
window.addEventListener("keyup", this.handleOwn.bind(this, !0)) | |
}, | |
handleOwn: function (a, | |
b) { | |
if (this._ignore[b.target.tagName.toLowerCase()]) return this; | |
var c = this._keymap[b.which || b.keyCode]; | |
if (!c) return this; | |
var d = this._modifiers; | |
b.altKey && (c |= d.alt); | |
b.metaKey && (c |= d.meta); | |
b.ctrlKey && (c |= d.ctrl); | |
c = this._bindings[c]; | |
if (!c) return this; | |
b.preventDefault(); | |
b.stopPropagation(); | |
a && SpotifyApi.api.request("keyboard_trigger_binding", [c], this, this._empty, this._empty) | |
} | |
}).init() | |
})(); | |
(function (a, f, g) { | |
function b(a) { | |
if (a = d[a]) for (var c = a.slice(0), f = 0, k = c.length; f < k; f++) { | |
var l = c[f]; | |
if (l && (l.waiting > 0 && l.waiting--, !l.waiting)) { | |
a[f] = null; | |
var u = l.callback, | |
z = g[l.name] = {}; | |
u(z); | |
b(l.name) | |
} | |
} | |
} | |
function c(a, c, f) { | |
for (var k = { | |
name: a, | |
waiting: 0, | |
callback: f | |
}, l = c.length; l--;) { | |
var u = c[l]; | |
u in g || (k.waiting++, (d[u] || (d[u] = [])).push(k)) | |
} | |
k.waiting || (c = g[a] = {}, f(c), b(a)) | |
} | |
var d = {}; | |
c.getState = function () { | |
return JSON.parse(JSON.stringify(d)) | |
}; | |
a._unrequire = c | |
})(this, SpotifyApi.api, SpotifyApi.api._modules); | |
(function (a) { | |
_unrequire("$api/models", [], function (f) { | |
function g(e) { | |
this._items = {}; | |
this._class = e | |
} | |
function b() {} | |
function c(e) { | |
this.object = e; | |
this._done = []; | |
this._fail = [] | |
} | |
function d() {} | |
function h() {} | |
function i() { | |
this._filters = []; | |
this._receivers = [] | |
} | |
function j() {} | |
function k(e) { | |
this.resolve("uri", e) | |
} | |
function l(e) { | |
this.resolve("uri", e); | |
this.resolve("tracks", new r(q, e, "album_disc_tracks")) | |
} | |
function u(e, a) { | |
this.resolve("albums", a && a.albums ? a.albums.map(F) : []) | |
} | |
function z() {} | |
function t() {} | |
function s(e) { | |
this.resolve("uri", | |
e) | |
} | |
function v(e, w, b, c, d) { | |
this.resolve("type", e); | |
this.resolve("uri", w); | |
this._snapshot = b; | |
this._args = c !== void 0 ? c : w; | |
this._factory = d || a.bind(e.fromURI, e) | |
} | |
function r(e, a, b, c, d) { | |
v.call(this, e, a, this._requestSnapshot, c, d); | |
this._prefix = b | |
} | |
function x(e) { | |
this.resolve("uri", e) | |
} | |
function B(e) { | |
this.resolve("uri", e); | |
this.resolve("contexts", new r(x, e, "context_group")) | |
} | |
function p(e) { | |
this.resolve("id", e) | |
} | |
function m(e) { | |
this.resolve("uri", e) | |
} | |
function C(e, a) { | |
this.index = e; | |
this.uri = a | |
} | |
function A() { | |
this.resolve("user", o.fromURI("spotify:user:@")) | |
} | |
function y(e, a, b, c) { | |
this._collection = e; | |
this._off = a === void 0 ? 0 : a; | |
this._len = b === void 0 ? -1 : b; | |
this._raw = !! c | |
} | |
function q(e) { | |
this.resolve("uri", e) | |
} | |
function o(e) { | |
this.resolve("uri", e) | |
} | |
var G = function (e) { | |
this.object.resolveMany(0, e); | |
this.setDone() | |
}, H = function () { | |
this.setDone() | |
}, n = function (e, w, b, d) { | |
e = new c(e); | |
a.request(w, b, e, d ? G : H, e.setFail); | |
return e | |
}, D = function (e) { | |
return s.fromURI(e.uri, e) | |
}, F = function (e) { | |
return k.fromURI(e.uri, e) | |
}, I = function (e) { | |
return l.fromURI(e.uri, e) | |
}; | |
g.lookup = function (e, a) { | |
return this._cache.lookup(e, | |
a) | |
}; | |
g.lookupMany = function (e) { | |
for (var a = [], b = 0, c = e.length; b < c; b++) a.push(this._cache.lookup(e[b])); | |
return a | |
}; | |
g.prototype.cache = function (e, a) { | |
this._items[e] = a | |
}; | |
g.prototype.lookup = function (e, a) { | |
if (!e) return null; | |
var b = this._items[e]; | |
b || (b = new this._class(e), b.resolveMany(0, a), this._items[e] = b); | |
return b | |
}; | |
g.prototype.remove = function (e) { | |
delete this._items[e] | |
}; | |
g.prototype.update = function (e, a) { | |
for (var b = 0, c = e.length; b < c; b++) { | |
var d = this._items[e[b]]; | |
d && d.resolveMany(0, a) | |
} | |
}; | |
b.prototype._observed = function () {}; | |
b.prototype.addEventListener = function (e, a) { | |
if (a) { | |
if (!this._ob) this._ob = {}, this._obcount = 0; | |
var b = this._ob[e]; | |
b ? b.push(a) : this._ob[e] = [a]; | |
this._obcount++; | |
this._obcount == 1 && this._observed() | |
} | |
}; | |
b.prototype.removeEventListener = function (e, a) { | |
var b = this._ob || {}, c = b[e] || [], | |
d = c.indexOf(a); | |
d != -1 && (this._obcount--, c.splice(d, 1), c.length || delete b[e], this._obcount || delete this._ob) | |
}; | |
b.prototype.dispatchEvent = function (e) { | |
typeof e == "string" && (e = { | |
type: e | |
}); | |
if (!e || !e.type) throw Error("Dispatched event must have a type."); | |
if (!e.target) e.target = this; | |
var w = ((this._ob || {})[e.type] || []).slice(0); | |
if (!w.length) return !0; | |
var b = !0; | |
e.preventDefault = function () { | |
b = !1 | |
}; | |
for (var c = 0; c < w.length; c++) try { | |
w[c].call(this, e) === !1 && (b = !1) | |
} catch (d) { | |
if (a._throwError) throw d; | |
} | |
return b | |
}; | |
c.prototype.always = function (e, w) { | |
var b, c; | |
w ? (b = w, c = e) : (b = e, c = this); | |
if (typeof b != "function") throw Error("A callback function is required"); | |
this._done ? (this._done.push(a.callback(a.bind(b, c))), this._fail.push(a.callback(a.bind(b, c)))) : b.apply(c, this._args); | |
return this | |
}; | |
c.prototype.done = function (e, w) { | |
var b, c; | |
w ? (b = w, c = e) : (b = e, c = this); | |
if (typeof b != "function") throw Error("A callback function is required"); | |
this._isDone ? b.apply(c, this._args) : this._done && this._done.push(a.callback(a.bind(b, c))); | |
return this | |
}; | |
c.prototype.fail = function (e, b) { | |
var c, d; | |
b ? (c = b, d = e) : (c = e, d = this); | |
if (typeof c != "function") throw Error("A callback function is required"); | |
this._isFail ? c.apply(d, this._args) : this._fail && this._fail.push(a.callback(a.bind(c, d))); | |
return this | |
}; | |
c.prototype.each = function (e, b) { | |
if (this._objs) { | |
var c, | |
d; | |
b ? (c = b, d = e) : (c = e, d = this); | |
if (typeof c != "function") throw Error("A callback function is required"); | |
this._each && this._each.push(a.callback(a.bind(c, d))); | |
for (var f = 0, g = this._objs.length; f < g; f++) c.call(d, this._objs[f]) | |
} | |
return this | |
}; | |
c.prototype.setDone = function (e) { | |
if (this._done) { | |
var a = this._done, | |
b = this._fail; | |
delete this._done; | |
delete this._fail; | |
if (arguments.length == 1) this.object = e; | |
this._isDone = !0; | |
this._args = [this.object]; | |
for (var c = 0, d = a.length; c < d; c++) a[c].apply(void 0, this._args); | |
a = 0; | |
for (c = b.length; a < c; a++) b[a].clear(); | |
delete this._each; | |
delete this._join; | |
delete this._numResolved; | |
delete this._oneFailed | |
} | |
}; | |
c.prototype.setFail = function (e) { | |
if (this._done) { | |
var a = this._fail, | |
b = this._done; | |
delete this._done; | |
delete this._fail; | |
this._isFail = !0; | |
this._args = [this.object, e]; | |
for (var e = 0, c = a.length; e < c; e++) a[e].apply(void 0, this._args); | |
a = 0; | |
for (e = b.length; a < e; a++) b[a].clear(); | |
delete this._each; | |
delete this._join; | |
delete this._numResolved; | |
delete this._oneFailed | |
} | |
}; | |
c.join = function (e) { | |
var b = new c, | |
e = a.varargs(arguments, | |
0, !0); | |
b._join = e; | |
b._each = []; | |
b._objs = []; | |
b._numResolved = 0; | |
e.length === 0 && b.setDone([]); | |
for (var d = 0, f = e.length; d < f; d++) e[d].done(b, b._oneDone).fail(b, b._oneFail); | |
return b | |
}; | |
c.prototype._oneEither = function () { | |
this._numResolved++; | |
if (!(this._numResolved < this._join.length)) { | |
this.object = []; | |
for (var e = 0, a = this._join.length; e < a; e++) this.object.push(this._join[e].object); | |
e = 0; | |
for (a = this._each.length; e < a; e++) this._each[e].clear(); | |
this._oneFailed ? this.setFail() : this.setDone() | |
} | |
}; | |
c.prototype._oneDone = function (e) { | |
if (this._done) { | |
this._objs.push(e); | |
for (var a = [], b = 0, c = this._each.length; b < c; b++) { | |
var d = this._each[b]; | |
a.push(d.copy()); | |
d.call(void 0, e) | |
} | |
this._each = a; | |
this._oneEither(e) | |
} | |
}; | |
c.prototype._oneFail = function (e) { | |
if (this._done) this._oneFailed = !0, this._oneEither(e) | |
}; | |
a.inherit(d, b); | |
d.define = function (e, a, b) { | |
e = e.prototype; | |
if (!e._prop) e._prop = {}; | |
if (!e._next) e._next = 0; | |
for (var b = { | |
mask: 0, | |
func: b | |
}, c = 0, d = a.length; c < d; c++) { | |
var f = 1 << e._next++; | |
b.mask |= f; | |
e._prop[a[c]] = { | |
mask: f, | |
group: b | |
} | |
} | |
}; | |
d.prototype._make = function (e, a) { | |
var b = this["_make_" + e]; | |
return b ? b(a) : a | |
}; | |
d.prototype.resolve = function (e, a, b) { | |
this._prop[e] && (this._done |= this._prop[e].mask, this._wait &= ~this._done, a = this._make(e, a), this.hasOwnProperty(e) && !b ? (b = this[e], b !== a && (this[e] = a, this.dispatchEvent({ | |
type: "change:" + e, | |
property: e, | |
oldValue: b | |
}))) : this[e] = a, this._wait || delete this._wait) | |
}; | |
d.prototype.resolveMany = function (e, a, b) { | |
for (var c in a) this.resolve(c, a[c], b); | |
this._done |= e; | |
this._wait &= ~e; | |
this.resolveDone() | |
}; | |
d.prototype.resolveDone = function () { | |
if (this._reqs) { | |
for (var e = [], a = 0; a < this._reqs.length; a++) this._reqs[a]._need & ~this._done || e.push(this._reqs.splice(a--, 1)[0]); | |
this._reqs.length || delete this._reqs; | |
this._wait || delete this._wait; | |
for (var a = 0, b = e.length; a < b; a++) e[a].setDone() | |
} | |
}; | |
d.prototype.resolveFail = function (e, a) { | |
this._wait &= ~e; | |
if (this._reqs) { | |
for (var b = [], c = 0; c < this._reqs.length; c++) this._reqs[c]._need & e && b.push(this._reqs.splice(c--, 1)[0]); | |
this._reqs.length || delete this._reqs; | |
this._wait || delete this._wait; | |
for (var c = 0, d = b.length; c < d; c++) b[c].setFail(a) | |
} | |
}; | |
d.prototype.load = function (e) { | |
var b = a.varargs(arguments), | |
d = new c(this); | |
d._need = this._neededForLoad(b); | |
d._need ? (this._reqs ? this._reqs.push(d) : this._reqs = [d], this._requestProperties(d._need)) : d.setDone(); | |
return d | |
}; | |
d.prototype._neededForLoad = function (e) { | |
for (var a = 0, b = 0, c = e.length; b < c; b++) { | |
var d = e[b], | |
f = this._prop[d]; | |
if (!f) throw Error(d + " is not a property."); | |
a |= f.mask | |
} | |
return a & ~this._done | |
}; | |
d.prototype._requestProperties = function (e) { | |
var a = [], | |
b; | |
for (b in this._prop) { | |
var c = this._prop[b], | |
d = c.group.mask; | |
if (d & e && !(d & this._wait) && (a.push(c.group), this._wait |= d, e &= ~d, !e)) break | |
} | |
e = 0; | |
for (b = a.length; e < b; e++)(c = this[a[e].func]) && c.call(this, a[e].mask) | |
}; | |
a.inherit(h, d); | |
h.prototype.bridgeListen = function (e, a) { | |
this._requestName = e; | |
this._requestArgs = a; | |
this._listening = !0; | |
this._eventWait() | |
}; | |
h.prototype.bridgeUnlisten = function () { | |
delete this._requestName; | |
delete this._requestArgs; | |
delete this._listening | |
}; | |
h.prototype._eventWait = function () { | |
this._listening && a.request(this._requestName, this._requestArgs, this, this._eventDone, this._eventFail) | |
}; | |
h.prototype._eventDone = function (e) { | |
this._eventWait(); | |
this.eventDone(e) | |
}; | |
h.prototype.eventDone = function (e) { | |
if (e.receiver && this.hasOwnProperty(e.receiver)) { | |
var a = this[e.receiver]; | |
a.resolveMany(0, e.data); | |
a.dispatchEvent(e) | |
} else this.resolveMany(0, e.data), this.dispatchEvent(e) | |
}; | |
h.prototype._eventFail = function (e) { | |
e.error == "timeout" && this._eventWait(); | |
this.eventFail(e) | |
}; | |
h.prototype.eventFail = function () {}; | |
a.inherit(i, h); | |
i.prototype.filter = function (e) { | |
this._filters.push(e) | |
}; | |
i.prototype.proxyTo = function (e) { | |
this._receivers.push(e) | |
}; | |
i.prototype.eventDone = function (e) { | |
var a, | |
b, c = !0; | |
for (a = 0, b = this._filters.length; a < b; a++) this._filters[a](e) === !1 && (c = !1); | |
if (c) for (a = 0, b = this._receivers.length; a < b; a++) this._receivers[a].eventDone(e) | |
}; | |
a.inherit(j, h); | |
j.init = function (e, a) { | |
e._type = a | |
}; | |
j.prototype.imageForSize = function (e) { | |
var a = this.images; | |
e *= window.devicePixelRatio || 1; | |
for (var b = 0, c = a ? a.length : 0; b < c; b++) if (a[b][0] >= e || b == c - 1) return a[b][1].replace("{size}", e); | |
return this.image | |
}; | |
j.prototype._metadata = function (e) { | |
a.request(this.constructor._type + "_metadata", [this.uri], this, function (a) { | |
this.resolveMany(e, | |
a) | |
}, function (a) { | |
this.resolveFail(e, a) | |
}) | |
}; | |
j.prototype._profile = function (e) { | |
a.request(this.constructor._type + "_profile", [this.uri], this, function (a) { | |
this.resolveMany(e, a) | |
}, function (a) { | |
this.resolveFail(e, a) | |
}) | |
}; | |
j.prototype.toString = function () { | |
return this.uri | |
}; | |
a.inherit(k, j); | |
d.define(k, ["uri"]); | |
d.define(k, "availability,artists,date,discs,image,images,label,name,playable,popularity,type".split(","), "_metadata"); | |
d.define(k, ["copyrights"], "_profile"); | |
d.define(k, ["tracks"], "_collections"); | |
j.init(k, "album"); | |
k.prototype._make_artists = function (e) { | |
return e && e.map(D) | |
}; | |
k.prototype._make_discs = function (e) { | |
return e && e.map(I) | |
}; | |
k.prototype._collections = function () { | |
this.resolve("tracks", new r(q, this.uri, "album_tracks")); | |
this.resolveDone() | |
}; | |
k.fromURI = g.lookup; | |
k.fromURIs = g.lookupMany; | |
k._cache = new g(k); | |
a.inherit(l, j); | |
d.define(l, ["uri", "tracks"]); | |
d.define(l, ["album", "number"], "_metadata"); | |
j.init(l, "disc"); | |
l.prototype._make_album = function (e) { | |
return e && k.fromURI(e) | |
}; | |
l.fromURI = g.lookup; | |
l.fromURIs = g.lookupMany; | |
l._cache = new g(l); | |
a.inherit(u, d); | |
d.define(u, ["albums"]); | |
u.fromURI = function (e, a) { | |
return new this(e, a) | |
}; | |
a.inherit(z, d); | |
d.define(z, ["features"], "_features"); | |
z.prototype._features = function (e) { | |
a.request("client_features", [], this, function (a) { | |
this.resolveMany(e, a) | |
}, function (a) { | |
this.resolveFail(e, a) | |
}) | |
}; | |
z.prototype.showShareUI = function (e, a, b) { | |
e = [e.uri || e, a || ""]; | |
b && "x" in b && "y" in b && (e.push(b.x), e.push(b.y)); | |
return n(this, "client_show_share_ui", e) | |
}; | |
z.prototype.showContextUI = function (e, b, c) { | |
e = [Array.isArray(e) ? a.uris(e) : [e.uri]]; | |
b && "x" in b && "y" in b && (e.push(b.x), e.push(b.y)); | |
c && c.uri && e.push(c.uri); | |
return n(this, "client_show_context_ui", e) | |
}; | |
a.inherit(t, h); | |
d.define(t, ["arguments", "dropped", "identifier", "name", "uri"], "_query"); | |
t.prototype._observed = function () { | |
this.bridgeListen("application_event_wait", []) | |
}; | |
t.prototype._make_dropped = function (e) { | |
return e && e.map(function (e) { | |
return E(e) | |
}) | |
}; | |
t.prototype._query = function (e) { | |
a.request("application_query", [], this, function (a) { | |
this.resolveMany(e, a) | |
}, function (a) { | |
this.resolveFail(e, | |
a) | |
}) | |
}; | |
t.prototype.activate = function () { | |
return n(this, "application_activate", [this.uri]) | |
}; | |
t.prototype.deactivate = function () { | |
return n(this, "application_deactivate", [this.uri]) | |
}; | |
t.prototype.exit = function (e) { | |
return n(this, "application_notify_exit", [e || 0]) | |
}; | |
t.prototype.hideLoadingScreen = function () { | |
a.request("application_notify_loaded", []) | |
}; | |
t.prototype.readFile = function (e) { | |
var a = new c, | |
b = new XMLHttpRequest; | |
b.open("GET", e, !0); | |
b.onreadystatechange = function () { | |
b.readyState === 4 && (b.status !== 200 && b.status !== 0 ? a.setFail() : a.setDone(b.responseText)) | |
}; | |
b.send(null); | |
return a | |
}; | |
t.prototype.openURI = function (e, a) { | |
return n(this, "application_open_uri", [e, a || null]) | |
}; | |
t.prototype.openApp = function (e, b) { | |
for (var c = a.varargs(arguments, 1), d = ["spotify", "app", e], f = 0, g = c.length; f < g; f++) d.push(encodeURIComponent(c[f])); | |
return this.openURI(d.join(":")) | |
}; | |
t.prototype.setTitle = function (e, a) { | |
return n(this, "application_set_title", [e, a || ""]) | |
}; | |
t.prototype.setPreferredSize = function (e, b) { | |
var d = new c; | |
a.request("application_set_preferred_size", [e, b], d, d.setDone, d.setFail); | |
return d | |
}; | |
t.prototype.clientEvent = function (a, b, c, d, f) { | |
return n(this, "application_client_event", [].slice.call(arguments)) | |
}; | |
a.inherit(s, j); | |
d.define(s, ["uri"]); | |
d.define(s, ["image", "images", "name", "popularity"], "_metadata"); | |
d.define(s, ["biography", "genres", "portraits", "years"], "_profile"); | |
d.define(s, ["albums", "appearances", "related", "singles"], "_collections"); | |
d.define(s, ["user"], "_associatedUser"); | |
j.init(s, "artist"); | |
s.prototype._collections = function () { | |
this.resolve("albums", | |
new r(u, this.uri, "artist_albums")); | |
this.resolve("appearances", new r(u, this.uri, "artist_appearances")); | |
this.resolve("related", new r(s, this.uri, "artist_related_artists")); | |
this.resolve("singles", new r(u, this.uri, "artist_singles")); | |
this.resolveDone() | |
}; | |
s.prototype._associatedUser = function (e) { | |
a.request("artist_associated_user", [this.uri], this, function (a) { | |
this.resolveMany(e, a) | |
}, function (a) { | |
this.resolveFail(e, a) | |
}) | |
}; | |
s.prototype._make_user = function (a) { | |
return a && o.fromURI(a) | |
}; | |
s.fromURI = g.lookup; | |
s.fromURIs = g.lookupMany; | |
s._cache = new g(s); | |
a.inherit(v, d); | |
d.define(v, ["type", "uri"]); | |
v.prototype.snapshot = function (a, b, c) { | |
return (new y(this, a, b, c)).load("length", "range") | |
}; | |
v.prototype.add = function () { | |
throw Error("This method has not been implemented."); | |
}; | |
v.prototype.insert = function () { | |
throw Error("This method has not been implemented."); | |
}; | |
v.prototype.remove = function () { | |
throw Error("This method has not been implemented."); | |
}; | |
v.prototype.trim = function () { | |
throw Error("This method has not been implemented."); | |
}; | |
v.prototype.clear = function () { | |
throw Error("This method has not been implemented."); | |
}; | |
v.prototype.sorted = function () { | |
throw Error("sorting is not implemented"); | |
}; | |
a.inherit(r, v); | |
r.prototype._requestSnapshot = function (e, b, d, f) { | |
var g = new c; | |
a.request(this._prefix + "_snapshot", [e, b, d, f], g, g.setDone, g.setFail); | |
return g | |
}; | |
r.prototype.add = function (e) { | |
var b = a.uris(arguments); | |
b.unshift(this._args); | |
return n(this, this._prefix + "_append", b) | |
}; | |
r.prototype.clear = function () { | |
return n(this, this._prefix + "_clear", [this._args]) | |
}; | |
r.prototype.insert = function (e, b) { | |
var c = [this._args, e.index, e.uri], | |
d = a.uris(arguments, | |
1); | |
return n(this, this._prefix + "_insert", c.concat(d)) | |
}; | |
r.prototype.remove = function (a) { | |
return n(this, this._prefix + "_remove", [this._args, a.index, a.uri]) | |
}; | |
r.prototype.trim = function (a) { | |
return n(this, this._prefix + "_trim", [this._args, a.index, a.uri]) | |
}; | |
a.inherit(x, d); | |
d.define(x, ["uri"]); | |
x.prototype.toString = function () { | |
return this.uri | |
}; | |
x.fromURI = function (a) { | |
return new x(a) | |
}; | |
a.inherit(B, d); | |
d.define(B, ["contexts", "uri"]); | |
B.create = function (e) { | |
var b = new c; | |
a.request("context_group_create", [e], b, function (a) { | |
a = new B(a.uri); | |
b.setDone(a) | |
}, b.setFail); | |
return b | |
}; | |
a.inherit(p, h); | |
d.define(p, "context,duration,id,index,playing,position,repeat,shuffle,track,volume".split(","), "_query"); | |
p.prototype._observed = function () { | |
this.bridgeListen("player_event_wait", [this.id]) | |
}; | |
p.prototype.eventDone = function (a) { | |
p._superClass.eventDone.call(this, a); | |
this._queryPosition() | |
}; | |
p.prototype._make_context = function (a) { | |
return a && x.fromURI(a.uri, a) | |
}; | |
p.prototype._make_track = function (a) { | |
return a && q.fromURI(a.uri, a) | |
}; | |
p.prototype._query = function (e) { | |
a.request("player_query", [this.id], this, function (a) { | |
this.resolveMany(e, a); | |
this._queryPosition() | |
}, function (a) { | |
this.resolveFail(e, a) | |
}) | |
}; | |
p.prototype._queryPosition = function () { | |
if (!this._pq && this.playing) { | |
var e = this; | |
this._pq = setTimeout(function () { | |
a.request("player_query", [e.id], e, e._progress) | |
}, 500) | |
} | |
}; | |
p.prototype._progress = function (a) { | |
this._pq = null; | |
this.resolve("position", a.position, !0); | |
delete a.position; | |
this.resolveMany(0, a); | |
this._queryPosition() | |
}; | |
p.prototype.mapTrackIdentifiers = function (a) { | |
return n(this, "player_map_track_identifiers", [this.id, a]) | |
}; | |
p.prototype.setVolume = function (a) { | |
return n(this, "player_set_volume", [this.id, a]) | |
}; | |
p.prototype.setRepeat = function (a) { | |
return n(this, "player_set_repeat", [this.id, a]) | |
}; | |
p.prototype.setShuffle = function (a) { | |
return n(this, "player_set_shuffle", [this.id, a]) | |
}; | |
p.prototype.play = function () { | |
return n(this, "player_play", [this.id]) | |
}; | |
p.prototype.pause = function () { | |
return n(this, "player_pause", [this.id]) | |
}; | |
p.prototype.stop = function () { | |
return n(this, "player_stop", [this.id]) | |
}; | |
p.prototype.playTrack = function (a, | |
b, c) { | |
return n(this, "player_play_track", [this.id, a.uri, b || 0, c != void 0 ? c : -1]) | |
}; | |
p.prototype.playContext = function (a, b, c, d) { | |
b == null && (b = -1); | |
return n(this, "player_play_context", [this.id, a.uri, b, c || 0, d != void 0 ? d : -1]) | |
}; | |
p.prototype.playContextGroup = function (a, b, c, d) { | |
b == void 0 && (b = -1); | |
c == void 0 && (c = -1); | |
return n(this, "player_play_context_group", [this.id, a.uri, b, c, d || 0]) | |
}; | |
p.prototype.skipToPrevTrack = function () { | |
return n(this, "player_skip_to_prev", [this.id]) | |
}; | |
p.prototype.skipToNextTrack = function () { | |
return n(this, | |
"player_skip_to_next", [this.id]) | |
}; | |
p.prototype.seek = function (a) { | |
return n(this, "player_seek", [this.id, a]) | |
}; | |
a.inherit(m, j); | |
d.define(m, ["uri"]); | |
d.define(m, "allows,collaborative,description,subscribed,name,owner,published".split(","), "_metadata"); | |
d.define(m, ["image", "images"], "_profile"); | |
d.define(m, ["subscribers", "tracks"], "_collections"); | |
d.define(m, ["popularity"], "_popularity"); | |
j.init(m, "playlist"); | |
m.prototype._make_owner = function (a) { | |
return a && o.fromURI(a.uri, a) | |
}; | |
m.prototype._collections = function () { | |
this.resolve("subscribers", | |
new r(o, this.uri, "playlist_subscribers")); | |
this.resolve("tracks", new r(q, this.uri, "playlist_tracks")); | |
this.resolveDone() | |
}; | |
m.prototype._popularity = function (b) { | |
a.request("playlist_popularity", [this.uri], this, function (a) { | |
this.resolveMany(b, a) | |
}, function (a) { | |
this.resolveFail(b, a) | |
}) | |
}; | |
m._libraryListener = null; | |
m.fromURI = g.lookup; | |
m.fromURIs = g.lookupMany; | |
m._cache = new g(m); | |
m.createTemporary = function (b) { | |
var d = new c; | |
a.request("playlist_create_temporary", [b], d, function (a) { | |
var c = new m(a.uri); | |
m._cache.cache(a.uri, c); | |
c.resolve("name", b); | |
d.setDone(c) | |
}, d.setFail); | |
return d | |
}; | |
m.removeTemporary = function (b) { | |
var d = new c; | |
a.request("playlist_remove_temporary", [b.name], d, function () { | |
m._cache.remove(b.uri); | |
d.setDone() | |
}, d.setFail); | |
return d | |
}; | |
m.create = function (b) { | |
var d = new c; | |
a.request("playlist_create", [b], d, function (a) { | |
var c = new m(a.uri); | |
m._cache.cache(a.uri, c); | |
c.resolve("name", b); | |
d.setDone(c) | |
}, d.setFail); | |
return d | |
}; | |
m.getOrCreateLibraryListener = function () { | |
var a = m._libraryListener; | |
if (!a) a = new i, a.bridgeListen("library_event_wait", [f.session.user.uri]), a.filter(function (a) { | |
if (!(a.type != "insert" && a.type != "remove")) { | |
var b = a.type == "insert"; | |
switch (a.receiver) { | |
case "playlists": | |
m._cache.update(a.uris, { | |
subscribed: b | |
}); | |
break; | |
case "published": | |
m._cache.update(a.uris, { | |
published: b | |
}) | |
} | |
} | |
}), m._libraryListener = a; | |
return a | |
}; | |
m.prototype.load = function () { | |
var b = a.varargs(arguments); | |
Array.prototype.indexOf.call(b, "subscribed") >= 0 && m.getOrCreateLibraryListener(); | |
return m._superClass.load.apply(this, b) | |
}; | |
m.prototype._observed = function () { | |
this.bridgeListen("playlist_event_wait", [this.uri]) | |
}; | |
m.prototype.eventFail = function (a) { | |
this._obcount || this.bridgeUnlisten(); | |
m._superClass.eventFail.call(this, a) | |
}; | |
m.prototype.setDescription = function (a) { | |
return n(this, "playlist_set_description", [this.uri, a], !0) | |
}; | |
m.prototype.setImage = function (a) { | |
return n(this, "playlist_set_image", [this.uri, a], !0) | |
}; | |
m.prototype.setName = function (a) { | |
return n(this, "playlist_set_name", [this.uri, a], !0) | |
}; | |
m.prototype.setSource = function (a, b) { | |
return n(this, "playlist_set_source", [this.uri, a, b]) | |
}; | |
m.prototype.enforceRules = function (a) { | |
return n(this, "playlist_enforce_rules", [this.uri, a]) | |
}; | |
a.inherit(A, h); | |
d.define(A, ["user"]); | |
d.define(A, "connecting,connection,country,developer,device,incognito,language,online,partner,product,resolution,streaming,testGroup,capabilities".split(","), "_query"); | |
A.prototype._observed = function () { | |
this.bridgeListen("session_event_wait", []) | |
}; | |
A.prototype._query = function (b) { | |
a.request("session_query", [], this, function (a) { | |
this.resolveMany(b, a) | |
}, function (a) { | |
this.resolveFail(b, a) | |
}) | |
}; | |
a.inherit(y, d); | |
d.define(y, ["length", "range"], "_request"); | |
y.prototype._request = function () { | |
var a = this._collection; | |
a._snapshot(a._args, this._off, this._len, this._raw).done(this, function (a) { | |
this._uris = a.array; | |
this._meta = a.metadata || []; | |
this.resolve("length", a.length); | |
this.resolve("range", { | |
offset: this._off, | |
length: this._uris.length | |
}); | |
this.resolveDone() | |
}).fail(this, function (a) { | |
this.resolveFail(this._neededForLoad(["length", "range"]), a) | |
}) | |
}; | |
y.prototype.get = function (a) { | |
if (a instanceof C) a = a.index; | |
a -= this._off; | |
return a < 0 || a > this._uris.length ? null : this._collection._factory(this._uris[a], this._meta[a]) | |
}; | |
y.prototype.find = function (a, b) { | |
if (b instanceof C) b = b.index; | |
var c = this._uris.indexOf(a.uri, b || 0); | |
return c == -1 ? null : new C(c + this._off, this._uris[c]) | |
}; | |
y.prototype.loadAll = function () { | |
for (var a = [], b = this.toArray(), d = 0, f = b.length; d < f; d++) { | |
var g = b[d]; | |
a.push(g.load.apply(g, arguments)) | |
} | |
return c.join(a) | |
}; | |
y.prototype.ref = function (a) { | |
var b = this.get(a); | |
return new C(a, b ? b.uri : null) | |
}; | |
y.prototype.toArray = function () { | |
for (var a = [], b = this._collection, c = 0, d = this._uris.length; c < d; c++) a[c] = b._factory(this._uris[c], this._meta[c]); | |
return a | |
}; | |
y.prototype.toURIs = function () { | |
return this._uris.slice() | |
}; | |
a.inherit(q, j); | |
d.define(q, ["uri"]); | |
d.define(q, "advertisement,album,artists,availability,disc,duration,explicit,image,images,local,name,number,placeholder,playable,popularity,starred".split(","), "_metadata"); | |
j.init(q, "track"); | |
q.prototype._make_album = function (a) { | |
return a && k.fromURI(a.uri, a) | |
}; | |
q.prototype._make_artists = function (a) { | |
return a && a.map(D) | |
}; | |
q.fromURI = g.lookup; | |
q.fromURIs = g.lookupMany; | |
q._cache = new g(q); | |
q.prototype.star = function () { | |
return n(this, "library_star", [f.session.user.uri, this.uri]) | |
}; | |
q.prototype.unstar = function () { | |
return n(this, "library_unstar", [f.session.user.uri, this.uri]) | |
}; | |
q._trackEventWait = function () { | |
a.request("track_event_wait_any", [], this, this._trackEventDone, this._trackEventFail) | |
}; | |
q._trackEventDone = function (a) { | |
var b = q.fromURI(a.data.uri); | |
b.resolveMany(0, a.data); | |
b.dispatchEvent(a); | |
this._trackEventWait() | |
}; | |
q._trackEventFail = function (a) { | |
a.error == | |
"timeout" && this._trackEventWait() | |
}; | |
a.inherit(o, j); | |
d.define(o, ["uri"]); | |
d.define(o, "currentUser,identifier,image,images,name,subscribed,username".split(","), "_metadata"); | |
d.define(o, ["artist"], "_associatedArtist"); | |
j.init(o, "user"); | |
o.prototype._associatedArtist = function (b) { | |
a.request("user_associated_artist", [this.uri], this, function (a) { | |
this.resolveMany(b, a) | |
}, function (a) { | |
this.resolveFail(b, a) | |
}) | |
}; | |
o.prototype._make_artist = function (a) { | |
return a && s.fromURI(a) | |
}; | |
o._relationsListener = null; | |
o.fromURI = g.lookup; | |
o.fromURIs = g.lookupMany; | |
o._cache = new g(o); | |
o.fromUsername = function (a) { | |
for (var a = encodeURIComponent(a), b = -1; | |
(b = a.indexOf("%", b + 1)) > -1;) a = a.substring(0, b + 1) + a.substring(b + 1, b + 3).toLowerCase() + a.substring(b + 3); | |
return o.fromURI("spotify:user:" + a) | |
}; | |
o.getOrCreateRelationsListener = function () { | |
var a = o._relationsListener; | |
if (!a) a = new i, a.bridgeListen("relations_event_wait", [f.session.user.uri]), a.filter(function (a) { | |
a.receiver != "subscriptions" || a.type != "add" && a.type != "remove" || o._cache.update(a.uris, { | |
subscribed: a.type == "add" | |
}) | |
}), o._relationsListener = a; | |
return a | |
}; | |
o.prototype.load = function () { | |
var b = a.varargs(arguments); | |
Array.prototype.indexOf.call(b, "subscribed") >= 0 && o.getOrCreateRelationsListener(); | |
return o._superClass.load.apply(this, b) | |
}; | |
var E = function (a, b) { | |
var c = a.split(":"); | |
switch (c[1]) { | |
case "album": | |
return c.length == 4 ? l.fromURI(a, b) : k.fromURI(a, b); | |
case "artist": | |
return s.fromURI(a, b); | |
case "track": | |
return q.fromURI(a, b); | |
case "user": | |
return c.length > 3 && c[2] != "facebook" ? m.fromURI(a, b) : o.fromURI(a, b) | |
} | |
return null | |
}; | |
q._trackEventWait(); | |
f.Observable = b; | |
f.Loadable = d; | |
f.BridgeLoadable = h; | |
f.Album = k; | |
f.Application = t; | |
f.Artist = s; | |
f.Cache = g; | |
f.Client = z; | |
f.Collection = v; | |
f.BridgeCollection = r; | |
f.Context = x; | |
f.Disc = l; | |
f.Group = B; | |
f.Player = p; | |
f.Playlist = m; | |
f.Promise = c; | |
f.Session = A; | |
f.Track = q; | |
f.User = o; | |
f.application = new t; | |
f.client = new z; | |
f.fromURI = E; | |
f.player = new p("main"); | |
f.preview = new p("preview"); | |
f.promisedRequest = n; | |
f.session = new A | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function (a, f) { | |
_unrequire("$api/hermes", ["$api/models"], function (g) { | |
(function (b) { | |
function c(a) { | |
return a.schema.id + "#" + a.name | |
} | |
function d() {} | |
function f(a, b, c, d, g) { | |
j.call(this); | |
this.resolve("uri", b); | |
this.resolve("method", a); | |
this.resolve("timeout", g || 0); | |
this._rtypes = c; | |
this._atypes = d; | |
a = k.join(this._rtypes.map(function (a) { | |
return a.schema.load("id") | |
})); | |
b = k.join(this._atypes.map(function (a) { | |
return a.schema.load("id") | |
})); | |
this._load = k.join(a, b) | |
} | |
function i(a) { | |
j.call(this); | |
this._urls = a | |
} | |
var j = b.Loadable, | |
k = b.Promise; | |
d.get = function (a, b, c, d) { | |
return new f("GET", a, b, c, d) | |
}; | |
d.request = function (a, b, c, d, g) { | |
return new f(a, b, c, d, g) | |
}; | |
a.inherit(f, j); | |
j.define(f, ["uri", "method", "timeout"]); | |
f.prototype.send = function (b) { | |
var d = new k, | |
f = this, | |
g = [].slice.call(arguments); | |
this._load.done(function () { | |
var b = f._rtypes.map(c), | |
h = f._atypes.map(c); | |
a.request("hermes_send_request", [f.uri, f.method, b, h, g, f.timeout], d, function (a) { | |
d.setDone(a.result) | |
}, d.setFail) | |
}).fail(function (a, b) { | |
d.setFail(b) | |
}); | |
return d | |
}; | |
a.inherit(i, j); | |
j.define(i, ["id"], "_register"); | |
i.fromURL = function (a) { | |
typeof a === "string" && (a = [a]); | |
return new this(a) | |
}; | |
i.prototype.type = function (a) { | |
return { | |
schema: this, | |
name: a | |
} | |
}; | |
i.prototype._register = function (b) { | |
a.request("hermes_register_schema", this._urls, this, function (a) { | |
this.resolveMany(b, a) | |
}, function (a) { | |
this.resolveFail(b, a) | |
}) | |
}; | |
g.Hermes = d; | |
g.Schema = i | |
})(f["$api/models"]) | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function (a, f) { | |
_unrequire("$api/search", ["$api/models"], function (g) { | |
(function (b) { | |
function c(a, b) { | |
d.call(this); | |
var c = "spotify:search:" + encodeURIComponent(b).replace(/%20/g, "+"); | |
this.resolve("uri", c); | |
this.resolve("query", b); | |
this.resolve("albums", new f(i, null, a + "_albums", b)); | |
this.resolve("artists", new f(j, null, a + "_artists", b)); | |
this.resolve("playlists", new f(k, null, a + "_playlists", b)); | |
this.resolve("tracks", new f(l, c, a + "_tracks", b)) | |
} | |
var d = b.Loadable, | |
f = b.BridgeCollection, | |
i = b.Album, | |
j = b.Artist, | |
k = b.Playlist, | |
l = b.Track; | |
a.inherit(c, d); | |
d.define(c, "albums,artists,playlists,query,tracks,uri".split(",")); | |
d.define(c, ["fuzzyMatch"], "_fuzzy"); | |
c.search = function (a) { | |
return new this("search", a) | |
}; | |
c.suggest = function (a) { | |
return new this("suggest", a) | |
}; | |
c.prototype._fuzzy = function (b) { | |
a.request("search_fuzzy_match", [this.query], this, function (a) { | |
this.resolveMany(b, a) | |
}, function (a) { | |
this.resolveFail(b, a) | |
}) | |
}; | |
g.Search = c | |
})(f["$api/models"]) | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function (a, f) { | |
_unrequire("$api/toplists", ["$api/models"], function (g) { | |
(function (b) { | |
function c(a, b, c, g) { | |
d.call(this); | |
this.resolve("uri", c + "tracks" + g); | |
this.resolve("albums", new f(i, c + "albums" + g, a + "_albums", b)); | |
this.resolve("artists", new f(j, c + "artists" + g, a + "_artists", b)); | |
this.resolve("tracks", new f(l, c + "tracks" + g, a + "_tracks", b)); | |
this.resolve("playlists", new f(k, c + "playlists" + g, a + "_playlists", b)) | |
} | |
var d = b.Loadable, | |
f = b.BridgeCollection, | |
i = b.Album, | |
j = b.Artist, | |
k = b.Playlist, | |
l = b.Track, | |
u = b.session; | |
a.inherit(c, | |
d); | |
d.define(c, ["albums", "artists", "tracks", "playlists", "uri"]); | |
c.forCurrentUser = function () { | |
return new this("toplist_user", u.user.uri, u.user.uri + ":top:", "") | |
}; | |
c.forUser = function (a) { | |
return new this("toplist_user", a.uri, a.uri + ":top:", "") | |
}; | |
c.forWorld = function () { | |
return new this("toplist_region", "global", "spotify:top:", "") | |
}; | |
c.forCurrentRegion = function () { | |
return new this("toplist_region", null, "spotify:top:", ":country:USER") | |
}; | |
c.forRegion = function (a) { | |
return new this("toplist_region", a, "spotify:top:", ":country:" + a) | |
}; | |
c.forArtist = function (a, b) { | |
return new this("toplist_artist", a.uri, a.uri + ":top:", b ? ":country:" + b : "") | |
}; | |
g.Toplist = c | |
})(f["$api/models"]) | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function (a, f) { | |
_unrequire("$api/location", ["$api/models"], function (g) { | |
(function (b) { | |
function c() { | |
b.Loadable.call(this) | |
} | |
a.inherit(c, b.Loadable); | |
b.Loadable.define(c, ["accuracy", "latitude", "longitude"], "_query"); | |
c.prototype._query = function (b) { | |
a.request("location_query", [], this, function (a) { | |
this.resolveMany(b, a) | |
}, function (a) { | |
this.resolveFail(b, a) | |
}) | |
}; | |
c.query = function () { | |
return new c | |
}; | |
g.Location = c | |
})(f["$api/models"]) | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function (a, f) { | |
_unrequire("$api/library", ["$api/models"], function (g) { | |
(function (b) { | |
function c(a) { | |
b.Track._cache.update(a.uris, { | |
starred: a.type == "insert" | |
}) | |
} | |
function d(a) { | |
b.BridgeLoadable.call(this); | |
var d = b.User.fromURI(a); | |
this.resolve("owner", d); | |
this.resolve("albums", new b.BridgeCollection(b.Album, null, "library_albums", d.uri)); | |
this.resolve("artists", new b.BridgeCollection(b.Artist, null, "library_artists", d.uri)); | |
this.resolve("playlists", new b.BridgeCollection(b.Playlist, null, "library_playlists", d.uri)); | |
this.resolve("published", new b.BridgeCollection(b.Playlist, null, "library_published", d.uri)); | |
this.resolve("starred", b.Playlist.fromURI(d.uri + ":starred")); | |
this.resolve("toplist", b.Playlist.fromURI(d.uri + ":toplist")); | |
this.resolve("tracks", new b.BridgeCollection(b.Track, this.uri, "library_tracks", d.uri)); | |
if (d.uri == b.session.user.uri) b.Playlist.getOrCreateLibraryListener().proxyTo(this), this.starred.addEventListener("insert", c), this.starred.addEventListener("remove", c); | |
else { | |
var f = this, | |
a = function () { | |
f.bridgeListen("library_event_wait", [d.uri]) | |
}; | |
this.albums._observed = a; | |
this.artists._observed = a; | |
this.playlists._observed = a; | |
this.published._observed = a; | |
this.tracks._observed = a | |
} | |
} | |
a.inherit(d, b.BridgeLoadable); | |
d.fromURI = b.Cache.lookup; | |
d._cache = new b.Cache(d); | |
b.Loadable.define(d, "albums,artists,owner,playlists,published,starred,toplist,tracks".split(",")); | |
d.prototype.publish = function (c) { | |
return b.promisedRequest(this, "library_publish", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.prototype.star = function (c) { | |
return b.promisedRequest(this, "library_star", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.prototype.subscribe = function (c) { | |
return b.promisedRequest(this, "library_subscribe", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.prototype.unpublish = function (c) { | |
return b.promisedRequest(this, "library_unpublish", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.prototype.unstar = function (c) { | |
return b.promisedRequest(this, "library_unstar", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.prototype.unsubscribe = function (c) { | |
return b.promisedRequest(this, "library_unsubscribe", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.forCurrentUser = function () { | |
return d.forUser(b.session.user) | |
}; | |
d.forUser = function (a) { | |
return d.fromURI(a.uri) | |
}; | |
g.Library = d | |
})(f["$api/models"]) | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function (a, f) { | |
_unrequire("$api/activity", ["$api/models"], function (g) { | |
(function (b) { | |
function c(a, b) { | |
this.resolve("identifier", a); | |
this.resolveMany(0, b) | |
} | |
function d(a) { | |
b.BridgeLoadable.call(this); | |
this.resolve("user", a); | |
this.resolve("activities", new b.BridgeCollection(c, null, "feed_activities", a ? a.uri : null)) | |
} | |
a.inherit(c, b.Loadable); | |
b.Loadable.define(c, "activityType,context,item,message,referrer,timestamp,user".split(",")); | |
c.Type = { | |
PLAYLIST_PUBLISHED: "playlist-published", | |
PLAYLIST_TRACK_ADDED: "playlist-track-added", | |
TRACK_FINISHED_PLAYING: "track-finished-playing", | |
APP_ADDED: "app-added", | |
TRACK_STARTED_PLAYING: "track-started-playing", | |
URI_SHARED: "uri-shared", | |
ARTIST_FOLLOWED: "artist-followed", | |
UNKNOWN: "unknown" | |
}; | |
c.prototype._make_activityType = function (a) { | |
switch (a) { | |
case 1: | |
return c.Type.PLAYLIST_PUBLISHED; | |
case 2: | |
return c.Type.PLAYLIST_TRACK_ADDED; | |
case 3: | |
return c.Type.TRACK_FINISHED_PLAYING; | |
case 4: | |
return c.Type.APP_ADDED; | |
case 5: | |
return c.Type.TRACK_STARTED_PLAYING; | |
case 6: | |
return c.Type.URI_SHARED; | |
case 7: | |
return c.Type.ARTIST_FOLLOWED; | |
default: | |
return c.Type.UNKNOWN | |
} | |
}; | |
c.prototype._make_context = function (a) { | |
return a && b.fromURI(a.uri, a) | |
}; | |
c.prototype._make_item = function (a) { | |
return a && b.fromURI(a.uri, a) | |
}; | |
c.prototype._make_referrer = function (a) { | |
return a | |
}; | |
c.prototype._make_timestamp = function (a) { | |
return new Date(a) | |
}; | |
c.fromURI = function (a, b) { | |
return new c(a, b) | |
}; | |
a.inherit(d, b.BridgeLoadable); | |
b.Loadable.define(d, ["activities", "user"]); | |
d.prototype._observed = function () { | |
this.bridgeListen("feed_event_wait", [this.user ? this.user.uri : null]) | |
}; | |
d.forCurrentUser = function () { | |
return new d(b.session.user) | |
}; | |
d.forUser = function (a) { | |
return new d(a) | |
}; | |
d.forRelations = function () { | |
return new d(null) | |
}; | |
g.Feed = d | |
})(f["$api/models"]) | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function (a, f) { | |
_unrequire("$api/relations", ["$api/models"], function (g) { | |
(function (b) { | |
function c(a) { | |
b.BridgeLoadable.call(this); | |
a = b.User.fromURI(a); | |
this.resolve("owner", a); | |
this.resolve("subscribers", new b.BridgeCollection(b.User, null, "relations_subscribers_users", a.uri)); | |
this.resolve("subscriptions", new b.BridgeCollection(b.User, null, "relations_subscriptions_users", a.uri)) | |
} | |
function d(a) { | |
c.call(this, a); | |
this.resolve("blocked", new b.BridgeCollection(b.User, null, "relations_blocked_users", this.owner.uri)); | |
this.resolve("dismissed", new b.BridgeCollection(b.User, null, "relations_dismissed_users", this.owner.uri)); | |
this.resolve("hidden", new b.BridgeCollection(b.User, null, "relations_hidden_users", this.owner.uri)); | |
b.User.getOrCreateRelationsListener().proxyTo(this) | |
} | |
a.inherit(c, b.BridgeLoadable); | |
c.fromURI = b.Cache.lookup; | |
c._cache = new b.Cache(c); | |
b.Loadable.define(c, ["owner", "subscribers", "subscriptions"]); | |
a.inherit(d, c); | |
b.Loadable.define(d, ["blocked", "dismissed", "hidden"]); | |
d.prototype.block = function (c) { | |
return b.promisedRequest(this, | |
"relations_block", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.prototype.dismiss = function (c) { | |
return b.promisedRequest(this, "relations_dismiss", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.prototype.subscribe = function (c) { | |
return b.promisedRequest(this, "relations_subscribe", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.prototype.unblock = function (c) { | |
return b.promisedRequest(this, "relations_unblock", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
d.prototype.unsubscribe = function (c) { | |
return b.promisedRequest(this, | |
"relations_unsubscribe", [this.owner.uri].concat(a.uris(arguments))) | |
}; | |
c._currentUser = null; | |
c.forCurrentUser = function () { | |
if (!c._currentUser) c._currentUser = new d(b.session.user.uri); | |
return c._currentUser | |
}; | |
c.forUser = function (a) { | |
return c.fromURI(a.uri) | |
}; | |
g.Relations = c | |
})(f["$api/models"]) | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function (a, f) { | |
_unrequire("$api/runtime", ["$api/models", "$api/../vendor/js-yaml.min"], function (g) { | |
(function (b, c) { | |
function d(a) { | |
return (a = a.match(/^(\$([^\/]+)\/)/)) ? a[2] : void 0 | |
} | |
function f(a, c, d) { | |
b.Loadable.call(this); | |
this.resolve("level", d); | |
this.resolve("message", c); | |
this.resolve("timestamp", new Date(a)) | |
} | |
function i(a) { | |
b.BridgeLoadable.call(this); | |
this.resolve("application", a); | |
this.resolve("entries", new b.BridgeCollection(f, a.uri, "log_entries")); | |
this.bridgeListen("log_event_wait", [a.uri]) | |
} | |
c = window.jsyaml; | |
a.inherit(f, b.Loadable); | |
b.Loadable.define(f, ["level", "message", "timestamp"]); | |
f.fromURI = function (a, b) { | |
return new f(b.timestamp, b.message, b.level) | |
}; | |
a.inherit(i, b.BridgeLoadable); | |
b.Loadable.define(i, ["application", "entries"]); | |
i.forApplication = function (a) { | |
return new i(a) | |
}; | |
i.forCurrentApplication = function () { | |
return new i(b.application) | |
}; | |
g.require = function (b, c, f) { | |
for (var g = [], h = [], i = 0, s = b.length; i < s; i++) { | |
var v = b[i], | |
r = d(v); | |
if (!r) throw Error("Empty module name in require."); | |
g.push(r); | |
var x = r.split("@"); | |
h.push(v.replace(r, | |
x[0])) | |
} | |
a.request("application_require", g, this, function () { | |
window.require(h, c) | |
}, function (a) { | |
if (f) f(a); | |
else throw Error("Error requiring modules: " + b.join(", ")); | |
}) | |
}; | |
g.isRequestImplemented = function (c) { | |
var d = new b.Promise; | |
a.request("core_request_lookup", [c], this, function (a) { | |
d.setDone(a.found) | |
}, function () { | |
d.setFail() | |
}); | |
return d | |
}; | |
g.getBridgeDefinition = function () { | |
var a = new b.Promise; | |
b.application.readFile("$api/bridge/requests.yaml").done(function (b) { | |
a.setDone(c.load(b)) | |
}).fail(function () { | |
a.setFail() | |
}); | |
return a | |
}; | |
g.Log = i | |
})(f["$api/models"], f["$api/../vendor/js-yaml.min"]) | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function () { | |
_unrequire("$api/utils/base", [], function (a) { | |
var f = Array.prototype.slice; | |
a.bind = Function.prototype.bind ? function (a, b) { | |
return a.bind(b) | |
} : function (a, b) { | |
return function () { | |
return !arguments.length ? a.call(b) : a.apply(b, arguments) | |
} | |
}; | |
a.partial = Function.prototype.bind ? function (a, b) { | |
var c = f.call(arguments, 1); | |
return a.bind.apply(a, c) | |
} : function (a, b) { | |
var c = f.call(arguments, 2); | |
return !c.length ? this.bind(a, b) : function () { | |
return a.apply(b, !arguments.length ? c : c.concat(f.call(arguments))) | |
} | |
} | |
}) | |
})(SpotifyApi.api, | |
SpotifyApi.api._modules); | |
(function () { | |
_unrequire("$api/utils/css", [], function (a) { | |
var f = document.head || document.getElementsByTagName("head")[0], | |
g = {}; | |
a.importSheet = function (a) { | |
var b = a.match(/^(\$(?:[^\/]+)\/)(?!css)(.*)/); | |
b && (a = b[1] + "css/" + b[2]); | |
a += ".css"; | |
if (g[a]) return this; | |
g[a] = 1; | |
b = document.createElement("link"); | |
b.rel = "stylesheet"; | |
b.href = a; | |
f.appendChild(b); | |
return this | |
}; | |
a.importSheets = function () { | |
if (!arguments.length) return this; | |
if (arguments.length == 1) return this.importSheet(arguments[0]); | |
for (var a = 0, b = arguments.length; a < b; a++) this.importSheet(arguments[0]); | |
return this | |
}; | |
var b = {}; | |
a.appendStyles = function (a, d) { | |
a = "sp-" + a; | |
if (b[a]) return getElementById(a); | |
b[a] = 1; | |
var g = document.createElement("style"); | |
g.id = g.name = a; | |
if (!d) return g; | |
var i = "", | |
j, k; | |
for (k in d) if (d.hasOwnProperty(k)) { | |
var l = d[k]; | |
i += k; | |
j = []; | |
for (k in l) l.hasOwnProperty(k) && j.push(k + ": " + l[k]); | |
i += " {" + j.join("; ") + "}\n" | |
} | |
g.innerHTML = i; | |
f.appendChild(g); | |
return g | |
}; | |
a.getStyle = "currentStyle" in f ? function (a, b) { | |
return a.currentStyle[b] | |
} : function (a, b) { | |
var f = a.ownerDocument.defaultView; | |
if (!f) return null; | |
f = f.getComputedStyle(a, | |
null); | |
return !f ? null : f.getPropertyValue(b) | |
} | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); | |
(function () { | |
_unrequire("$api/utils/dom", [], function (a) { | |
var f = Array.prototype.slice; | |
a.id = function (a) { | |
return document.getElementById(a) | |
}; | |
a.query = function (a, b) { | |
return (b || document).querySelector(a) | |
}; | |
a.queryAll = function (a, b) { | |
return f.call((b || document).querySelectorAll(a)) | |
}; | |
a.queryClasses = function (a, b) { | |
return f.call((b || document).getElementsByClassName(a)) | |
}; | |
a.queryTags = function (a, b) { | |
return f.call((b || document).getElementsByTagName(className)) | |
} | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://play.spotify.com/static/proto/discovery.proto | |
// 15/12/2012 | |
package spotify.discovery.proto; | |
message VoidRequest { | |
} | |
message UserInfo { | |
optional string country = 1; | |
} | |
message WhatsNewRequest { | |
optional UserInfo user_info = 1; | |
} | |
message SuggestPlaylistsRequest { | |
repeated string fb_uids = 1; | |
repeated string staff_ids = 2; | |
// Number of (in)active playlists to get, will get max_playlists each | |
optional int32 max_playlists = 3; | |
optional int32 max_staff_pick_playlists = 4; | |
} | |
enum SuggestionSourceType { | |
SUGGESTION_SOURCE_FRIEND = 1; | |
SUGGESTION_SOURCE_NON_FRIEND = 2; | |
SUGGESTION_SOURCE_STAFF = 3; | |
} | |
message SuggestedPlaylist { | |
optional string playlist_uri = 1; | |
optional string playlist_picture = 2; | |
optional string playlist_name = 3; | |
optional string playlist_creator_social_name = 4; | |
// fb_uid or username depending on what kind of suggested playlist this is | |
optional string suggestion_source = 5; | |
optional SuggestionSourceType suggestion_source_type = 6; | |
} | |
message SuggestPlaylistsReply { | |
repeated SuggestedPlaylist inactive_playlists = 1; | |
repeated SuggestedPlaylist active_playlists = 2; | |
repeated SuggestedPlaylist staff_pick_playlists = 3; | |
} | |
message NewAlbum { | |
optional string album_uri = 1; | |
// The artists on the album | |
repeated string artist_uris = 2; | |
} | |
message NewAlbumsReply { | |
repeated NewAlbum albums = 1; | |
} | |
message FriendsPlaylist { | |
optional string playlist_uri = 1; | |
repeated string friends = 2; | |
// Total friends that has this playlist | |
// This number may be higher than len(friends) | |
optional int32 total_friends = 3; | |
optional string playlist_name = 4; | |
optional string playlist_creator_social_name = 5; | |
} | |
message FriendsPlaylistsReply { | |
repeated FriendsPlaylist playlists = 1; | |
} | |
message FriendsTrackToplists { | |
optional string track_uri = 1; | |
repeated string friends = 2; | |
// Total friends that has this playlist | |
// This number may be higher than len(friends) | |
optional int32 total_friends = 3; | |
} | |
message FriendsToplistEntry { | |
optional string item_uri = 1; | |
repeated string friends = 2; | |
optional int32 total_friends = 3; | |
} | |
message FriendsToplist { | |
optional string toplist_type = 1; | |
repeated FriendsToplistEntry entries = 2; | |
} | |
message FriendsToplistsReply { | |
repeated FriendsToplist toplists = 1; | |
} | |
message FriendsTrackToplistsReply { | |
repeated FriendsTrackToplists track_toplists = 1; | |
} | |
message NewFriendsReply { | |
repeated string new_friends = 1; | |
} | |
message RegionTrack { | |
optional string track_uri = 1; | |
} | |
message RegionTracksReply { | |
repeated RegionTrack region_tracks = 1; | |
} | |
message RegionPlaylist { | |
optional string playlist_uri = 1; | |
optional int32 popularity = 2; // in parts per thousand | |
optional string playlist_name = 3; | |
optional string playlist_creator_social_name = 4; | |
} | |
message RegionPlaylistReply { | |
repeated RegionPlaylist region_playlists = 1; | |
} | |
message WhatsNewReply { | |
optional NewAlbumsReply new_albums = 1; | |
optional FriendsPlaylistsReply friends_playlists = 2; | |
optional FriendsTrackToplistsReply friends_track_toplists = 3; | |
optional NewFriendsReply new_friends = 4; | |
optional RegionTracksReply region_tracks = 5; | |
optional RegionPlaylistReply region_playlists = 6; | |
} | |
message RegionTracksPlaylistsReply { | |
repeated RegionTrack region_tracks = 1; | |
repeated RegionPlaylist region_playlists = 2; | |
} | |
//#service DiscoveryService { | |
// rpc get_new_albums (VoidRequest) returns (NewAlbumsReply); | |
// rpc get_friends_playlists (VoidRequest) returns (FriendsPlaylistsReply); | |
// rpc get_friends_track_toplists (VoidRequest) returns (FriendsTrackToplistsReply); | |
// rpc get_new_friends (VoidRequest) returns (NewFriendsReply); | |
//} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* https://spapps.spotify.edgekey.net/player/36b195f/scripts/main.js | |
* | |
* 15/12/2012 | |
*/ | |
(function (Y, e) { | |
_unrequire("/scripts/player.events", [], function (e) { | |
function f() { | |
this.listeners = {} | |
} | |
f.prototype.subscribe = function (f, g, d) { | |
this.listeners[f] === void 0 && (this.listeners[f] = []); | |
this.listeners[f].push([g, d || null]) | |
}; | |
f.prototype.unsubscribe = function (f, g) { | |
if (this.listeners[f] !== void 0) for (var d = this.listeners[f].length, c = 0; c < d; c++) if (this.listeners[f][c][0] === g) { | |
this.listeners[f].splice(c, 1); | |
break | |
} | |
}; | |
f.prototype.trigger = function (f, g) { | |
if (this.listeners[f] !== void 0) for (var d = this.listeners[f].length, | |
c = 0; c < d; c++) this.listeners[f][c][0].call(this.listeners[f][c][1] || this, g || {}) | |
}; | |
f.prototype.Events = { | |
TRACK_CHANGED: "TRACK_CHANGED", | |
AD_CLICKED: "AD_CLICKED", | |
TRACK_SKIPPED: "TRACK_SKIPPED", | |
BACK_BUTTON_PRESS_START: "BACK_BUTTON_PRESS_START", | |
BACK_BUTTON_PRESS_COMPLETE: "BACK_BUTTON_PRESS_COMPLETE" | |
}; | |
e.EventManager = f | |
}); | |
_unrequire("/scripts/player.suggestions", ["$api/hermes", "$api/models"], function (i) { | |
(function (f) { | |
var o = f.Schema.fromURL(["/static/proto/radio.proto"]); | |
o.load().done(function () { | |
var g = f.Hermes; | |
i.getTrackSuggestions = function (d, c, b, a) { | |
d = { | |
salt: Math.floor(Math.random() * 1E6), | |
uris: d, | |
lastTracks: [], | |
length: c | |
}; | |
g.get("hm://radio/", [o.type("Tracks")], [o.type("RadioRequest")]).send(d).done(b).fail(a) | |
} | |
}).fail(function () {}) | |
})(e["$api/hermes"], e["$api/models"]) | |
}); | |
_unrequire("/scripts/player-utils", [], function (e) { | |
function f(c) { | |
this._maxLength = c; | |
this._items = [] | |
} | |
function o() { | |
this.store = typeof window.localStorage != "undefined" ? window.localStorage : !1 | |
} | |
function g(c, b) { | |
this.utils = d; | |
this.element = c; | |
this.maxWidth = b; | |
this.timer = null; | |
this.left = 0; | |
this.shouldScroll = this.scrolling = this.hovered = !1 | |
} | |
f.prototype.add = function (c) { | |
for (var b = this._items.slice(0), a = 0; a < b.length; a++) if (b[a].uri === c.uri) return !1; | |
this._items[0] = c; | |
for (a = 1; a < this._maxLength; a++) typeof b[a - 1] !== "undefined" && (this._items[a] = b[a - 1]); | |
return this._items | |
}; | |
f.prototype.show = function (c) { | |
if (!c || typeof this.get(0)[c] === "undefined") return this._items; | |
for (var b = [], a = 0; a < this._items.length; a++) b[a] = this._items[a][c]; | |
return b | |
}; | |
f.prototype.get = function (c) { | |
return this._items[c] | |
}; | |
f.prototype.size = function () { | |
return this._items.length | |
}; | |
f.prototype.forEach = function (c) { | |
for (var b = 0; b < this._items.length; b++) c(this._items[b]) | |
}; | |
o.prototype.set = function (c, b) { | |
if (!this.store) return !1; | |
try { | |
this.store.setItem(c, b) | |
} catch (a) { | |
return !1 | |
} | |
}; | |
o.prototype.get = function (c) { | |
return !this.store ? !1 : this.store.getItem(c) | |
}; | |
var d = { | |
hasClassList: "classList" in document.createElement("a"), | |
secsToMins: function (c, b) { | |
var a = Math.floor(c), | |
d = Math.floor(a / 60) + ":" + ("0" + a % 60).slice(-2); | |
void 0 !== b && b && (d += "." + Math.round((c - a) * 1E3)); | |
return d | |
}, | |
getId: function (c) { | |
return document.getElementById(c) | |
}, | |
hasClass: function (c, b) { | |
return this.hasClassList ? c.classList.contains(b) : c.className.match(RegExp("(\\s|^)" + b + "(\\s|$)")) | |
}, | |
addClass: function (c, b) { | |
this.hasClass(c, b) || (this.hasClassList ? c.classList.add(b) : c.className += " " + b) | |
}, | |
removeClass: function (c, b) { | |
if (this.hasClass(c, b)) this.hasClassList ? c.classList.remove(b) : c.className = c.className.replace(RegExp("(\\s|^)" + b + "(\\s|$)"), " ") | |
}, | |
addEventSimple: function (c, b, a) { | |
c.addEventListener ? c.addEventListener(b, | |
a, !1) : c.attachEvent && c.attachEvent("on" + b, a) | |
}, | |
removeEventSimple: function (c, b, a) { | |
c.removeEventListener ? c.removeEventListener(b, a, !1) : c.detachEvent && c.detachEvent("on" + b, a) | |
}, | |
extendObject: function (c, b) { | |
for (var a in b) b[a] && b[a].constructor && b[a].constructor === Object ? (c[a] = c[a] || {}, arguments.callee(c[a], b[a])) : c[a] = b[a]; | |
return c | |
}, | |
proxy: function (c, b) { | |
return function () { | |
return c.apply(b, arguments) | |
} | |
} | |
}; | |
g.prototype.init = function () { | |
this.onMouseOver = this.onMouseOver.bind(this); | |
this.onMouseOut = this.onMouseOut.bind(this); | |
this.scroll = this.scroll.bind(this); | |
this.utils.addEventSimple(this.element, "mouseover", this.onMouseOver); | |
this.utils.addEventSimple(this.element, "mouseout", this.onMouseOut); | |
this.element.style.position = "relative" | |
}; | |
g.prototype.refresh = function () { | |
this.scrolling && this.stop(); | |
this.textWidth = this.element.offsetWidth; | |
(this.shouldScroll = this.textWidth > this.maxWidth) ? (this.element.style.left = "0px", this.left = 0) : this.element.style.left = (this.maxWidth - this.element.offsetWidth) / 2 + 5 + "px" | |
}; | |
g.prototype.widthAdjust = function (c) { | |
this.maxWidth = c; | |
this.refresh() | |
}; | |
g.prototype.stop = function () { | |
if (this.timer) clearInterval(this.timer), this.element.innerHTML = this._originalText, this.scrolling = !1, this.refresh() | |
}; | |
g.prototype.scroll = function () { | |
Math.abs(this.left) === this.textWidth + 10 ? (this.element.style.left = "0px", this.left = 0, this.hovered || this.stop()) : (this.left--, this.element.style.left = "" + this.left + "px") | |
}; | |
g.prototype.onMouseOver = function () { | |
if (this.shouldScroll && !this.scrolling) this.scrolling = !0, this._originalText = this.element.innerHTML, | |
this.element.innerHTML = this._originalText + '<span class="padder"></span>' + this._originalText, this.timer = setInterval(this.scroll, 15) | |
}; | |
g.prototype.onMouseOut = function () { | |
this.hovered = !1 | |
}; | |
e.trackHistory = f; | |
e.playerStorage = o; | |
e.playerUtils = d; | |
e.Marquee = g; | |
e.kc = function () { | |
var c = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 13], | |
b = c.length, | |
a = null, | |
d = null, | |
j = 0, | |
f = function (a) { | |
a.keyCode === c[j] ? (j += 1, j === b && (d(), j = 0)) : j = 0 | |
}, g = function () { | |
if (a.addEventListener) a.addEventListener("keydown", f, !1); | |
else if (a.attachEvent) a.attachEvent("onkeydown", | |
f); | |
else if (typeof a.onkeydown === "function") { | |
var b = a.onkeydown; | |
a.onkeydown = function (a) { | |
b(a); | |
f(a) | |
} | |
} else a.onkeydown = f | |
}; | |
return { | |
onSuccess: function () {}, | |
listenerTarget: window, | |
init: function () { | |
d = this.onSuccess; | |
a = this.listenerTarget; | |
g() | |
} | |
} | |
} | |
}); | |
_unrequire("/scripts/player.widgets", ["$api/models", "/scripts/player-utils", "/scripts/player-utils"], function (i) { | |
(function (f, e, g) { | |
function d(c, b, a) { | |
this.element = c; | |
this.eventManager = a; | |
this.track = null; | |
this.artistsAdded = this.artistsWanted = 0; | |
this.marquee = new g(c, b); | |
this.marquee.init(); | |
this.eventManager.subscribe(this.eventManager.Events.TRACK_CHANGED, this.setTrack, this) | |
} | |
d.prototype.init = function () { | |
this.onArtistLoaded = this.onArtistLoaded.bind(this); | |
this.onArtistClicked = this.onArtistClicked.bind(this); | |
e.addEventSimple(this.element, "click", this.onArtistClicked) | |
}; | |
d.prototype.resize = function (c) { | |
this.marquee.widthAdjust(c) | |
}; | |
d.prototype.onArtistClicked = function (c) { | |
c.preventDefault(); | |
c.target.href && (this.track.advertisement ? this.eventManager.trigger(this.eventManager.Events.AD_CLICKED) : f.application.openURI(c.target.href.toSpotifyURI())) | |
}; | |
d.prototype.onArtistLoaded = function (c) { | |
this.addArtist(c) | |
}; | |
d.prototype.setTrack = function (c) { | |
var b = this; | |
c.load("artists").done(function (a) { | |
b.clear(); | |
b.track = a; | |
b.artistsWanted = a.artists && a.artists.length || 0; | |
for (var c = b.artistsWanted, d = 0; d < c; d++) a.artists[d].load(["name", "uri"]).done(function (a) { | |
b.onArtistLoaded(a) | |
}) | |
}) | |
}; | |
d.prototype.addArtist = function (c) { | |
this.artistsAdded > 0 && this.element.appendChild(document.createTextNode(", ")); | |
var b = document.createElement("a"); | |
b.innerHTML = c.name.decodeForHtml(); | |
b.href = c.uri.toSpotifyURL(); | |
this.element.appendChild(b); | |
this.artistsAdded++; | |
this.artistsAdded === this.artistsWanted && this.marquee.refresh() | |
}; | |
d.prototype.clear = function () { | |
if (this.track !== null) this.track = null, this.element.innerHTML = "", this.artistsAdded = 0 | |
}; | |
i.ArtistWidget = d | |
})(e["$api/models"], e["/scripts/player-utils"].playerUtils, e["/scripts/player-utils"].Marquee) | |
}); | |
_unrequire("/scripts/player.shufflebutton", ["$api/models", "/scripts/player-utils"], function (i) { | |
(function (f, | |
e) { | |
function g(b) { | |
var a = this, | |
d = f.player; | |
a._node = document.getElementById(b); | |
a._store = new c; | |
d.load(["shuffle"]).done(function (b) { | |
a._player = b; | |
a.init() | |
}) | |
} | |
var d = e.playerUtils, | |
c = e.playerStorage; | |
f.Loadable.define(f.Player, ["__rules"], "_playapp"); | |
g.prototype.init = function () { | |
var b = this; | |
b._player.addEventListener("change:shuffle", function () { | |
b.updateStatus() | |
}); | |
d.addEventSimple(b._node, "click", function () { | |
b.toggle() | |
}); | |
b._player.addEventListener("change", function () { | |
b._handleRules() | |
}); | |
if (b._store.get("spShuffle") === | |
"true") b.on() | |
}; | |
g.prototype._handleRules = function () { | |
this._player.__rules.shuffle ? this.enableButton() : this.disableButton() | |
}; | |
g.prototype.updateStatus = function () { | |
this._player.shuffle ? (d.addClass(this._node, "active"), this._store.set("spShuffle", "true")) : (d.removeClass(this._node, "active"), this._player.__rules && this._player.__rules.shuffle && this._store.set("spShuffle", "false")) | |
}; | |
g.prototype.on = function () { | |
var b = this; | |
b._player.setShuffle(!0).done(function () { | |
b.updateStatus() | |
}) | |
}; | |
g.prototype.off = function () { | |
var b = this; | |
b._player.setShuffle(!1).done(function () { | |
b.updateStatus() | |
}) | |
}; | |
g.prototype.toggle = function () { | |
if (d.hasClass(this._node, "disabled")) return !1; | |
if (this._player.shuffle) this.off(); | |
else this.on() | |
}; | |
g.prototype.disableButton = function () { | |
d.addClass(this._node, "disabled"); | |
this.updateStatus() | |
}; | |
g.prototype.enableButton = function () { | |
d.removeClass(this._node, "disabled"); | |
this.updateStatus() | |
}; | |
i.ShuffleButton = g | |
})(e["$api/models"], e["/scripts/player-utils"]) | |
}); | |
_unrequire("/scripts/player.repeatbutton", ["$api/models", | |
"/scripts/player-utils"], function (i) { | |
(function (f, e) { | |
function g(b) { | |
var a = this, | |
d = f.player; | |
a._node = document.getElementById(b); | |
a._store = new c; | |
a._disabled = !1; | |
d.load(["repeat"]).done(function (c) { | |
a._player = c; | |
a.init(b) | |
}) | |
} | |
var d = e.playerUtils, | |
c = e.playerStorage; | |
f.Loadable.define(f.Player, ["__rules"], "_playapp"); | |
g.prototype.init = function () { | |
var b = this; | |
b._player.addEventListener("change:repeat", function () { | |
b.updateStatus() | |
}); | |
b._player.addEventListener("change", function () { | |
b._handleRules() | |
}); | |
d.addEventSimple(b._node, | |
"click", function () { | |
b.toggle() | |
}); | |
if (b._store.get("spRepeat") === "true") b.on() | |
}; | |
g.prototype._handleRules = function () { | |
this._player.__rules.repeat ? this.enableButton() : this.disableButton() | |
}; | |
g.prototype.updateStatus = function () { | |
this._player.repeat ? (d.addClass(this._node, "active"), this._store.set("spRepeat", "true")) : (d.removeClass(this._node, "active"), this._player.__rules && this._player.__rules.repeat && this._store.set("spRepeat", "false")) | |
}; | |
g.prototype.on = function () { | |
var b = this; | |
b._player.setRepeat(!0).done(function () { | |
b.updateStatus() | |
}) | |
}; | |
g.prototype.off = function () { | |
var b = this; | |
b._player.setRepeat(!1).done(function () { | |
b.updateStatus() | |
}) | |
}; | |
g.prototype.toggle = function () { | |
if (d.hasClass(this._node, "disabled")) return !1; | |
if (this._player.repeat) this.off(); | |
else this.on() | |
}; | |
g.prototype.disableButton = function () { | |
this._disabled = !0; | |
d.addClass(this._node, "disabled"); | |
this.updateStatus() | |
}; | |
g.prototype.enableButton = function () { | |
this._disabled = !1; | |
d.removeClass(this._node, "disabled"); | |
this.updateStatus() | |
}; | |
i.RepeatButton = g | |
})(e["$api/models"], e["/scripts/player-utils"]) | |
}); | |
_unrequire("/scripts/player.playpausebutton", ["$api/models", "/scripts/player-utils"], function (i) { | |
(function (f, e) { | |
function g(c) { | |
var b = this, | |
a = f.player; | |
b._node = document.getElementById(c); | |
a.load(["playing", "track", "context"]).done(function (a) { | |
b._player = a; | |
b.init() | |
}) | |
} | |
var d = e.playerUtils; | |
g.prototype.init = function () { | |
var c = this; | |
d.addEventSimple(c._node, "click", function (b) { | |
c.toggle(b) | |
}); | |
c._player.addEventListener("change:playing", function () { | |
c.updateStatus() | |
}); | |
c._player.addEventListener("change", function () { | |
c.updateStatus() | |
}); | |
c.updateStatus() | |
}; | |
g.prototype.toggle = function (c) { | |
c && c.preventDefault(); | |
this._player.playing ? this._player.pause() : (this._player.track && this._player.track.advertisement && this._player.volume === 0 && this._player.setVolume(0.1), this._player.play()) | |
}; | |
g.prototype.updateStatus = function () { | |
this._player.playing ? d.addClass(this._node, "playing") : d.removeClass(this._node, "playing"); | |
!this._player.track && (!this._player.context || !this._player.context.uri) ? this.disableButton() : this.enableButton() | |
}; | |
g.prototype.disableButton = function () { | |
d.addClass(this._node, "disabled"); | |
d.removeClass(this._node, "playing") | |
}; | |
g.prototype.enableButton = function () { | |
d.removeClass(this._node, "disabled") | |
}; | |
i.PlayPauseButton = g | |
})(e["$api/models"], e["/scripts/player-utils"]) | |
}); | |
_unrequire("/scripts/player.nextbackbuttons", ["$api/models", "/scripts/player-utils"], function (i) { | |
(function (f, e) { | |
function g(a, c) { | |
var d = this; | |
d._node = document.getElementById(a); | |
d._eventManager = c; | |
d._disabled = !1; | |
b.load(["playing"]).done(function (a) { | |
d._player = a; | |
d.init() | |
}) | |
} | |
function d(a, | |
c) { | |
var d = this; | |
d._eventManager = c; | |
d._disabled = !1; | |
d._node = document.getElementById(a); | |
b.load(["playing"]).done(function (a) { | |
d._player = a; | |
d.init() | |
}) | |
} | |
var c = e.playerUtils, | |
b = f.player; | |
f.Loadable.define(f.Player, ["__rules"], "_playapp"); | |
g.prototype.init = function () { | |
var a = this; | |
c.addEventSimple(a._node, "click", function (b) { | |
b.preventDefault(); | |
a.playerNext(); | |
a._node.blur() | |
}); | |
a._player.addEventListener("change", function () { | |
a._handleRules() | |
}) | |
}; | |
g.prototype._handleRules = function () { | |
this._player.__rules.next ? !this._player.track || !this._player.context ? this.disableButton() : this.enableButton() : this.disableButton() | |
}; | |
g.prototype.playerNext = function () { | |
this._disabled || (this._eventManager.trigger(this._eventManager.Events.TRACK_SKIPPED), this._player.skipToNextTrack()) | |
}; | |
g.prototype.disableButton = function () { | |
this._disabled = !0; | |
c.addClass(this._node, "disabled") | |
}; | |
g.prototype.enableButton = function () { | |
this._disabled = !1; | |
c.removeClass(this._node, "disabled") | |
}; | |
d.prototype.init = function () { | |
var a = this; | |
c.addEventSimple(a._node, "click", function (b) { | |
b.preventDefault(); | |
a.playerBack(); | |
a._node.blur() | |
}); | |
a._player.addEventListener("change", function () { | |
a._handleRules() | |
}) | |
}; | |
d.prototype._handleRules = function () { | |
this._player.__rules.previous ? (this._disabled && this.enableButton(), !this._player.track || !this._player.context ? this.disableButton() : this.enableButton()) : this.disableButton() | |
}; | |
d.prototype.playerBack = function () { | |
if (this._disabled || this._player.track.duration - this._player.position < 500) return !1; | |
this._eventManager.trigger(this._eventManager.Events.BACK_BUTTON_PRESS_START); | |
this._player.position > 4E3 || this._player.__index === 0 && !this._player.repeat ? (this._player.seek(0), this._player.playing || this._player.play()) : (this._player.skipToPrevTrack(), this._eventManager.trigger(this._eventManager.Events.TRACK_SKIPPED)); | |
this._eventManager.trigger(this._eventManager.Events.BACK_BUTTON_PRESS_COMPLETE) | |
}; | |
d.prototype.disableButton = function () { | |
this._disabled = !0; | |
c.addClass(this._node, "disabled") | |
}; | |
d.prototype.enableButton = function () { | |
this._disabled = !1; | |
c.removeClass(this._node, "disabled") | |
}; | |
i.NextButton = g; | |
i.BackButton = d | |
})(e["$api/models"], e["/scripts/player-utils"]) | |
}); | |
_unrequire("/scripts/utils.draggable", [], function (e) { | |
e.Draggable = function (f, e) { | |
var g = void 0, | |
d = void 0, | |
c = void 0, | |
b = void 0, | |
a = void 0, | |
m = !1, | |
j = { | |
constrainDir: !1, | |
constrainParent: !1, | |
onStart: function () {}, | |
onMove: function () {}, | |
onComplete: function () {} | |
}; | |
self.element = f; | |
if (typeof f === "string") self.element = document.getElementById(f); | |
f.onmousedown = function (a) { | |
y(a) | |
}; | |
for (var i in e) j[i] = e[i]; | |
this.setContainerSize = function () { | |
m = { | |
maxW: f.offsetParent.offsetWidth, | |
maxH: f.offsetParent.offsetHeight | |
} | |
}; | |
j.constrainParent && this.setContainerSize(); | |
var y = function (e) { | |
if (j.onStart(f) === !1) return !1; | |
a && p(); | |
c = f.offsetLeft; | |
b = f.offsetTop; | |
a = f; | |
e = e || window.event; | |
e.preventDefault(); | |
g = e.clientX; | |
d = e.clientY; | |
document.addEventListener("mousemove", w); | |
document.addEventListener("mouseup", p); | |
document.addEventListener("mouseout", x); | |
return !1 | |
}, w = function (f) { | |
var e = f || window.event; | |
e.preventDefault(); | |
f = c + (e.clientX - g); | |
e = b + (e.clientY - d); | |
if (j.constrainDir !== "y") m && (f < 0 && (f = 0), f > m.maxW - a.offsetWidth && (f = m.maxW - a.offsetWidth)), a.style.left = f + "px"; | |
if (j.constrainDir !== "x") m && (e < 0 && (e = 0), e > m.maxH - a.offsetHeight && (e = m.maxH - a.offsetHeight)), a.style.top = e + "px"; | |
j.onMove(a, f, e); | |
return !1 | |
}, x = function (a) { | |
a = a ? a : window.event; | |
a = a.relatedTarget || a.toElement; | |
(!a || a.nodeName == "HTML") && p() | |
}, p = function () { | |
document.removeEventListener("mousemove", w); | |
document.removeEventListener("mouseup", p); | |
document.removeEventListener("mouseout", x); | |
j.onComplete(a); | |
a = null | |
}; | |
this.startDrag = y | |
} | |
}); | |
_unrequire("/scripts/utils.slider", ["/scripts/utils.draggable"], | |
function (i) { | |
(function (f) { | |
function e(g, d, c) { | |
var b = this; | |
b._opts = { | |
steps: 100, | |
start: 0, | |
onStart: function () {}, | |
onChange: function () {}, | |
onComplete: function () {} | |
}; | |
b._disabled = !1; | |
b._element = g; | |
b._handle = d; | |
if (typeof d === "string") b._handle = document.getElementById(d); | |
b.step = b._opts.start; | |
b.totalPx = g.offsetWidth - b._handle.offsetWidth; | |
for (var a in c) b._opts[a] = c[a]; | |
b._moveHandle = function () { | |
b._handle.style.left = b.step / b._opts.steps * b.totalPx + "px" | |
}; | |
var m = function (a) { | |
b.step = Math.round(a / b.totalPx * b._opts.steps); | |
b._opts.onChange.apply(b) | |
}; | |
this._handleClick = function (a, b) { | |
if (this._disabled || a.target === d) return !1; | |
a.stopPropagation(); | |
var c = b || a.offsetX || a.layerX; | |
c -= this._handle.offsetWidth / 2; | |
c = c < 0 ? 0 : c > this.totalPx ? this.totalPx : c; | |
m(c); | |
this._moveHandle(); | |
this._opts.onChange.apply(this); | |
this._knob.startDrag(a) | |
}; | |
this._knob = new f(d, { | |
constrainParent: !0, | |
constrainDir: "x", | |
onStart: function (a) { | |
if (b._disabled) return !1; | |
a.className = "dragging"; | |
b._opts.onStart.apply(b) | |
}, | |
onMove: function (a, b) { | |
m(b) | |
}, | |
onComplete: function () { | |
b._handle.className = ""; | |
b._opts.onComplete.apply(b) | |
} | |
}); | |
g.addEventListener("mousedown", function (a) { | |
b._handleClick(a) | |
}, !1); | |
b.handle = b._handle; | |
b.jumpToStep(b._opts.start, !1) | |
} | |
e.prototype.jumpToStep = function (f, d) { | |
if (self._disabled) return !1; | |
this.step = f; | |
this._opts.onChange.apply(this); | |
this._moveHandle(); | |
d !== !1 && this._opts.onComplete.apply(this) | |
}; | |
e.prototype.handleResize = function () { | |
this.totalPx = this._element.offsetWidth - this._handle.offsetWidth; | |
this._moveHandle(); | |
this._knob.setContainerSize(); | |
this._opts.onChange.apply(this) | |
}; | |
e.prototype.setSteps = function (f) { | |
this._opts.steps = f | |
}; | |
e.prototype.disable = function () { | |
this._disabled = !0 | |
}; | |
e.prototype.enable = function () { | |
this._disabled = !1 | |
}; | |
e.prototype.handleClick = function (f, d) { | |
this._handleClick(f, d) | |
}; | |
i.Slider = e | |
})(e["/scripts/utils.draggable"].Draggable) | |
}); | |
_unrequire("/scripts/player.volumecontrol", ["$api/models", "/scripts/player-utils", "/scripts/utils.slider"], function (i) { | |
(function (f, e, g) { | |
function d(a) { | |
var c = this, | |
d = f.player; | |
c._wrapper = document.getElementById(a); | |
c._dragging = !1; | |
c._store = new b; | |
d.load(["volume"]).done(function (a) { | |
c._player = a; | |
c.init() | |
}) | |
} | |
var c = e.playerUtils, | |
b = e.playerStorage; | |
d.prototype.reload = function () { | |
this._control.handleResize() | |
}; | |
d.prototype.buildNodes = function () { | |
this._barOuter = document.createElement("div"); | |
this._barOuter.id = "volume-bar"; | |
this._handle = document.createElement("span"); | |
this._handle.id = "vol-position"; | |
this._barInner = document.createElement("div"); | |
this._barInner.id = "vol-bar-inner"; | |
this._barOuter.appendChild(this._barInner); | |
this._barOuter.appendChild(this._handle); | |
this._wrapper.appendChild(this._barOuter); | |
this._handleWidth = this._handle.offsetWidth | |
}; | |
d.prototype.init = function () { | |
var a = this, | |
b = a._store.get("spVolume") || 100, | |
b = b < 0 ? 0 : b > 100 ? 100 : b; | |
a.buildNodes(); | |
a._control = new g(a._barOuter, a._handle, { | |
steps: 100, | |
start: parseInt(b, 10), | |
onStart: function () { | |
a._dragging = !0; | |
c.addClass(a._wrapper, "in-use") | |
}, | |
onChange: function () { | |
a._player.setVolume(this.step / 100); | |
a._barInner.style.width = Math.floor(this.step / this._opts.steps * this.totalPx + a._handleWidth) - 2 + "px" | |
}, | |
onComplete: function () { | |
a._dragging = !1; | |
c.removeClass(a._wrapper, | |
"in-use"); | |
a._store.set("spVolume", this.step) | |
} | |
}); | |
a._player.addEventListener("change:volume", function () { | |
a._dragging || a.setVolume(parseInt(a._player.volume * 100, 10)) | |
}) | |
}; | |
d.prototype.setVolume = function (a) { | |
if (isNaN(a) || a < 0 || a > 100) throw Error("Volume must be an integer between 0 and 100"); | |
this._control.jumpToStep(a, !0) | |
}; | |
i.VolumeControl = d | |
})(e["$api/models"], e["/scripts/player-utils"], e["/scripts/utils.slider"].Slider) | |
}); | |
_unrequire("/scripts/player.progressbar", ["$api/models", "/scripts/player-utils", "/scripts/utils.slider"], | |
function (i) { | |
(function (f, e, g) { | |
function d(a, c) { | |
var d = this; | |
d._wrapper = document.getElementById(a); | |
d._eventManager = c; | |
d._timer = null; | |
d._updateInterval = 310; | |
d._control = null; | |
d._isScrubbing = !1; | |
d._seekingTo = null; | |
d._timeMarker = null; | |
d._timeMarkerCenter = 0; | |
d._currentTrackUID = -1; | |
d._maxContainerWidth = null; | |
d._timeMarkerWidth = null; | |
b.load(["playing", "track", "position"]).done(function (a) { | |
d._player = a; | |
d._currentTrackUID = a.__uid; | |
d.init() | |
}) | |
} | |
var c = e.playerUtils, | |
b = f.player; | |
f.Loadable.define(f.Player, ["__uid"], "_playapp"); | |
d.prototype.init = function () { | |
var a = this; | |
a.buildNodes(); | |
a._control = new g(a._barOuter, a._scrubber, { | |
steps: a._player.track ? a._player.track.duration : 100, | |
onStart: function () { | |
a._isScrubbing = !0; | |
c.addClass(a._timeMarker, "active"); | |
c.addClass(a._timeMarkerArrow, "active") | |
}, | |
onChange: function () { | |
a._player.track && setTimeout(function () { | |
a.updateElapsedTime(this.step); | |
a.setPageTitle(this.step); | |
var b = this.handle.offsetLeft + this.handle.offsetWidth / 2; | |
a.moveTimeMarker(b); | |
a._barInner.style.width = b + "px" | |
}.bind(this), 1) | |
}, | |
onComplete: function () { | |
a._player.seek(this.step); | |
a._seekingTo = this.step; | |
a._barInner.style.width = this.handle.offsetLeft + this.handle.offsetWidth / 2 + "px"; | |
a._isScrubbing = !1; | |
c.removeClass(a._timeMarker, "active"); | |
c.removeClass(a._timeMarkerArrow, "active"); | |
a.pauseTimer(600) | |
} | |
}); | |
a._wrapper.addEventListener("mousedown", function (b) { | |
if (b.target.id.indexOf("widget") !== -1) return !1; | |
var c = b.offsetX || b.layerX; | |
return b.target.offsetParent === a._wrapper ? a._control.handleClick(b) : a._control.handleClick(b, c) | |
}, !1); | |
a._player.addEventListener("change:track", function () { | |
a._handleTrackChange() | |
}); | |
a._player.addEventListener("change", function () { | |
a._currentTrackUID !== b.__uid && a._handleTrackChange() | |
}); | |
a._eventManager.subscribe(a._eventManager.Events.TRACK_SKIPPED, function () { | |
a._handleTrackChange() | |
}); | |
a._eventManager.subscribe(a._eventManager.Events.BACK_BUTTON_PRESS_START, function () { | |
a._handleTrackChange() | |
}); | |
a._player.addEventListener("change:playing", function () { | |
a._player.playing ? a.runTimer() : a.stopTimer() | |
}); | |
a.moveTimeMarker(0); | |
a.runTimer() | |
}; | |
d.prototype.moveTimeMarker = function (a) { | |
var b = this, | |
c = function (a) { | |
a < b._timeMarkerArrowWidth ? a = b._timeMarkerArrowWidth : a > b._maxContainerWidth - b._timeMarkerArrowWidth - 2 && (a = b._maxContainerWidth - b._timeMarkerArrowWidth - 2); | |
return a = a - b._timeMarkerArrowWidth / 2 + 1 | |
}(a), | |
d = a - b._timeMarkerCenter; | |
d < 2 ? d = 2 : a > b._maxContainerWidth - b._timeMarkerCenter - 2 && (d = b._maxContainerWidth - b._timeMarkerWidth - 2); | |
b._timeMarkerArrow.style.left = c + "px"; | |
b._timeMarker.style.left = d + "px" | |
}; | |
d.prototype.setPageTitle = function (a, b) { | |
var d; | |
d = (d = this._player.track) ? d.name + " - " + (d.artists && d.artists[0].name) || | |
"" : ""; | |
if (this._player.playing || a && b) d = "[" + c.secsToMins((a || this._player.position) / 1E3) + "] " + d; | |
f.application.setTitle(d) | |
}; | |
d.prototype.buildNodes = function () { | |
this._barOuter = document.createElement("div"); | |
this._barOuter.id = "bar-outer"; | |
this._barInner = document.createElement("div"); | |
this._barInner.id = "bar-inner"; | |
this._scrubber = document.createElement("span"); | |
this._scrubber.id = "position"; | |
this._barOuter.appendChild(this._barInner); | |
this._barOuter.appendChild(this._scrubber); | |
this._wrapper.appendChild(this._barOuter); | |
this._timeWrapper = document.createElement("div"); | |
this._timeWrapper.id = "time"; | |
this._trackCurrentPos = document.createElement("span"); | |
this._trackCurrentPos.id = "track-current"; | |
this._trackLength = document.createElement("span"); | |
this._trackLength.id = "track-length"; | |
this._timeMarker = document.createElement("div"); | |
this._timeMarker.id = "time-marker"; | |
this._timeMarkerText = document.createElement("div"); | |
this._timeMarkerText.id = "time-marker-text"; | |
this._timeMarkerArrow = document.createElement("span"); | |
this._timeMarkerArrow.id = | |
"time-marker-arrow"; | |
this._timeMarker.appendChild(this._timeMarkerText); | |
this._timeMarkerText.appendChild(this._trackCurrentPos); | |
this._timeMarkerText.appendChild(this._trackLength); | |
this._trackLength.textContent = c.secsToMins(0); | |
this._wrapper.appendChild(this._timeMarker); | |
this._wrapper.appendChild(this._timeMarkerArrow); | |
this._wrapper.appendChild(this._timeWrapper); | |
var a = this; | |
setTimeout(function () { | |
a.setupMarkerSizing() | |
}, 10) | |
}; | |
d.prototype.setupMarkerSizing = function () { | |
this._timeMarkerWidth = this._timeMarker.offsetWidth; | |
this._timeMarkerCenter = this._timeMarkerWidth / 2; | |
this._timeMarkerArrowWidth = this._timeMarkerArrow.offsetWidth; | |
this._timeMarkerDefaultPos = this._timeMarkerCenter + this._timeMarkerArrowWidth / 2; | |
this._maxContainerWidth = this._barOuter.offsetWidth; | |
this._maxMarkerRightPos = this._maxContainerWidth - this._timeMarkerWidth - 2; | |
this._maxArrowRightPos = this._maxContainerWidth + this._timeMarkerArrowWidth - this._timeMarkerWidth - 2 | |
}; | |
d.prototype._handleTrackChange = function () { | |
if (!this._player.track) return this.stopTimer(), !1; | |
this._trackLength.textContent = c.secsToMins(this._player.track.duration / 1E3); | |
this.updateElapsedTime(0); | |
this._seekingTo = null; | |
this._control.jumpToStep(0, !1); | |
this._control.setSteps(this._player.track.duration); | |
this._currentTrackUID = b.__uid || -1; | |
this.pauseTimer(1E3); | |
this.setPageTitle(0); | |
this.setupMarkerSizing() | |
}; | |
d.prototype.runTimer = function () { | |
var a = this; | |
!a._timer && a._player.playing ? a._timer = setInterval(function () { | |
a._isScrubbing || a.updatePosition() | |
}.bind(a), a._updateInterval) : a._timer && !a._player.playing && a.stopTimer() | |
}; | |
d.prototype.stopTimer = function () { | |
clearInterval(this._timer); | |
this._timer = null | |
}; | |
d.prototype.pauseTimer = function (a) { | |
if (!a) throw Error("You must enter a pause time"); | |
var b = this; | |
b.stopTimer(); | |
setTimeout(function () { | |
b.runTimer() | |
}.bind(b), a) | |
}; | |
d.prototype.updateElapsedTime = function (a) { | |
this._trackCurrentPos.textContent = c.secsToMins(a / 1E3) | |
}; | |
d.prototype.enable = function () { | |
this._control && this._control.enable() | |
}; | |
d.prototype.disable = function () { | |
this._control.disable() | |
}; | |
d.prototype.reload = function () { | |
this._control.handleResize(); | |
this.setupMarkerSizing() | |
}; | |
d.prototype.updatePosition = function () { | |
if (!this._player || !this._player.track || !this._player.playing || this._isScrubbing) return this.stopTimer(), !1; | |
var a = this._player.position; | |
if (a > this._player.track.duration) a = this._player.track.duration; | |
if (this._seekingTo && Math.abs(this._seekingTo - a) > 1500) return !1; | |
this._seekingTo = null; | |
this._control.jumpToStep(a, !1); | |
this.updateElapsedTime(a); | |
this.setPageTitle(a) | |
}; | |
i.ProgressBar = d | |
})(e["$api/models"], e["/scripts/player-utils"], e["/scripts/utils.slider"].Slider) | |
}); | |
_unrequire("/scripts/player.tracking", ["$api/models"], function (i) { | |
(function (f) { | |
function e() { | |
this.DEFAULT_DATA = {}; | |
this.DEFAULT_CONTEXT = "player-web"; | |
this.DEFAULT_EVENT_VERSION = "1"; | |
this.DEFAULT_TEST_VERSION = "base" | |
} | |
e.prototype.track = function (e, d, c, b, a) { | |
d = d || this.DEFAULT_DATA; | |
c = c || this.DEFAULT_CONTEXT; | |
b = b || this.DEFAULT_EVENT_VERSION; | |
a = a || this.DEFAULT_TEST_VERSION; | |
f.application.clientEvent(c, e, b, a, d) | |
}; | |
i.Tracker = e; | |
i.Events = { | |
DOWNLOAD_LINK_CLICKED: "download-link-clicked" | |
} | |
})(e["$api/models"]) | |
}); | |
_unrequire("scripts/player", | |
"$api/models,/scripts/player.events,/scripts/player.suggestions,$views/image,/scripts/player-utils,/scripts/player.widgets,/scripts/player.shufflebutton,/scripts/player.repeatbutton,/scripts/player.playpausebutton,/scripts/player.nextbackbuttons,/scripts/player.volumecontrol,/scripts/player.progressbar,/scripts/player.tracking,$views/contextapp".split(","), function (i) { | |
(function (f, e, g, d, c, b, a, m, j, K, y, w, x, p) { | |
var k = c.playerUtils, | |
R = c.trackHistory, | |
S = c.kc, | |
q = document.body.offsetWidth, | |
h = f.player, | |
D = f.Track, | |
z = k.getId, | |
L = -1, | |
t = z("track-name"), | |
E = document.getElementById("widget-more"), | |
F = new c.Marquee(t, q - 10), | |
n = new e.EventManager, | |
G = new b.ArtistWidget(z("track-artist"), q - 10, n), | |
M = new j("play-pause"), | |
N = new K.NextButton("next", n), | |
O = new K.BackButton("previous", n), | |
T = new a("shuffle"), | |
U = new m("repeat"), | |
A = new w("progress", n), | |
H = z("cover-art"), | |
r = null, | |
V = new y("volume"), | |
l = null, | |
s = new R(3), | |
B = z("suggestions"), | |
u = B.querySelector("ul"); | |
new x.Tracker; | |
var v = null; | |
f.Loadable.define(f.Player, ["__length", "__rules", "__index", "__owner", | |
"__uid"], "_playapp"); | |
var I = function () { | |
if (l.advertisement) { | |
if (h.__owner.indexOf("http") !== -1) return window.open(h.__owner), window.parent.postMessage('{"ad_clicked":"' + h.__owner + '"}', "*"), !1; | |
var a = h.__owner.toSpotifyURI(); | |
a.indexOf("spotify:track") !== -1 ? h.playTrack(D.fromURI(a)) : f.application.openURI(a); | |
window.parent.postMessage("ad_clicked", "*"); | |
return !1 | |
} | |
return !0 | |
}, W = function () { | |
u.innerHTML = ""; | |
document.createDocumentFragment(); | |
if (s.size() === 0) return !1; | |
g.getTrackSuggestions(s.show("uri"), 3, function (b) { | |
for (var b = b[0].gids, c = 0; c < 3; c++) D.fromURI("spotify:track:" + b[c]).load("name", "image").done(function (b) { | |
a(b) | |
}) | |
}, function () { | |
s.size() < 3 && s.get(0).album.load(["name", "uri", "image"]).done(function (b) { | |
a(b) | |
}); | |
s.forEach(a) | |
}); | |
var a = function (a) { | |
var b = document.createElement("li"), | |
c = a instanceof f.Album; | |
if (c = a instanceof f.Track ? d.forTrack : c ? d.forAlbum : !1) { | |
c = c(a, { | |
animate: !0, | |
height: 50, | |
width: 50, | |
style: "embossed" | |
}); | |
b.appendChild(c.node); | |
var e = document.createElement("p"), | |
g = document.createElement("span"); | |
e.innerHTML = a.name; | |
a.artists[0].load("name").done(function (c) { | |
g.innerHTML += c.name.decodeForHtml(); | |
b.appendChild(e); | |
b.appendChild(g); | |
b.setAttribute("data-uri", a.uri); | |
k.addEventSimple(b, "click", function (a) { | |
a.preventDefault(); | |
f.application.openURI(this.getAttribute("data-uri").replace("spotify:", "spotify:radio:")) | |
}); | |
u.appendChild(b) | |
}) | |
} | |
}; | |
B.appendChild(u); | |
k.addClass(B, "active"); | |
window.setTimeout(function () { | |
k.addClass(u, "active") | |
}, 300) | |
}, J = function () { | |
if (!h.track) return !1; | |
k.removeClass(document.body, "noplayback"); | |
k.removeClass(B, | |
"active"); | |
k.removeClass(u, "active"); | |
D.fromURI(h.track.uri).load("name,uri,image,duration,artists,starred".split(",")).done(function (a) { | |
var b = document.createElement("a"); | |
t.innerHTML = ""; | |
b.href = a.uri.toSpotifyURL(); | |
b.innerHTML = a.name.decodeForHtml(); | |
t.appendChild(b); | |
F.refresh(); | |
!a.advertisement && a.uri.indexOf("spotify:ad") === -1 ? (s.add(a), A.enable(), k.removeClass(document.body, "isannons"), k.removeClass(E, "disabled")) : (A.disable(), k.addClass(E, "disabled"), k.addClass(document.body, "isannons")); | |
if (!l || l.image !== a.image) r ? (r.setImage(h.track), r.setLink(h.__owner && h.__owner.toSpotifyURI() || "")) : (r = (h.track ? d.forTrack : d.forAlbum)(h.track || l.album, { | |
animate: !0, | |
height: 250, | |
width: 250, | |
style: "plain", | |
link: h.__owner && h.__owner.toSpotifyURI() || "" | |
}), H.appendChild(r.node)); | |
l = a; | |
n.trigger(n.Events.TRACK_CHANGED, a) | |
}) | |
}, Q = function () { | |
var a = h.track; | |
if (L !== h.__uid) L = h.__uid, J(); | |
P(); | |
if (a === null) { | |
if (l !== null) W(), H.innerHTML = "", r = null, G.clear(), t.innerHTML = " ", l = null, A.setPageTitle(), k.addClass(document.body, "noplayback"), N.disableButton(), | |
O.disableButton(), M.disableButton(); | |
return !1 | |
} | |
v && C() | |
}, P = function () { | |
var a = h.track; | |
if (a && (a.advertisement || a.uri.indexOf("spotify:ad") !== -1)) h.volume == 0 ? h.pause() : h.paused && h.play() | |
}, X = function () { | |
l.starred ? l.unstar().done(function () { | |
C() | |
}) : l.star().done(function () { | |
C() | |
}).fail(function () {}) | |
}, C = function () { | |
v && v.postMessage(JSON.stringify(h), "*") | |
}; | |
i.init = function () { | |
h.load("track,__uid,__owner,__rules,position,playing".split(",")).done(function () { | |
k.addEventSimple(t, "click", function (a) { | |
a.preventDefault(); | |
a.stopPropagation(); | |
if (a.target.href) { | |
if (l.advertisement) return I(), !1; | |
f.application.openURI(h.__owner.toSpotifyURI()) | |
} | |
}); | |
k.addEventSimple(H, "click", function (a) { | |
a.preventDefault(); | |
I() | |
}); | |
Q(); | |
J(); | |
h.addEventListener("change", Q); | |
h.addEventListener("change:volume", P); | |
h.addEventListener("change:track", J); | |
G.init(); | |
F.init(); | |
window.addEventListener("resize", function () { | |
var a = document.body.offsetWidth; | |
a !== q && (q = a, V.reload(), A.reload(), F.widthAdjust(q - 10), G.resize(q - 10)) | |
}, !1); | |
window.addEventListener("message", function (a) { | |
if (a.source === v) switch (a = JSON.parse(a.data), a.miniplayer) { | |
case "staterequest": | |
C(); | |
break; | |
case "playpause": | |
M.toggle(); | |
break; | |
case "next": | |
N.playerNext(); | |
break; | |
case "back": | |
O.playerBack(); | |
break; | |
case "shuffle": | |
T.toggle(); | |
break; | |
case "repeat": | |
U.toggle(); | |
break; | |
case "star": | |
X(); | |
break; | |
case "seek": | |
h.seek(a.target); | |
break; | |
case "volume": | |
h.setVolume(a.target); | |
break; | |
case "openuri": | |
f.application.openURI(a.target) | |
} | |
}, !1); | |
n.subscribe(n.Events.AD_CLICKED, I); | |
E.addEventListener("click", function (a) { | |
a.preventDefault(); | |
l && !k.hasClass(this, | |
"disabled") && p.show("context-actions", [l.uri], a.target, "spotify:temp-playlist:hellothere") | |
}, !1); | |
var a = new S; | |
a.onSuccess = function () { | |
v = window.open("vendor/mini/mini.html", "Spotify", "menubar=no,location=no,resizable=no,scrollbars=no,status=no,width=420,height=150") | |
}; | |
a.init() | |
}) | |
} | |
})(e["$api/models"], e["/scripts/player.events"], e["/scripts/player.suggestions"], e["$views/image"].Image, e["/scripts/player-utils"], e["/scripts/player.widgets"], e["/scripts/player.shufflebutton"].ShuffleButton, e["/scripts/player.repeatbutton"].RepeatButton, | |
e["/scripts/player.playpausebutton"].PlayPauseButton, e["/scripts/player.nextbackbuttons"], e["/scripts/player.volumecontrol"].VolumeControl, e["/scripts/player.progressbar"].ProgressBar, e["/scripts/player.tracking"], e["$views/contextapp"].ContextApp) | |
}); | |
_unrequire("main", ["scripts/player"], function () { | |
e["scripts/player"].init() | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- https://play.spotify.edgekey.net/client/c46d547/proto/data.xml --> | |
<!-- 2013-06-18 --> | |
<?xml version="1.0" encoding="UTF-8"?> | |
<services> | |
<search><![CDATA[ | |
message SearchRequest { | |
enum Type { | |
TRACK = 0; | |
ALBUM = 1; | |
ARTIST = 2; | |
PLAYLIST = 3; | |
USER = 4; | |
} | |
optional string query = 1; | |
optional Type type = 2; | |
optional int32 limit = 3; | |
optional int32 offset = 4; | |
optional bool did_you_mean = 5 | |
} | |
message Image { | |
optional Size size = 1; | |
optional string spotify_uri = 2; | |
repeated bytes file_id = 3; | |
optional string url = 4; | |
optional string slask_id = 5; | |
} | |
message Playlist { | |
optional string uri = 1; | |
optional string name = 2; | |
repeated Image image = 3; | |
} | |
message User { | |
optional string username = 1; | |
optional string full_name = 2; | |
repeated Image image = 3; | |
optional sint32 followers = 4; | |
} | |
message SearchReply { | |
optional sint32 hits = 1; | |
repeated Track track = 2; | |
repeated Album album = 3; | |
repeated Artist artist = 4; | |
repeated Playlist playlist = 5; | |
optional string did_you_mean = 6; | |
repeated User user = 7; | |
} | |
]]> | |
</search> | |
<suggest><![CDATA[ | |
message Track { | |
optional bytes gid = 1; | |
optional string name = 2; | |
optional bytes image = 3; | |
repeated string artist_name = 4; | |
repeated bytes artist_gid = 5; | |
optional uint32 rank = 6; | |
} | |
message Artist { | |
optional bytes gid = 1; | |
optional string name = 2; | |
optional bytes image = 3; | |
optional uint32 rank = 6; | |
} | |
message Album { | |
optional bytes gid = 1; | |
optional string name = 2; | |
optional bytes image = 3; | |
repeated string artist_name = 4; | |
repeated bytes artist_gid = 5; | |
optional uint32 rank = 6; | |
} | |
message Playlist { | |
optional string uri = 1; | |
optional string name = 2; | |
optional string image_uri = 3; | |
optional string owner_name = 4; | |
optional string owner_uri = 5; | |
optional uint32 rank = 6; | |
} | |
message Suggestions { | |
repeated Track track = 1; | |
repeated Album album = 2; | |
repeated Artist artist = 3; | |
repeated Playlist playlist = 4; | |
} | |
]]> | |
</suggest> | |
<appstore><![CDATA[ | |
package spotify.appstore.proto; | |
message AppInfo { | |
required string app_name = 1; | |
required int32 original_bundle_version = 2; | |
} | |
message AppInfoList { | |
repeated AppInfo items = 1; | |
} | |
message RequestHeader { | |
enum Platform { | |
WIN32_X86 = 0; | |
OSX_X86 = 1; | |
LINUX_X86 = 2; | |
IPHONE_ARM = 3; | |
SYMBIANS60_ARM = 4; | |
OSX_POWERPC = 5; | |
ANDROID_ARM = 6; | |
WINCE_ARM = 7; | |
LINUX_X86_64 = 8; | |
OSX_X86_64 = 9; | |
PALM_ARM = 10; | |
LINUX_SH = 11; | |
FREEBSD_X86 = 12; | |
FREEBSD_X86_64 = 13; | |
BLACKBERRY_ARM = 14; | |
SONOS_UNKNOWN = 15; | |
LINUX_MIPS = 16; | |
LINUX_ARM = 17; | |
LOGITECH_ARM = 18; | |
LINUX_BLACKFIN = 19; | |
ONKYO_ARM = 21; | |
QNXNTO_ARM = 22; | |
BADPLATFORM = 255; | |
} | |
enum Priority { | |
PRIORITY_DEFAULT = 0; | |
PRIORITY_POLLING = 1; | |
} | |
optional string market = 1; | |
optional Platform platform = 2; | |
optional Priority priority = 3; | |
optional int32 client_api_version_low = 4; | |
optional int32 client_api_version_high = 5; | |
optional AppInfoList app_infos = 6; | |
} | |
message AppItem { | |
enum Requirement { | |
REQUIRED_INSTALL = 1; | |
LAZYLOAD = 2; | |
OPTIONAL_INSTALL = 3; | |
} | |
optional string app_name = 1; | |
optional Requirement requirement = 2; | |
optional int32 status = 3; | |
optional string manifest = 4; | |
optional string checksum = 5; | |
optional string bundle_uri = 6; | |
optional string small_icon_uri = 7; | |
optional string large_icon_uri = 8; | |
optional string medium_icon_uri = 9; | |
optional IdentifierList categories = 10; | |
} | |
message AppList { | |
repeated AppItem items = 1; | |
} | |
message IdentifierList { | |
repeated string identifiers = 1; | |
} | |
]]> | |
</appstore> | |
<metadata><![CDATA[ | |
package spotify.metadata.proto; | |
option optimize_for = SPEED; | |
option java_package = "com.spotify.metadata.proto"; | |
option java_outer_classname = "Metadata"; | |
message TopTracks { | |
optional string country = 1; | |
repeated Track track = 2; | |
} | |
message ActivityPeriod { | |
optional sint32 start_year = 1; | |
optional sint32 end_year = 2; | |
optional sint32 decade = 3; | |
} | |
message Artist { | |
optional bytes gid = 1; | |
optional string name = 2; | |
optional sint32 popularity = 3; | |
repeated TopTracks top_track = 4; | |
repeated AlbumGroup album_group = 5; | |
repeated AlbumGroup single_group = 6; | |
repeated AlbumGroup compilation_group = 7; | |
repeated AlbumGroup appears_on_group = 8; | |
repeated string genre = 9; | |
repeated ExternalId external_id = 10; | |
repeated Image portrait = 11; | |
repeated Biography biography = 12; | |
repeated ActivityPeriod activity_period = 13; | |
repeated Restriction restriction = 14; | |
repeated Artist related = 15; | |
optional bool is_portrait_album_cover = 16; | |
optional ImageGroup portrait_group = 17; | |
} | |
message AlbumGroup { | |
repeated Album album = 1; | |
} | |
message Date { | |
optional sint32 year = 1; | |
optional sint32 month = 2; | |
optional sint32 day = 3; | |
} | |
message Album { | |
enum Type { | |
ALBUM = 1; | |
SINGLE = 2; | |
COMPILATION = 3; | |
} | |
optional bytes gid = 1; | |
optional string name = 2; | |
repeated Artist artist = 3; | |
optional Type type = 4; | |
optional string label = 5; | |
optional Date date = 6; | |
optional sint32 popularity = 7; | |
repeated string genre = 8; | |
repeated Image cover = 9; | |
repeated ExternalId external_id = 10; | |
repeated Disc disc = 11; | |
repeated string review = 12; | |
repeated Copyright copyright = 13; | |
repeated Restriction restriction = 14; | |
repeated Album related = 15; | |
repeated SalePeriod sale_period = 16; | |
optional ImageGroup cover_group = 17; | |
} | |
message Track { | |
optional bytes gid = 1; | |
optional string name = 2; | |
optional Album album = 3; | |
repeated Artist artist = 4; | |
optional sint32 number = 5; | |
optional sint32 disc_number = 6; | |
optional sint32 duration = 7; | |
optional sint32 popularity = 8; | |
optional bool explicit = 9; | |
repeated ExternalId external_id = 10; | |
repeated Restriction restriction = 11; | |
repeated AudioFile file = 12; | |
repeated Track alternative = 13; | |
repeated SalePeriod sale_period = 14; | |
repeated AudioFile preview = 15; | |
} | |
message Image { | |
enum Size { | |
DEFAULT = 0; | |
SMALL = 1; | |
LARGE = 2; | |
XLARGE = 3; | |
} | |
optional bytes file_id = 1; | |
optional Size size = 2; | |
optional sint32 width = 3; | |
optional sint32 height = 4; | |
} | |
message ImageGroup { | |
repeated Image image = 1; | |
} | |
message Biography { | |
optional string text = 1; | |
repeated Image portrait = 2; | |
repeated ImageGroup portrait_group = 3; | |
} | |
message Disc { | |
optional sint32 number = 1; | |
optional string name = 2; | |
repeated Track track = 3; | |
} | |
message Copyright { | |
enum Type { | |
P = 0; | |
C = 1; | |
} | |
optional Type type = 1; | |
optional string text = 2; | |
} | |
message Restriction { | |
enum Catalogue { | |
AD = 0; | |
SUBSCRIPTION = 1; | |
} | |
enum Type { | |
STREAMING = 0; | |
} | |
repeated Catalogue catalogue = 1; | |
optional string countries_allowed = 2; | |
optional string countries_forbidden = 3; | |
optional Type type = 4; | |
} | |
message SalePeriod { | |
repeated Restriction restriction = 1; | |
optional Date start = 2; | |
optional Date end = 3; | |
} | |
message ExternalId { | |
optional string type = 1; | |
optional string id = 2; | |
} | |
message AudioFile { | |
enum Format { | |
OGG_VORBIS_96 = 0; | |
OGG_VORBIS_160 = 1; | |
OGG_VORBIS_320 = 2; | |
MP3_256 = 3; | |
MP3_320 = 4; | |
MP3_160 = 5; | |
MP3_96 = 6; | |
} | |
optional bytes file_id = 1; | |
optional Format format = 2; | |
} | |
]]> | |
</metadata> | |
<mercury><![CDATA[ | |
package spotify.mercury.proto; | |
message MercuryMultiGetRequest { | |
repeated MercuryRequest request = 1; | |
} | |
message MercuryMultiGetReply { | |
repeated MercuryReply reply = 1; | |
} | |
message MercuryRequest { | |
optional string uri = 1; | |
optional string content_type = 2; | |
optional bytes body = 3; | |
optional bytes etag = 4; | |
} | |
message MercuryReply { | |
enum CachePolicy { | |
CACHE_NO = 1; | |
CACHE_PRIVATE = 2; | |
CACHE_PUBLIC = 3; | |
} | |
optional sint32 status_code = 1; | |
optional string status_message = 2; | |
optional CachePolicy cache_policy = 3; | |
optional sint32 ttl = 4; | |
optional bytes etag = 5; | |
optional string content_type = 6; | |
optional bytes body = 7; | |
} | |
]]> | |
</mercury> | |
<toplist><![CDATA[ | |
message Toplist { | |
repeated string items = 1; | |
} | |
]]> | |
</toplist> | |
<social><![CDATA[ | |
message DecorationData { | |
optional string username = 1; | |
optional string full_name = 2; | |
optional string image_url = 3; | |
optional string large_image_url = 5; | |
optional string first_name = 6; | |
optional string last_name = 7; | |
optional string facebook_uid = 8; | |
} | |
]]> | |
</social> | |
<playlist4changes><![CDATA[ | |
package spotify.playlist4.proto; | |
option optimize_for = SPEED; | |
option java_package = "com.spotify.playlist4.proto"; | |
message ChangeInfo { | |
optional string user = 1; | |
optional int32 timestamp = 2; | |
optional bool admin = 3; | |
optional bool undo = 4; | |
optional bool redo = 5; | |
optional bool merge = 6; | |
optional bool compressed = 7; | |
optional bool migration = 8; | |
} | |
message Delta { | |
optional bytes base_version = 1; | |
repeated Op ops = 2; | |
optional ChangeInfo info = 4; | |
} | |
message Merge { | |
optional bytes base_version = 1; | |
optional bytes merge_version = 2; | |
optional ChangeInfo info = 4; | |
} | |
message ChangeSet { | |
enum Kind { | |
KIND_UNKNOWN = 0; | |
DELTA = 2; | |
MERGE = 3; | |
}; | |
required Kind kind = 1; | |
optional Delta delta = 2; | |
optional Merge merge = 3; | |
} | |
message RevisionTaggedChangeSet { | |
required bytes revision = 1; | |
required ChangeSet change_set = 2; | |
} | |
message Diff { | |
required bytes from_revision = 1; | |
repeated Op ops = 2; | |
required bytes to_revision = 3; | |
} | |
message ListDump { | |
optional bytes latestRevision = 1; | |
optional int32 length = 2; | |
optional ListAttributes attributes = 3; | |
optional ListChecksum checksum = 4; | |
optional ListItems contents = 5; | |
repeated Delta pendingDeltas = 7; | |
} | |
message ListChanges { | |
optional bytes baseRevision = 1; | |
repeated Delta deltas = 2; | |
optional bool wantResultingRevisions = 3; | |
optional bool wantSyncResult = 4; | |
optional ListDump dump = 5; | |
repeated int32 nonces = 6; | |
} | |
message SelectedListContent { | |
optional bytes revision = 1; | |
optional int32 length = 2; | |
optional ListAttributes attributes = 3; | |
optional ListChecksum checksum = 4; | |
optional ListItems contents = 5; | |
optional Diff diff = 6; | |
optional Diff syncResult = 7; | |
repeated bytes resultingRevisions = 8; | |
optional bool multipleHeads = 9; | |
optional bool upToDate = 10; | |
repeated ClientResolveAction resolveAction = 12; | |
repeated ClientIssue issues = 13; | |
repeated int32 nonces = 14; | |
} | |
]]> | |
</playlist4changes> | |
<playlist4content><![CDATA[ | |
package spotify.playlist4.proto; | |
option optimize_for = SPEED; | |
option java_package = "com.spotify.playlist4.proto"; | |
message Item { | |
required string uri = 1; | |
optional ItemAttributes attributes = 2; | |
} | |
message ListItems { | |
required int32 pos = 1; | |
required bool truncated = 2; | |
repeated Item items = 3; | |
} | |
message ContentRange { | |
required int32 pos = 1; | |
optional int32 length = 2; | |
} | |
message ListContentSelection { | |
optional bool wantRevision = 1; | |
optional bool wantLength = 2; | |
optional bool wantAttributes = 3; | |
optional bool wantChecksum = 4; | |
optional bool wantContent = 5; | |
optional ContentRange contentRange = 6; | |
optional bool wantDiff = 7; | |
optional bytes baseRevision = 8; | |
optional bytes hintRevision = 9; | |
optional bool wantNothingIfUpToDate = 10; | |
optional bool wantResolveAction = 12; | |
repeated ClientIssue issues = 13; | |
repeated ClientResolveAction resolveAction = 14; | |
} | |
]]> | |
</playlist4content> | |
<playlist4issues><![CDATA[ | |
package spotify.playlist4.proto; | |
option optimize_for = SPEED; | |
option java_package = "com.spotify.playlist4.proto"; | |
message ClientIssue { | |
enum Level { | |
LEVEL_UNKNOWN = 0; | |
LEVEL_DEBUG = 1; | |
LEVEL_INFO = 2; | |
LEVEL_NOTICE = 3; | |
LEVEL_WARNING = 4; | |
LEVEL_ERROR = 5; | |
} | |
enum Code { | |
CODE_UNKNOWN = 0; | |
CODE_INDEX_OUT_OF_BOUNDS = 1; | |
CODE_VERSION_MISMATCH = 2; | |
CODE_CACHED_CHANGE = 3; | |
CODE_OFFLINE_CHANGE = 4; | |
CODE_CONCURRENT_CHANGE = 5; | |
} | |
optional Level level = 1; | |
optional Code code = 2; | |
optional int32 repeatCount = 3; | |
} | |
message ClientResolveAction { | |
enum Code { | |
CODE_UNKNOWN = 0; | |
CODE_NO_ACTION = 1; | |
CODE_RETRY = 2; | |
CODE_RELOAD = 3; | |
CODE_DISCARD_LOCAL_CHANGES = 4; | |
CODE_SEND_DUMP = 5; | |
CODE_DISPLAY_ERROR_MESSAGE = 6; | |
} | |
enum Initiator { | |
INITIATOR_UNKNOWN = 0; | |
INITIATOR_SERVER = 1; | |
INITIATOR_CLIENT = 2; | |
} | |
optional Code code = 1; | |
optional Initiator initiator = 2; | |
} | |
]]> | |
</playlist4issues> | |
<playlist4meta><![CDATA[ | |
package spotify.playlist4.proto; | |
option optimize_for = SPEED; | |
option java_package = "com.spotify.playlist4.proto"; | |
message ListChecksum { | |
required int32 version = 1; | |
optional bytes sha1 = 4; | |
} | |
message DownloadFormat { | |
enum Codec { | |
CODEC_UNKNOWN = 0; | |
OGG_VORBIS = 1; | |
FLAC = 2; | |
MPEG_1_LAYER_3 = 3; | |
} | |
required Codec codec = 1; | |
} | |
enum ListAttributeKind { | |
LIST_UNKNOWN = 0; | |
LIST_NAME = 1; | |
LIST_DESCRIPTION = 2; | |
LIST_PICTURE = 3; | |
LIST_COLLABORATIVE = 4; | |
LIST_PL3_VERSION = 5; | |
LIST_DELETED_BY_OWNER = 6; | |
LIST_RESTRICTED_COLLABORATIVE = 7; | |
} | |
message ListAttributes { | |
optional string name = 1; | |
optional string description = 2; | |
optional bytes picture = 3; | |
optional bool collaborative = 4; | |
optional string pl3_version = 5; | |
optional bool deleted_by_owner = 6; | |
optional bool restricted_collaborative = 7; | |
} | |
enum ItemAttributeKind { | |
ITEM_UNKNOWN = 0; | |
ITEM_ADDED_BY = 1; | |
ITEM_TIMESTAMP = 2; | |
ITEM_MESSAGE = 3; | |
ITEM_SEEN = 4; | |
ITEM_DOWNLOAD_COUNT = 5; | |
ITEM_DOWNLOAD_FORMAT = 6; | |
ITEM_SEVENDIGITAL_ID = 7; | |
ITEM_SEVENDIGITAL_LEFT = 8; | |
ITEM_SEEN_AT = 9; | |
} | |
message ItemAttributes { | |
optional string added_by = 1; | |
optional int64 timestamp = 2; | |
optional string message = 3; | |
optional bool seen = 4; | |
optional int64 download_count = 5; | |
optional DownloadFormat download_format = 6; | |
optional string sevendigital_id = 7; | |
optional int64 sevendigital_left = 8; | |
optional int64 seen_at = 9; | |
} | |
message StringAttribute { | |
required string key = 1; | |
required string value = 2; | |
} | |
message StringAttributes { | |
repeated StringAttribute attribute = 1; | |
} | |
]]> | |
</playlist4meta> | |
<playlist4ops><![CDATA[ | |
package spotify.playlist4.proto; | |
option optimize_for = SPEED; | |
option java_package = "com.spotify.playlist4.proto"; | |
message Add { | |
optional int32 fromIndex = 1; | |
repeated Item items = 2; | |
optional ListChecksum list_checksum = 3; | |
optional bool addLast = 4; | |
optional bool addFirst = 5; | |
} | |
message Rem { | |
optional int32 fromIndex = 1; | |
optional int32 length = 2; | |
repeated Item items = 3; | |
optional ListChecksum list_checksum = 4; | |
optional ListChecksum items_checksum = 5; | |
optional ListChecksum uris_checksum = 6; | |
optional bool itemsAsKey = 7; | |
} | |
message Mov { | |
required int32 fromIndex = 1; | |
required int32 length = 2; | |
required int32 toIndex = 3; | |
optional ListChecksum list_checksum = 4; | |
optional ListChecksum items_checksum = 5; | |
optional ListChecksum uris_checksum = 6; | |
} | |
message ItemAttributesPartialState { | |
required ItemAttributes values = 1; | |
repeated ItemAttributeKind no_value = 2; | |
} | |
message ListAttributesPartialState { | |
required ListAttributes values = 1; | |
repeated ListAttributeKind no_value = 2; | |
} | |
message UpdateItemAttributes { | |
required int32 index = 1; | |
required ItemAttributesPartialState new_attributes = 2; | |
optional ItemAttributesPartialState old_attributes = 3; | |
optional ListChecksum list_checksum = 4; | |
optional ListChecksum old_attributes_checksum = 5; | |
} | |
message UpdateListAttributes { | |
required ListAttributesPartialState new_attributes = 1; | |
optional ListAttributesPartialState old_attributes = 2; | |
optional ListChecksum list_checksum = 3; | |
optional ListChecksum old_attributes_checksum = 4; | |
} | |
message Op { | |
enum Kind { | |
KIND_UNKNOWN = 0; | |
ADD = 2; | |
REM = 3; | |
MOV = 4; | |
UPDATE_ITEM_ATTRIBUTES = 5; | |
UPDATE_LIST_ATTRIBUTES = 6; | |
}; | |
required Kind kind = 1; | |
optional Add add = 2; | |
optional Rem rem = 3; | |
optional Mov mov = 4; | |
optional UpdateItemAttributes update_item_attributes = 5; | |
optional UpdateListAttributes update_list_attributes = 6; | |
} | |
message OpList { | |
repeated Op ops = 1; | |
} | |
]]> | |
</playlist4ops> | |
<playlist4service><![CDATA[ | |
package spotify.playlist4.proto; | |
option optimize_for = SPEED; | |
message RequestContext { | |
optional bool administrative = 2; | |
optional bool migration = 4; | |
optional string tag = 7; | |
optional bool useStarredView = 8; | |
optional bool syncWithPublished = 9; | |
} | |
message GetCurrentRevisionArgs { | |
optional bytes uri = 1; | |
optional RequestContext context = 2; | |
} | |
message GetChangesInSequenceRangeArgs { | |
optional bytes uri = 1; | |
optional RequestContext context = 2; | |
optional int32 fromSequenceNumber = 3; | |
optional int32 toSequenceNumber = 4; | |
} | |
message GetChangesInSequenceRangeMatchingPl3VersionArgs { | |
optional bytes uri = 1; | |
optional RequestContext context = 2; | |
optional int32 fromSequenceNumber = 3; | |
optional int32 toSequenceNumber = 4; | |
optional string pl3Version = 5; | |
} | |
message GetChangesInSequenceRangeReturn { | |
repeated RevisionTaggedChangeSet result = 1; | |
} | |
message ObliterateListArgs { | |
optional bytes uri = 1; | |
optional RequestContext context = 2; | |
} | |
message UpdatePublishedArgs { | |
optional bytes publishedUri = 1; | |
optional RequestContext context = 2; | |
optional bytes uri = 3; | |
optional bool isPublished = 4; | |
} | |
message SynchronizeArgs { | |
optional bytes uri = 1; | |
optional RequestContext context = 2; | |
optional ListContentSelection selection = 3; | |
optional ListChanges changes = 4; | |
} | |
message GetSnapshotAtRevisionArgs { | |
optional bytes uri = 1; | |
optional RequestContext context = 2; | |
optional bytes revision = 3; | |
} | |
message SubscribeRequest { | |
repeated bytes uris = 1; | |
} | |
message UnsubscribeRequest { | |
repeated bytes uris = 1; | |
} | |
enum Playlist4InboxErrorKind { | |
INBOX_NOT_ALLOWED = 2; | |
INBOX_INVALID_USER = 3; | |
INBOX_INVALID_URI = 4; | |
INBOX_LIST_TOO_LONG = 5; | |
} | |
message Playlist4ServiceException { | |
optional string why = 1; | |
optional string symbol = 2; | |
optional bool permanent = 3; | |
optional string serviceErrorClass = 4; | |
optional Playlist4InboxErrorKind inboxErrorKind = 5; | |
} | |
message SynchronizeReturn { | |
optional SelectedListContent result = 1; | |
optional Playlist4ServiceException exception = 4; | |
} | |
enum Playlist4ServiceMethodKind { | |
METHOD_UNKNOWN = 0; | |
METHOD_GET_CURRENT_REVISION = 2; | |
METHOD_GET_CHANGES_IN_SEQUENCE_RANGE = 3; | |
METHOD_OBLITERATE_LIST = 4; | |
METHOD_SYNCHRONIZE = 5; | |
METHOD_UPDATE_PUBLISHED = 6; | |
METHOD_GET_CHANGES_IN_SEQUENCE_RANGE_MATCHING_PL3_VERSION = 7; | |
METHOD_GET_SNAPSHOT_AT_REVISION = 8; | |
} | |
message Playlist4ServiceCall { | |
optional Playlist4ServiceMethodKind kind = 1; | |
optional GetCurrentRevisionArgs getCurrentRevisionArgs = 2; | |
optional GetChangesInSequenceRangeArgs getChangesInSequenceRangeArgs = 3; | |
optional ObliterateListArgs obliterateListArgs = 4; | |
optional SynchronizeArgs synchronizeArgs = 5; | |
optional UpdatePublishedArgs updatePublishedArgs = 6; | |
optional GetChangesInSequenceRangeMatchingPl3VersionArgs getChangesInSequenceRangeMatchingPl3VersionArgs = 7; | |
optional GetSnapshotAtRevisionArgs getSnapshotAtRevisionArgs = 8; | |
} | |
message Playlist4ServiceReturn { | |
optional Playlist4ServiceMethodKind kind = 1; | |
optional Playlist4ServiceException exception = 2; | |
optional bytes getCurrentRevisionReturn = 3; | |
optional GetChangesInSequenceRangeReturn getChangesInSequenceRangeReturn = 4; | |
optional bool obliterateListReturn = 5; | |
optional SynchronizeReturn synchronizeReturn = 6; | |
optional bool updatePublishedReturn = 7; | |
optional GetChangesInSequenceRangeReturn getChangesInSequenceRangeMatchingPl3VersionReturn = 8; | |
optional RevisionTaggedListSnapshot getSnapshotAtRevisionReturn = 9; | |
} | |
message CreateListReply { | |
required bytes uri = 1; | |
optional bytes revision = 2; | |
} | |
message ModifyReply { | |
required bytes uri = 1; | |
optional bytes revision = 2; | |
} | |
message PlaylistModificationInfo { | |
optional bytes uri = 1; | |
optional bytes new_revision = 2; | |
} | |
]]> | |
</playlist4service> | |
<spirc><![CDATA[ | |
package spotify.spirc.proto; | |
enum MessageType { | |
kMessageTypeHello = 1; | |
kMessageTypeGoodbye = 2; | |
kMessageTypeNotify = 10; | |
kMessageTypeLoad = 20; | |
kMessageTypePlay = 21; | |
kMessageTypePause = 22; | |
kMessageTypePlayPause = 23; | |
kMessageTypeSeek = 24; | |
kMessageTypePrev = 25; | |
kMessageTypeNext = 26; | |
kMessageTypeVolume = 27; | |
kMessageTypeShuffle = 28; | |
kMessageTypeRepeat = 29; | |
kMessageTypeQueue = 30; | |
kMessageTypeVolumeDown = 31; | |
kMessageTypeVolumeUp = 32; | |
} | |
enum PlayStatus { | |
kPlayStatusStop = 0; | |
kPlayStatusPlay = 1; | |
kPlayStatusPause = 2; | |
kPlayStatusLoading = 3; | |
kPlayStatusError = 4; | |
} | |
message Goodbye { | |
optional string reason = 1; | |
} | |
message State { | |
optional string trackURI = 1; | |
optional string contextURI = 2; | |
optional uint32 index = 3; | |
optional uint32 position = 4; | |
optional PlayStatus status = 5; | |
optional uint32 errorCode = 6; | |
optional uint32 volume = 8; | |
optional uint32 duration = 9; | |
repeated string history = 10; | |
repeated string queued = 11; | |
repeated string future = 12; | |
optional bool shuffle = 13; | |
optional bool repeat = 14; | |
optional uint32 volumeCaps = 15; | |
} | |
message Frame { | |
optional uint32 version = 1; | |
optional string ident = 2; | |
optional string name = 3; | |
optional uint32 msgid = 4; | |
optional MessageType type = 5; | |
optional Goodbye goodbye = 11; | |
optional State state = 12; | |
optional uint32 position = 13; | |
optional uint32 volume = 14; | |
repeated string toQueue = 15; | |
} | |
message VoidReply { | |
} | |
]]> | |
</spirc> | |
<pubsub><![CDATA[ | |
package spotify.hermes.pubsub.proto; | |
message Subscription { | |
optional string uri = 1; | |
optional int32 expiry = 2; | |
optional int32 status_code = 3; | |
} | |
]]> | |
</pubsub> | |
<popcount><![CDATA[ | |
package spotify.popcount2.proto; | |
message PopcountRequest { | |
} | |
message PopcountResult { | |
optional sint64 count = 1; | |
optional bool truncated = 2; | |
repeated string user = 3; | |
repeated sint64 subscriptionTimestamps = 4; | |
repeated sint64 insertionTimestamps = 5; | |
} | |
]]> | |
</popcount> | |
<presence><![CDATA[ | |
package spotify.presence.proto; | |
message PlaylistPublishedState { | |
optional string uri = 1; | |
optional int64 timestamp = 2; | |
} | |
message PlaylistTrackAddedState { | |
optional string playlist_uri = 1; | |
optional string track_uri = 2; | |
optional int64 timestamp = 3; | |
} | |
message TrackFinishedPlayingState { | |
optional string uri = 1; | |
optional string context_uri = 2; | |
optional int64 timestamp = 3; | |
optional string referrer_uri = 4; | |
} | |
message FavoriteAppAddedState { | |
optional string app_uri = 1; | |
optional int64 timestamp = 2; | |
} | |
message TrackStartedPlayingState { | |
optional string uri = 1; | |
optional string context_uri = 2; | |
optional int64 timestamp = 3; | |
optional string referrer_uri = 4; | |
} | |
message UriSharedState { | |
optional string uri = 1; | |
optional string message = 2 [default=""]; | |
optional int64 timestamp = 3; | |
} | |
message ArtistFollowedState { | |
optional string uri = 1; | |
optional string artist_name = 2 [default=""]; | |
optional string artist_cover_uri = 3 [default=""]; | |
optional int64 timestamp = 4; | |
} | |
message DeviceInformation { | |
optional string os = 1; | |
optional string type = 2; | |
} | |
message GenericPresenceState { | |
optional int32 type = 1; | |
optional int64 timestamp = 2; | |
optional string item_uri = 3; | |
optional string item_name = 4; | |
optional string item_image = 5; | |
optional string context_uri = 6; | |
optional string context_name = 7; | |
optional string context_image = 8; | |
optional string referrer_uri = 9; | |
optional string referrer_name = 10; | |
optional string referrer_image = 11; | |
optional string message = 12; | |
optional DeviceInformation device_information = 13; | |
} | |
message State { | |
optional int64 timestamp = 1; | |
enum Type { | |
PLAYLIST_PUBLISHED = 1; | |
PLAYLIST_TRACK_ADDED = 2; | |
TRACK_FINISHED_PLAYING = 3; | |
FAVORITE_APP_ADDED = 4; | |
TRACK_STARTED_PLAYING = 5; | |
URI_SHARED = 6; | |
ARTIST_FOLLOWED = 7; | |
GENERIC = 11; | |
} | |
optional Type type = 2; | |
optional string uri = 3; | |
optional PlaylistPublishedState playlist_published = 4; | |
optional PlaylistTrackAddedState playlist_track_added = 5; | |
optional TrackFinishedPlayingState track_finished_playing = 6; | |
optional FavoriteAppAddedState favorite_app_added = 7; | |
optional TrackStartedPlayingState track_started_playing = 8; | |
optional UriSharedState uri_shared = 9; | |
optional ArtistFollowedState artist_followed = 10; | |
optional GenericPresenceState generic = 11; | |
} | |
message StateList { | |
repeated State states = 1; | |
} | |
]]> | |
</presence> | |
<socialgraph><![CDATA[ | |
package spotify.socialgraph.proto; | |
message CountReply { | |
repeated int32 counts = 1; | |
} | |
message UserListRequest { | |
optional string last_result = 1; | |
optional int32 count = 2; | |
optional bool include_length = 3; | |
} | |
message UserListReply { | |
repeated User users = 1; | |
optional int32 length = 2; | |
} | |
message User { | |
optional string username = 1; | |
optional int32 subscriber_count = 2; | |
optional int32 subscription_count = 3; | |
} | |
message ArtistListReply { | |
repeated Artist artists = 1; | |
} | |
message Artist { | |
optional string artistid = 1; | |
optional int32 subscriber_count = 2; | |
} | |
message StringListRequest { | |
repeated string args = 1; | |
} | |
message StringListReply { | |
repeated string reply = 1; | |
} | |
message TopPlaylistsRequest { | |
optional string username = 1; | |
optional int32 count = 2; | |
} | |
message TopPlaylistsReply { | |
repeated string uris = 1; | |
} | |
]]> | |
</socialgraph> | |
<facebook><![CDATA[ | |
message Credential { | |
optional string facebook_uid = 1; | |
optional string access_token = 2; | |
} | |
message EnableRequest { | |
optional Credential credential = 1; | |
} | |
message EnableReply { | |
optional Credential credential = 1; | |
} | |
message DisableRequest { | |
optional Credential credential = 1; | |
} | |
message RevokeRequest { | |
optional Credential credential = 1; | |
} | |
message InspectCredentialRequest { | |
optional Credential credential = 1; | |
} | |
message InspectCredentialReply { | |
optional Credential alternative_credential = 1; | |
optional bool app_user = 2; | |
optional bool permanent_error = 3; | |
optional bool transient_error = 4; | |
} | |
message UserState { | |
optional Credential credential = 1; | |
} | |
message UpdateUserStateRequest { | |
optional Credential credential = 1; | |
} | |
message OpenGraphError { | |
repeated string permanent = 1; | |
repeated string invalid_token = 2; | |
repeated string retries = 3; | |
} | |
message OpenGraphScrobble { | |
optional int32 create_delay = 1; | |
} | |
message OpenGraphConfig { | |
optional OpenGraphError error = 1; | |
optional OpenGraphScrobble scrobble = 2; | |
} | |
message AuthConfig { | |
optional string url = 1; | |
repeated string permissions = 2; | |
repeated string blacklist = 3; | |
repeated string whitelist = 4; | |
repeated string cancel = 5; | |
} | |
message ConfigReply { | |
optional string domain = 1 [default = 'facebook.com']; | |
optional string app_id = 2 [default = '174829003346']; | |
optional string app_namespace = 3 [default = 'get-spotify']; | |
optional AuthConfig auth = 4; | |
optional OpenGraphConfig og = 5; | |
} | |
message UserFields { | |
optional bool app_user = 1; | |
optional bool display_name = 2; | |
optional bool first_name = 3; | |
optional bool middle_name = 4; | |
optional bool last_name = 5; | |
optional bool picture_large = 6; | |
optional bool picture_square = 7; | |
optional bool gender = 8; | |
optional bool email = 9; | |
} | |
message UserOptions { | |
optional bool cache_is_king = 1 [default = true]; | |
} | |
message UserRequest { | |
optional UserOptions options = 1; | |
optional UserFields fields = 2; | |
} | |
message User { | |
optional string spotify_username = 1; | |
optional string facebook_uid = 2; | |
optional bool app_user = 3; | |
optional string display_name = 4; | |
optional string first_name = 5; | |
optional string middle_name = 6; | |
optional string last_name = 7; | |
optional string picture_large = 8; | |
optional string picture_square = 9; | |
optional string gender = 10; | |
optional string email = 11; | |
} | |
message FriendsFields { | |
optional bool app_user = 1; | |
optional bool display_name = 2; | |
optional bool picture_large = 6; | |
} | |
message FriendsOptions { | |
optional int32 limit = 1; | |
optional int32 offset = 2; | |
optional bool cache_is_king = 3 [default = true]; | |
optional bool app_friends = 4 [default = true]; | |
optional bool non_app_friends = 5 [default = true]; | |
} | |
message FriendsRequest { | |
optional FriendsOptions options = 1; | |
optional FriendsFields fields = 2; | |
} | |
message FriendsReply { | |
repeated User friends = 1; | |
optional bool more = 2; | |
} | |
message ShareRequest { | |
optional Credential credential = 1; | |
optional string uri = 2; | |
optional string message_text = 3; | |
} | |
message ShareReply { | |
optional string post_id = 1; | |
} | |
message InboxRequest { | |
optional Credential credential = 1; | |
repeated string facebook_uids = 3; | |
optional string message_text = 4; | |
optional string message_link = 5; | |
} | |
message InboxReply { | |
optional string message_id = 1; | |
optional string thread_id = 2; | |
} | |
message PermissionsOptions { | |
optional bool cache_is_king = 1 [default = true]; | |
} | |
message PermissionsRequest { | |
optional Credential credential = 1; | |
optional PermissionsOptions options = 2; | |
} | |
message PermissionsReply { | |
repeated string permissions = 1; | |
} | |
message GrantPermissionsRequest { | |
optional Credential credential = 1; | |
repeated string permissions = 2; | |
} | |
message GrantPermissionsReply { | |
repeated string granted = 1; | |
repeated string failed = 2; | |
} | |
message TransferRequest { | |
optional Credential credential = 1; | |
optional string source_username = 2; | |
optional string target_username = 3; | |
} | |
]]> | |
</facebook> | |
<collection2><![CDATA[ | |
package spotify.collection2.proto; | |
option java_package = "com.spotify.collection2.proto"; | |
message CollectionItem { | |
enum Type { | |
TRACK = 0; | |
ALBUM = 1; | |
LOCAL_TRACK = 2; | |
} | |
optional Type type = 1; | |
optional bytes identifier = 2; | |
optional int32 starred_at = 3; | |
optional bool unheard = 4; | |
optional int32 added_at = 5; | |
optional bool removed = 6; | |
} | |
message CollectionItems { | |
repeated CollectionItem item = 1; | |
} | |
]]> | |
</collection2> | |
<collection2cache><![CDATA[ | |
package spotify.collection2cache.proto; | |
option java_package = "com.spotify.collection2cache.proto"; | |
message PlaylistOccurrence { | |
optional bytes identifier = 1; | |
optional bytes revision = 2; | |
optional int32 count = 3 [default = 1]; | |
} | |
message CollectionTrack { | |
optional bytes identifier = 1; | |
optional string name = 2; | |
optional bool in_collection = 3; | |
repeated PlaylistOccurrence playlists = 4; | |
optional int32 added_at = 5; | |
} | |
message CollectionAlbum { | |
optional bytes identifier = 1; | |
optional int32 track_count = 2; | |
optional string name = 3; | |
repeated string artist_names = 4; | |
} | |
message CollectionArtist { | |
optional bytes identifier = 1; | |
optional int32 track_count = 2; | |
optional string name = 3; | |
} | |
message CollectionTracks { | |
repeated CollectionTrack track = 1; | |
} | |
message CollectionAlbums { | |
repeated CollectionAlbum album = 1; | |
} | |
message CollectionArtists { | |
repeated CollectionArtist artist = 1; | |
} | |
]]> | |
</collection2cache> | |
<radio><![CDATA[ | |
package spotify.radio.proto; | |
message RadioRequest { | |
repeated string uris = 1; | |
optional int32 salt = 2; | |
optional int32 length = 4; | |
optional string stationId = 5; | |
repeated string lastTracks = 6; | |
} | |
message MultiSeedRequest { | |
repeated string uris = 1; | |
} | |
message Feedback { | |
optional string uri = 1; | |
optional string type = 2; | |
optional double timestamp = 3; | |
} | |
message Tracks { | |
repeated string gids = 1; | |
optional string source = 2; | |
optional string identity = 3; | |
repeated string tokens = 4; | |
repeated Feedback feedback = 5; | |
} | |
message Station { | |
optional string id = 1; | |
optional string title = 2; | |
optional string titleUri = 3; | |
optional string subtitle = 4; | |
optional string subtitleUri = 5; | |
optional string imageUri = 6; | |
optional double lastListen = 7; | |
repeated string seeds = 8; | |
optional int32 thumbsUp = 9; | |
optional int32 thumbsDown = 10; | |
} | |
message Rules { | |
optional string js = 1; | |
} | |
message StationResponse { | |
optional Station station = 1; | |
repeated Feedback feedback = 2; | |
} | |
message StationList { | |
repeated Station stations = 1; | |
} | |
message LikedPlaylist { | |
optional string uri = 1; | |
} | |
]]> | |
</radio> | |
<mergedprofile><![CDATA[ | |
message MergedProfileRequest { | |
} | |
message MergedProfileReply { | |
optional string username = 1; | |
optional string artistid = 2; | |
} | |
]]> | |
</mergedprofile> | |
<facebook-publish><![CDATA[ | |
message EventReply { | |
optional int32 queued = 1; | |
optional RetryInfo retry = 2; | |
} | |
message RetryInfo { | |
optional int32 retry_delay = 1; | |
optional int32 max_retry = 2; | |
} | |
message Id { | |
optional string uri = 1; | |
optional int64 start_time = 2; | |
} | |
message Start { | |
optional int32 length = 1; | |
optional string context_uri = 2; | |
optional int64 end_time = 3; | |
} | |
message Seek { | |
optional int64 end_time = 1; | |
} | |
message Pause { | |
optional int32 seconds_played = 1; | |
optional int64 end_time = 2; | |
} | |
message Resume { | |
optional int32 seconds_played = 1; | |
optional int64 end_time = 2; | |
} | |
message End { | |
optional int32 seconds_played = 1; | |
optional int64 end_time = 2; | |
} | |
message Event { | |
optional Id id = 1; | |
optional Start start = 2; | |
optional Seek seek = 3; | |
optional Pause pause = 4; | |
optional Resume resume = 5; | |
optional End end = 6; | |
} | |
]]> | |
</facebook-publish> | |
</services> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* https://spapps.spotify.edgekey.net/radio/692f491/scripts/main.js | |
* | |
* 15/12/2012 | |
*/ | |
(function (B, r) { | |
_unrequire("scripts/imageCarousel", [], function (l) { | |
l.ImageCarousel = function (l, e, n, j) { | |
function i() { | |
d.setStyle("width", g * (k + 2 * h) + "px") | |
} | |
var k = 120, | |
h = 12, | |
c = 4, | |
a = null, | |
d = null, | |
g = 0, | |
f = 0, | |
b = this; | |
this.addItem = function (b, a, f, e, w, z) { | |
var u = document.createElement("li"), | |
p = document.createElement("a"); | |
B.defer(this, function () { | |
j.loadImgAsync(p, a, b, 120, z); | |
p.addClass("image-cover"); | |
p.addClass(z); | |
p.addClass(w); | |
p.href = b.replace("spotify:", "spotify:radio:").decodeForLink().toSpotifyURL(); | |
p.setStyle("display", "block"); | |
var o = document.createElement("div"); | |
o.setStyle("backgroundImage", "url(img/radio-btn.png)"); | |
o.addClass("imageHover"); | |
p.adopt(o); | |
u.adopt(p); | |
o = document.createElement("div"); | |
o.addClass("imageCarouselTitle"); | |
u.adopt(o); | |
var s = document.createElement("a"); | |
s.set("html", f.name.decodeForHtml()); | |
s.set("href", f.link.decodeForLink().toSpotifyURL()); | |
s.set("title", f.name.decodeForHtml()); | |
s.addClass("main outgoing"); | |
if (f.link == "") s.style.pointerEvents = "none", s.style.cursor = "default"; | |
o.adopt(s); | |
o.adopt(document.createElement("br")); | |
for (s = 0; s < e.length; s++) { | |
var m = e[s], | |
A = document.createElement("a"); | |
A.addClass("outgoing"); | |
A.set("html", m.name.decodeForHtml()); | |
A.set("href", m.link.decodeForLink().toSpotifyURL()); | |
o.adopt(A); | |
o.adopt(document.createElement("br")) | |
} | |
u.setStyle("paddingLeft", u.style.paddingRight = h + "px"); | |
d.adopt(u); | |
g++; | |
g > c && $$(".imageCarouselNext").removeClass("disabled"); | |
i() | |
}) | |
}; | |
this.scrollTo = function (b) { | |
function t(b, d) { | |
var f = a.getElement(b); | |
d ? f.addClass("disabled") : f.removeClass("disabled") | |
} | |
b > g - c && (b = g - c); | |
b < 0 && (b = 0); | |
t(".imageCarouselPrev", | |
b == 0); | |
t(".imageCarouselNext", b >= g - c); | |
d.setStyle("marginLeft", "-" + b * (k + 2 * h) + "px"); | |
f = b | |
}; | |
this.clear = function () { | |
for (var b = d.getElements("li"), a = 0; a < b.length; a++) d.removeChild(b[a]); | |
g = 0 | |
}; | |
this.handleResize = function () { | |
var d = a.getWidth(); | |
c = Math.floor(d / (k + 24)); | |
h = Math.floor((d / c - k) / 2); | |
for (var g = a.getElements("li"), e = 0; e < g.length; e++) g[e].style.paddingLeft = g[e].style.paddingRight = h + "px"; | |
a.getElement(".imageCarouselTitle").style.paddingLeft = h + "px"; | |
a.getElement(".imageCarouselTitle").style.width = d - 2 * h - 50 + "px"; | |
a.getElement(".imageCarouselPagination").style.paddingRight = h + "px"; | |
i(); | |
b.scrollTo(f) | |
}; | |
window.addEventListener("resize", b.handleResize); | |
(function () { | |
a = document.createElement("div"); | |
a.addClass("imageCarouselWrapper"); | |
$$(l).adopt(a); | |
var g = document.createElement("h2"); | |
g.addClass("imageCarouselTitle"); | |
g.set("html", e); | |
a.adopt(g); | |
g = document.createElement("div"); | |
g.addClass("imageCarouselPagination"); | |
a.adopt(g); | |
var t = document.createElement("div"); | |
t.addClass("imageCarouselPrev disabled"); | |
g.adopt(t); | |
var x = document.createElement("div"); | |
x.addClass("imageCarouselNext disabled"); | |
g.adopt(x); | |
t.addEventListener("click", function () { | |
b.scrollTo(f - c) | |
}); | |
x.addEventListener("click", function () { | |
b.scrollTo(f + c) | |
}); | |
g = document.createElement("div"); | |
g.addClass("imageCarousel"); | |
a.adopt(g); | |
d = document.createElement("ul"); | |
g.adopt(d); | |
b.handleResize(); | |
setTimeout(function () { | |
b.handleResize() | |
}, 1E3) | |
})() | |
} | |
}); | |
_unrequire("scripts/util", [], function (l) { | |
function q(a, d, g, f, b, c) { | |
b = { | |
height: b, | |
width: b | |
}; | |
if (g === "genre") f = d, b.placeholder = "artist"; | |
if (c && (c === "recent" || c === "header")) b.style = | |
"embossed"; | |
d = new j(f, b); | |
a.appendChild(d.node) | |
} | |
var e, n, j; | |
l.init = function (a, d, g) { | |
e = a; | |
n = d; | |
j = g | |
}; | |
l.loadImgAsync = function (a, d, g, f, b) { | |
var c; | |
if (g.indexOf("spotify:track:") === 0) c = e.Track.fromURI(g); | |
else if (g.indexOf("spotify:album:") == 0) c = e.Album.fromURI(g); | |
else if (g.indexOf("spotify:artist:") === 0) c = e.Artist.fromURI(g); | |
else if (g.indexOf("spotify:user:") == 0) c = e.Playlist.fromURI(g); | |
else if (g.indexOf("spotify:genre:") === 0) { | |
(d = k(g)) && d.type && q(a, d[d.type].image, d.type, d.item, f, b); | |
return | |
} | |
q(a, null, "not-genre", c, | |
f, b) | |
}; | |
l.buildPlaylistMosaic = function (a, d) { | |
var g = a.split("/"), | |
g = g[g.length - 1].match(/.{1,40}/g); | |
g.length === 4 ? d("spotify:mosaic:" + g[0] + ":" + g[1] + ":" + g[2] + ":" + g[3]) : d("spotify:mosaic:" + g[0]) | |
}; | |
var i = l.getTrackMetaData = function (a, d, g) { | |
var f = {}, b = ["name", "uri"].concat(["album", "artists"]); | |
f.track = {}; | |
f.album = {}; | |
f.artist = {}; | |
f.type = "track"; | |
f.seed = a.uri; | |
g && b.push("image"); | |
a.load(b).done(function (a) { | |
b.each(function (b) { | |
f.track[b] = a[b] | |
}); | |
f.artist.name = a.artists[0].name; | |
f.artist.uri = a.artists[0].uri; | |
f.album.name = a.album.name; | |
f.album.uri = a.album.uri; | |
if (g) f.album.image = a.image; | |
f.item = a; | |
d(f) | |
}).fail(function (b) { | |
h.error("error loading track data: ", b); | |
d() | |
}) | |
}, k = function (a) { | |
var d = { | |
type: "genre", | |
genre: {} | |
}; | |
d.seed = a; | |
var g = a.replace("spotify:genre:", ""); | |
if (g in n) d.genre.name = n[g][0], d.genre.mosaic = n[g][2], d.genre.uri = a, d.genre.image = "img/genre-images/genre-" + g + ".jpg"; | |
return d | |
}; | |
l.getSeedMetadata = function (a, d, g, f) { | |
var b = {}, c = ["name", "uri"], | |
t = g || 300; | |
b.artist = {}; | |
b.playlist = {}; | |
b.album = {}; | |
b.seed = a; | |
f && c.push("image"); | |
g = c.concat(["artists"]); | |
a.indexOf("spotify:track:") === 0 ? i(e.Track.fromURI(a), d, f) : a.indexOf("spotify:album:") == 0 ? (b.type = "album", e.Album.fromURI(a).load(g).done(function (a) { | |
a.artists[0].load(c).done(function (g) { | |
c.forEach(function (d) { | |
b.album[d] = a[d]; | |
b.artist[d] = g[d] | |
}); | |
b.item = a; | |
if (f) b.image = a.imageForSize(t); | |
d(b) | |
}).fail(function (b) { | |
h.error("problem getting artist data: ", b); | |
d() | |
}) | |
}).fail(function (b) { | |
h.error("problem getting album data: ", b); | |
d() | |
})) : a.indexOf("spotify:artist:") === 0 ? (b.type = "artist", e.Artist.fromURI(a).load(c).done(function (a) { | |
c.forEach(function (d) { | |
b.artist[d] = a[d] | |
}); | |
b.item = a; | |
if (f) b.image = a.imageForSize(t); | |
d(b) | |
}).fail(function (b) { | |
h.error("problem getting artist data: ", b); | |
d() | |
})) : a.indexOf("spotify:user:") == 0 ? (b.type = "playlist", e.Playlist.fromURI(a).load(c).done(function (a) { | |
c.forEach(function (d) { | |
b.playlist[d] = a[d] | |
}); | |
b.item = a; | |
if (f) b.image = a.imageForSize(t); | |
d(b) | |
}).fail(function (b) { | |
h.error("problem getting playlist data: ", b); | |
d() | |
})) : a.indexOf("spotify:genre:") === 0 && d(k(a)) | |
}; | |
l.getTopTracks = function (a, d, g) { | |
var a = a.toArray(), | |
f = [], | |
b = [], | |
e = c("top tracks"); | |
a.each(function (a) { | |
b.push(a.load(["name", | |
"uri", "image", "album", "artists"])) | |
}); | |
d.join(b).done(function (b) { | |
e.stop(); | |
b ? b.each(function (a, d) { | |
a.artists[0].load("name").done(function () { | |
var c = { | |
type: "track" | |
}; | |
c.name = a.name; | |
c.uri = a.uri; | |
c.albumUri = a.album.uri; | |
c.image = a.image; | |
c.item = a; | |
c.subtitles = [{ | |
name: a.artists[0].name, | |
link: a.artists[0].uri | |
}]; | |
f.push(c); | |
d === b.length - 1 && g(f) | |
}).fail(function () { | |
h.error("failed to load artist name") | |
}) | |
}) : g([]) | |
}).fail(function (b, a) { | |
h.error("failed to load all promises: ", b, a); | |
g(f) | |
}) | |
}; | |
l.getTopArtists = function (a, d, g) { | |
var f = [], | |
b = [], | |
e; | |
a.toArray().each(function (a) { | |
b.push(a.load(["name", "image"])) | |
}); | |
e = c("top artists"); | |
d.join(b).done(function (b) { | |
e.stop(); | |
b ? (b.each(function (b) { | |
var a = { | |
type: "artist" | |
}; | |
a.name = b.name; | |
a.uri = b.uri; | |
a.image = b.image; | |
a.subtitles = []; | |
a.item = b; | |
f.push(a) | |
}), g(f)) : g([]) | |
}).fail(function (b, a) { | |
h.error("failed to load all promises: ", b, a); | |
g(f) | |
}) | |
}; | |
l.Buffer = function (a) { | |
var d = {}, c = []; | |
d.add = function (d) { | |
d.forEach ? d.forEach(function (b) { | |
c.length === a && c.shift(); | |
c.push(b) | |
}) : h.error(d, " does not appear to be an array") | |
}; | |
d.getItems = function () { | |
return c.concat() | |
}; | |
d.clear = function () { | |
c = [] | |
}; | |
return d | |
}; | |
var h = l.console = function () { | |
var a = "log", | |
d = !1, | |
c = function () { | |
d && window.console && window.console[a] && window.console[a].apply && window.console[a].apply(window.console, ["[RADIO] ", arguments]) | |
}, f = {}; | |
["log", "info", "warn", "error", "debug"].forEach(function (b) { | |
f[b] = function () { | |
a = b; | |
c.apply(this, arguments) | |
} | |
}); | |
f.enable = function () { | |
d = !0 | |
}; | |
return f | |
}(), | |
c = l.Timer = function (a) { | |
var d = {}; | |
d.name = a; | |
d.start = (new Date).getTime(); | |
d.stop = function () { | |
d.end = (new Date).getTime(); | |
d.result = d.end - d.start; | |
h.log(a + " timer = " + d.result); | |
return d.result | |
}; | |
return d | |
} | |
}); | |
_unrequire("scripts/strings.json", [], function (l) { | |
l.strings = { | |
by: "by", | |
"Not Available": "Radio is not available while offline", | |
"Please Connect": "You must connect to a Wi-Fi or cellular data network to access Radio", | |
"Current Station": "Current <span>Station</span>", | |
"Current album station": "Album Radio based on", | |
"Current artist station": "Artist Radio based on", | |
"Current genre station": "Genre Radio for", | |
"Current playlist station": "Playlist Radio for", | |
"Current track station": "Track Radio based on", | |
genres: { | |
"60s": "60s", | |
"70s": "70s", | |
"80s": "80s", | |
"90s": "90s", | |
Alternative: "Alternative", | |
"Black Metal": "Black Metal", | |
Blues: "Blues", | |
Classical: "Classical", | |
"Club/House": "Club/House", | |
Country: "Country", | |
"Death Metal": "Death Metal", | |
Electronic: "Electronic", | |
Emo: "Emo", | |
Folk: "Folk", | |
Hardcore: "Hardcore", | |
"Heavy Metal": "Heavy Metal", | |
"Hip-Hop": "Hip-Hop", | |
Indie: "Indie", | |
Jazz: "Jazz", | |
Latin: "Latin", | |
Pop: "Pop", | |
Punk: "Punk", | |
"R&B": "R&B", | |
Reggae: "Reggae", | |
Rock: "Rock", | |
"Singer-Songwriter": "Singer-Songwriter", | |
Soul: "Soul", | |
Trance: "Trance" | |
}, | |
Loading: "Loading...", | |
"Missing station": "<strong>Sorry. This radio station cannot be started.</strong><br/>Please try with something else.", | |
"Popular Genre Stations": "Popular Genre <span>Stations</span>", | |
"Popular Stations": "Popular <span>Stations</span>", | |
"Recent Stations": "Recent <span>Stations</span>", | |
"Search prompt": "Search for music to create a new station...", | |
"Create prompt": "Create new station...", | |
"Your Top Albums Stations": "Your Top Albums <span>Stations</span>", | |
"Your Top Artists Stations": "Your Top Artists <span>Stations</span>", | |
"Your Top Tracks Stations": "Your Top Tracks <span>Stations</span>" | |
} | |
}); | |
_unrequire("scripts/eventhandler", [], function (l) { | |
function q(e) { | |
this.handler_ = e || null; | |
this.listeners_ = [] | |
} | |
function e(e, j, i, k) { | |
this.src = e; | |
this.type = j; | |
this.originalListener = i; | |
this.listener = k ? i.bind(k) : i | |
} | |
q.prototype.listen = function (n, j, i) { | |
n = new e(n, j, i, this.handler_); | |
this.listeners_.push(n); | |
n.listen(); | |
return this | |
}; | |
q.prototype.unlisten = function (e, j, i) { | |
for (var k = this.listeners_, h = 0; h < k.length; h++) { | |
var c = k[h]; | |
if (c.src === e && c.type === j && c.originalListener === i) { | |
c.unlisten(); | |
k.splice(h, 1); | |
break | |
} | |
} | |
return this | |
}; | |
q.prototype.removeAll = function () { | |
for (var e = this.listeners_, j = 0; j < e.length; j++) e[j].unlisten(); | |
e.splice(0) | |
}; | |
e.prototype.listen = function () { | |
this.src.addEventListener(this.type, this.listener) | |
}; | |
e.prototype.unlisten = function () { | |
this.src.removeEventListener(this.type, this.listener) | |
}; | |
l.EventHandler = q | |
}); | |
_unrequire("scripts/cloud", [], function (l) { | |
l.Cloud = function (l, e) { | |
function n() { | |
var k = j.getWidth()[0]; | |
j.getFirst().dispose(); | |
var h = new Element("ul"); | |
h.className = "cloudLine"; | |
j.adopt(h); | |
for (var c = 0, a = 0; a < e.length; a++) c + i[a] > k ? (h.style.width = c + "px", h = document.createElement("ul"), h.className = "cloudLine", j.adopt(h), c = i[a]) : c += i[a], h.appendChild(e[a]); | |
h.style.width = c + "px" | |
} | |
var j = null, | |
i = []; | |
window.addEventListener("resize", n); | |
(function () { | |
j = $$(l); | |
var k = new Element("ul"); | |
j.adopt(k); | |
for (var h = 0; h < e.length; h++) { | |
var c = e[h]; | |
k.adopt(c); | |
i.push(c.getWidth() + 25) | |
} | |
j.adopt(k); | |
n() | |
})() | |
} | |
}); | |
_unrequire("scripts/ui", ["$api/models"], function (l) { | |
(function (q) { | |
function e(w, e, u, p) { | |
b = this; | |
this.thumbUp = this.thumbDown = this.stationLoaded = !1; | |
f.call(b); | |
i = $$(h)[0]; | |
k = w; | |
a = new u.EventHandler(d); | |
d = e; | |
v = d.util; | |
g = p; | |
var w = $$("#radio"), | |
e = $$("#hide-first-time"), | |
o = $$("#first-time"), | |
s = $$("#station-error"), | |
u = $$(c), | |
m = $$(".auto-completeForm"); | |
a.listen(w[0], "click", y).listen(window, "resize", x).listen(window, "beforeunload", j).listen(e[0], "click", function () { | |
o.setStyle("display", "none") | |
}).listen(s[0], | |
"click", function () { | |
s.setStyle("visibility", "hidden"); | |
window.clearTimeout(d._stationErrorTimeout) | |
}).listen(u[0], "click", function (a) { | |
m.getStyle("display")[0] === "block" ? b.hideAutocomplete() : b.showAutocomplete(); | |
a.stopPropagation() | |
}); | |
(new Image).src = "img/radio-btn.png"; | |
b.thumbsup = $$("#thumbsup"); | |
b.thumbsdown = $$("#thumbsdown"); | |
b.thumbsup.addEvent("click", function () { | |
!b.thumbsup.hasClass("selected")[0] && !b.thumbsup.hasClass("disabled")[0] && (b.dispatchEvent({ | |
type: "thumb", | |
thumbType: "up" | |
}), b.doThumbsup()) | |
}); | |
b.thumbsdown.addEvent("click", function () { | |
!b.thumbsdown.hasClass("selected")[0] && !b.thumbsdown.hasClass("disabled")[0] && (b.dispatchEvent({ | |
type: "thumb", | |
thumbType: "down" | |
}), b.doThumbsdown()) | |
}); | |
b.radioEl = w; | |
b.hideFirstTimeButton = e; | |
b.firstTimeEl = o; | |
b.stationErrEl = s; | |
b.createStationEl = u; | |
b.searchEl = m | |
} | |
function n(b) { | |
b = b.target; | |
getComputedStyle(b).opacity === "0" && b && b.parentNode.removeChild(b) | |
} | |
function j() { | |
a.removeAll() | |
} | |
var i, k, h = "#playing-covers", | |
c = "#create-station-handler", | |
a, d, g, f, b, v, t = []; | |
f = q.Observable; | |
e.prototype = new f; | |
e.prototype.disableThumbs = function () { | |
b.thumbsdown.addClass("disabled"); | |
b.thumbsup.addClass("disabled") | |
}; | |
e.prototype.enableThumbs = function () { | |
b.thumbsdown.removeClass("selected"); | |
b.thumbsup.removeClass("selected"); | |
b.thumbsdown.removeClass("disabled"); | |
b.thumbsup.removeClass("disabled"); | |
b.thumbDown = !1; | |
b.thumbUp = !1 | |
}; | |
e.prototype.resumeThumbs = function () { | |
b.thumbUp || b.thumbsdown.removeClass("disabled"); | |
b.thumbDown || b.thumbsup.removeClass("disabled") | |
}; | |
e.prototype.showFeedback = function (b) { | |
var a = $$(".improvingFeedback"), | |
d = $$(".improvingFeedbackCover"); | |
a.setStyle("display", "block"); | |
d.setStyle("display", "block"); | |
$$(".improvingFeedbackInfo").setStyle("display", "block"); | |
$$(".improvingFeedbackImg").setStyle("display", "block"); | |
$$(".improvingStation").setStyle("display", "block"); | |
t.push(setTimeout(function () { | |
b && ($$(".improvingStation").setStyle("display", "none"), $$(".addedToLiked").setStyle("display", "block")); | |
t.push(setTimeout(function () { | |
$$(".improvingFeedbackImg").setStyle("display", "none"); | |
$$(".improvingStation").setStyle("display", | |
"none"); | |
$$(".addedToLiked").setStyle("display", "none"); | |
$$(".doneImproving .improvingFeedbackImg").setStyle("display", "block"); | |
$$(".doneImproving").setStyle("display", "block"); | |
t.push(setTimeout(function () { | |
a.setStyle("display", "none"); | |
$$(".improvingFeedbackImg").setStyle("display", "none"); | |
$$(".doneImproving .improvingFeedbackImg").setStyle("display", "none"); | |
$$(".doneImproving").setStyle("display", "none") | |
}, 1E3)) | |
}, 2E3)) | |
}, 3E3)) | |
}; | |
e.prototype.resetFeedback = function () { | |
for (var b = $$(".improvingFeedback"), a = !1, d = 0, c = t.length; d < c; d++) a = !0, clearTimeout(t.shift()); | |
a && ($$(".improvingStation").setStyle("display", "none"), $$(".improvingFeedbackImg").setStyle("display", "none"), $$(".improvingStation").setStyle("display", "none"), $$(".addedToLiked").setStyle("display", "none"), b.setStyle("display", "none"), $$(".improvingFeedbackImg").setStyle("display", "none"), $$(".doneImproving .improvingFeedbackImg").setStyle("display", "none"), $$(".doneImproving").setStyle("display", "none")) | |
}; | |
e.prototype.displayThumbUp = function () { | |
b.thumbsdown.addClass("disabled"); | |
b.thumbsup.addClass("selected"); | |
b.thumbsup.removeClass("disabled"); | |
b.thumbsdown.removeClass("selected") | |
}; | |
e.prototype.doThumbsup = function () { | |
b.resetFeedback(); | |
b.displayThumbUp(); | |
b.thumbDown = !1; | |
b.thumbUp = !0; | |
setTimeout(function () { | |
b.showFeedback(!0) | |
}, 500) | |
}; | |
e.prototype.displayThumbDown = function () { | |
b.resetFeedback(); | |
b.thumbsdown.addClass("selected"); | |
b.thumbsup.removeClass("selected"); | |
b.thumbsup.addClass("disabled"); | |
b.thumbsdown.removeClass("disabled") | |
}; | |
e.prototype.doThumbsdown = function () { | |
b.displayThumbDown(); | |
b.thumbDown = !0; | |
b.thumbUp = !1 | |
}; | |
e.prototype.setStationHeader = function (b, a, d, c) { | |
var o = $$("#radio-seed"); | |
o.setStyle("display", "block"); | |
var f = o.getElement("span"); | |
f[0].empty(); | |
var m = document.createElement("div"); | |
m.addClass("img"); | |
m.addClass(d); | |
f.adopt(m); | |
v.loadImgAsync(m, b, c, 36, "header"); | |
o.getElement("h2").set("html", a) | |
}; | |
e.prototype.showAutocomplete = function () { | |
b.stationErrEl.setStyle("visibility", "hidden"); | |
b._showingAutocomplete = !0; | |
this.dispatchEvent("show-search") | |
}; | |
e.prototype.hideAutocomplete = function () { | |
b._showingAutocomplete = !1; | |
this.dispatchEvent("hide-search") | |
}; | |
e.prototype.showLoadingScreen = function () { | |
b.stationErrEl.setStyle("visibility", "hidden"); | |
$$("#loading-throbber").setStyle("display", "block"); | |
$$("#loading").setStyle("display", "block"); | |
var a = $$("#playButton"); | |
a != null && a.setStyle("display", "none"); | |
$$("#playing-speaker").setStyle("display", "none"); | |
$$("#playing-skip>a").setStyle("display", "none") | |
}; | |
e.prototype.loadingStation = function () { | |
for (var b = window.pageYOffset, a = 1; b >= -100; b -= 100, ++a) setTimeout("window.scrollTo(window.pageXOffset, " + Math.max(b, 0) + ")", 10 * a); | |
this.stationLoading = !0; | |
this.disableThumbs(); | |
this.showLoadingScreen() | |
}; | |
e.prototype.hideLoadingScreen = function () { | |
$$("#loading").setStyle("display", "none"); | |
$$("#loading-throbber").setStyle("display", "none") | |
}; | |
e.prototype.hideAppLoadingScreen = function () { | |
$$("#app-loading").setStyle("display", "none"); | |
$$("#app-loading-throbber").setStyle("display", "none") | |
}; | |
e.prototype.fillTopList = function (b, a, c) { | |
var f = this; | |
setTimeout(function () { | |
f.hideAppLoadingScreen(); | |
if (typeof c === "undefined" || c.length === 0) $$(b).setStyle("display", "none"); | |
else { | |
for (var o = new g.ImageCarousel(b, a, d.enStrings, d.util), s = 0; s < c.length && s < 20; s++) { | |
var m = c[s]; | |
var e = m.image; | |
e && e.length > 0 && e.substr(e.lastIndexOf(":") + 1); | |
o.addItem(m.uri, m.image, { | |
name: m.name, | |
link: m.albumUri || m.uri | |
}, m.subtitles, m.type, "recommended") | |
} | |
o.scrollTo(0) | |
} | |
}, 25) | |
}; | |
e.prototype.fillGenres = function () { | |
function b(d, o) { | |
var c = document.createElement("li"), | |
m = document.createElement("button"); | |
m.className = "main"; | |
m.addClass("genre"); | |
m.href = ("spotify:radio:genre:" + o).toSpotifyURL(); | |
var f = document.createElement("span"); | |
f.className = "genre-image"; | |
var g = document.createElement("span"); | |
g.className = "genre-text"; | |
g.innerHTML = d; | |
m.appendChild(f); | |
m.appendChild(g); | |
c.appendChild(m); | |
a.push(c) | |
} | |
var a = [], | |
c; | |
for (c in d.genreDict) b(d.genreDict[c][0], c); | |
new k.Cloud("#genres>div", a) | |
}; | |
e.prototype.fillRecentStationList = function (a) { | |
setTimeout(function () { | |
var c = d._recent, | |
f = $$("#recent"), | |
g, o; | |
c.imageCarousel.clear(); | |
if (!a || a.length <= 1) f.setStyle("display", "none"); | |
else { | |
for (var e = 1; e < 21 && e < a.length; e++) { | |
var m = a[e]; | |
if (typeof m === "object" && m.seeds) { | |
o = m.seeds[0]; | |
var v = {}, i = []; | |
if (o.indexOf("spotify:track") > -1) { | |
g = "track"; | |
var v = { | |
name: m.title, | |
link: m.titleUri | |
}, h = m.imageUri; | |
i.push({ | |
name: m.subtitle, | |
link: m.subtitleUri | |
}) | |
} else if (o.indexOf("spotify:album") > -1) g = "album", v = { | |
name: m.title, | |
link: m.titleUri | |
}, i.push({ | |
name: m.subtitle, | |
link: m.subtitleUri | |
}), h = m.imageUri; | |
else if (o.indexOf("spotify:artist") > -1) g = "artist", v = { | |
name: m.title, | |
link: m.titleUri | |
}, h = m.imageUri; | |
else if (o.indexOf("spotify:genre") > -1) g = "genre", v = { | |
name: m.title, | |
link: "" | |
}, h = "img/genre-images/genre-" + m.seeds[0].replace("spotify:genre:", "") + ".jpg"; | |
else if (o.indexOf("spotify:user") > -1) g = "playlist", v = { | |
name: m.title, | |
link: m.titleUri | |
}, h = m.imageUri; | |
h && c.imageCarousel.addItem(o, h, v, i, g, "recent") | |
} | |
} | |
f.setStyle("display", "block"); | |
c.imageCarousel.handleResize(); | |
c.imageCarousel.scrollTo(0); | |
b.hideAppLoadingScreen() | |
} | |
}, 50) | |
}; | |
e.prototype.rotateCovers = function (a) { | |
var c = i.getElement("li"), | |
f, a = a || this.track; | |
if (this.stationLoading && a) this.track = a; | |
else if (a) { | |
this.newItem ? (f = i.getElement("li"), | |
this.newItem = null) : (f = document.createElement("li"), c ? i.insertBefore(f, c) : i.insertBefore(f, null)); | |
d.ui.resetFeedback(); | |
c = a.image; | |
f.addEventListener("webkitTransitionEnd", n); | |
var g = document.createElement("span"); | |
g.id = "playButton"; | |
g.style.display = "none"; | |
(new Image).src = "img/play-button-XL.png"; | |
f.appendChild(g); | |
var o = document.createElement("a"); | |
o.href = a.uri.decodeForLink().toSpotifyURL(); | |
o.className = "outgoing"; | |
f.appendChild(o); | |
f.firstChild.title = a.name.decodeForHtml(); | |
var e = new Image; | |
e.onerror = function () { | |
e.src = | |
"img/300-album.png"; | |
e.onerror = function () {} | |
}; | |
e.onload = function () { | |
o.appendChild(e); | |
$$(e).addClass("imgCoverflow") | |
}; | |
e.src = c; | |
f = $$("#radio-track"); | |
c = $$("#radio-artist"); | |
$$("#radio-star"); | |
f.set("html", '<a class="outgoing" href="' + a.uri.decodeForLink().toSpotifyURL() + '">' + a.name.decodeForHtml() + "</a>"); | |
c.set("html", '<a class="outgoing" href="' + a.artists[0].uri.decodeForLink().toSpotifyURL() + '">' + a.artists[0].name.decodeForHtml() + "</a>"); | |
this.track = null; | |
b.addFeedbackElements(); | |
setTimeout(function () { | |
b.enableThumbs() | |
}, | |
500); | |
b.updatePlayPause(!1) | |
} else this.newItem = f = document.createElement("li"), i.insertBefore(f, null) | |
}; | |
e.prototype.addFeedbackElements = function () { | |
$$(".improvingFeedback").destroy(); | |
var a = $$("#playing-covers li:first-child"), | |
d = new Element("div.improvingFeedback"), | |
c = new Element("div.improvingFeedbackImg"), | |
f = new Element("div.text.improvingStation"), | |
o = new Element("div.improvingFeedbackCover"), | |
g = new Element("div.improvingFeedbackInfo"), | |
m = new Element("div.text.addedToLiked"), | |
e = new Element("div.text.doneImproving"), | |
v = new Element("div.improvingFeedbackImg"); | |
f.appendText("Improving Station..."); | |
m.set("html", "Added to playlist:<br>Liked from Radio"); | |
e.set("html", "<p>Done!</p>"); | |
d.adopt(o); | |
d.adopt(g); | |
g.adopt(c); | |
g.adopt(f); | |
g.adopt(m); | |
g.adopt(e); | |
e.adopt(v); | |
a.adopt(d); | |
b.thumbDown && setTimeout(function () { | |
b.showFeedback() | |
}, 250) | |
}; | |
e.prototype.playerStateChange = function (a, d) { | |
a === "playing" && (this.rotateCovers(d), b.updatePlayPause(!0)); | |
a === "resume" && b.updatePlayPause(!1) | |
}; | |
e.prototype.stationAvailable = function (b, a, c, f) { | |
var o = $$("#echonest"); | |
if (c) { | |
this.stationLoaded = !0; | |
this.stationLoading = !1; | |
$$("#playing-skip>a").setStyle("display", "block"); | |
b.indexOf("en") >= 0 && (o.setStyle("display", "block"), setTimeout(function () { | |
o.setStyle("display", "none") | |
}, 3E3)); | |
if (c.type === "track") { | |
var g = "<a class='outgoing' href='" + c.track.uri.decodeForLink().toSpotifyURL() + "'>" + c.track.name.decodeForHtml() + "</a>", | |
b = "<a class='outgoing' href='" + c.artist.uri.decodeForLink().toSpotifyURL() + "'>" + c.artist.name.decodeForHtml() + "</a>", | |
b = d._("<header>Current track station</header>") + g + " by " + b; | |
this.setStationHeader(c.album.image, b, c.type, a) | |
} else c.type === "artist" ? (b = "<a class='outgoing' href='" + c.artist.uri.decodeForLink().toSpotifyURL() + "'>" + c.artist.name.decodeForHtml() + "</a>", b = d._("<header>Current artist station</header>") + b, this.setStationHeader(c.artist.image, b, c.type, a)) : c.type === "album" ? (g = "<a class='outgoing' href='" + c.album.uri.decodeForLink().toSpotifyURL() + "'>" + c.album.name.decodeForHtml() + "</a>", b = "<a class='outgoing' href='" + c.artist.uri.decodeForLink().toSpotifyURL() + | |
"'>" + c.artist.name.decodeForHtml() + "</a>", b = d._("<header>Current album station</header>") + g + " by " + b, this.setStationHeader(c.album.image, b, c.type, a)) : c.type === "genre" ? (b = d._("<header>Current genre station</header>") + c.genre.name.decodeForHtml(), this.setStationHeader("img/genre-images/genre-" + c.genre.image + ".jpg", b, c.type, a)) : c.type === "playlist" && (b = "<a class='outgoing' href='" + c.playlist.uri.decodeForLink().toSpotifyURL() + "'>" + c.playlist.name.decodeForHtml() + "</a>", this.setStationHeader(c.playlist.image, | |
d._("<header>Current playlist station</header>") + b, c.type, a)); | |
i.empty(); | |
this.rotateCovers(); | |
this.hideLoadingScreen(); | |
this.updatePlayPause(f) | |
} else i.empty(), this.rotateCovers(), this.failedStation() | |
}; | |
var x = e.prototype.adjustHeaderWidth = function () { | |
var b = $$("#playing-header"), | |
a = $$("#radio-seed"), | |
c = $$("#right-header"), | |
b = b.getSize()[0].x - c.getSize()[0].x - 34 + "px"; | |
a.setStyle("width", b) | |
}, y = e.prototype.handleClick = function (a) { | |
b.stationErrEl.setStyle("visibility", "hidden"); | |
for (var c = a.target; c && c !== a.currentTarget; c = c.parentNode) if (c.tagName === "A" || c.tagName === "BUTTON") if (c.href && c.href.indexOf("spotify.com") > -1) { | |
if (c.className.indexOf("outgoing") === -1) { | |
a.preventDefault(); | |
for (a = c; a = a.parentNode;) if (a.tagName == "SECTION") break; | |
a = c.href.toSpotifyURI().replace("spotify:radio:", "spotify:"); | |
b.dispatchEvent({ | |
type: "start-station", | |
seed: a, | |
elClass: c.className | |
}) | |
} else a.preventDefault(), c = c.href.toSpotifyURI(), c.indexOf("spotify:track") > -1 && d._models.Track.fromURI(c).load("album").done(function (b) { | |
d._models.application.openURI(b.album.uri) | |
}).fail(function () {}), | |
d._models.application.openURI(c); | |
break | |
} else if (c.href === "radio:skip") { | |
if (a.preventDefault(), c.className.search("disabled") === -1) { | |
b.dispatchEvent("skip"); | |
break | |
} | |
} else { | |
if (c.href === "radio:play-pause") { | |
a.preventDefault(); | |
b.dispatchEvent("play-pause"); | |
break | |
} | |
} else if (c.id === "playButton") { | |
a.preventDefault(); | |
b.dispatchEvent("play-pause"); | |
break | |
} else b._showingAutocomplete && !c.hasClass("search") && b.hideAutocomplete() | |
}; | |
e.prototype.updatePlayPause = function (b) { | |
var a = $$("#playButton")[0], | |
c = $$("#playing-speaker"); | |
c.setStyle("display", "inline"); | |
if (a) b ? (a.className = "playing", c.className = "playing") : (a.className = "paused", c.className = "paused"), a.style.display === "none" && setTimeout(function () { | |
a.setStyle("display", "inline") | |
}, 100) | |
}; | |
e.prototype.firstTime = function () { | |
b.firstTimeEl.setStyle("display", "block") | |
}; | |
e.prototype.disableSkip = function () { | |
$$("#playing-skip>a").addClass("disabled") | |
}; | |
e.prototype.enableSkip = function () { | |
$$("#playing-skip>a").setStyle("display", "block"); | |
$$("#playing-skip>a").removeClass("disabled") | |
}; | |
e.prototype.enableControls = function () { | |
this.enableSkip(); | |
this.resumeThumbs(); | |
var b = $$("#playButton")[0]; | |
$$("#playing-speaker").setStyle("display", "inline"); | |
b.setStyle("display", "inline") | |
}; | |
e.prototype.failedStation = function () { | |
this.hideAppLoadingScreen(); | |
this.hideLoadingScreen(); | |
this.stationLoading = !1; | |
this.stationLoaded && this.enableControls(); | |
b.stationErrEl.setStyle("visibility", "visible") | |
}; | |
l.RadioUi = e | |
})(r["$api/models"]) | |
}); | |
_unrequire("scripts/station", ["$api/models"], function (l) { | |
(function (q) { | |
var e = null, | |
n, j, i = function (c, a) { | |
q.Observable.call(this); | |
this.id = a; | |
this._tracks = []; | |
this._radio = c; | |
this._models = c._models; | |
this.index = -2; | |
this._position = 0; | |
this._state = "loading"; | |
this._hermes = c.hermes.Hermes; | |
this._schema = c.schema; | |
this._temporaryPlaylist = this._posIntervalId = this._currentTrack = null; | |
this._recents = c.util.Buffer(200); | |
this.thumbed = !1; | |
this.feedback = {}; | |
n = c.util; | |
j = n.Timer | |
}; | |
i.models = q; | |
e = q.Observable; | |
i.prototype = new e; | |
i.prototype.playerStateChanged = function (c) { | |
try { | |
var a = this, | |
d = c.target; | |
a.player = d; | |
a._temporaryPlaylist && d.load(["playing", "position", "track", | |
"index", "context"]).done(function (c) { | |
var b = c.track, | |
d = c.context, | |
g = c.index; | |
if (d && d.uri === a._temporaryPlaylist.uri) if (c.playing && a._playing === !1) a._playing = !0, a.dispatchEvent("is-playing"); | |
else if (!c.playing && a._playing) a._playing = !1, a.dispatchEvent("paused"); | |
else if (c.position !== 0 && c.position === c.duration) a.dispatchEvent("track-end"); | |
else { | |
if (b && g > -1 && a.index !== g) a.dispatchEvent({ | |
type: "new-track", | |
track: b | |
}), a.index = g, a._currentTrack = b, a._recents.add([b.uri.replace("spotify:track:", "")]), a._position = 0, | |
a._temporaryPlaylist.sizeNeeded = Math.max(a.index + 40, 30), a._temporaryPlaylist.load(["tracks"]).done(function (b) { | |
a._refillAndPlayFirst(b.tracks, !1) | |
}).fail(function () {}) | |
} else a._playing = !1, a.dispatchEvent("leavingRadio") | |
}).fail(function () {}) | |
} catch (g) {} | |
}; | |
i.prototype._failedStation = function () { | |
this.dispatchEvent("failed-station") | |
}; | |
var k = function (c, a, d, g) { | |
try { | |
if (a._temporaryPlaylist) { | |
var f = 20, | |
b = a._tracks.length, | |
e = 0, | |
i, h = [], | |
k = a._firstFill, | |
n = 0, | |
l = 0, | |
q; | |
if (g) f = a._tracks.length; | |
for (var p = function (b, o) { | |
q = j("add to tmp playlist"); | |
d.snapshot().done(function (f) { | |
var m = a.index >= 0 ? a.index : 0, | |
e; | |
if (o || !a.thumbed) e = d.add(b); | |
if (a.thumbed) e = d.insert(f.ref(m), b), a.thumbed = !1; | |
e.done(function () { | |
q.stop(); | |
g || (a._temporaryPlaylist.size += b.length); | |
if (a._firstFill && a._startPlay === !1) a._currentTrack = b[0], a.dispatchEvent({ | |
type: "track-added", | |
track: b[0] | |
}), a._firstFill = !1; | |
a._firstFill = !1; | |
if (a._startPlay && c.getCurrentStation() === a && a._temporaryPlaylist.size > 0) a.dispatchEvent({ | |
type: "track-added", | |
track: b[0] | |
}), a.dispatchEvent({ | |
type: "start-playing", | |
playlist: a._temporaryPlaylist | |
}), | |
a._startPlay = !1; | |
g && d.snapshot().done(function (c) { | |
var o = m + b.length; | |
d.trim(c.ref(o)).done(function () { | |
a._temporaryPlaylist.size = o + 1 | |
}).fail(function () {}) | |
}) | |
}).fail(function () {}) | |
}).fail(function () {}) | |
}, o = []; b > 0;) { | |
var s = "spotify:track:" + a._tracks.shift(); | |
o.push(c._models.Track.fromURI(s).load("playable")); | |
e += 1; | |
b -= 1; | |
if (e >= f) break | |
} | |
i = j("load done"); | |
c._models.Promise.join(o).done(function () {}).fail(function () {}).always(function (b) { | |
i.stop(); | |
b.forEach(function (b) { | |
b.playable ? (k ? (k = !1, l = 1, p([b], !0)) : h.push(b), a._temporaryPlaylist.tracksCache.push(b)) : n += 1; | |
h.length === e - (n + l) && p(h) | |
}) | |
}) | |
} | |
} catch (m) {} | |
}; | |
i.prototype._refillAndPlayFirst = function (c, a, d) { | |
try { | |
var g = this._radio, | |
f = this; | |
f._startPlay = a; | |
if (d || !(f._temporaryPlaylist.size >= f._temporaryPlaylist.sizeNeeded)) if (!d && this._tracks.length > 5) k(g, f, c); | |
else if (d || this._tracks.length < f._temporaryPlaylist.sizeNeeded - f._temporaryPlaylist.size) a = 50, d && (a = f._temporaryPlaylist.size - f.index), f._hermesCall(f._actualSeed, f._recents.getItems(), a, function (b) { | |
try { | |
f._addTracksFromHermesResult(b[0]), k(g, f, c, d) | |
} catch (a) {} | |
}, | |
function () {}) | |
} catch (b) {} | |
}; | |
var h = function (c, a) { | |
c.feedback = c.feedback || {}; | |
a.forEach(function (a) { | |
c.feedback["spotify:track:" + a.uri] = a.type | |
}) | |
}; | |
i.prototype._hermesSuccess = function (c) { | |
try { | |
this.hermesTimer.stop(), c && c.length > 0 && c[0].gids && c[0].gids.length > 0 ? this._stationAvailable(c[0], this.originalSeed, this.newSeed, this._startPlay) : this._hermesFailure() | |
} catch (a) {} | |
}; | |
i.prototype._hermesFailure = function () { | |
var c = this; | |
c.hermesTimer.stop(); | |
try { | |
c.newSeed.indexOf("spotify:track") === 0 || c.newSeed.indexOf("spotify:album") === 0 ? c._radio.util.getSeedMetadata(c.newSeed, function (a) { | |
a && a.artist && a.artist.uri ? c._loadStationWithFallback(a.artist.uri, c._startPlay, c.originalSeed) : c._failedStation() | |
}, null, !1) : c._failedStation() | |
} catch (a) {} | |
}; | |
i.prototype._loadStationWithFallback = function (c, a, d) { | |
try { | |
c === null ? this._failedStation() : (this.newSeed = c, this.originalSeed = d, this.hermesTimer = j("hermes"), this._hermesCall(c, this._recents.getItems(), 20, this._hermesSuccess, this._hermesFailure)) | |
} catch (g) {} | |
}; | |
i.prototype.loadStation = function (c, a) { | |
try { | |
this.clickToPlayingTimer = j("click to playing"), this._currentTrack = {}, this._currentTrack.uri = "", this.seed = c, this._loading = !0, this._startPlay = a, this.loadStationTimer = j("load station"), this._loadStationWithFallback(c, a, c), this.index = -2, this._playing = !1 | |
} catch (d) {} | |
}; | |
i.prototype._addTracksFromHermesResult = function (c) { | |
try { | |
for (var a = 0, d = c.gids.length; a < d; a++) this._tracks.push(c.gids[a]); | |
c.feedback && c.feedback.length > 0 && h(this, c.feedback) | |
} catch (g) {} | |
}; | |
i.prototype._stationAvailable = function (c, a, d, g) { | |
try { | |
var f = this, | |
b = this._radio, | |
e = c.source; | |
f._firstFill = !0; | |
this.loadStationTimer.stop(); | |
this._actualSeed = d; | |
var h = j("create temp playlist"); | |
f.dispatchEvent({ | |
type: "stationAvailable", | |
trackSource: e, | |
originalSeed: a, | |
startPlay: g | |
}); | |
b._models.Playlist.createTemporary(a).done(function (b) { | |
h.stop(); | |
var a = j("enforce radio rules"); | |
b.enforceRules("radio").done(function (b) { | |
a.stop(); | |
var d = j("load temp playlist tracks collection"); | |
b.load(["tracks"]).done(function (b) { | |
d.stop(); | |
var a = b.tracks; | |
f._temporaryPlaylist = b; | |
f._temporaryPlaylist.tracksCache = []; | |
f._temporaryPlaylist.sizeNeeded = 5; | |
f._temporaryPlaylist.size = 0; | |
f._tracks = []; | |
f._addTracksFromHermesResult(c); | |
(function () { | |
try { | |
a.clear().done(function () { | |
f._refillAndPlayFirst(a, g) | |
}).fail(function () {}) | |
} catch (b) {} | |
})() | |
}).fail(function () { | |
f._failedStation() | |
}) | |
}).fail(function () { | |
f._failedStation() | |
}) | |
}).fail(function () { | |
f._failedStation() | |
}) | |
} catch (i) { | |
f._failedStation() | |
} | |
}; | |
i.prototype._hermesCall = function (c, a, d, g, f) { | |
var b = this, | |
e = function (a) { | |
g.call(b, a) | |
}, h = function (a) { | |
f.call(b, a) | |
}, i = b._radio, | |
j = { | |
salt: Math.floor(Math.random() * 1E6), | |
lastTracks: a, | |
length: d | |
}, | |
k = this._hermes.get("hm://radio/", [b._schema.type("Tracks")], [b._schema.type("RadioRequest")]); | |
if (b.id) j.stationId = b.id; | |
c.indexOf("spotify:user") === -1 ? (j.uris = [c], k.send(j).done(e).fail(h)) : i._models.Playlist.fromURI(c).load("tracks").done(function (b) { | |
b.tracks.snapshot(0, 250).done(function (b) { | |
for (var a = [], b = b.toArray(), c = b.length, d = 0; d < c; d++) { | |
var g = d + Math.floor(Math.random() * (c - d)), | |
f = b[g].uri; | |
if (f.substr(0, 14) !== "spotify:local:" && (a.push(f), a.length >= 50)) break; | |
b[g] = b[d]; | |
b[d] = f | |
} | |
j.uris = a; | |
k.send(j).done(e).fail(h) | |
}).fail(h) | |
}).fail(h) | |
}; | |
i.prototype._updatePlaylist = function () { | |
var c = this._temporaryPlaylist; | |
c.tracksCache = []; | |
this._tracks = []; | |
this.index === -2 && this._tracks.push(this._currentTrack.uri.replace("spotify:track:", "")); | |
this._refillAndPlayFirst(c.tracks, this._startPlay, !0) | |
}; | |
i.prototype.thumbEvent = function () { | |
this.thumbed = !0; | |
this._updatePlaylist() | |
}; | |
i.prototype.skipTrack = function (c) { | |
var a = this; | |
a._models.player.load(["context"]).done(function (d) { | |
d.context && d.context.uri === a._temporaryPlaylist.uri && d.skipToNextTrack().done(function () { | |
c && c() | |
}).fail(function () { | |
c && c() | |
}) | |
}).fail(function () {}) | |
}; | |
l.Station = i | |
})(r["$api/models"]) | |
}); | |
_unrequire("scripts/searchUtil", [], function (l) { | |
l.init = function () {}; | |
var q = l.setBg = function (e, n) { | |
var j = "url(" + e.target.src + ")", | |
i = n.getElementsByClassName("searchImg"), | |
i = $$(i); | |
i.setStyle("background-image", j); | |
i.removeClass("sp-image-placeholder-visible") | |
}; | |
l.decorate = function (e, n, j) { | |
var i = function () {}; | |
e === "tracks" && j.Track.fromURI(n.uri).load(["album", "artists"]).done(function (e) { | |
e.album.load("image").done(function (h) { | |
e.artists[0].load("name").done(function (c) { | |
var a = new Image; | |
a.onload = function (a) { | |
q(a, n) | |
}; | |
var d = h.imageForSize(60); | |
a.src = d; | |
n.innerHTML = n.innerHTML + " " + c.name.decodeForHtml() | |
}).fail(i) | |
}).fail(i) | |
}).fail(i); | |
e === "albums" && j.Album.fromURI(n.uri).load(["artists"]).done(function (e) { | |
e.artists.length < 1 || e.artists[0].load("name").done(function (e) { | |
n.innerHTML = n.innerHTML + " " + e.name.decodeForHtml() | |
}).fail(i) | |
}).fail(i) | |
}; | |
l.doSearch = function (e, n, j, i) { | |
function k(a, f, b, e) { | |
a[f].snapshot(0, d).done(function (b) { | |
var a = b.toArray(); | |
e && (a = e.concat(a)); | |
if (a.length < 1) j(null); | |
else { | |
for (var b = [], d = 0, g = a.length; d < g; d++) b.push(a[d].load(c)); | |
i.Promise.join(b).done(function () { | |
j(a, f, h) | |
}).fail(function () {}) | |
} | |
}).fail(function () {}) | |
} | |
var h = n, | |
c = ["name", "uri", "image"], | |
a = ["artists", "tracks", "albums"], | |
d = 3; | |
(function (c, d) { | |
for (var b = 0, e = a.length; b < e; b++) k(c, a[b], d) | |
})(e.suggest(n), "suggest") | |
}; | |
l.throttle = function (e, n) { | |
var j = null, | |
i = null; | |
return function () { | |
var k = arguments, | |
h = Date.now(), | |
c = h - (i || 0); | |
j && (clearTimeout(j), j = null); | |
c >= n ? (i = h, e.apply(e, k)) : j = setTimeout(function () { | |
i = h; | |
e.apply(e, k) | |
}, n - c) | |
} | |
} | |
}); | |
_unrequire("scripts/searchWidget", ["$api/search", "scripts/eventhandler", "scripts/searchUtil", "$api/models", "$api/models"], function (l) { | |
(function (q, e, n, j, i) { | |
function k() { | |
var b = this; | |
b.input = document.createElement("input"); | |
b.input.id = "autocompleteSearchWidget"; | |
b.input.addClass("search"); | |
b.node = document.createElement("div"); | |
b.node.className = "input token-input"; | |
b.node.appendChild(b.input); | |
h.listen(b.input, "input", function () { | |
b.input.value.length > 0 ? b.input.value.indexOf("spotify:") > -1 ? (c.dispatchEvent({ | |
type: "open-uri", | |
seed: b.input.value, | |
elClass: "searchPaste" | |
}), c.hide(), b.input.value = "") : b.searchHandler(b.input.value, function (a, c, d) { | |
a !== null && d && b.input.value === d && b.addTokens(a, c) | |
}) : c.setInitialResults() | |
}).listen(b.input, "focus", function () { | |
$$(b.node).addClass("focus") | |
}).listen(b.input, "blur", function () { | |
$$(b.node).removeClass("focus") | |
}) | |
} | |
var h = new e.EventHandler(f), | |
c, a, d = ["artists", "albums", "tracks"], | |
g = function (b) { | |
for (var a = b.target; a;) { | |
if (a.tagName !== "A" && a.hasClass("search")) { | |
b.preventDefault(); | |
b.stopPropagation(); | |
c.show(); | |
break | |
} else if (a.tagName === "A") { | |
b.preventDefault(); | |
b.stopPropagation(); | |
b = a.href.toSpotifyURI().replace("spotify:radio:", "spotify:"); | |
c.dispatchEvent({ | |
type: "open-uri", | |
seed: b, | |
elClass: a.className | |
}); | |
c.hide(); | |
break | |
} | |
a = a.parentNode | |
} | |
}, f = function (b, d) { | |
j.call(this); | |
this.widgetContainer = b[0]; | |
a = d; | |
n.init(a); | |
c = this; | |
this.init(); | |
var f = $$(".auto-completeForm"), | |
e = new Element("#close-search"); | |
f.adopt(e); | |
h.listen(e, "click", function (b) { | |
b.preventDefault(); | |
b.stopPropagation(); | |
c.clear() | |
}); | |
h.listen(c.widgetContainer, | |
"click", g) | |
}; | |
f.prototype = new j; | |
f.prototype.constructor = f; | |
f.prototype.onURISearch = function () {}; | |
f.prototype.init = function () { | |
if (!this.searchHandler) this.searchHandler = n.throttle(function (b, a) { | |
n.doSearch(q, b, a, i) | |
}, 500); | |
this.initInputField(); | |
this.initKeyboardNav(); | |
this.initialResults && this.setInitialResults(this.initialResults) | |
}; | |
f.prototype.show = function () { | |
c.widgetContainer.setStyle("display", "block"); | |
c.widgetContainer.getElement("input").focus() | |
}; | |
f.prototype.hide = function () { | |
c.widgetContainer.setStyle("display", | |
"none") | |
}; | |
f.prototype.setInitialResults = function (b) { | |
var a = this.widgetContainer.getElement(".albums"); | |
a && a.setStyle("display", "none"); | |
if (b) this.initialResults = b; | |
for (var c in this.initialResults) this.tokenInput.addTokens(this.initialResults[c], c) | |
}; | |
f.prototype.initKeyboardNav = function () { | |
h.listen(window, "keydown", function (b) { | |
var a = b.keyCode === 38, | |
d = b.keyCode === 40, | |
f = b.keyCode === 13, | |
b = b.keyCode === 27, | |
e = c.widgetContainer.getElements("a"), | |
g = c.widgetContainer.getElements("a.selected").pop(), | |
h = e.indexOf(g); | |
b === !0 && this.hide(); | |
if (f === !0) return h > -1 && (this.onEnter({ | |
target: g, | |
currentTarget: null, | |
preventDefault: function () { | |
return !1 | |
} | |
}), this.hide()), !1; | |
a && (h === -1 ? $$(e[e.length - 1]).addClass("selected") : h > 0 && ($$(g).removeClass("selected"), $$(e[h - 1]).addClass("selected"))); | |
d && (h === -1 ? $$(e[0]).addClass("selected") : h < e.length - 1 && ($$(g).removeClass("selected"), $$(e[h + 1]).addClass("selected"))) | |
}.bind(this)) | |
}; | |
f.prototype.initInputField = function () { | |
this.tokenInput = new k("uris"); | |
this.tokenInput.callback = this.onURISearch; | |
this.tokenInput.searchHandler = this.searchHandler; | |
this.tokenInput.resultHandler = this.onSearchResults; | |
var b = document.createElement("div"); | |
b.tabIndex = 1; | |
$$(b).addClass("auto-complete"); | |
$$(b).addClass("show"); | |
$$(b).addClass("search"); | |
this.tokenInput.node.appendChild(b); | |
this.widgetContainer.adopt(this.tokenInput.node); | |
for (var a = 0, c = d.length; a < c; a++) { | |
var e = document.createElement("div"); | |
$$(e).addClass(d[a]); | |
$$(e).addClass("search"); | |
var f = document.createElement("span"); | |
f.textContent = d[a]; | |
e.appendChild(f); | |
b.appendChild(e) | |
} | |
return this | |
}; | |
f.prototype.clear = function () { | |
this.tokenInput.input.value = ""; | |
this.tokenInput.input.focus(); | |
this.setInitialResults(); | |
return this | |
}; | |
k.prototype.addTokens = function (b, a) { | |
var c = this.node.getElement("." + a); | |
c && (c.setStyle("display", "block"), this.clear(c), b.each(function (b) { | |
c.getElements("a"); | |
var d = document.createElement("a"), | |
e = document.createElement("div"); | |
d.uri = b.uri; | |
d.href = b.uri.replace("spotify:", "spotify:radio:").decodeForLink().toSpotifyURL(); | |
d.addClass("search"); | |
var f = new Image; | |
e.addClass("searchImg"); | |
e.addClass("sp-image-placeholder-visible"); | |
d.appendChild(e); | |
f.onload = function (b) { | |
n.setBg(b, d) | |
}; | |
f.src = b.image; | |
if (b.imageForSize) f.src = b.imageForSize(60); | |
if (b.item) f.src = b.item.imageForSize(60); | |
e = document.createElement("strong"); | |
e.textContent = b.name.decodeForText(); | |
d.appendChild(e); | |
c.appendChild(d); | |
n.decorate(a, d, i) | |
})) | |
}; | |
k.prototype.clear = function (b) { | |
b.getElements("a").each(function (b) { | |
b.parentNode && b.parentNode.removeChild(b) | |
}); | |
return this | |
}; | |
k.prototype.disable = function () { | |
this.input.disabled = !0; | |
return this | |
}; | |
k.prototype.enable = function () { | |
this.input.disabled = !1; | |
return this | |
}; | |
l.SearchWidget = f | |
})(r["$api/search"].Search, r["scripts/eventhandler"], r["scripts/searchUtil"], r["$api/models"].Observable, r["$api/models"]) | |
}); | |
_unrequire("scripts/genreDict", [], function (l) { | |
l.gd = { | |
alternative: ["Alternative", 1, "spotify:mosaic:1207d776aa45b693cad70ef95450dc8e0db18d83:47e2da2028246491b0478e406cfdba230ff5b1fa:597def07fa6398d6d35b90d181265fb75424bac5:d386c2a1d1dc719c2940254830831c97c1a8ff0a"], | |
black_metal: ["Black Metal", 2, "spotify:mosaic:ddbde13be788ae958a3fbbcef448dbf199610b5f:c3edd0e8343dcf84f04d5788df6a93ec3b0654e2:897f6ac957c4e42907646e6c6624273ea65a005b:f6ab9901b9eee306bd1425911ea0bc722d76cfa4"], | |
blues: ["Blues", 4, "spotify:mosaic:e94afef050d571055224f89d2b5d29ba9e3b9300:91b2278c242c141aebc5f4164cf1e4eaa9c1e9d5:96175d5bda99b24fd05c614137f76f5c5fc31e21:cb6c654d4fc2a4d78ff00be187d95467424096df"], | |
classical: ["Classical", 8, "spotify:mosaic:fcfc1d5444184b2036664bed9426668ddf0a9fd0:6a69b6cad2ea198a12e4e77fa6cbc5b3875656a6:f91adc2448a5c7b5adb18fc85bf90fc6c9d6d64f:09890f2fd461a1c577afbc42be97363c32b5d49e"], | |
country: ["Country", 16, "spotify:mosaic:f7641a20c01f7758d58c9d364b13d7edd0e879cd:945e69e836de6b244ca6019ecac26ac4cf229ba7:4c8d5465f8bf657f91837dd15154124c8bbf247a:050cb4785cff6411b62b829b9beb2bc063fb5dd3"], | |
dance: ["Club/House", 32, "spotify:mosaic:7cd9eb1ae4d684ca87228a90e667008393aaa881:d25f570e5a25bb0f746c2a3e86f906abde0ac281:6b8ec3aee1c373572e32ba0e967cc1cf022faaba:588ffff3ef8f1097aa816f0f00cb7bd0267816b3"], | |
death_metal: ["Death Metal", 64, "spotify:mosaic:dd184055dad8f57cd693683881ae39a9cf9c5582:9a82b57a4f208740bad05046e1ee876a8f7a1f91:3d921ff52b2a731465a0e8a2f92c5f8233ea02ad:45af8d31e3d994addf90fec7b0867b25dd594543"], | |
electronic: ["Electronic", 128, "spotify:mosaic:1196dcd5fe2fb9ce78f84f324f2a31dcd6f18b99:171c3048bdf313d824a30d4c52c8dc7bbcc58cfd:8311fdd10a0a9bc60170caaee8ef92e6f9487654:961f901c6b91af8cb640861db629914c0c8a980a"], | |
emo: ["Emo", 256, "spotify:mosaic:56ff711a44e4770a49f7c240bf228c577effc628:9b4183ba24fcb35cfe40edb6f2762c23fef4aa99:0dfeef9cc746cbf08c9848a929523ec5d088355f:0a919fa5734a469d282876f46825ce5509d33643"], | |
folk: ["Folk", 512, "spotify:mosaic:3facf19343a4e3204b5c1bf7676ba7f23b1a303e:38f73045ef7424f62d8bffbf304a183e4eb07269:84cb37746c836a900285d7ee0fdf6b2bbf8c7c3d:bb59d4023f2714d5057469f84a4554d2d31e1893"], | |
hardcore: ["Hardcore", 1024, "spotify:mosaic:e55c3e91200dd089ac78cc1a3c64dfbf3bc5370d:33ad1fb66fb6a45bb8b0f49b774b72188d05c61a:ab854c15cca135c88bb5a8e95373faee5b15166a:1a9cc1af8bc740a539255cdd256a1565e9180c67"], | |
heavy_metal: ["Heavy Metal", 2048, "spotify:mosaic:61fa42a2ad6c0d6cd57537b2c751b2c6c317758a:910a245bd2dafa05646683d70045bda63d524f2d:7a21c513cd94aff040ad695947321659c9e1b94b:7835b7891fb5d3dba8af1fa361bb600d65469308"], | |
hip_hop: ["Hip-Hop", 4096, "spotify:mosaic:9b9cc2b96384754810c46f5aa4d4ed89865615ff:753754a3f01bdcbe7c573ca8a74a6c2015ce7611:f55d28ca1a35496d1e41f4893763dd512dc820c0:b37fbe8e3be71234510cff162d1d1ef346336495"], | |
indie: ["Indie", 8192, "spotify:mosaic:7f6cebe3f3df4a95fde0931678abeab0e40308cd:c61bf879b941b4e3a11b2a46d70706ec788350bb:6620449cd7c56a9d17e068ec67a5645ef6561bb0:bf5c73dafeef02d42195cd42e007fe52d790befd"], | |
jazz: ["Jazz", 16384, "spotify:mosaic:7f3328e0ed8c9b64dba1bedf5a716226aaa719ad:31af688c12c57f7e5a750f7e678a4f5e9fc5c6dd:02d7097cf5c6383ad6523be736cfb6d916403dfe:9b90ff4da7042657cebba3852e67179baa59c4d5"], | |
latin: ["Latin", 32768, "spotify:mosaic:4c53a95cc9e6f3f5e93d597be203d7399def992f:4b762fb152e807048cbc026f30bc207d2c829294:642a6caa913fa93829a740b1a3122d195c2cdda1:876cd17f5274d28d153163e83ecf6f26da2b621b"], | |
pop: ["Pop", 65536, "spotify:mosaic:2abc9491a29d418572d1c0a555dc27217b9e29db:c9a3235bd39a917d588ff1bed66d788cc95bb1bb:b1720e5ca90f9a6428d97a72839cb9b1fe0d9883:0b44e33dd6deefd66e47bf183b04649017fc0552"], | |
punk: ["Punk", 131072, "spotify:mosaic:ba0aac39d5de6872e28acfeaaca2090eafad3cc2:f2d77487e24929bb389b99081574f8b6810863a6:767e92219e253bc83abab74d6c6dd166499222f1:772a723d0e4970a7f43a8ea4c73d70daeffd7d76"], | |
reggae: ["Reggae", 262144, "spotify:mosaic:8c06a3c655a3c52cd8cbfb2b5c299f61038e1930:4a07511acf0a83324021e80b7d677f0e66cc483a:e2f9fc0aa7180e037d05c9cf42ac1df730470d42:cf377968f983f926ba6ea6c2167f1f119a65bea6"], | |
r_n_b: ["R&B", 524288, "spotify:mosaic:8fe5e06c997bc793176af7daeefb43ca07636add:397c26076714475fff46b6cd88db8bb9f421ead6:c8c59aa15f5a52287ed354c9fc65eb6ff74e4c3d:ae763483112428a4336e6ec6323bf79228975789"], | |
rock: ["Rock", 1048576, "spotify:mosaic:8d3a4a465d857afc78734a8924766bde30260151:a0f1f0457556d6628ad90bf81fd751c061c2d1ba:f1a986d8044336ae6b09b5556cb4e140284cc0b0:1b20bd802ecea1cb1e3e35225debf7744294bda4"], | |
singer_songwriter: ["Singer-Songwriter", 2097152, "spotify:mosaic:37c7c980c10268efce2f20c6992195bd87a26302:582e3edd5030b7d2d240f09652306c62f9afda9d:6bacef6930b03b43826d0e855ea0b29fa06c2e82:8a99c564dd9be04b255c96050ab039d3250ce7d1"], | |
soul: ["Soul", 4194304, "spotify:mosaic:74b0d6d7750805926fd459cf114c010510339538:009c43b2bf76a6fa3ed621838f770ebdb393d16a:d4559fcf57b05a0b50a1bfc10cbc1ab1223b0fba:3f86a43016c0f207f12fd4a32da7a567be0d0a09"], | |
trance: ["Trance", 8388608, "spotify:mosaic:50f92f42b47f048754af4a808a1aca181590e7e8:99e94b809a68b8e37b9bb371535f2b252c213719:b4ad7cf639abd7dcb7f72d7c5888b4986f7dd24e:3ccfcc35121591808ae35c1ee98abc9352f302f7"], | |
"60s": ["60s", 16777216, "spotify:mosaic:bc2796fd1244da0dd756f12138cb7d918996b301:86be7f57948fa7f3a39c5a56dc5ca2fdb137e1b1:1c9a73dd3c378cd3c521bd01317a3faabcb47817:431b250293487ad8fcdbe490b7c6e21711d0d57e"], | |
"70s": ["70s", 33554432, "spotify:mosaic:9f55557d77188544d1c9fe3a24bbf8356fd1cf52:5049ca63240c296644f13c4f2eadfa6e7a68f4b0:3326e1f51f1eb147c3b24a4b828ed5f1191e09db:bd1dae68bd817e11177e7eb58a4eb9faa41d7ef1"], | |
"80s": ["80s", 67108864, "spotify:mosaic:56b7bec5311cee3945a8eceed91778ad13c083d9:25053d53407cfaaa378a8cad745caaea33204503:fc74c5a8e560a296c6c336a2ef73efe2081741ec:59168df306885f6d2f44ad96e6cb8ebb678cbdea"], | |
"90s": ["90s", 134217728, "spotify:mosaic:7faf97f3580957f9568592e874fb2e3539149817:84851eb084a308fbdf860174d8835b5e72d9548e:0418233365825a89632d628a9a5b1f69f615f7d0:72a43570b40b67b6efbf3128188a211d95ec043a"] | |
} | |
}); | |
_unrequire("scripts/RecentStations", [], function (l) { | |
l.RecentStations = function (l, e, n) { | |
var j = {}, i = [], | |
k = function (a) { | |
var c; | |
switch (a.type) { | |
case "track": | |
c = { | |
title: a.track.name, | |
titleUri: a.album.uri, | |
imageUri: a.album.image, | |
subtitle: a.artist.name, | |
subtitleUri: a.artist.uri | |
}; | |
break; | |
case "album": | |
c = { | |
title: a.album.name, | |
titleUri: a.album.uri, | |
imageUri: a.album.image, | |
subtitle: a.artist.name, | |
subtitleUri: a.artist.uri | |
}; | |
break; | |
case "artist": | |
c = { | |
title: a.artist.name, | |
titleUri: a.artist.uri, | |
imageUri: a.artist.image, | |
subtitle: "", | |
subtitleUri: "" | |
}; | |
break; | |
case "genre": | |
c = { | |
title: a.genre.name, | |
titleUri: "", | |
imageUri: a.genre.mosaic, | |
subtitle: "", | |
subtitleUri: "" | |
}; | |
break; | |
case "playlist": | |
c = { | |
title: a.playlist.name, | |
titleUri: a.playlist.uri, | |
imageUri: a.playlist.uri, | |
subtitle: "", | |
subtitleUri: "" | |
} | |
} | |
if (c.imageUri.indexOf("http") > -1) { | |
var e = c.imageUri.split("/"); | |
c.imageUri = "spotify:image:" + e[e.length - 1] | |
} | |
c.seeds = [a.seed]; | |
return c | |
}, h = function (a, c, f) { | |
var b = l.get("hm://radio/stations/", [e.type("Station")], [e.type("Station")]); | |
b.method = "POST"; | |
b.send(a).done(function (b) { | |
j[c.seed] = b[0]; | |
i.push(b[0]); | |
f(b[0]) | |
}).fail(function () {}) | |
}, c = function (a, c) { | |
var e = k(a); | |
setTimeout(function () { | |
a.type === | |
"playlist" ? n.buildPlaylistMosaic(a.playlist.image, function (b) { | |
e.imageUri = b; | |
h(e, a, c) | |
}) : h(e, a, c) | |
}, 20); | |
c(e) | |
}, a = function (a, c) { | |
var f = j[a.seed]; | |
setTimeout(function () { | |
var a = l.get("hm://radio/stations/" + f.id, [], [e.type("Station")]); | |
a.method = "TOUCH"; | |
a.send(f).done(function () {}).fail(function () {}) | |
}, 50); | |
c(f) | |
}; | |
return { | |
list: function (a) { | |
i.length > 0 ? a(i) : l.get("hm://radio/stations/", [e.type("StationList")], []).send().done(function (c) { | |
if (c && c[0] && c[0].stations && c[0].stations.length) for (var c = c[0].stations, e = 0; e < c.length; e++) { | |
var b = c[e]; | |
b.id && b.title && b.imageUri && b.seeds && b.seeds.length && !j[b.seeds[0]] && (i.push(b), j[b.seeds[0]] = b) | |
} | |
a(i.concat([])) | |
}).fail(function () { | |
a(null) | |
}) | |
}, | |
store: function (d, e) { | |
j[d.seed] ? a(d, e) : c(d, e) | |
}, | |
getId: function (a) { | |
return j[a] ? j[a].id : null | |
} | |
} | |
} | |
}); | |
_unrequire("scripts/Feedback", [], function (l) { | |
l.Feedback = function (l, e, n, j, i, k) { | |
var h, c, a = function () { | |
j.call(this) | |
}; | |
a.prototype = new j; | |
h = new a; | |
h.addFeedback = function (a, g, f) { | |
f === "up" && c.addToLiked(a); | |
a = { | |
uri: a.replace("spotify:track:", ""), | |
type: f | |
}; | |
g = l.get("hm://radio/stations/" + g + "/feedback/", [], [e.type("Feedback")]); | |
g.method = "POST"; | |
g.send(a).done(function () { | |
h.dispatchEvent({ | |
type: "feedback-added", | |
thumbType: f | |
}) | |
}).fail(function () {}) | |
}; | |
c = i.LikedPlaylist(l, e, n, k); | |
return h | |
} | |
}); | |
_unrequire("scripts/LikedPlaylist", [], function (l) { | |
l.LikedPlaylist = function (l, e, n, j) { | |
var i = null, | |
k = null, | |
h = function () { | |
return function () {} | |
}, c = function (a) { | |
a.tracks.add(i).done(function () {}).fail(function () {}) | |
}, a = function (a) { | |
j.Playlist.fromURI(a).load(["name", "subscribed", "tracks"]).done(function (a) { | |
var b = ["Liked from Radio", | |
"Radio-Favoriten", "Favoritas de la radio", "Favoris des radios", "Radio-favorieten"]; | |
a.subscribed && b.indexOf(a.name) !== -1 ? c(a) : f() | |
}).fail(h("Could not load playlist")) | |
}, d = function (a) { | |
k = a.uri; | |
var b = l.get("hm://radio/liked-playlist", [], [e.type("LikedPlaylist")]); | |
b.method = "PUT"; | |
b.send({ | |
uri: a.uri | |
}).done(function () {}).fail(h("could not store playlist uri on server")); | |
a.load(["tracks"]).done(c).fail(h("Could not load playlist")) | |
}, g = function (a) { | |
a.load(["uri"]).done(d).fail(h("Could not load new playlist")) | |
}, | |
f = function () { | |
j.Playlist.create("Liked from Radio").done(g).fail(h("Could not create playlist")) | |
}, b = function (b) { | |
var c; | |
if (b && b.length > 0 && b[0].uri) c = b[0].uri; | |
c ? (k = c, a(c)) : f() | |
}; | |
return { | |
addToLiked: function (c) { | |
i = j.Track.fromURI(c); | |
k ? a(k) : l.get("hm://radio/liked-playlist", [e.type("LikedPlaylist")], []).send().done(b).fail(h("Could not fetch playlist from backend")) | |
} | |
} | |
} | |
}); | |
_unrequire("scripts/radio", "$api/models,$api/hermes,$api/toplists,scripts/imageCarousel,scripts/util,scripts/strings.json,scripts/eventhandler,scripts/cloud,scripts/ui,scripts/station,scripts/searchWidget,scripts/genreDict,scripts/RecentStations,scripts/Feedback,scripts/LikedPlaylist,$views/image".split(","), | |
function (l) { | |
(function (q, e, n, j, i, k, h, c, a, d, g, f, b, r, t, x) { | |
function y(a, b, c) { | |
return a === "playlist" ? "spotify:user:" + c + ":" + a + ":" + b : a === "starred" ? "spotify:user:" + c + ":starred" : "spotify:" + a + ":" + b | |
} | |
var w, z, u = function (a, b) { | |
if (a in k) { | |
if (b) { | |
var c = k[a]; | |
return b in c ? c[b] : b | |
} | |
return k[a] | |
} else return a | |
}, p = function () { | |
this.topArtists = []; | |
this.topTracks = []; | |
this._recent = { | |
stations: [], | |
imageCarousel: null | |
}; | |
this._currentTrack = null; | |
this._loadingStation = !1; | |
this._stations = []; | |
this._currentStation = null; | |
this._leftRadio = !1; | |
this._openUri = !0; | |
this.genreDict = f.gd; | |
this._models = q; | |
this.hermes = e; | |
w = n.Toplist.forCurrentUser(); | |
z = n.Toplist.forWorld(); | |
this.util = i; | |
this.enStrings = k.strings; | |
this.ui = a; | |
this._handler = h; | |
this._station = d; | |
this._ = u; | |
this.schema = this.hermes.Schema.fromURL(["/static/proto/radio.proto"]); | |
this.util.init(q, f.gd, x); | |
this.init() | |
}; | |
p.prototype.init = function () { | |
var d = this; | |
d.ui = a = new a.RadioUi(c, d, d._handler, j); | |
d._loadTopStations(w); | |
try { | |
this._recent.stations = JSON.parse(localStorage.getItem("RecentStations")) || [] | |
} catch (f) {} | |
this._RecentStations = b.RecentStations(e.Hermes, d.schema, d.util); | |
this._Feedback = r.Feedback(e.Hermes, d.schema, d.util, d._models.Observable, t, q); | |
this._Feedback.addEventListener("feedback-added", function (a) { | |
d._feedbackAdded(a) | |
}); | |
this._recent.imageCarousel = new j.ImageCarousel("#recent", u("Your Stations"), k, d.util); | |
d._RecentStations.list(function (b) { | |
d._startStationFromArguments(null, function (c) { | |
if (b && b.length > 1) d._recent.stations = b, d.ui.fillRecentStationList(b), c || d._showStation(d._recent.stations[0].seeds[0], "recent"); | |
else if (d._recent.stations && d._recent.stations.length > 0 && d._recent.stations[0].seeds) d.ui.fillRecentStationList(d._recent.stations), c || d._showStation(d._recent.stations[0].seeds[0], "recent"); | |
else if (!d._recent.stations || d._recent.stations.length < 1) d.firstTime = !0, a.firstTime(), c || d._showStation(d.topArtists[0].uri, "recommended") | |
}) | |
}); | |
d.searchWidget = new g.SearchWidget($$(".auto-completeForm"), d.util); | |
d.searchWidget.onEnter = d.ui.handleClick; | |
d.searchWidget.addEventListener("open-uri", function (a) { | |
d._startStation(a) | |
}); | |
d.ui.addEventListener("show-search", | |
d.searchWidget.show); | |
d.ui.addEventListener("hide-search", d.searchWidget.hide); | |
d.ui.addEventListener("thumb", function (a) { | |
d.thumb(a) | |
}); | |
d._models.session.load(["user", "online"]).done(function () {}).fail(function () {}); | |
a.addEventListener("start-station", function (a) { | |
d._startStation(a) | |
}); | |
a.addEventListener("play-pause", function () { | |
d._playPause() | |
}); | |
a.addEventListener("skip", function () { | |
d._skip() | |
}); | |
a.adjustHeaderWidth(); | |
a.fillGenres(); | |
d._models.application.addEventListener("arguments", function (a) { | |
d._startStationFromArguments(a.data.arguments) | |
}); | |
d._thumbed = !1 | |
}; | |
p.prototype._feedbackAdded = function () { | |
this._currentStation.thumbEvent(); | |
this._thumbed = !1 | |
}; | |
p.prototype._displayThumbed = function (a) { | |
var b = this; | |
b._currentStation.feedback && b._currentStation.feedback[a.uri] && setTimeout(function () { | |
b._currentStation.feedback[a.uri] === "up" && b.ui.displayThumbUp(); | |
b._currentStation.feedback[a.uri] === "down" && b.ui.displayThumbDown() | |
}, 1E3) | |
}; | |
p.prototype.thumb = function (a) { | |
a = a.thumbType; | |
if (this._currentStation.id && this._currentStation.id.length > 0) if (a === "down") this._thumbed = | |
"down", this._skip(); | |
else if (a === "up") this._thumbed = "up", this._Feedback.addFeedback(this._currentTrack.uri, this._currentStation.id, "up") | |
}; | |
p.prototype.getCurrentStation = function () { | |
return this._currentStation | |
}; | |
p.prototype._addRecentStation = function (a) { | |
if (a) { | |
var b = this, | |
c = this._recent.stations, | |
d = !0; | |
c && c.length > 0 && c[0].seeds[0] === a.seed && (d = !1); | |
var e = function (a) { | |
var e; | |
for (e = 0; e < c.length && c[e].seeds[0] !== a.seeds[0]; e++); | |
c.splice(e, 1); | |
c.splice(0, 0, a); | |
c.splice(20); | |
d && b.ui.fillRecentStationList(c); | |
localStorage.setItem("RecentStations", | |
JSON.stringify(c)) | |
}; | |
b._RecentStations.store(a, function (a) { | |
if (a.id) b._currentStation.id = a.id; | |
c.length < 1 ? e(a) : c.length > 0 && c[0].seeds[0] !== a.seeds[0] && e(a) | |
}) | |
} | |
}; | |
p.prototype._preloadImages = function () { | |
var a = this; | |
setTimeout(function () { | |
a._currentStation._temporaryPlaylist.tracksCache.shift(); | |
for (var b = 0; b < 3; b++) { | |
var c = a._currentStation._temporaryPlaylist.tracksCache.shift(); | |
if (c && c.image)(new Image).src = c.image | |
} | |
}, 50) | |
}; | |
p.prototype._newTrack = function (a) { | |
a = a.track; | |
if (!(this._currentTrack && a.uri === this._currentTrack.uri)) this._preloadImages(), | |
this._currentTrack = a, this.ui.rotateCovers(a), this.ui.updatePlayPause(!0), this._displayThumbed(a) | |
}; | |
p.prototype._isPlaying = function () { | |
this.ui.updatePlayPause(!0) | |
}; | |
p.prototype._leavingRadio = function () { | |
this._leftRadio = !0; | |
this.ui.updatePlayPause(!1) | |
}; | |
p.prototype._paused = function () { | |
this.ui.updatePlayPause(!1) | |
}; | |
p.prototype._skip = function () { | |
var a = this, | |
b = a._currentStation; | |
a._startedPlay && !a._leftRadio ? a._thumbed === "down" ? b.skipTrack(function () { | |
a._Feedback.addFeedback(a._currentTrack.uri, a._currentStation.id, | |
"down") | |
}) : b.skipTrack() : (a._leftRadio ? (a._startPlaying({ | |
playlist: b._temporaryPlaylist, | |
index: a._currentStation.index + 1 | |
}), a._leftRadio = !1) : (a._startPlaying({ | |
playlist: b._temporaryPlaylist, | |
index: 1 | |
}), a._startedPlay = !0), a._thumbed === "down" && a._Feedback.addFeedback(a._currentTrack.uri, a._currentStation.id, "down")) | |
}; | |
p.prototype._loadStation = function (a, b) { | |
var c = this; | |
c._startedPlay = b; | |
c._loadingStation = !0; | |
c.ui.loadingStation(); | |
try { | |
var d = new this._station.Station(this, c._RecentStations.getId(a)); | |
if (!d) return null; | |
d.addEventListener("stationAvailable", function (a) { | |
c._loadingStation = !1; | |
d.addEventListener("track-added", function (a) { | |
c._trackAdded(a) | |
}); | |
d.addEventListener("start-playing", function (a) { | |
c._startPlaying(a) | |
}); | |
d.addEventListener("leavingRadio", function () { | |
c._leavingRadio() | |
}); | |
d.addEventListener("is-playing", function () { | |
c._isPlaying() | |
}); | |
d.addEventListener("new-track", function (a) { | |
c._newTrack(a) | |
}); | |
d.addEventListener("paused", function () { | |
c._paused() | |
}); | |
d.addEventListener("track-end", function () { | |
c.trackEnd() | |
}); | |
c._currentStation = null; | |
c._currentStation = d; | |
if (!c.psc) c.psc = function (a) { | |
c._currentStation && c._currentStation.playerStateChanged(a) | |
}, q.player.addEventListener("change", c.psc); | |
c._stationAvailable(a) | |
}); | |
d.addEventListener("failed-station", function () { | |
c._loadingStation = !1; | |
c.ui.failedStation() | |
}); | |
d.loadStation(a, b); | |
return d | |
} catch (e) { | |
return null | |
} | |
}; | |
p.prototype.trackEnd = function () { | |
this.ui.disableThumbs() | |
}; | |
p.prototype._trackAdded = function (a) { | |
a = a.track; | |
this._preloadImages(); | |
this._currentTrack = a; | |
this.ui.rotateCovers(a); | |
this._displayThumbed(a) | |
}; | |
p.prototype._stationAvailable = function (a) { | |
var b = this, | |
c = a.trackSource, | |
d = a.originalSeed, | |
e = a.startPlay; | |
if (b.firstTime) b.firstTime = !1; | |
b.util.getSeedMetadata(d, function (a) { | |
b.ui.stationAvailable(c, d, a, e); | |
b._addRecentStation(a) | |
}, null, !0); | |
b._models.application.clientEvent("", "loadstation", "1", "1", { | |
source: b.startApp, | |
context: "", | |
element: b.startSource, | |
target: d, | |
targetsource: c | |
}); | |
b._openUri && b._models.application.openURI(d.replace("spotify", "spotify:app:radio"), !0); | |
b._openUri = !0 | |
}; | |
p.prototype._showStation = function (a, | |
b) { | |
this._loadStation(a, !1); | |
this.startApp = "spotify:app:radio"; | |
this.startSource = b | |
}; | |
p.prototype._startStation = function (a) { | |
var b = a.seed, | |
c = a.elClass, | |
d = "spotify:app:radio"; | |
a.app > 2 && (d = "spotify:app:" + a.app); | |
this.startApp = d; | |
if (c.indexOf("recent") > -1) this.startSource = "recent"; | |
else if (c.indexOf("recommended") > -1) this.startSource = "recommended"; | |
else if (c.indexOf("search") > -1) this.startSource = "search"; | |
else if (c.indexOf("genre") > -1) this.startSource = "genre"; | |
else if (c.indexOf("external") > -1) this.startSource = "external"; | |
this._loadStation(b, !0) | |
}; | |
p.prototype._startStationFromArguments = function (a, b) { | |
var c = this, | |
d = function (a) { | |
if (a.length < 2) b && b(); | |
else { | |
var d = unescape(a[0]), | |
e = unescape(a[1]); | |
if ((a.length === 2 || a.length === 3 || a.length === 4) && (d === "album" || d === "artist" || d === "track" || d === "user" || d === "genre")) { | |
var f = d, | |
g; | |
f === "user" ? (d = unescape(a[1]), a.length === 4 && (f = "playlist", e = unescape(a[3]), g = y(f, e, d)), a.length === 3 && (f = "starred", g = y(f, null, d))) : g = y(d, e); | |
if (c._currentStation && g !== c._currentStation.originalSeed || !c._currentStation) c._openUri = !1, c._startStation({ | |
seed: g, | |
elClass: "external", | |
app: f | |
}); | |
b && b(!0) | |
} else b && b(!1) | |
} | |
}; | |
a ? d(a) : c._models.application.load("arguments").done(function (a) { | |
d(a.arguments) | |
}).fail(function () {}) | |
}; | |
p.prototype._topStationsDone = function () { | |
this._fillTopStations(); | |
this.searchWidget.setInitialResults({ | |
artists: this.topArtists.slice(0, 3), | |
tracks: this.topTracks.slice(0, 3) | |
}) | |
}; | |
p.prototype._loadTopStations = function (a, b) { | |
var c = this, | |
d = 0, | |
e = function () { | |
d += 1; | |
d === 2 && (c.topTracks.length > 0 && c.topArtists.length > 0 ? c._topStationsDone() : b ? c._topStationsDone() : c._loadTopStations(z, !0)) | |
}; | |
a.artists.snapshot(0, 10).done(function (a) { | |
c.util.getTopArtists(a, c._models.Promise, function (a) { | |
c.topArtists = a; | |
c.firstTime && c._showStation(c.topArtists[0].uri, "recommended"); | |
e() | |
}) | |
}).fail(function () { | |
e() | |
}); | |
a.tracks.snapshot(0, 10).done(function (a) { | |
c.util.getTopTracks(a, c._models.Promise, function (a) { | |
c.topTracks = a; | |
e() | |
}) | |
}).fail(function () { | |
e() | |
}) | |
}; | |
p.prototype._fillTopStations = function () { | |
for (var a = this.topArtists, b = this.topTracks, c = [], d = !0, e = 0, f = 0; d;) d = !1, a.length > e && (c.push(a[e]), e += 1, d = !0), b.length > f && (c.push(b[f]), f += 1, d = !0); | |
this.ui.fillTopList("#topstations", u("Recommended Stations"), c) | |
}; | |
p.prototype._loadStationFromLinksChanged = function () { | |
var a = sp.core.getLinks(); | |
return a.length ? (this._loadStation(a[0], "spotify:app:radio", "", "drop", !0), !0) : !1 | |
}; | |
p.prototype._startPlaying = function (a) { | |
q.player.playContext(a.playlist, a.index || 0).done(function () {}).fail(function () {}) | |
}; | |
p.prototype._playPause = function () { | |
var a = this; | |
if (a._leftRadio) { | |
a._leftRadio = !1; | |
var b = a._currentStation, | |
c = 0; | |
if (b.index > 0) c = b.index; | |
a._startPlaying({ | |
playlist: b._temporaryPlaylist, | |
index: c | |
}) | |
} else a._startedPlay ? q.player.load(["playing"]).done(function (b) { | |
!a._leftRadio && a._startedPlay && b.playing ? q.player.pause() : q.player.play() | |
}).fail(function () {}) : (b = a._currentStation, a._startedPlay = !0, a._startPlaying({ | |
playlist: b._temporaryPlaylist | |
})) | |
}; | |
l.Radio = p | |
})(r["$api/models"], r["$api/hermes"], r["$api/toplists"], r["scripts/imageCarousel"], r["scripts/util"], r["scripts/strings.json"], r["scripts/eventhandler"], r["scripts/cloud"], | |
r["scripts/ui"], r["scripts/station"], r["scripts/searchWidget"], r["scripts/genreDict"], r["scripts/RecentStations"], r["scripts/Feedback"], r["scripts/LikedPlaylist"], r["$views/image"].Image) | |
}); | |
_unrequire("main", ["scripts/radio", "scripts/util"], function () { | |
window.env !== "test" && new r["scripts/radio"].Radio | |
}) | |
})(SpotifyApi.api, SpotifyApi.api._modules); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://play.spotify.com/static/proto/radio.proto | |
// 15/12/2012 | |
package spotify.radio.proto; | |
message RadioRequest { | |
repeated string uris = 1; // For a playlist, this will be a list of 20 sampled tracks | |
optional int32 salt = 2; // If set to 0, it will trigger the old behavior where all 250 tracks are returned | |
// optional int32 offset = 3; // DEPRECATED | |
optional int32 length = 4; | |
optional string stationId = 5; // This is used only for decorating with thumbs up/down, not to pull the uris | |
repeated string lastTracks = 6; // spotify uri's with spotify:track: stripped | |
} | |
// Deprecated | |
message MultiSeedRequest { | |
repeated string uris = 1; | |
} | |
message Feedback { // i.e. thumb | |
optional string uri = 1; // omit the spotify:track: prefix | |
optional string type = 2; | |
optional double timestamp = 3; | |
} | |
// Result from a radio station request | |
message Tracks { | |
repeated string gids = 1; | |
optional string source = 2; | |
optional string identity = 3; | |
repeated string tokens = 4; // As many as there are tracks | |
repeated Feedback feedback = 5; // all thumbs for the station among the tracks returned (no particular order) | |
} | |
message Station { | |
optional string id = 1; | |
optional string title = 2; | |
optional string titleUri = 3; // If it's a playlist then this will be a playlist uri | |
optional string subtitle = 4; | |
optional string subtitleUri = 5; // For a track radio this will be the artist, etc.. | |
optional string imageUri = 6; | |
optional double lastListen = 7; // Used for sorting | |
repeated string seeds = 8; // Not really used today. This should essentially be a list with only [titleUri] | |
optional int32 thumbsUp = 9; | |
optional int32 thumbsDown = 10; | |
} | |
// Reponse for rules request. Contains the javascript as a string. | |
message Rules { | |
optional string js = 1; | |
} | |
message StationResponse { | |
optional Station station = 1; | |
repeated Feedback feedback = 2; | |
} | |
message StationList { | |
repeated Station stations = 1; | |
} | |
message LikedPlaylist { | |
optional string uri = 1; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* https://play.spotify.edgekey.net/client/geeb4ad7/js/spotify.web.base.js | |
* | |
* 15/12/2012 | |
*/ | |
var Spotify = Spotify || {}; | |
Spotify.Web = Spotify.Web || {}; | |
Spotify.Web.Screens = Spotify.Web.Screens || {}; | |
Spotify.Web.Storage = Spotify.Web.Storage || {}; | |
var _ = function(c) { | |
return "undefined" != typeof spotLang && spotLang[c] ? spotLang[c] : c.replace("_", " ") | |
}; | |
Spotify.Web.Dotter = function(c, f, a) { | |
var e = 0, d, b = c.innerHTML; | |
this.start = function() { | |
d || (d = setInterval(function() { | |
e++; | |
e > f && (e = 0); | |
for (var d = b, a = 0; a < e; a++) | |
d += "."; | |
c.innerHTML = d | |
}, a)) | |
}; | |
this.stop = function() { | |
d && clearInterval(d); | |
c.innerHTML = b | |
} | |
}; | |
Spotify.Web.Authenticator = function() { | |
var c = !1, f = function(a, e, d) { | |
if (!c) { | |
c = !0; | |
var b = new XMLHttpRequest; | |
b.onreadystatechange = function() { | |
if (b.readyState === 4 && b.status === 200) { | |
setTimeout(function() { | |
c = !1 | |
}, 1E3); | |
var a = JSON.parse(b.responseText); | |
a.status === "OK" ? e(a.config) : d(a.error) | |
} | |
}; | |
b.open("POST", "/xhr/json/auth.php", !0); | |
b.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | |
b.send(a) | |
} | |
}; | |
this.authenticateWithFacebookCredentials = function(a, e, d, b, c) { | |
a = "type=fb&fbuid=" + encodeURIComponent(a) + | |
"&token=" + encodeURIComponent(e) + "&secret=" + encodeURIComponent(d); | |
f(a, b, c) | |
}; | |
this.authenticateWithUsernameAndPassword = function(a, c, d, b, g) { | |
a = "type=sp&username=" + encodeURIComponent(a) + "&password=" + encodeURIComponent(c) + "&secret=" + encodeURIComponent(d); | |
f(a, b, g) | |
} | |
}; | |
Spotify.Web.Screens.Intermediate = function(c) { | |
var f = new Spotify.Web.Authenticator, a = document.getElementById("login-screen"), e = document.querySelector("form #secret").value, d = !1, b = !1, g = function(a) { | |
document.getElementById("timeout").style.display = "block"; | |
var b = new XMLHttpRequest; | |
b.open("GET", "/xhr/json/log.php?type=FB_CONNECTION_FAILED&error=" + (a || "unknown"), !0); | |
b.send() | |
}, h = function(a) { | |
if (b) | |
return !0; | |
return Spotify && Spotify.Web && Spotify.Web.App ? (setTimeout(function() { | |
b = !0; | |
Spotify.Web.App.initialize(a, | |
window.FB) | |
}, 1), !0) : !1 | |
}, i = function(c) { | |
d = !0; | |
b = h(c); | |
if (!b) | |
var e = setInterval(function() { | |
h(c) && clearInterval(e) | |
}, 2E3); | |
a.className = "hidden"; | |
setTimeout(function() { | |
a.style.display = "none" | |
}, 1E3) | |
}, k = function() { | |
g("account_creation_failed") | |
}, j = function() { | |
FB.init(c); | |
FB.getLoginStatus(function(a) { | |
a.status === "connected" ? f.authenticateWithFacebookCredentials(a.authResponse.userID, a.authResponse.accessToken, e, i, k) : g("not_connected") | |
}) | |
}; | |
this.init = function() { | |
var a = new XMLHttpRequest; | |
a.open("GET", "/xhr/json/log.php?type=INTERMEDIATE_JS_READY", | |
!0); | |
a.send(); | |
setTimeout(function() { | |
d || g("timed_out") | |
}, 3E4); | |
window.fbAsyncInit = j; | |
var b = document.getElementsByTagName("script")[0]; | |
if (!document.getElementById("facebook-jssdk")) | |
a = document.createElement("script"), a.id = "facebook-jssdk", a.async = !0, a.src = "//connect.facebook.net/en_US/all/vb.js", b.parentNode.insertBefore(a, b) | |
} | |
}; | |
Spotify.Web.Screens.Login = function(c, f) { | |
var a = {invalid_credentials: _("Incorrect username and password"),invalid_country: _("Spotify is currently not available in your country"),capped: _("You have reached your maximum number of login attempts, please try again later"),service_unavailable: _("Service is currently unavailable. Please try again later"),fallback: _("Authentication failed. Please try again.")}, e = new Spotify.Web.Authenticator, d, b = !1, g = document.getElementById("fb-login-btn"), h = new Spotify.Web.Dotter(g, | |
3, 500), i = document.getElementById("sp-login-form"), k = document.getElementById("login-screen"), j = document.getElementById("login-method"), q = document.getElementById("bg-wrap"), r = document.getElementById("login-spotify"), s = document.getElementById("login-usr"), t = document.getElementById("login-cancel"), o = document.querySelector("#login .error"), l = i.querySelector('[name="secret"]').value, p = function(a) { | |
if (b) | |
return !0; | |
return Spotify && Spotify.Web && Spotify.Web.App ? (setTimeout(function() { | |
b = !0; | |
Spotify.Web.App.initialize(a, | |
window.FB) | |
}, 1), !0) : !1 | |
}, m = function(a) { | |
b = p(a); | |
if (!b) | |
var c = setInterval(function() { | |
p(a) && clearInterval(c) | |
}, 2E3); | |
h.stop(); | |
k.className = "hidden"; | |
setTimeout(function() { | |
k.style.display = "none" | |
}, 1E3) | |
}, n = function(b) { | |
o.innerHTML = a[b] ? a[b] : a.fallback; | |
o.style.display = "block" | |
}, u = function() { | |
FB.init(c); | |
FB.getLoginStatus(function(a) { | |
d = a | |
}) | |
}, v = function() { | |
i.addEventListener("submit", function(a) { | |
a.preventDefault(); | |
var a = i.querySelector('[name="username"]').value, b = i.querySelector('[name="password"]').value; | |
e.authenticateWithUsernameAndPassword(a, | |
b, l, m, n) | |
}); | |
j.addEventListener("dragstart", function(a) { | |
a.preventDefault() | |
}); | |
r.addEventListener("click", function(a) { | |
a.preventDefault(); | |
j.className = "flip"; | |
s.focus() | |
}); | |
t.addEventListener("click", function(a) { | |
a.preventDefault(); | |
j.className = "unflip" | |
}); | |
g.addEventListener("click", function(a) { | |
a.preventDefault(); | |
h.start(); | |
typeof d !== "undefined" && (d.status === "connected" ? e.authenticateWithFacebookCredentials(d.authResponse.userID, d.authResponse.accessToken, l, m, n) : FB.login(function(a) { | |
a.authResponse ? e.authenticateWithFacebookCredentials(a.authResponse.userID, | |
a.authResponse.accessToken, l, m, n) : h.stop() | |
})) | |
}) | |
}; | |
this.init = function() { | |
v(); | |
var a = new Image; | |
a.onload = function() { | |
q.className = "loaded" | |
}; | |
a.src = f; | |
window.fbAsyncInit = u; | |
var b = document.getElementsByTagName("script")[0]; | |
if (!document.getElementById("facebook-jssdk")) | |
a = document.createElement("script"), a.id = "facebook-jssdk", a.async = !0, a.src = "//connect.facebook.net/en_US/all/vb.js", b.parentNode.insertBefore(a, b) | |
} | |
}; |
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* https://play.spotify.edgekey.net/client/c46d547/js/spotify.web.client.js | |
* | |
* 2013-06-18 | |
*/ | |
/* | |
Copyright Spotify AB 2012. All rights reserved. | |
History.getInternetExplorerMajorVersion() | |
Get's the major version of Internet Explorer | |
@return {integer} | |
@license Public Domain | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
@author James Padolsey <https://gist.github.com/527683> | |
History.isInternetExplorer() | |
Are we using Internet Explorer? | |
@return {boolean} | |
@license Public Domain | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
History.js Core | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
@copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com> | |
@license New BSD License <http://creativecommons.org/licenses/BSD/> | |
History.js HTML4 Support | |
Depends on the HTML5 Support | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
@copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com> | |
@license New BSD License <http://creativecommons.org/licenses/BSD/> | |
SWFObject v2.2 <http://code.google.com/p/swfobject/> is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>. | |
CryptoJS v3.1.2 | |
code.google.com/p/crypto-js | |
(c) 2009-2013 by Jeff Mott. All rights reserved. | |
code.google.com/p/crypto-js/wiki/License | |
History.js Native Adapter | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
@copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com> | |
@license New BSD License <http://creativecommons.org/licenses/BSD/> | |
parseUri 1.2.2. | |
@author Steven Levithan <stevenlevithan.com> | |
@license MIT License. | |
*/ | |
Spotify.Web.ABTester = Spotify.Web.ABTester || {}; | |
(function (d) { | |
function g(f) { | |
var k = 0, | |
m = q[f]; | |
if (m) return m; | |
k = 0; | |
m = Array(1E4); | |
for (i = 0; i < m.length; i++) m[i] = i; | |
var c = b(h(a(f))), | |
k = parseInt(c.substring(0, 8), 16); | |
(function (f) { | |
for (var a = f.length - 1; a >= 1; a--) { | |
k = 16807 * k % 2147483647; | |
var m = k % (a + 1), | |
b = f[a]; | |
f[a] = f[m]; | |
f[m] = b | |
} | |
})(m); | |
return q[f] = m | |
} | |
function c(f, k) { | |
if (k && k.substring(0, 4) == "NTX_") { | |
var m = g(k), | |
c = parseInt(b(h(a("spotify:test:" + f))).substring(0, 8), 16), | |
c = Math.floor(1E4 * c * Math.pow(2, -32)); | |
return Math.floor(m[c] / 10) | |
} else return m = "spotify:test:", k && (m += k + ":"), m += | |
f, m = parseInt(b(h(a(m))).substring(0, 8), 16), Math.floor(1E3 * m * Math.pow(2, -32)) | |
} | |
function h(a) { | |
for (var b = Array(a.length >> 2), c = 0; c < b.length; c++) b[c] = 0; | |
for (c = 0; c < a.length * 8; c += 8) b[c >> 5] |= (a.charCodeAt(c / 8) & 255) << c % 32; | |
a = a.length * 8; | |
b[a >> 5] |= 128 << a % 32; | |
b[(a + 64 >>> 9 << 4) + 14] = a; | |
for (var a = 1732584193, c = -271733879, h = -1732584194, d = 271733878, g = 0; g < b.length; g += 16) var q = a, | |
n = c, G = h, B = d, a = k(a, c, h, d, b[g + 0], 7, -680876936), d = k(d, a, c, h, b[g + 1], 12, -389564586), h = k(h, d, a, c, b[g + 2], 17, 606105819), c = k(c, h, d, a, b[g + 3], 22, -1044525330), | |
a = k(a, c, h, d, b[g + 4], 7, -176418897), d = k(d, a, c, h, b[g + 5], 12, 1200080426), h = k(h, d, a, c, b[g + 6], 17, -1473231341), c = k(c, h, d, a, b[g + 7], 22, -45705983), a = k(a, c, h, d, b[g + 8], 7, 1770035416), d = k(d, a, c, h, b[g + 9], 12, -1958414417), h = k(h, d, a, c, b[g + 10], 17, -42063), c = k(c, h, d, a, b[g + 11], 22, -1990404162), a = k(a, c, h, d, b[g + 12], 7, 1804603682), d = k(d, a, c, h, b[g + 13], 12, -40341101), h = k(h, d, a, c, b[g + 14], 17, -1502002290), c = k(c, h, d, a, b[g + 15], 22, 1236535329), a = m(a, c, h, d, b[g + 1], 5, -165796510), d = m(d, a, c, h, b[g + 6], 9, -1069501632), h = m(h, d, a, c, b[g + 11], 14, 643717713), | |
c = m(c, h, d, a, b[g + 0], 20, -373897302), a = m(a, c, h, d, b[g + 5], 5, -701558691), d = m(d, a, c, h, b[g + 10], 9, 38016083), h = m(h, d, a, c, b[g + 15], 14, -660478335), c = m(c, h, d, a, b[g + 4], 20, -405537848), a = m(a, c, h, d, b[g + 9], 5, 568446438), d = m(d, a, c, h, b[g + 14], 9, -1019803690), h = m(h, d, a, c, b[g + 3], 14, -187363961), c = m(c, h, d, a, b[g + 8], 20, 1163531501), a = m(a, c, h, d, b[g + 13], 5, -1444681467), d = m(d, a, c, h, b[g + 2], 9, -51403784), h = m(h, d, a, c, b[g + 7], 14, 1735328473), c = m(c, h, d, a, b[g + 12], 20, -1926607734), a = f(c ^ h ^ d, a, c, b[g + 5], 4, -378558), d = f(a ^ c ^ h, d, a, b[g + 8], 11, -2022574463), | |
h = f(d ^ a ^ c, h, d, b[g + 11], 16, 1839030562), c = f(h ^ d ^ a, c, h, b[g + 14], 23, -35309556), a = f(c ^ h ^ d, a, c, b[g + 1], 4, -1530992060), d = f(a ^ c ^ h, d, a, b[g + 4], 11, 1272893353), h = f(d ^ a ^ c, h, d, b[g + 7], 16, -155497632), c = f(h ^ d ^ a, c, h, b[g + 10], 23, -1094730640), a = f(c ^ h ^ d, a, c, b[g + 13], 4, 681279174), d = f(a ^ c ^ h, d, a, b[g + 0], 11, -358537222), h = f(d ^ a ^ c, h, d, b[g + 3], 16, -722521979), c = f(h ^ d ^ a, c, h, b[g + 6], 23, 76029189), a = f(c ^ h ^ d, a, c, b[g + 9], 4, -640364487), d = f(a ^ c ^ h, d, a, b[g + 12], 11, -421815835), h = f(d ^ a ^ c, h, d, b[g + 15], 16, 530742520), c = f(h ^ d ^ a, c, h, b[g + 2], 23, -995338651), | |
a = o(a, c, h, d, b[g + 0], 6, -198630844), d = o(d, a, c, h, b[g + 7], 10, 1126891415), h = o(h, d, a, c, b[g + 14], 15, -1416354905), c = o(c, h, d, a, b[g + 5], 21, -57434055), a = o(a, c, h, d, b[g + 12], 6, 1700485571), d = o(d, a, c, h, b[g + 3], 10, -1894986606), h = o(h, d, a, c, b[g + 10], 15, -1051523), c = o(c, h, d, a, b[g + 1], 21, -2054922799), a = o(a, c, h, d, b[g + 8], 6, 1873313359), d = o(d, a, c, h, b[g + 15], 10, -30611744), h = o(h, d, a, c, b[g + 6], 15, -1560198380), c = o(c, h, d, a, b[g + 13], 21, 1309151649), a = o(a, c, h, d, b[g + 4], 6, -145523070), d = o(d, a, c, h, b[g + 11], 10, -1120210379), h = o(h, d, a, c, b[g + 2], 15, | |
718787259), c = o(c, h, d, a, b[g + 9], 21, -343485551), a = p(a, q), c = p(c, n), h = p(h, G), d = p(d, B); | |
b = [a, c, h, d]; | |
a = ""; | |
for (c = 0; c < b.length * 32; c += 8) a += String.fromCharCode(b[c >> 5] >>> c % 32 & 255); | |
return a | |
} | |
function b(a) { | |
for (var f = n ? "0123456789ABCDEF" : "0123456789abcdef", k = "", b, m = 0; m < a.length; m++) b = a.charCodeAt(m), k += f.charAt(b >>> 4 & 15) + f.charAt(b & 15); | |
return k | |
} | |
function a(a) { | |
for (var f = "", k = -1, b, m; ++k < a.length;) b = a.charCodeAt(k), m = k + 1 < a.length ? a.charCodeAt(k + 1) : 0, 55296 <= b && b <= 56319 && 56320 <= m && m <= 57343 && (b = 65536 + ((b & 1023) << 10) + (m & | |
1023), k++), b <= 127 ? f += String.fromCharCode(b) : b <= 2047 ? f += String.fromCharCode(192 | b >>> 6 & 31, 128 | b & 63) : b <= 65535 ? f += String.fromCharCode(224 | b >>> 12 & 15, 128 | b >>> 6 & 63, 128 | b & 63) : b <= 2097151 && (f += String.fromCharCode(240 | b >>> 18 & 7, 128 | b >>> 12 & 63, 128 | b >>> 6 & 63, 128 | b & 63)); | |
return f | |
} | |
function f(a, f, b, k, m, c) { | |
a = p(p(f, a), p(k, c)); | |
return p(a << m | a >>> 32 - m, b) | |
} | |
function k(a, b, k, m, c, h, d) { | |
return f(b & k | ~b & m, a, b, c, h, d) | |
} | |
function m(a, b, k, m, c, h, d) { | |
return f(b & m | k & ~m, a, b, c, h, d) | |
} | |
function o(a, b, k, m, c, h, d) { | |
return f(k ^ (b | ~m), a, b, c, h, d) | |
} | |
function p(a, | |
f) { | |
var b = (a & 65535) + (f & 65535); | |
return (a >> 16) + (f >> 16) + (b >> 16) << 16 | b & 65535 | |
} | |
var q = {}, n = 0; | |
d.getGroupId = c; | |
d.getDefaultGroupId = function (a) { | |
return c(a, "") | |
} | |
})(Spotify.Web.ABTester); | |
(function (d, g) { | |
var c = d.History = d.History || {}; | |
if (typeof c.Adapter !== "undefined") throw Error("History.js Adapter has already been loaded..."); | |
c.Adapter = { | |
handlers: {}, | |
_uid: 1, | |
uid: function (h) { | |
return h._uid || (h._uid = c.Adapter._uid++) | |
}, | |
bind: function (h, b, a) { | |
var f = c.Adapter.uid(h); | |
c.Adapter.handlers[f] = c.Adapter.handlers[f] || {}; | |
c.Adapter.handlers[f][b] = c.Adapter.handlers[f][b] || []; | |
c.Adapter.handlers[f][b].push(a); | |
h["on" + b] = function (a, f) { | |
return function (b) { | |
c.Adapter.trigger(a, f, b) | |
} | |
}(h, b) | |
}, | |
trigger: function (h, | |
b, a) { | |
var a = a || {}, h = c.Adapter.uid(h), | |
f, k; | |
c.Adapter.handlers[h] = c.Adapter.handlers[h] || {}; | |
c.Adapter.handlers[h][b] = c.Adapter.handlers[h][b] || []; | |
for (f = 0, k = c.Adapter.handlers[h][b].length; f < k; ++f) c.Adapter.handlers[h][b][f].apply(this, [a]) | |
}, | |
extractEventData: function (c, b) { | |
return b && b[c] || g | |
}, | |
onDomLoad: function (c) { | |
var b = d.setTimeout(function () { | |
c() | |
}, 2E3); | |
d.onload = function () { | |
clearTimeout(b); | |
c() | |
} | |
} | |
}; | |
typeof c.init !== "undefined" && c.init() | |
})(window); | |
(function (d, g) { | |
var c = d.console || g, | |
h = d.document, | |
b = d.navigator, | |
a = d.sessionStorage || !1, | |
f = d.setTimeout, | |
k = d.clearTimeout, | |
m = d.setInterval, | |
o = d.clearInterval, | |
p = d.JSON, | |
q = d.alert, | |
n = d.History = d.History || {}, s = d.history; | |
p.stringify = p.stringify || p.encode; | |
p.parse = p.parse || p.decode; | |
if (typeof n.init !== "undefined") throw Error("History.js Core has already been loaded..."); | |
n.init = function () { | |
if (typeof n.Adapter === "undefined") return !1; | |
typeof n.initCore !== "undefined" && n.initCore(); | |
typeof n.initHtml4 !== "undefined" && n.initHtml4(); | |
return !0 | |
}; | |
n.initCore = function () { | |
if (typeof n.initCore.initialized !== "undefined") return !1; | |
else n.initCore.initialized = !0; | |
n.options = n.options || {}; | |
n.options.hashChangeInterval = n.options.hashChangeInterval || 100; | |
n.options.safariPollInterval = n.options.safariPollInterval || 500; | |
n.options.doubleCheckInterval = n.options.doubleCheckInterval || 500; | |
n.options.storeInterval = n.options.storeInterval || 1E3; | |
n.options.busyDelay = n.options.busyDelay || 250; | |
n.options.debug = n.options.debug || !1; | |
n.options.initialTitle = n.options.initialTitle || | |
h.title; | |
n.intervalList = []; | |
n.clearAllIntervals = function () { | |
var a, f = n.intervalList; | |
if (typeof f !== "undefined" && f !== null) { | |
for (a = 0; a < f.length; a++) o(f[a]); | |
n.intervalList = null | |
} | |
}; | |
n.debug = function () { | |
n.options.debug && n.log.apply(n, arguments) | |
}; | |
n.log = function () { | |
var a = !(typeof c === "undefined" || typeof c.log === "undefined" || typeof c.log.apply === "undefined"), | |
f = h.getElementById("log"), | |
b, k, m, d; | |
a ? (k = Array.prototype.slice.call(arguments), b = k.shift(), typeof c.debug !== "undefined" ? c.debug.apply(c, [b, k]) : c.log.apply(c, [b, | |
k | |
])) : b = "\n" + arguments[0] + "\n"; | |
for (k = 1, m = arguments.length; k < m; ++k) { | |
d = arguments[k]; | |
if (typeof d === "object" && typeof p !== "undefined") try { | |
d = p.stringify(d) | |
} catch (o) {} | |
b += "\n" + d + "\n" | |
} | |
f ? (f.value += b + "\n-----\n", f.scrollTop = f.scrollHeight - f.clientHeight) : a || q(b); | |
return !0 | |
}; | |
n.getInternetExplorerMajorVersion = function () { | |
return n.getInternetExplorerMajorVersion.cached = typeof n.getInternetExplorerMajorVersion.cached !== "undefined" ? n.getInternetExplorerMajorVersion.cached : function () { | |
for (var a = 3, f = h.createElement("div"), | |
b = f.getElementsByTagName("i"); | |
(f.innerHTML = "<\!--[if gt IE " + ++a + "]><i></i><![endif]--\>") && b[0];); | |
return a > 4 ? a : !1 | |
}() | |
}; | |
n.isInternetExplorer = function () { | |
return n.isInternetExplorer.cached = typeof n.isInternetExplorer.cached !== "undefined" ? n.isInternetExplorer.cached : Boolean(n.getInternetExplorerMajorVersion()) | |
}; | |
n.emulated = { | |
pushState: !Boolean(d.history && d.history.pushState && d.history.replaceState && !(/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(b.userAgent) || /AppleWebKit\/5([0-2]|3[0-2])/i.test(b.userAgent))), | |
hashChange: Boolean(!("onhashchange" in d || "onhashchange" in h) || n.isInternetExplorer() && n.getInternetExplorerMajorVersion() < 8) | |
}; | |
n.enabled = !n.emulated.pushState; | |
n.bugs = { | |
setHash: Boolean(!n.emulated.pushState && b.vendor === "Apple Computer, Inc." && /AppleWebKit\/5([0-2]|3[0-3])/.test(b.userAgent)), | |
safariPoll: Boolean(!n.emulated.pushState && b.vendor === "Apple Computer, Inc." && /AppleWebKit\/5([0-2]|3[0-3])/.test(b.userAgent)), | |
ieDoubleCheck: Boolean(n.isInternetExplorer() && n.getInternetExplorerMajorVersion() < 8), | |
hashEscape: Boolean(n.isInternetExplorer() && n.getInternetExplorerMajorVersion() < 7) | |
}; | |
n.isEmptyObject = function (a) { | |
for (var f in a) return !1; | |
return !0 | |
}; | |
n.cloneObject = function (a) { | |
a ? (a = p.stringify(a), a = p.parse(a)) : a = {}; | |
return a | |
}; | |
n.getRootUrl = function () { | |
var a = h.location.protocol + "//" + (h.location.hostname || h.location.host); | |
h.location.port && (a += ":" + h.location.port); | |
a += "/"; | |
return a | |
}; | |
n.getBaseHref = function () { | |
var a = h.getElementsByTagName("base"), | |
f = null, | |
f = ""; | |
a.length === 1 && (f = a[0], f = f.href.replace(/[^\/]+$/, "")); | |
(f = f.replace(/\/+$/, "")) && (f += "/"); | |
return f | |
}; | |
n.getBaseUrl = function () { | |
return n.getBaseHref() || n.getBasePageUrl() || n.getRootUrl() | |
}; | |
n.getPageUrl = function () { | |
return ((n.getState(!1, !1) || {}).url || h.location.href).replace(/\/+$/, "").replace(/[^\/]+$/, function (a) { | |
return /\./.test(a) ? a : a + "/" | |
}) | |
}; | |
n.getBasePageUrl = function () { | |
return h.location.href.replace(/[#\?].*/, "").replace(/[^\/]+$/, function (a) { | |
return /[^\/]$/.test(a) ? "" : a | |
}).replace(/\/+$/, "") + "/" | |
}; | |
n.getFullUrl = function (a, f) { | |
var b = a, | |
k = a.substring(0, 1), | |
f = typeof f === | |
"undefined" ? !0 : f; | |
/[a-z]+\:\/\//.test(a) || (b = k === "/" ? n.getRootUrl() + a.replace(/^\/+/, "") : k === "#" ? n.getPageUrl().replace(/#.*/, "") + a : k === "?" ? n.getPageUrl().replace(/[\?#].*/, "") + a : f ? n.getBaseUrl() + a.replace(/^(\.\/)+/, "") : n.getBasePageUrl() + a.replace(/^(\.\/)+/, "")); | |
return b.replace(/\#$/, "") | |
}; | |
n.getShortUrl = function (a) { | |
var f = n.getBaseUrl(), | |
b = n.getRootUrl(); | |
n.emulated.pushState && (a = a.replace(f, "")); | |
a = a.replace(b, "/"); | |
n.isTraditionalAnchor(a) && (a = "./" + a); | |
return a = a.replace(/^(\.\/)+/g, "./").replace(/\#$/, | |
"") | |
}; | |
n.getLocationHref = function (a) { | |
a = a || h; | |
return a.URL === a.location.href ? a.location.href : a.location.href === decodeURIComponent(a.URL) ? a.URL : a.location.hash && decodeURIComponent(a.location.href.replace(/^[^#]+/, "")) === a.location.hash ? a.location.href : a.URL.indexOf("#") == -1 && a.location.href.indexOf("#") != -1 ? a.location.href : a.URL || a.location.href | |
}; | |
n.store = {}; | |
n.idToState = n.idToState || {}; | |
n.stateToId = n.stateToId || {}; | |
n.urlToId = n.urlToId || {}; | |
n.storedStates = n.storedStates || []; | |
n.savedStates = n.savedStates || []; | |
n.normalizeStore = function () { | |
n.store.idToState = n.store.idToState || {}; | |
n.store.urlToId = n.store.urlToId || {}; | |
n.store.stateToId = n.store.stateToId || {} | |
}; | |
n.getState = function (a, f) { | |
typeof a === "undefined" && (a = !0); | |
typeof f === "undefined" && (f = !0); | |
var b = n.getLastSavedState(); | |
!b && f && (b = n.createStateObject()); | |
if (a) b = n.cloneObject(b), b.url = b.cleanUrl || b.url; | |
return b | |
}; | |
n.getIdByState = function (a) { | |
var f = n.extractId(a.url), | |
b; | |
if (!f) | |
if (b = n.getStateString(a), typeof n.stateToId[b] !== "undefined") f = n.stateToId[b]; | |
else if (typeof n.store.stateToId[b] !== | |
"undefined") f = n.store.stateToId[b]; | |
else { | |
for (;;) | |
if (f = (new Date).getTime() + String(Math.random()).replace(/\D/g, ""), typeof n.idToState[f] === "undefined" && typeof n.store.idToState[f] === "undefined") break; | |
n.stateToId[b] = f; | |
n.idToState[f] = a | |
} | |
return f | |
}; | |
n.normalizeState = function (a) { | |
var f; | |
if (!a || typeof a !== "object") a = {}; | |
if (typeof a.normalized !== "undefined") return a; | |
if (!a.data || typeof a.data !== "object") a.data = {}; | |
f = { | |
normalized: !0 | |
}; | |
f.title = a.title || ""; | |
f.url = n.getFullUrl(a.url || n.getLocationHref()); | |
f.hash = n.getShortUrl(f.url); | |
f.data = n.cloneObject(a.data); | |
f.id = n.getIdByState(f); | |
f.cleanUrl = f.url.replace(/\??\&_suid.*/, ""); | |
f.url = f.cleanUrl; | |
a = !n.isEmptyObject(f.data); | |
if (f.title || a) f.hash = n.getShortUrl(f.url).replace(/\??\&_suid.*/, ""), /\?/.test(f.hash) || (f.hash += "?"), f.hash += "&_suid=" + f.id; | |
f.hashedUrl = n.getFullUrl(f.hash); | |
if ((n.emulated.pushState || n.bugs.safariPoll) && n.hasUrlDuplicate(f)) f.url = f.hashedUrl; | |
return f | |
}; | |
n.createStateObject = function (a, f, b) { | |
a = { | |
data: a, | |
title: f, | |
url: b | |
}; | |
return a = n.normalizeState(a) | |
}; | |
n.getStateById = function (a) { | |
a = | |
String(a); | |
return n.idToState[a] || n.store.idToState[a] || g | |
}; | |
n.getStateString = function (a) { | |
a = { | |
data: n.normalizeState(a).data, | |
title: a.title, | |
url: a.url | |
}; | |
return p.stringify(a) | |
}; | |
n.getStateId = function (a) { | |
return n.normalizeState(a).id | |
}; | |
n.getHashByState = function (a) { | |
return n.normalizeState(a).hash | |
}; | |
n.extractId = function (a) { | |
return ((a = /(.*)\&_suid=([0-9]+)$/.exec(a)) ? String(a[2] || "") : "") || !1 | |
}; | |
n.isTraditionalAnchor = function (a) { | |
return !/[\/\?\.]/.test(a) | |
}; | |
n.extractState = function (a, f) { | |
var b = null, | |
k, m, f = f || !1; | |
(k = n.extractId(a)) && | |
(b = n.getStateById(k)); | |
b || (m = n.getFullUrl(a), (k = n.getIdByUrl(m) || !1) && (b = n.getStateById(k)), !b && f && !n.isTraditionalAnchor(a) && (b = n.createStateObject(null, null, m))); | |
return b | |
}; | |
n.getIdByUrl = function (a) { | |
return n.urlToId[a] || n.store.urlToId[a] || g | |
}; | |
n.getLastSavedState = function () { | |
return n.savedStates[n.savedStates.length - 1] || g | |
}; | |
n.getLastStoredState = function () { | |
return n.storedStates[n.storedStates.length - 1] || g | |
}; | |
n.hasUrlDuplicate = function (a) { | |
var f = !1; | |
return f = (f = n.extractState(a.url)) && f.id !== a.id | |
}; | |
n.storeState = | |
function (a) { | |
n.urlToId[a.url] = a.id; | |
n.storedStates.push(n.cloneObject(a)); | |
return a | |
}; | |
n.isLastSavedState = function (a) { | |
var f = !1; | |
if (n.savedStates.length) a = a.id, f = n.getLastSavedState(), f = f.id, f = a === f; | |
return f | |
}; | |
n.saveState = function (a) { | |
if (n.isLastSavedState(a)) return !1; | |
n.savedStates.push(n.cloneObject(a)); | |
return !0 | |
}; | |
n.getStateByIndex = function (a) { | |
var f = null; | |
return f = typeof a === "undefined" ? n.savedStates[n.savedStates.length - 1] : a < 0 ? n.savedStates[n.savedStates.length + a] : n.savedStates[a] | |
}; | |
n.getHash = function () { | |
return n.unescapeHash(h.location.hash) | |
}; | |
n.unescapeString = function (a) { | |
return a | |
}; | |
n.unescapeHash = function (a) { | |
a = n.normalizeHash(a); | |
return a = decodeURI(a) | |
}; | |
n.normalizeHash = function (a) { | |
return a.replace(/[^#]*#/, "").replace(/#.*/, "") | |
}; | |
n.setHash = function (a, f) { | |
var b, k; | |
if (f !== !1 && n.busy()) return n.pushQueue({ | |
scope: n, | |
callback: n.setHash, | |
args: arguments, | |
queue: f | |
}), !1; | |
b = n.escapeHash(a); | |
n.busy(!0); | |
if ((k = n.extractState(a, !0)) && !n.emulated.pushState) n.pushState(k.data, k.title, k.url, !1); | |
else if (h.location.hash !== b) n.bugs.setHash ? (k = n.getPageUrl(), n.pushState(null, | |
null, k + "#" + b, !1)) : h.location.hash = b; | |
return n | |
}; | |
n.escapeHash = function (a) { | |
a = n.normalizeHash(a); | |
a = d.encodeURI(a); | |
n.bugs.hashEscape || (a = a.replace(/\%21/g, "!").replace(/\%26/g, "&").replace(/\%3D/g, "=").replace(/\%3F/g, "?")); | |
return a | |
}; | |
n.getHashByUrl = function (a) { | |
a = String(a).replace(/([^#]*)#?([^#]*)#?(.*)/, "$2"); | |
return a = n.unescapeHash(a) | |
}; | |
n.setTitle = function (a) { | |
var f = a.title, | |
b; | |
f || (b = n.getStateByIndex(0)) && b.url === a.url && (f = b.title || n.options.initialTitle); | |
try { | |
h.getElementsByTagName("title")[0].innerHTML = | |
f.replace("<", "<").replace(">", ">").replace(" & ", " & ") | |
} catch (k) {} | |
h.title = f; | |
return n | |
}; | |
n.queues = []; | |
n.busy = function (a) { | |
if (typeof a !== "undefined") n.busy.flag = a; | |
else if (typeof n.busy.flag === "undefined") n.busy.flag = !1; | |
if (!n.busy.flag) { | |
k(n.busy.timeout); | |
var b = function () { | |
var a, k; | |
if (!n.busy.flag) | |
for (a = n.queues.length - 1; a >= 0; --a) | |
if (k = n.queues[a], k.length !== 0) k = k.shift(), n.fireQueueItem(k), n.busy.timeout = f(b, n.options.busyDelay) | |
}; | |
n.busy.timeout = f(b, n.options.busyDelay) | |
} | |
return n.busy.flag | |
}; | |
n.busy.flag = !1; | |
n.fireQueueItem = function (a) { | |
return a.callback.apply(a.scope || n, a.args || []) | |
}; | |
n.pushQueue = function (a) { | |
n.queues[a.queue || 0] = n.queues[a.queue || 0] || []; | |
n.queues[a.queue || 0].push(a); | |
return n | |
}; | |
n.queue = function (a, f) { | |
typeof a === "function" && (a = { | |
callback: a | |
}); | |
if (typeof f !== "undefined") a.queue = f; | |
n.busy() ? n.pushQueue(a) : n.fireQueueItem(a); | |
return n | |
}; | |
n.clearQueue = function () { | |
n.busy.flag = !1; | |
n.queues = []; | |
return n | |
}; | |
n.stateChanged = !1; | |
n.doubleChecker = !1; | |
n.doubleCheckComplete = function () { | |
n.stateChanged = !0; | |
n.doubleCheckClear(); | |
return n | |
}; | |
n.doubleCheckClear = function () { | |
if (n.doubleChecker) k(n.doubleChecker), n.doubleChecker = !1; | |
return n | |
}; | |
n.doubleCheck = function (a) { | |
n.stateChanged = !1; | |
n.doubleCheckClear(); | |
if (n.bugs.ieDoubleCheck) n.doubleChecker = f(function () { | |
n.doubleCheckClear(); | |
n.stateChanged || a(); | |
return !0 | |
}, n.options.doubleCheckInterval); | |
return n | |
}; | |
n.safariStatePoll = function () { | |
var a = n.extractState(h.location.href); | |
if (!n.isLastSavedState(a)) return a || n.createStateObject(), n.Adapter.trigger(d, "popstate"), n | |
}; | |
n.back = function (a) { | |
if (a !== !1 && n.busy()) return n.pushQueue({ | |
scope: n, | |
callback: n.back, | |
args: arguments, | |
queue: a | |
}), !1; | |
n.busy(!0); | |
n.doubleCheck(function () { | |
n.back(!1) | |
}); | |
s.go(-1); | |
return !0 | |
}; | |
n.forward = function (a) { | |
if (a !== !1 && n.busy()) return n.pushQueue({ | |
scope: n, | |
callback: n.forward, | |
args: arguments, | |
queue: a | |
}), !1; | |
n.busy(!0); | |
n.doubleCheck(function () { | |
n.forward(!1) | |
}); | |
s.go(1); | |
return !0 | |
}; | |
n.go = function (a, f) { | |
var b; | |
if (a > 0) | |
for (b = 1; b <= a; ++b) n.forward(f); | |
else if (a < 0) | |
for (b = -1; b >= a; --b) n.back(f); | |
else throw Error("History.go: History.go requires a positive or negative integer passed."); | |
return n | |
}; | |
if (n.emulated.pushState) { | |
var t = function () {}; | |
n.pushState = n.pushState || t; | |
n.replaceState = n.replaceState || t | |
} else n.onPopState = function (a, f) { | |
var b = !1, | |
b = !1; | |
n.doubleCheckComplete(); | |
if (b = n.getHash()) return (b = n.extractState(b || h.location.href, !0)) ? n.replaceState(b.data, b.title, b.url, !1) : (n.Adapter.trigger(d, "anchorchange"), n.busy(!1)), n.expectedStateId = !1; | |
(b = (b = n.Adapter.extractEventData("state", a, f) || !1) ? n.getStateById(b) : n.expectedStateId ? n.getStateById(n.expectedStateId) : n.extractState(h.location.href)) || | |
(b = n.createStateObject(null, null, h.location.href)); | |
n.expectedStateId = !1; | |
if (n.isLastSavedState(b)) return n.busy(!1), !1; | |
n.storeState(b); | |
n.saveState(b); | |
n.setTitle(b); | |
n.Adapter.trigger(d, "statechange"); | |
n.busy(!1); | |
return !0 | |
}, n.Adapter.bind(d, "popstate", n.onPopState), n.pushState = function (a, f, b, k) { | |
if (n.getHashByUrl(b) && n.emulated.pushState) throw Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); | |
if (k !== !1 && n.busy()) return n.pushQueue({ | |
scope: n, | |
callback: n.pushState, | |
args: arguments, | |
queue: k | |
}), !1; | |
n.busy(!0); | |
var m = n.createStateObject(a, f, b); | |
n.isLastSavedState(m) ? n.busy(!1) : (n.storeState(m), n.expectedStateId = m.id, s.pushState(m.id, m.title, m.url), n.Adapter.trigger(d, "popstate")); | |
return !0 | |
}, n.replaceState = function (a, f, b, k) { | |
if (n.getHashByUrl(b) && n.emulated.pushState) throw Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); | |
if (k !== !1 && n.busy()) return n.pushQueue({ | |
scope: n, | |
callback: n.replaceState, | |
args: arguments, | |
queue: k | |
}), !1; | |
n.busy(!0); | |
var m = n.createStateObject(a, | |
f, b); | |
n.isLastSavedState(m) ? n.busy(!1) : (n.storeState(m), n.expectedStateId = m.id, s.replaceState(m.id, m.title, m.url), n.Adapter.trigger(d, "popstate")); | |
return !0 | |
}; if (a) try { | |
n.store = p.parse(a.getItem("History.store")) || {} | |
} catch (u) { | |
n.store = {} | |
} else n.store = {}; | |
n.normalizeStore(); | |
n.Adapter.bind(d, "beforeunload", n.clearAllIntervals); | |
n.Adapter.bind(d, "unload", n.clearAllIntervals); | |
n.saveState(n.storeState(n.extractState(h.location.href, !0))); | |
if (a) n.onUnload = function () { | |
var f, b; | |
try { | |
f = p.parse(a.getItem("History.store")) || {} | |
} catch (k) { | |
f = {} | |
} | |
f.idToState = f.idToState || {}; | |
f.urlToId = f.urlToId || {}; | |
f.stateToId = f.stateToId || {}; | |
for (b in n.idToState) n.idToState.hasOwnProperty(b) && (f.idToState[b] = n.idToState[b]); | |
for (b in n.urlToId) n.urlToId.hasOwnProperty(b) && (f.urlToId[b] = n.urlToId[b]); | |
for (b in n.stateToId) n.stateToId.hasOwnProperty(b) && (f.stateToId[b] = n.stateToId[b]); | |
n.store = f; | |
n.normalizeStore(); | |
a.setItem("History.store", p.stringify(f)) | |
}, n.intervalList.push(m(n.onUnload, n.options.storeInterval)), n.Adapter.bind(d, "beforeunload", | |
n.onUnload), n.Adapter.bind(d, "unload", n.onUnload); | |
if (!n.emulated.pushState && (n.bugs.safariPoll && n.intervalList.push(m(n.safariStatePoll, n.options.safariPollInterval)), b.vendor === "Apple Computer, Inc." || (b.appCodeName || "") === "Mozilla")) | |
if (n.Adapter.bind(d, "hashchange", function () { | |
n.Adapter.trigger(d, "popstate") | |
}), n.getHash()) n.Adapter.onDomLoad(function () { | |
n.Adapter.trigger(d, "hashchange") | |
}) | |
}; | |
n.init() | |
})(window); | |
(function (d) { | |
var g = d.document, | |
c = d.setInterval || c, | |
h = d.History = d.History || {}; | |
if (typeof h.initHtml4 !== "undefined") throw Error("History.js HTML4 Support has already been loaded..."); | |
h.initHtml4 = function () { | |
if (typeof h.initHtml4.initialized !== "undefined") return !1; | |
else h.initHtml4.initialized = !0; | |
h.enabled = !0; | |
h.savedHashes = []; | |
h.isLastHash = function (b) { | |
var a = h.getHashByIndex(); | |
return b === a | |
}; | |
h.saveHash = function (b) { | |
if (h.isLastHash(b)) return !1; | |
h.savedHashes.push(b); | |
return !0 | |
}; | |
h.getHashByIndex = function (b) { | |
var a = | |
null; | |
return a = typeof b === "undefined" ? h.savedHashes[h.savedHashes.length - 1] : b < 0 ? h.savedHashes[h.savedHashes.length + b] : h.savedHashes[b] | |
}; | |
h.discardedHashes = {}; | |
h.discardedStates = {}; | |
h.discardState = function (b, a, f) { | |
var k = h.getHashByState(b); | |
h.discardedStates[k] = { | |
discardedState: b, | |
backState: f, | |
forwardState: a | |
}; | |
return !0 | |
}; | |
h.discardHash = function (b, a, f) { | |
h.discardedHashes[b] = { | |
discardedHash: b, | |
backState: f, | |
forwardState: a | |
}; | |
return !0 | |
}; | |
h.discardedState = function (b) { | |
b = h.getHashByState(b); | |
return h.discardedStates[b] || !1 | |
}; | |
h.discardedHash = function (b) { | |
return h.discardedHashes[b] || !1 | |
}; | |
h.recycleState = function (b) { | |
var a = h.getHashByState(b); | |
h.discardedState(b) && delete h.discardedStates[a]; | |
return !0 | |
}; | |
if (h.emulated.hashChange) h.hashChangeInit = function () { | |
h.checkerFunction = null; | |
var b = "", | |
a, f, k; | |
h.isInternetExplorer() ? (a = g.createElement("iframe"), a.setAttribute("id", "historyjs-iframe"), a.style.display = "none", g.body.appendChild(a), a.contentWindow.document.open(), a.contentWindow.document.close(), f = "", k = !1, h.checkerFunction = function () { | |
if (k) return !1; | |
k = !0; | |
var m = h.getHash() || "", | |
c = h.unescapeHash(a.contentWindow.document.location.hash) || ""; | |
if (m !== b) { | |
b = m; | |
if (c !== m) f = m, a.contentWindow.document.open(), a.contentWindow.document.close(), a.contentWindow.document.location.hash = h.escapeHash(m); | |
h.Adapter.trigger(d, "hashchange") | |
} else c !== f && (f = c, h.setHash(c, !1)); | |
k = !1; | |
return !0 | |
}) : h.checkerFunction = function () { | |
var a = h.getHash(); | |
a !== b && (b = a, h.Adapter.trigger(d, "hashchange")); | |
return !0 | |
}; | |
h.intervalList.push(c(h.checkerFunction, h.options.hashChangeInterval)); | |
return !0 | |
}, | |
h.Adapter.onDomLoad(h.hashChangeInit); | |
if (h.emulated.pushState) h.onHashChange = function (b) { | |
var a = h.getHashByUrl(b && b.newURL || g.location.href), | |
b = null; | |
if (h.isLastHash(a)) return h.busy(!1), !1; | |
h.doubleCheckComplete(); | |
h.saveHash(a); | |
if (a && h.isTraditionalAnchor(a)) return h.Adapter.trigger(d, "anchorchange"), h.busy(!1), !1; | |
b = h.extractState(h.getFullUrl(a || g.location.href, !1), !0); | |
if (h.isLastSavedState(b)) return h.busy(!1), !1; | |
h.getHashByState(b); | |
if (a = h.discardedState(b)) return h.getHashByIndex(-2) === h.getHashByState(a.forwardState) ? | |
h.back(!1) : h.forward(!1), !1; | |
h.pushState(b.data, b.title, b.url, !1); | |
return !0 | |
}, h.Adapter.bind(d, "hashchange", h.onHashChange), h.pushState = function (b, a, f, k) { | |
if (h.getHashByUrl(f)) throw Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); | |
if (k !== !1 && h.busy()) return h.pushQueue({ | |
scope: h, | |
callback: h.pushState, | |
args: arguments, | |
queue: k | |
}), !1; | |
h.busy(!0); | |
var m = h.createStateObject(b, a, f), | |
c = h.getHashByState(m), | |
p = h.getState(!1), | |
p = h.getHashByState(p), | |
q = h.getHash(); | |
h.storeState(m); | |
h.expectedStateId = | |
m.id; | |
h.recycleState(m); | |
h.setTitle(m); | |
if (c === p) return h.busy(!1), !1; | |
if (c !== q && c !== h.getShortUrl(g.location.href)) return h.setHash(c, !1), !1; | |
h.saveState(m); | |
h.Adapter.trigger(d, "statechange"); | |
h.busy(!1); | |
return !0 | |
}, h.replaceState = function (b, a, f, k) { | |
if (h.getHashByUrl(f)) throw Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); | |
if (k !== !1 && h.busy()) return h.pushQueue({ | |
scope: h, | |
callback: h.replaceState, | |
args: arguments, | |
queue: k | |
}), !1; | |
h.busy(!0); | |
var m = h.createStateObject(b, a, f), | |
c = h.getState(!1), | |
d = h.getStateByIndex(-2); | |
h.discardState(c, m, d); | |
h.pushState(m.data, m.title, m.url, !1); | |
return !0 | |
}; | |
if (h.emulated.pushState && h.getHash() && !h.emulated.hashChange) h.Adapter.onDomLoad(function () { | |
h.Adapter.trigger(d, "hashchange") | |
}) | |
}; | |
typeof h.init !== "undefined" && h.init() | |
})(window); | |
swfobject = function () { | |
function d() { | |
if (!P) { | |
try { | |
var a = E.getElementsByTagName("body")[0].appendChild(E.createElement("span")); | |
a.parentNode.removeChild(a) | |
} catch (f) { | |
return | |
} | |
P = !0; | |
for (var a = K.length, b = 0; b < a; b++) K[b]() | |
} | |
} | |
function g(a) { | |
P ? a() : K[K.length] = a | |
} | |
function c(a) { | |
if (typeof B.addEventListener != A) B.addEventListener("load", a, !1); | |
else if (typeof E.addEventListener != A) E.addEventListener("load", a, !1); | |
else if (typeof B.attachEvent != A) s(B, "onload", a); | |
else if (typeof B.onload == "function") { | |
var f = | |
B.onload; | |
B.onload = function () { | |
f(); | |
a() | |
} | |
} else B.onload = a | |
} | |
function h() { | |
var a = E.getElementsByTagName("body")[0], | |
f = E.createElement(x); | |
f.setAttribute("type", F); | |
var k = a.appendChild(f); | |
if (k) { | |
var m = 0; | |
(function () { | |
if (typeof k.GetVariable != A) { | |
var c = k.GetVariable("$version"); | |
if (c) c = c.split(" ")[1].split(","), J.pv = [parseInt(c[0], 10), parseInt(c[1], 10), parseInt(c[2], 10)] | |
} else if (m < 10) { | |
m++; | |
setTimeout(arguments.callee, 10); | |
return | |
} | |
a.removeChild(f); | |
k = null; | |
b() | |
})() | |
} else b() | |
} | |
function b() { | |
var b = L.length; | |
if (b > 0) | |
for (var c = 0; c < | |
b; c++) { | |
var h = L[c].id, | |
d = L[c].callbackFn, | |
o = { | |
success: !1, | |
id: h | |
}; | |
if (J.pv[0] > 0) { | |
var g = n(h); | |
if (g) | |
if (t(L[c].swfVersion) && !(J.wk && J.wk < 312)) { | |
if (w(h, !0), d) o.success = !0, o.ref = a(h), d(o) | |
} else if (L[c].expressInstall && f()) { | |
o = {}; | |
o.data = L[c].expressInstall; | |
o.width = g.getAttribute("width") || "0"; | |
o.height = g.getAttribute("height") || "0"; | |
if (g.getAttribute("class")) o.styleclass = g.getAttribute("class"); | |
if (g.getAttribute("align")) o.align = g.getAttribute("align"); | |
for (var p = {}, g = g.getElementsByTagName("param"), q = g.length, s = 0; s < | |
q; s++) g[s].getAttribute("name").toLowerCase() != "movie" && (p[g[s].getAttribute("name")] = g[s].getAttribute("value")); | |
k(o, p, h, d) | |
} else m(g), d && d(o) | |
} else if (w(h, !0), d) { | |
if ((h = a(h)) && typeof h.SetVariable != A) o.success = !0, o.ref = h; | |
d(o) | |
} | |
} | |
} | |
function a(a) { | |
var f = null; | |
if ((a = n(a)) && a.nodeName == "OBJECT") typeof a.SetVariable != A ? f = a : (a = a.getElementsByTagName(x)[0]) && (f = a); | |
return f | |
} | |
function f() { | |
return !O && t("6.0.65") && (J.win || J.mac) && !(J.wk && J.wk < 312) | |
} | |
function k(a, f, b, k) { | |
O = !0; | |
y = k || null; | |
D = { | |
success: !1, | |
id: b | |
}; | |
var m = n(b); | |
if (m) { | |
m.nodeName == | |
"OBJECT" ? (z = o(m), C = null) : (z = m, C = b); | |
a.id = G; | |
if (typeof a.width == A || !/%$/.test(a.width) && parseInt(a.width, 10) < 310) a.width = "310"; | |
if (typeof a.height == A || !/%$/.test(a.height) && parseInt(a.height, 10) < 137) a.height = "137"; | |
E.title = E.title.slice(0, 47) + " - Flash Player Installation"; | |
k = J.ie && J.win ? "ActiveX" : "PlugIn"; | |
k = "MMredirectURL=" + B.location.toString().replace(/&/g, "%26") + "&MMplayerType=" + k + "&MMdoctitle=" + E.title; | |
typeof f.flashvars != A ? f.flashvars += "&" + k : f.flashvars = k; | |
if (J.ie && J.win && m.readyState != 4) k = E.createElement("div"), | |
b += "SWFObjectNew", k.setAttribute("id", b), m.parentNode.insertBefore(k, m), m.style.display = "none", | |
function () { | |
m.readyState == 4 ? m.parentNode.removeChild(m) : setTimeout(arguments.callee, 10) | |
}(); | |
p(a, f, b) | |
} | |
} | |
function m(a) { | |
if (J.ie && J.win && a.readyState != 4) { | |
var f = E.createElement("div"); | |
a.parentNode.insertBefore(f, a); | |
f.parentNode.replaceChild(o(a), f); | |
a.style.display = "none"; | |
(function () { | |
a.readyState == 4 ? a.parentNode.removeChild(a) : setTimeout(arguments.callee, 10) | |
})() | |
} else a.parentNode.replaceChild(o(a), a) | |
} | |
function o(a) { | |
var f = | |
E.createElement("div"); | |
if (J.win && J.ie) f.innerHTML = a.innerHTML; | |
else if (a = a.getElementsByTagName(x)[0]) | |
if (a = a.childNodes) | |
for (var b = a.length, k = 0; k < b; k++)!(a[k].nodeType == 1 && a[k].nodeName == "PARAM") && a[k].nodeType != 8 && f.appendChild(a[k].cloneNode(!0)); | |
return f | |
} | |
function p(a, f, b) { | |
var k, m = n(b); | |
if (J.wk && J.wk < 312) return k; | |
if (m) { | |
if (typeof a.id == A) a.id = b; | |
if (J.ie && J.win) { | |
var c = "", | |
h; | |
for (h in a) | |
if (a[h] != Object.prototype[h]) h.toLowerCase() == "data" ? f.movie = a[h] : h.toLowerCase() == "styleclass" ? c += ' class="' + a[h] + '"' : | |
h.toLowerCase() != "classid" && (c += " " + h + '="' + a[h] + '"'); | |
h = ""; | |
for (var d in f) f[d] != Object.prototype[d] && (h += '<param name="' + d + '" value="' + f[d] + '" />'); | |
m.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + c + ">" + h + "</object>"; | |
N[N.length] = a.id; | |
k = n(a.id) | |
} else { | |
d = E.createElement(x); | |
d.setAttribute("type", F); | |
for (var o in a) a[o] != Object.prototype[o] && (o.toLowerCase() == "styleclass" ? d.setAttribute("class", a[o]) : o.toLowerCase() != "classid" && d.setAttribute(o, a[o])); | |
for (c in f) f[c] != Object.prototype[c] && | |
c.toLowerCase() != "movie" && (a = d, h = c, o = f[c], b = E.createElement("param"), b.setAttribute("name", h), b.setAttribute("value", o), a.appendChild(b)); | |
m.parentNode.replaceChild(d, m); | |
k = d | |
} | |
} | |
return k | |
} | |
function q(a) { | |
var f = n(a); | |
if (f && f.nodeName == "OBJECT") J.ie && J.win ? (f.style.display = "none", function () { | |
if (f.readyState == 4) { | |
var b = n(a); | |
if (b) { | |
for (var k in b) typeof b[k] == "function" && (b[k] = null); | |
b.parentNode.removeChild(b) | |
} | |
} else setTimeout(arguments.callee, 10) | |
}()) : f.parentNode.removeChild(f) | |
} | |
function n(a) { | |
var f = null; | |
try { | |
f = E.getElementById(a) | |
} catch (b) {} | |
return f | |
} | |
function s(a, f, b) { | |
a.attachEvent(f, b); | |
M[M.length] = [a, f, b] | |
} | |
function t(a) { | |
var f = J.pv, | |
a = a.split("."); | |
a[0] = parseInt(a[0], 10); | |
a[1] = parseInt(a[1], 10) || 0; | |
a[2] = parseInt(a[2], 10) || 0; | |
return f[0] > a[0] || f[0] == a[0] && f[1] > a[1] || f[0] == a[0] && f[1] == a[1] && f[2] >= a[2] ? !0 : !1 | |
} | |
function u(a, f, b, k) { | |
if (!J.ie || !J.mac) { | |
var m = E.getElementsByTagName("head")[0]; | |
if (m) { | |
b = b && typeof b == "string" ? b : "screen"; | |
k && (T = R = null); | |
if (!R || T != b) k = E.createElement("style"), k.setAttribute("type", "text/css"), k.setAttribute("media", b), R = m.appendChild(k), | |
J.ie && J.win && typeof E.styleSheets != A && E.styleSheets.length > 0 && (R = E.styleSheets[E.styleSheets.length - 1]), T = b; | |
J.ie && J.win ? R && typeof R.addRule == x && R.addRule(a, f) : R && typeof E.createTextNode != A && R.appendChild(E.createTextNode(a + " {" + f + "}")) | |
} | |
} | |
} | |
function w(a, f) { | |
if (S) { | |
var b = f ? "visible" : "hidden"; | |
P && n(a) ? n(a).style.visibility = b : u("#" + a, "visibility:" + b) | |
} | |
} | |
function v(a) { | |
return /[\\\"<>\.;]/.exec(a) != null && typeof encodeURIComponent != A ? encodeURIComponent(a) : a | |
} | |
var A = "undefined", | |
x = "object", | |
F = "application/x-shockwave-flash", | |
G = "SWFObjectExprInst", | |
B = window, | |
E = document, | |
H = navigator, | |
I = !1, | |
K = [ | |
function () { | |
I ? h() : b() | |
} | |
], | |
L = [], | |
N = [], | |
M = [], | |
z, C, y, D, P = !1, | |
O = !1, | |
R, T, S = !0, | |
J = function () { | |
var a = typeof E.getElementById != A && typeof E.getElementsByTagName != A && typeof E.createElement != A, | |
f = H.userAgent.toLowerCase(), | |
b = H.platform.toLowerCase(), | |
k = b ? /win/.test(b) : /win/.test(f), | |
b = b ? /mac/.test(b) : /mac/.test(f), | |
f = /webkit/.test(f) ? parseFloat(f.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : !1, | |
m = !+"\u000b1", | |
c = [0, 0, 0], | |
h = null; | |
if (typeof H.plugins != A && typeof H.plugins["Shockwave Flash"] == | |
x) { | |
if ((h = H.plugins["Shockwave Flash"].description) && !(typeof H.mimeTypes != A && H.mimeTypes[F] && !H.mimeTypes[F].enabledPlugin)) I = !0, m = !1, h = h.replace(/^.*\s+(\S+\s+\S+$)/, "$1"), c[0] = parseInt(h.replace(/^(.*)\..*$/, "$1"), 10), c[1] = parseInt(h.replace(/^.*\.(.*)\s.*$/, "$1"), 10), c[2] = /[a-zA-Z]/.test(h) ? parseInt(h.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0 | |
} else if (typeof B.ActiveXObject != A) try { | |
var d = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); | |
if (d && (h = d.GetVariable("$version"))) m = !0, h = h.split(" ")[1].split(","), | |
c = [parseInt(h[0], 10), parseInt(h[1], 10), parseInt(h[2], 10)] | |
} catch (o) {} | |
return { | |
w3: a, | |
pv: c, | |
wk: f, | |
ie: m, | |
win: k, | |
mac: b | |
} | |
}(); | |
(function () { | |
J.w3 && ((typeof E.readyState != A && E.readyState == "complete" || typeof E.readyState == A && (E.getElementsByTagName("body")[0] || E.body)) && d(), P || (typeof E.addEventListener != A && E.addEventListener("DOMContentLoaded", d, !1), J.ie && J.win && (E.attachEvent("onreadystatechange", function () { | |
E.readyState == "complete" && (E.detachEvent("onreadystatechange", arguments.callee), d()) | |
}), B == top && function () { | |
if (!P) { | |
try { | |
E.documentElement.doScroll("left") | |
} catch (a) { | |
setTimeout(arguments.callee, | |
0); | |
return | |
} | |
d() | |
} | |
}()), J.wk && function () { | |
P || (/loaded|complete/.test(E.readyState) ? d() : setTimeout(arguments.callee, 0)) | |
}(), c(d))) | |
})(); | |
(function () { | |
J.ie && J.win && window.attachEvent("onunload", function () { | |
for (var a = M.length, f = 0; f < a; f++) M[f][0].detachEvent(M[f][1], M[f][2]); | |
a = N.length; | |
for (f = 0; f < a; f++) q(N[f]); | |
for (var b in J) J[b] = null; | |
J = null; | |
for (var k in swfobject) swfobject[k] = null; | |
swfobject = null | |
}) | |
})(); | |
return { | |
registerObject: function (a, f, b, k) { | |
if (J.w3 && a && f) { | |
var m = {}; | |
m.id = a; | |
m.swfVersion = f; | |
m.expressInstall = b; | |
m.callbackFn = | |
k; | |
L[L.length] = m; | |
w(a, !1) | |
} else k && k({ | |
success: !1, | |
id: a | |
}) | |
}, | |
getObjectById: function (f) { | |
if (J.w3) return a(f) | |
}, | |
embedSWF: function (a, b, m, c, h, d, o, q, n, s) { | |
var u = { | |
success: !1, | |
id: b | |
}; | |
J.w3 && !(J.wk && J.wk < 312) && a && b && m && c && h ? (w(b, !1), g(function () { | |
m += ""; | |
c += ""; | |
var g = {}; | |
if (n && typeof n === x) | |
for (var v in n) g[v] = n[v]; | |
g.data = a; | |
g.width = m; | |
g.height = c; | |
v = {}; | |
if (q && typeof q === x) | |
for (var F in q) v[F] = q[F]; | |
if (o && typeof o === x) | |
for (var K in o) typeof v.flashvars != A ? v.flashvars += "&" + K + "=" + o[K] : v.flashvars = K + "=" + o[K]; | |
if (t(h)) F = p(g, v, b), g.id == | |
b && w(b, !0), u.success = !0, u.ref = F; | |
else if (d && f()) { | |
g.data = d; | |
k(g, v, b, s); | |
return | |
} else w(b, !0); | |
s && s(u) | |
})) : s && s(u) | |
}, | |
switchOffAutoHideShow: function () { | |
S = !1 | |
}, | |
ua: J, | |
getFlashPlayerVersion: function () { | |
return { | |
major: J.pv[0], | |
minor: J.pv[1], | |
release: J.pv[2] | |
} | |
}, | |
hasFlashPlayerVersion: t, | |
createSWF: function (a, f, b) { | |
if (J.w3) return p(a, f, b) | |
}, | |
showExpressInstall: function (a, b, m, c) { | |
J.w3 && f() && k(a, b, m, c) | |
}, | |
removeSWF: function (a) { | |
J.w3 && q(a) | |
}, | |
createCSS: function (a, f, b, k) { | |
J.w3 && u(a, f, b, k) | |
}, | |
addDomLoadEvent: g, | |
addLoadEvent: c, | |
getQueryParamValue: function (a) { | |
var f = | |
E.location.search || E.location.hash; | |
if (f) { | |
/\?/.test(f) && (f = f.split("?")[1]); | |
if (a == null) return v(f); | |
for (var f = f.split("&"), b = 0; b < f.length; b++) | |
if (f[b].substring(0, f[b].indexOf("=")) == a) return v(f[b].substring(f[b].indexOf("=") + 1)) | |
} | |
return "" | |
}, | |
expressInstallCallback: function () { | |
if (O) { | |
var a = n(G); | |
if (a && z) { | |
a.parentNode.replaceChild(z, a); | |
if (C && (w(C, !0), J.ie && J.win)) z.style.display = "block"; | |
y && y(D) | |
} | |
O = !1 | |
} | |
} | |
} | |
}(), | |
Spotify = Spotify || {}; | |
Spotify.Cache = Spotify.Cache || {}; | |
Spotify.Logging = Spotify.Logging || {}; | |
Spotify.App = Spotify.App || {}; | |
Spotify.Utils = Spotify.Utils || {}; | |
Spotify.Flash = Spotify.Flash || {}; | |
Spotify.Services = Spotify.Services || {}; | |
Spotify.Services.CollectionStorageImplementation = Spotify.Services.CollectionStorageImplementation || {}; | |
Spotify.Services.CollectionSuggestionsImplementation = Spotify.Services.CollectionSuggestionsImplementation || {}; | |
Spotify.Services.CollectionViewImplementation = Spotify.Services.CollectionViewImplementation || {}; | |
Spotify.Services.CurrentFavoritesImplementation = Spotify.Services.CurrentFavoritesImplementation || {}; | |
Spotify.WebSockets = Spotify.WebSockets || {}; | |
Spotify.Protobuf = Spotify.Protobuf || {}; | |
Spotify.Hermes = Spotify.Hermes || {}; | |
Spotify.Parsers = Spotify.Parsers || {}; | |
Spotify.Models = Spotify.Models || {}; | |
Spotify.HTML5 = Spotify.HTML5 || {}; | |
Spotify.Audio = Spotify.Audio || {}; | |
Spotify.Proto = Spotify.Proto || {}; | |
Spotify.Errors = Spotify.Errors || {}; | |
Spotify.Errors.Domains = Spotify.Errors.Domains || {}; | |
Spotify.Errors.Codes = Spotify.Errors.Codes || {}; | |
Spotify.Calls = Spotify.Calls || {}; | |
Spotify.Managers = Spotify.Managers || {}; | |
DebuggerJS = Spotify.DebuggerJS = new function () { | |
this.Parsers = {}; | |
this.Loggers = {}; | |
this.Parsers = {}; | |
this.Utils = { | |
isArray: Array.isArray || function (c) { | |
return Object.prototype.toString.call(c) == "[object Array]" | |
} | |
}; | |
var d = {}, g = {}; | |
this.register = function (c, h, b) { | |
if (typeof c !== "string" || typeof h === "undefined" || h === null) throw Error("Not valid arguments"); | |
d[c] || (d[c] = h); | |
g[c] || (g[c] = b || new DebuggerJS.Parsers.Console); | |
return !0 | |
}; | |
this.log = function () {}; | |
this.warn = function () {}; | |
this.error = function () {}; | |
this.on = function (c, h) { | |
if (typeof c !== | |
"undefined" && !DebuggerJS.Utils.isArray(c) && c !== null) throw Error("The modules argument should be an array"); | |
if (typeof h !== "undefined" && !DebuggerJS.Utils.isArray(h) && h !== null) throw Error("The tags argument should be an array"); | |
}; | |
this.off = function () {} | |
}; | |
DebuggerJS.Parsers.Default = function () { | |
this.parse = function (d, g, c) { | |
d += " |"; | |
return [d].concat(g).concat("| Tag: " + c) | |
} | |
}; | |
DebuggerJS.Loggers.Console = function () { | |
this.log = function () { | |
console.log.apply(console, arguments); | |
return !0 | |
}; | |
this.error = function () { | |
console.error.apply(console, arguments); | |
return !0 | |
}; | |
this.warn = function () { | |
console.warn.apply(console, arguments); | |
return !0 | |
} | |
}; | |
DebuggerJS.Loggers.Memory = function () { | |
this.log = function () { | |
return !0 | |
}; | |
this.error = function () { | |
return !0 | |
}; | |
this.warn = function () { | |
return !0 | |
} | |
}; | |
Spotify.Storage = { | |
localStorage: null, | |
indexedDB: { | |
storage: null, | |
IDBKeyRange: null, | |
IDBTransaction: null | |
} | |
}; | |
(function () { | |
var d = [].slice; | |
if (!("bind" in Function.prototype)) Function.prototype.bind = function (c) { | |
var h = this, | |
b = null; | |
arguments.length > 1 && (b = d.call(arguments, 1)); | |
return function () { | |
var a; | |
!arguments.length && !b ? a = h.call(c) : h.apply(c, !b ? arguments : !arguments.length ? b : b.concat(d.call(arguments))); | |
return a | |
} | |
}; | |
if (!("indexOf" in Array.prototype)) Array.prototype.indexOf = function () { | |
for (var c = this.length >>> 0, h = from < 0 ? Math.max(0, c + from) : from || 0; h < c; h++) | |
if (this[h] === item) return h; | |
return -1 | |
}; | |
var g; | |
Spotify.Utils = { | |
isArray: Array.isArray || function (c) { | |
return Object.prototype.toString.call(c) == "[object Array]" | |
}, | |
inherit: function (c, h) { | |
function b() {} | |
b.prototype = new c; | |
h.prototype = new b; | |
return h.prototype.constructor = h | |
}, | |
isFunction: function (c) { | |
return typeof c == "function" | |
}, | |
toFixed: function (c, h) { | |
var h = h || 0, | |
b = c < 0, | |
a = Math.pow(10, h), | |
c = Math.round(c * a), | |
f = String((b ? Math.ceil : Math.floor)(c / a)), | |
b = String((b ? -c : c) % a), | |
a = Array(Math.max(h - b.length, 0) + 1).join("0"); | |
return h ? f + "." + a + b : f | |
}, | |
convertStringToXML: function (c) { | |
if (window.DOMParser) return g = new DOMParser, | |
g.parseFromString(c.replace(/\n/g, ""), "text/xml"); | |
else { | |
var h = new ActiveXObject("Microsoft.XMLDOM"); | |
h.async = !1; | |
return h.loadXML(c.replace(/\n/g, "")) | |
} | |
}, | |
convertXMLToJSON: function (c) { | |
var h = {}, b = c.nodeType == 1 && c.attributes.length > 0, | |
a = c.hasChildNodes(); | |
if (!b && !a) return c.data || ""; | |
if (b) { | |
h["@attributes"] = {}; | |
for (b = 0; b < c.attributes.length; b++) { | |
var f = c.attributes.item(b); | |
h["@attributes"][f.nodeName] = f.nodeValue | |
} | |
} | |
if (a) { | |
if (c.childNodes.length == 1 && c.childNodes[0].nodeName == "#text") return c.childNodes[0].data; | |
for (a = | |
0; a < c.childNodes.length; a++) f = c.childNodes[a], b = f.nodeName, f = this.convertXMLToJSON(f), b != "#text" && (typeof h[b] === "undefined" ? h[b] = f : (this.isArray(h[b]) || (h[b] = Array(h[b])), h[b].push(f))) | |
} | |
return h | |
}, | |
hex2str: function (c) { | |
for (var h = [], b = 0, a = c.length; b < a - 1; b += 2) h.push(String.fromCharCode(parseInt(c.substr(b, 2), 16))); | |
return h.join("") | |
}, | |
str2hex: function (c) { | |
for (var h = "", b = 0, a = c.length; b < a; ++b) h += (c.charCodeAt(b) + 256).toString(16).slice(-2); | |
return h | |
}, | |
parseURL: function (c) { | |
for (var h = "source,protocol,authority,userInfo,user,password,host,port,relative,path,directory,file,query,anchor".split(","), | |
c = RegExp("^(?:(?![^:@]+:[^:@/]*@)([^:/?#.]+):)?(?://)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:/?#]*)(?::(\\d*))?)(((/(?:[^?#](?![^?#/]*\\.[^?#/.]+(?:[?#]|$)))*/?)?([^?#/]*))(?:\\?([^#]*))?(?:#(.*))?)").exec(c), b = {}, a = 14; a--;) b[h[a]] = c[a] || ""; | |
b.queryKey = {}; | |
b[h[12]].replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function (a, k, m) { | |
k && (b.queryKey[k] = m) | |
}); | |
return b | |
} | |
} | |
})(); | |
Spotify.Utils.Base62 = function () { | |
function d(a, b, m) { | |
for (var c = [0], h = [1], d = 0; d < a.length; ++d) { | |
for (var g = c, s = h, t = a[d], u = m, w = 0, v = 0; v < s.length; ++v) w = ~~g[v] + s[v] * t + w, g[v] = w % u, w = ~~ (w / u); | |
for (; w;) w = ~~g[v] + w, g[v] = w % u, w = ~~ (w / u), ++v; | |
g = h; | |
s = b; | |
t = m; | |
for (u = v = 0; u < g.length; ++u) v = g[u] * s + v, g[u] = v % t, v = ~~ (v / t); | |
for (; v;) g.push(v % t), v = ~~ (v / t) | |
} | |
return c | |
} | |
function g(a, b) { | |
for (var m = 0, c = []; m < a.length; ++m) c.push(b[a[m]]); | |
return c.reverse() | |
} | |
function c(a, b) { | |
for (; a.length < b;) a.push(0); | |
return a | |
} | |
for (var h = {}, b = {}, a = 0; a < 62; ++a) b["0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" [a]] = | |
a; | |
for (a = 0; a < 16; ++a) h["0123456789abcdef" [a]] = a; | |
for (a = 0; a < 16; ++a) h["0123456789ABCDEF" [a]] = a; | |
return { | |
fromBytes: function (a, b) { | |
var m = d(a.slice(0).reverse(), 256, 62); | |
return g(c(m, b), "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ").join("") | |
}, | |
toBytes: function (a, k) { | |
var m = d(g(a, b), 62, 256); | |
return c(m, k).reverse() | |
}, | |
toHex: function (a, k) { | |
var m = d(g(a, b), 62, 16); | |
return g(c(m, k), "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ").join("") | |
}, | |
fromHex: function (a, b) { | |
var m = d(g(a, h), 16, 62); | |
return g(c(m, | |
b), "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ").join("") | |
} | |
} | |
}(); | |
Spotify.Utils.Base64 = function () { | |
for (var d = [], g = 0; g < 256; ++g) d[g] = 255; | |
for (g = 0; g < 64; ++g) d["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charCodeAt(g)] = g; | |
var c = String.fromCharCode.apply(String, d); | |
return { | |
encode: function (c) { | |
var b, a, f, k, m, d; | |
f = c.length; | |
a = 0; | |
for (b = ""; a < f;) { | |
k = c.charCodeAt(a++) & 255; | |
if (a == f) { | |
b += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(k >> 2); | |
b += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((k & 3) << 4); | |
b += "=="; | |
break | |
} | |
m = | |
c.charCodeAt(a++); | |
if (a == f) { | |
b += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(k >> 2); | |
b += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((k & 3) << 4 | (m & 240) >> 4); | |
b += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((m & 15) << 2); | |
b += "="; | |
break | |
} | |
d = c.charCodeAt(a++); | |
b += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(k >> 2); | |
b += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((k & 3) << 4 | (m & | |
240) >> 4); | |
b += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((m & 15) << 2 | (d & 192) >> 6); | |
b += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d & 63) | |
} | |
return b | |
}, | |
decode: function (h) { | |
for (var b = [], a = h.length, f, k, m = 0;;) { | |
do f = c.charCodeAt(h.charCodeAt(m++) & 255); while (f === 255 && m < a); | |
do k = c.charCodeAt(h.charCodeAt(m++) & 255); while (k === 255 && m < a); | |
if (k === 255) break; | |
b.push((f << 2 | k >> 4) & 255); | |
do f = c.charCodeAt(h.charCodeAt(m++) & 255); while (f === 255 && m < a); | |
if (f === 255) break; | |
b.push((k << | |
4 | f >> 2) & 255); | |
do k = c.charCodeAt(h.charCodeAt(m++) & 255); while (k === 255 && m < a); | |
if (k === 255) break; | |
b.push((f << 6 | k) & 255) | |
} | |
if (b.length < 4096) b = String.fromCharCode.apply(String, b); | |
else { | |
h = 0; | |
a = []; | |
do a.push(String.fromCharCode.apply(String, b.slice(h, h + 4096))), h += 4096; while (h < b.length); | |
b = a.join("") | |
} | |
return b | |
} | |
} | |
}(); | |
Spotify.Calls.Hermes = function (d, g, c) { | |
this.calleeId = ""; | |
this.success = g || function () {}; | |
this.error = c || function () {}; | |
this.type = d.type || ""; | |
this.persistent = typeof d.persistent === "undefined" ? !0 : d.persistent; | |
this.bypassCache = typeof d.bypassCache === "undefined" ? !1 : d.bypassCache; | |
this.context = d.context || null; | |
this.isMultiGet = typeof d.isMultiGet === "undefined" ? !1 : d.isMultiGet; | |
this.header = { | |
uri: "", | |
method: "", | |
source: "", | |
content_type: this.isMultiGet ? "vnd.spotify/mercury-mget-request" : "" | |
}; | |
this.payload = []; | |
this.payloadSchemas = []; | |
this.responseSchemas = []; | |
this.mercuryMultiGetPayloadSchemas = ["mercury#MercuryMultiGetRequest"]; | |
this.mercuryMultiGetResponseSchemas = ["mercury#MercuryMultiGetReply"]; | |
if (d.header) this.header.uri = d.header.uri || "", this.header.method = d.header.method || "", this.header.source = d.header.source || ""; | |
this.payload = d.payload || []; | |
this.payloadSchemas = d.payloadSchemas || []; | |
this.responseSchemas = d.responseSchemas || [] | |
}; | |
Spotify.Calls.Simple = function (d, g, c) { | |
this.calleeId = ""; | |
this.success = g || function () {}; | |
this.error = c || function () {}; | |
this.type = d.type || ""; | |
this.payload = d.payload || []; | |
this.persistent = d.persistent || !0; | |
this.bypassCache = d.bypassCache || !1; | |
this.method = d.method || ""; | |
this.context = d.context || null; | |
this.retries = d.retries || 2 | |
}; | |
Spotify.Errors.Domains.HERMES_ERROR = 13; | |
Spotify.Errors.Domains.HERMES_SERVICE_ERROR = 14; | |
Spotify.Errors.Codes.HM_TOO_MANY_REQUESTS = 429; | |
Spotify.Errors.Codes.HM_TIMEOUT = 408; | |
Spotify.Errors.Codes.HM_FAILED_TO_SEND_TO_BACKEND = 1; | |
Spotify.Errors.Domains.TRACK_ERROR = 12; | |
Spotify.Errors.Codes.TRACK_REQUEST_RATE_LIMITED = 8; | |
Spotify.Errors.Codes.TRACK_CAP = 11; | |
Spotify.Errors.Codes.TIME_CAP = 12; | |
Spotify.Errors.Codes.ADS_ERROR = 15; | |
Spotify.Errors.Codes.ADS_SERVER_ERROR = 500; | |
Spotify.Errors.Codes.ADS_NOT_FOUND = 404; | |
Spotify.Errors.Error = function (d) { | |
d = d || []; | |
this.domain = d[0] || 0; | |
this.code = d[1] || 0; | |
this.description = d[2] || ""; | |
this.data = d[3] || null | |
}; | |
Spotify.RateLimiter = function (d, g) { | |
Spotify.EventTarget.call(this); | |
var c = this, | |
h = !1, | |
b = [], | |
a = new Spotify.Events, | |
f = 0; | |
this.totalPendingRequests = function () { | |
return b.length | |
}; | |
this.getItemAtIndex = function (a) { | |
return b[a] | |
}; | |
this.addToBucket = function (a, f) { | |
typeof f === "undefined" && (f = !0); | |
typeof a !== "undefined" && (f ? b.push(a) : b[0] = a) | |
}; | |
this.isStarted = function () { | |
return h | |
}; | |
this.start = function () { | |
h || (h = !0, clearInterval(f), f = setInterval(k, d)) | |
}; | |
var k = function () { | |
var k = 0, | |
d, p = g; | |
if (g > b.length) p = b.length; | |
for (; k < p; k++) d = b.shift(), | |
c.trigger(a.RATE_LIMIT_CALL, d); | |
c.trigger(a.RATE_LIMIT_AFTER_INTERVAL); | |
b.length === 0 && (h = !1, clearInterval(f), c.trigger(a.RATE_LIMIT_DISABLED)) | |
} | |
}; | |
Spotify.CallsManager = function () { | |
var d = 0, | |
g = {}, c = [0]; | |
this.addCall = function (c, b, a, f, k, m, o, p) { | |
var q = (new Date).getTime(); | |
d++; | |
g[d] = { | |
method: c, | |
params: b, | |
callback: a, | |
errback: f, | |
context: k, | |
persistent: m, | |
retries: typeof o === "undefined" ? 2 : o, | |
timestamp: q, | |
callType: p | |
}; | |
return d | |
}; | |
this.getCall = function (c, b) { | |
typeof b === "undefined" && (b = !0); | |
if (typeof g[c] !== void 0) { | |
var a = g[c]; | |
b && delete g[c]; | |
return a | |
} | |
}; | |
this.getCalls = function () { | |
var c, b, a = []; | |
for (b in g) c = b, c = this.getCall(c), c.retries > 0 && a.push(c); | |
return a | |
}; | |
this.getPersistentCalls = | |
function () { | |
for (var h = 0, b = c.length, a, f = []; h < b; h++) c[h] !== null && c[h] !== 0 && (a = c[h], f.push(this.getCall(a))); | |
c = [0]; | |
return f | |
}; | |
this.setPersistent = function (h, b) { | |
b === !0 ? c.push(h) : c[0] = h | |
} | |
}; | |
Spotify.Managers.ProtobufSchemasManager = function () { | |
var d = Spotify.DebuggerJS, | |
g = {}; | |
this.registerSchema = function (c, h) { | |
d.log("Spotify.Managers.ProtobufSchemasManager", ["Registering schema with id", c], "corejs"); | |
typeof g[c] !== "undefined" ? d.error("Spotify.Managers.ProtobufSchemasManager", ["Schema with id", c, "already exists"], "corejs") : (g[c] = new Spotify.Protobuf.Schema([], null, null, null), g[c].id = c, g[c].type = "proto", g[c].setData(h), g[c].encode()) | |
}; | |
this.getProtobufMsgParser = function (c, h) { | |
return typeof g[c] === | |
"undefined" ? null : g[c].msg(h) | |
} | |
}; | |
Spotify.ConnectionManager = function () { | |
Spotify.EventTarget.call(this); | |
var d = this, | |
g = 0, | |
c, h = new Spotify.Events, | |
b, a = function () { | |
d.trigger(h.ON_TRY_TO_CONNECT) | |
}, f = function () { | |
g = 0; | |
typeof c !== "undefined" && clearTimeout(c) | |
}; | |
this.reset = function () { | |
typeof c !== "undefined" && clearTimeout(c); | |
g = 0; | |
c = setTimeout(a, 0) | |
}; | |
var k = function (f) { | |
var b = []; | |
typeof f !== "undefined" && (b = f.params || []); | |
f = Math.pow(2, g) * 1E3; | |
g % 4 === 0 && g !== 0 && d.trigger(h.NOTIFY_OF_DISCONNECT, b); | |
f > 3E4 && (f = 3E4); | |
g++; | |
c && clearTimeout(c); | |
f === 1E3 && (f = 0); | |
c = setTimeout(a, | |
f) | |
}; | |
this.initialize = function (a) { | |
b = a; | |
b.bind(h.CONNECTION_ESTABLISHED, f, this); | |
b.bind(h.FAILED_CONNECTING, k, this) | |
} | |
}; | |
Spotify.Worker = function () { | |
Spotify.EventTarget.call(this); | |
var d = this, | |
g, c, h, b = new Spotify.Events, | |
a = function (a) { | |
eval(a.params) | |
}, f = function () {}, k = function () {}; | |
this.reply = function () { | |
var a = Array.prototype.slice.call(arguments); | |
h.rpc("work_done", a, k, f, d, !1, 0, "work_done") | |
}; | |
this.run = function (a) { | |
c.onReady(function () { | |
var f = "undefined 0"; | |
g || (g = c.getInterface()); | |
try { | |
f = g.run(a) | |
} catch (b) {} | |
h.rpc("pong_flash", [f], function () {}, function () {}, d, !1, 0, "pong_flash") | |
}, this) | |
}; | |
this.initialize = function (f, k) { | |
h = f; | |
c = k; | |
h.bind(b.WORK, | |
a, this); | |
h.bind(b.PING_FLASH, a, this) | |
} | |
}; | |
(function () { | |
Spotify.LinkedList = function () { | |
this.length = 0; | |
this.last = this.first = null | |
}; | |
Spotify.LinkedList.prototype.append = function (d) { | |
if (d === null) throw Error("Node is null!"); | |
if (d.list !== null) throw Error("Node already exists in another list!"); | |
d.list = this; | |
this.first === null ? this.first = d : (d.prev = this.last, d.next = null, this.last.next = d); | |
this.last = d; | |
this.length++ | |
}; | |
Spotify.LinkedList.prototype.insertAfter = function (d, g) { | |
if (d === null || g === null) throw Error("Node is null!"); | |
if (g.list !== null) throw Error("Node already exists in another list!"); | |
g.list = this; | |
g.prev = d; | |
g.next = d.next; | |
d.next.prev = g; | |
d.next = g; | |
if (g.prev === this.last) this.last = g; | |
this.length++ | |
}; | |
Spotify.LinkedList.prototype.remove = function (d) { | |
if (d === null) throw Error("Node is null!"); | |
if (this.length == 0 || d.list !== this) return !1; | |
else if (this.length > 1) { | |
if (d.prev !== null) d.prev.next = d.next; | |
if (d.next !== null) d.next.prev = d.prev; | |
if (d === this.first) this.first = d.next; | |
else if (d === this.last) this.last = d.prev | |
} else this.last = this.first = null; | |
delete d.list; | |
delete d.prev; | |
delete d.next; | |
d.list = null; | |
d.prev = null; | |
d.next = null; | |
this.length--; | |
return !0 | |
}; | |
Spotify.LinkedList.Node = function (d) { | |
this.next = this.prev = this.list = null; | |
this.value = d || null | |
} | |
})(); | |
(function () { | |
Spotify.SimpleCache = function (d) { | |
this._limit = d || 100; | |
this._map = {}; | |
this._lru = new Spotify.LinkedList; | |
this._stats = { | |
hits: 0, | |
misses: 0 | |
} | |
}; | |
Spotify.SimpleCache.prototype.get = function (d) { | |
if (d = this._map[d]) return this._lru.remove(d), this._lru.append(d), this._stats.hits++, d.value; | |
this._stats.misses++; | |
return null | |
}; | |
Spotify.SimpleCache.prototype.put = function (d, g) { | |
if (typeof d == "undefined" || d == null || d == "") throw Error("Cache key can't be empty!"); | |
this._lru.length >= this._limit && (delete this._map[this._lru.first.key], | |
this._lru.remove(this._lru.first)); | |
var c = this._map[d]; | |
c ? (this._lru.remove(c), c.value = g) : (c = new Spotify.LinkedList.Node(g), c.key = d); | |
this._lru.append(c); | |
this._map[d] = c | |
}; | |
Spotify.SimpleCache.prototype.remove = function (d) { | |
var g = this._map[d]; | |
return g ? (this._lru.remove(g), delete this._map[d], g.value) : null | |
}; | |
Spotify.SimpleCache.prototype.removeAllContaining = function (d) { | |
var g, c = [], | |
h; | |
for (h in this._map) | |
if (h.indexOf(d) >= 0 && (g = this._map[h])) this._lru.remove(g), delete this._map[h], c.push(h); | |
return c | |
}; | |
Spotify.SimpleCache.prototype.size = | |
function () { | |
return this._lru.length | |
}; | |
Spotify.SimpleCache.prototype.clear = function () { | |
this._lru = new Spotify.LinkedList; | |
this._map = {} | |
} | |
})(); | |
Spotify.Cache.PackageStore = function (d) { | |
var g = function (a) { | |
return a | |
}, c = function (a) { | |
return a | |
}, h = "PackageStore", | |
b = function () { | |
var a = {}; | |
Spotify.Storage.localStorage.getItem(h) !== null && (a = JSON.parse(c(Spotify.Storage.localStorage.getItem(h)))); | |
return a | |
}; | |
if (typeof d !== "undefined") typeof d.storageKey !== "undefined" && (h = d.storageKey), typeof d.encrypt === "function" && (g = d.encrypt), typeof d.decrypt === "function" && (c = d.decrypt); | |
this.setItem = function (a, f) { | |
var k = b(); | |
k[a] = f; | |
return Spotify.Storage.localStorage.setItem(h, | |
g(JSON.stringify(k))) | |
}; | |
this.getItem = function (a) { | |
var f = b(); | |
return typeof f[a] === "undefined" ? null : f[a] | |
}; | |
this.removeItem = function (a) { | |
var f = b(); | |
delete f[a]; | |
return Spotify.Storage.localStorage.setItem(h, g(JSON.stringify(f))) | |
}; | |
this.clear = function () { | |
return Spotify.Storage.localStorage.removeItem(h) | |
}; | |
this.length = function () { | |
var a = b(), | |
f = 0, | |
k; | |
for (k in a) a.hasOwnProperty(k) && (f += 1); | |
return f | |
}; | |
this.key = function (a) { | |
var f = b(), | |
k = 0, | |
m; | |
for (m in f) | |
if (f.hasOwnProperty(m)) { | |
if (k === a) return m; | |
k += 1 | |
} | |
return null | |
} | |
}; | |
Spotify.Cache.Default = function (d, g) { | |
this._limit = d || 100; | |
this._storage = g || new Spotify.Cache.MemoryStorage; | |
this._keyToNode = {}; | |
this._lru = new Spotify.LinkedList; | |
this._stats = { | |
hits: 0, | |
misses: 0 | |
}; | |
this.initialize = function (c, h, b) { | |
if (!Spotify.Utils.isFunction(c) || !Spotify.Utils.isFunction(h)) throw new TypeError("Argument is not a function!"); | |
var a = function (a, f) { | |
var b = new Spotify.LinkedList.Node(f); | |
b.key = a; | |
this._lru.append(b); | |
this._keyToNode[a] = b | |
}, f = function () { | |
c.call(b, this) | |
}; | |
this._storage.initialize(function () { | |
this._storage.each(a, | |
f, this) | |
}, h, this) | |
}; | |
this.get = function (c, h, b) { | |
if (!Spotify.Utils.isFunction(h)) throw new TypeError("Argument is not a function!"); | |
this._storage.get(c, function (a, f) { | |
var k = this._keyToNode[a] || null; | |
f !== null && k !== null ? (this._lru.remove(k), this._lru.append(k), this._stats.hits++, h.call(b, a, f)) : (this._stats.misses++, h.call(b, a, null)) | |
}, this) | |
}; | |
this.put = function (c, h, b, a, f, k) { | |
if (typeof c == "undefined" || c == null || c == "") throw Error("Cache key can't be empty!"); | |
var m = function (c, d, g) { | |
if (d === null) | |
if (Spotify.Utils.isFunction(f) && | |
f.call(k, g), d = Math.floor(this._lru.length * 0.9), d == 0) a.call(k, c, null); | |
else { | |
for (; this._lru.length > d;) this._storage.remove(this._lru.first.key), this._lru.remove(this._lru.first); | |
this._storage.set(c, h, m, this) | |
} else Spotify.Utils.isFunction(b) && b.call(k, c, d) | |
}; | |
this._lru.length >= this._limit && (this._storage.remove(this._lru.first.key), this._lru.remove(this._lru.first)); | |
this._storage.get(c, function (a, f) { | |
var b = this._keyToNode[a] || null; | |
f !== null && b !== null ? (this._lru.remove(b), b.value = h) : (b = new Spotify.LinkedList.Node(h), | |
b.key = a); | |
this._lru.append(b); | |
this._keyToNode[a] = b; | |
this._storage.set(a, h, m, this) | |
}, this) | |
}; | |
this.remove = function (c, h, b) { | |
this._storage.get(c, function (a, f) { | |
var k = this._keyToNode[a] || null; | |
f !== null && k !== null ? (this._lru.remove(k), this._storage.remove(a, h, b)) : Spotify.Utils.isFunction(h) && h.call(b, a) | |
}, this) | |
}; | |
this.removeAllContaining = function (c, h, b) { | |
this._storage.removeAllContaining(c, function (a) { | |
for (var f = 0; f < a.length; f++) { | |
var k = this._keyToNode[a[f]] || null; | |
k !== null && this._lru.remove(k) | |
} | |
Spotify.Utils.isFunction(h) && | |
h.call(b, a) | |
}, this) | |
}; | |
this.size = function () { | |
return this._lru.length | |
}; | |
this.clear = function (c, h) { | |
this._lru = new Spotify.LinkedList; | |
this._storage.clear(c, h) | |
} | |
}; | |
Spotify.Cache.DummyStorage = function () { | |
this.initialize = function (d, g, c) { | |
if (!Spotify.Utils.isFunction(d) || !Spotify.Utils.isFunction(g)) throw new TypeError("Argument is not a function!"); | |
g.call(c) | |
}; | |
this.isSupported = function () { | |
return !0 | |
} | |
}; | |
Spotify.Cache.MemoryStorage = function () { | |
this._data = {}; | |
this.get = function (d, g, c) { | |
if (!Spotify.Utils.isFunction(g)) throw new TypeError(ERROR_NOT_A_FUNCTION); | |
g.call(c, d, this._data[d] || null) | |
}; | |
this.set = function (d, g, c, h) { | |
this._data[d] = g; | |
Spotify.Utils.isFunction(c) && c.call(h, d, g) | |
}; | |
this.remove = function (d, g, c) { | |
delete this._data[d]; | |
Spotify.Utils.isFunction(g) && g.call(c, d) | |
}; | |
this.removeAllContaining = function (d, g, c) { | |
var h = [], | |
b = this._data, | |
a; | |
for (a in b) a.indexOf(d) >= 0 && (h.push(a), delete this._data[a]); | |
Spotify.Utils.isFunction(g) && | |
g.call(c, h) | |
}; | |
this.clear = function (d, g) { | |
this._data = {}; | |
Spotify.Utils.isFunction(d) && d.call(g) | |
}; | |
this.each = function (d, g, c) { | |
if (!Spotify.Utils.isFunction(d)) throw new TypeError(ERROR_NOT_A_FUNCTION); | |
var h = this._data, | |
b; | |
for (b in h) d.call(c, b, h[b]); | |
Spotify.Utils.isFunction(g) && g.call(c) | |
}; | |
this.initialize = function (d, g, c) { | |
if (!Spotify.Utils.isFunction(d) || !Spotify.Utils.isFunction(g)) throw new TypeError(ERROR_NOT_A_FUNCTION); | |
d.call(c) | |
}; | |
this.isSupported = function () { | |
return !0 | |
} | |
}; | |
Spotify.Cache.LocalStorage = function (d) { | |
this._prefix = "com.spotify.cache." + (d || "generic") + "."; | |
this.get = function (d, c, h) { | |
if (!Spotify.Utils.isFunction(c)) throw new TypeError("Argument is not a function!"); | |
var b = Spotify.Storage.localStorage.getItem(this._prefix + d); | |
c.call(h, d, b ? JSON.parse(b) : null) | |
}; | |
this.set = function (d, c, h, b) { | |
try { | |
Spotify.Storage.localStorage.setItem(this._prefix + d, JSON.stringify(c)), Spotify.Utils.isFunction(h) && h.call(b, d, c) | |
} catch (a) { | |
Spotify.Utils.isFunction(h) && h.call(b, d, null, a) | |
} | |
}; | |
this.remove = | |
function (d, c, h) { | |
Spotify.Storage.localStorage.removeItem(this._prefix + d); | |
Spotify.Utils.isFunction(c) && c.call(h, d) | |
}; | |
this.removeAllContaining = function (d, c, h) { | |
for (var b = [], a = Spotify.Storage.localStorage, d = this._prefix + d, f, k = 0, m = a.length; k < m; k++) f = a.key(k), f.indexOf(d) >= 0 && (b.push(f.substring(this._prefix.length)), a.removeItem(f), k--, m--); | |
Spotify.Utils.isFunction(c) && c.call(h, b) | |
}; | |
this.clear = function (d, c) { | |
for (var h = Spotify.Storage.localStorage, b = h.length - 1; b >= 0; --b) { | |
var a = h.key(b); | |
a.indexOf(this._prefix) == | |
0 && h.removeItem(a) | |
} | |
Spotify.Utils.isFunction(d) && d.call(c) | |
}; | |
this.each = function (d, c, h) { | |
if (!Spotify.Utils.isFunction(d)) throw new TypeError("Argument is not a function!"); | |
for (var b = Spotify.Storage.localStorage, a = 0, f = b.length; a < f; ++a) { | |
var k = b.key(a); | |
if (k.indexOf(this._prefix) == 0) { | |
var m = b.getItem(k); | |
d.call(h, k.slice(this._prefix.length), m ? JSON.parse(m) : null) | |
} | |
} | |
Spotify.Utils.isFunction(c) && c.call(h) | |
}; | |
this.initialize = function (d, c, h) { | |
if (!Spotify.Utils.isFunction(d) || !Spotify.Utils.isFunction(c)) throw new TypeError("Argument is not a function!"); | |
d.call(h) | |
}; | |
this.isSupported = function () { | |
return typeof Spotify.Storage.localStorage !== "undefined" | |
} | |
}; | |
Spotify.Cache.IndexedDBStorage = function (d) { | |
var g = null, | |
c = function (b, a, f, k, m) { | |
var c = Spotify.Storage.indexedDB.storage.open(b, a); | |
c.onsuccess = function (c) { | |
var h = c.target.result; | |
Spotify.Utils.isFunction(h.setVersion) ? (c = parseInt(h.version || "0", 10), c < a ? (c = h.setVersion(a.toString()), c.onsuccess = function () { | |
h.objectStoreNames.contains(b) || h.createObjectStore(b); | |
f.call(m, h) | |
}, c.onerror = function () { | |
k.call(m) | |
}) : c == a ? f.call(m, h) : k.call(m)) : f.call(m, h) | |
}; | |
c.onerror = function () { | |
k.call() | |
}; | |
c.onupgradeneeded = function (a) { | |
a = | |
a.target.result; | |
a.objectStoreNames.contains(b) || a.createObjectStore(b) | |
} | |
}, h = function (b, a) { | |
return function (f) { | |
g = f; | |
b.call(a) | |
} | |
}; | |
this._open = function (b, a, f) { | |
c(d, 1, h(b, f), a) | |
}; | |
this._transaction = function (b) { | |
return g.transaction(d, b).objectStore(d) | |
}; | |
this.get = function (b, a, f) { | |
if (!Spotify.Utils.isFunction(a)) throw new TypeError(ERROR_NOT_A_FUNCTION); | |
var k = this._transaction("readonly").get(b); | |
k.onsuccess = function (k) { | |
a.call(f, b, k.target.result) | |
}; | |
k.onerror = function (k) { | |
a.call(f, b, null, k.target.errorCode) | |
} | |
}; | |
this.set = | |
function (b, a, f, k) { | |
var m = this._transaction("readwrite").put(a, b); | |
if (Spotify.Utils.isFunction(f)) m.onsuccess = function () { | |
f.call(k, b, a) | |
}, m.onerror = function (a) { | |
f.call(k, b, null, a.target.errorCode) | |
} | |
}; | |
this.remove = function (b, a, f) { | |
var k = this._transaction("readwrite")["delete"](b); | |
if (Spotify.Utils.isFunction(a)) k.onsuccess = function () { | |
a.call(f, b) | |
}, k.onerror = function () { | |
a.call(f, null, e.target.errorCode) | |
} | |
}; | |
this.removeAllContaining = function (b, a, f) { | |
var k = []; | |
this._transaction("readwrite").openCursor().onsuccess = function (m) { | |
(m = | |
m.target.result) ? (m.key.indexOf(b) >= 0 && (k.push(m.key), m["delete"]()), m["continue"]()) : Spotify.Utils.isFunction(a) && a.call(f, k) | |
} | |
}; | |
this.clear = function (b, a) { | |
var f = this._transaction("readwrite").clear(); | |
if (Spotify.Utils.isFunction(b)) f.onsuccess = function () { | |
b.call(a) | |
}, f.onerror = function () { | |
b.call(a) | |
} | |
}; | |
this.each = function (b, a, f) { | |
if (!Spotify.Utils.isFunction(b)) throw new TypeError(ERROR_NOT_A_FUNCTION); | |
this._transaction("readonly").openCursor().onsuccess = function (k) { | |
(k = k.target.result) ? (b.call(f, k.key, k.value), | |
k["continue"]()) : Spotify.Utils.isFunction(a) && a.call(f) | |
} | |
}; | |
this.initialize = function (b, a, f) { | |
if (!Spotify.Utils.isFunction(b) || !Spotify.Utils.isFunction(a)) throw new TypeError(ERROR_NOT_A_FUNCTION); | |
this._open(b, a, f) | |
}; | |
this.isSupported = function () { | |
return Spotify.Storage.indexedDB.storage ? !0 : !1 | |
} | |
}; | |
Spotify.Cache.FileSystemStorage = function () { | |
throw Error("Not implemented!"); | |
}; | |
Spotify.Cache.PackageStore = function (d) { | |
var g = function (a) { | |
return a | |
}, c = function (a) { | |
return a | |
}, h = "PackageStore", | |
b = function () { | |
var a = {}; | |
Spotify.Storage.localStorage.getItem(h) !== null && (a = JSON.parse(c(Spotify.Storage.localStorage.getItem(h)))); | |
return a | |
}; | |
if (typeof d !== "undefined") typeof d.storageKey !== "undefined" && (h = d.storageKey), typeof d.encrypt === "function" && (g = d.encrypt), typeof d.decrypt === "function" && (c = d.decrypt); | |
return { | |
setItem: function (a, f) { | |
var k = b(); | |
k[a] = f; | |
return Spotify.Storage.localStorage.setItem(h, | |
g(JSON.stringify(k))) | |
}, | |
getItem: function (a) { | |
var f = b(); | |
return typeof f[a] === "undefined" ? null : f[a] | |
}, | |
removeItem: function (a) { | |
var f = b(); | |
delete f[a]; | |
return Spotify.Storage.localStorage.setItem(h, g(JSON.stringify(f))) | |
}, | |
clear: function () { | |
return Spotify.Storage.localStorage.remove(h) | |
}, | |
length: function () { | |
var a = b(), | |
f = 0, | |
k; | |
for (k in a) a.hasOwnProperty(k) && (f += 1); | |
return f | |
}, | |
key: function (a) { | |
var f = b(), | |
k = 0, | |
m; | |
for (m in f) | |
if (f.hasOwnProperty(m)) { | |
if (k === a) return m; | |
k += 1 | |
} | |
return null | |
} | |
} | |
}; | |
Spotify.Cache.Types = { | |
PERSISTENT: "persistent", | |
TEMPORARY: "temporary" | |
}; | |
(function () { | |
var d; | |
Spotify.Events = function () { | |
return typeof d !== "undefined" ? d : d = { | |
REQUEST: "REQUEST", | |
DATA_ERROR: "DATA_ERROR", | |
TRACK_PLAY_REQUEST: "TRACK_PLAY_REQUEST", | |
WAIT_FOR_COMMERCIAL_TO_FINISH: "WAIT_FOR_COMMERCIAL_TO_FINISH", | |
INTERCEPTED: "intercepted", | |
USER_INFO_CHANGE: "USER_INFO_CHANGE", | |
TRACK_ENDED: "TRACK_ENDED", | |
PLAYER_STATE: "PLAYER_STATE", | |
BEFORE_END: "BEFORE_END", | |
BEFORE_SEEK: "BEFORE_SEEK", | |
LOAD: "LOAD", | |
SONG_LOADED: "SONG_LOADED", | |
FIRST_BYTES: "FIRST_BYTES", | |
POSITION_CHANGED: "POSITION_CHANGED", | |
VOLUME_CHANGED: "VOLUME_CHANGED", | |
PLAYING: "PLAYING", | |
PAUSED: "PAUSED", | |
STOPPED: "STOPPED", | |
ACTIVE_PLAYER_CHANGED: "ACTIVE_PLAYER_CHANGED", | |
CONNECTION_ESTABLISHED: "CONNECTION_ESTABLISHED", | |
CONNECTION_CLOSED: "CONNECTION_CLOSED", | |
CONNECTED: "CONNECTED", | |
DISCONNECTED: "DISCONNECTED", | |
STREAM_INITIALIZED: "STREAM_INITIALIZED", | |
PLAYER_LOADED: "PLAYER_LOADED", | |
PLAYER_EVENT: "PLAYER_EVENT", | |
STREAM_LIMIT_REACHED: "STREAM_LIMIT_REACHED", | |
AUTHENTICATED: "AUTHENTICATED", | |
ERROR: "ERROR", | |
SUCCESS: "SUCCESS", | |
FAILED_CONNECTING: "FAILED_CONNECTING", | |
INVALID_TRACK_URI: "INVALID_TRACK_URI", | |
CANNOT_PLAY_TRACK: "CANNOT_PLAY_TRACK", | |
REGION_BLOCKED: "REGION_BLOCKED", | |
ACCOUNT_IN_USE: "ACCOUNT_IN_USE", | |
PLAYBACK_FAILED: "PLAYBACK_FAILED", | |
SECURITY_ERROR: "SECURITY_ERROR", | |
UNKNOWN_ERROR: "UNKNOWN_ERROR", | |
RPC_CALLBACK: "RPC_CALLBACK", | |
RPC_ERRBACK: "RPC_ERRBACK", | |
RPC_LOGGING_LATENCY_CALLBACK: "RPC_LOGGING_LATENCY_CALLBACK", | |
RPC_LOGGING_LATENCY_ERRBACK: "RPC_LOGGING_LATENCY_ERRBACK", | |
RPC_SUCCESS: "RPC_SUCCESS", | |
RPC_ERROR: "RPC_ERROR", | |
REAUTHORIZE_SUCCESS: "REAUTHORIZE_SUCCESS", | |
REAUTHORIZE_FAILED: "REAUTHORIZE_FAILED", | |
FLASH_LOADED: "FLASH_LOADED", | |
FLASH_UNAVAILABLE: "FLASH_UNAVAILABLE", | |
FLASH_AVAILABLE: "FLASH_AVAILABLE", | |
INITIALIZED: "INITIALIZED", | |
READY: "READY", | |
NOT_READY: "NOT_READY", | |
TOKEN_ACQUIRED: "TOKEN_ACQUIRED", | |
TOKEN_NOT_ACQUIRED: "TOKEN_NOT_ACQUIRED", | |
ON_TRY_TO_CONNECT: "ON_TRY_TO_CONNECT", | |
NOTIFY_OF_DISCONNECT: "NOTIFY_OF_DISCONNECT", | |
FATAL_ERROR: "FATAL_ERROR", | |
TOKEN_LOST: "TOKEN_LOST", | |
WORK: "WORK", | |
PING_FLASH: "PING_FLASH", | |
LOGIN_COMPLETE: "LOGIN_COMPLETE", | |
HERMES_B64_MESSAGE: "HERMES_B64_MESSAGE", | |
TIMEOUT: "TIMEOUT", | |
NO_SOUND_CAPABILITIES: "NO_SOUND_CAPABILITIES", | |
ON_REAUTHENTICATION_SUCCESS: "ON_REAUTHENTICATION_SUCCESS", | |
ON_REAUTHENTICATION_FAILED: "ON_REAUTHENTICATION_FAILED", | |
STORAGE_FULL: "STORAGE_FULL", | |
RATE_LIMIT_CALL: "RATE_LIMIT_CALL", | |
RATE_LIMIT_DISABLED: "RATE_LIMIT_DISABLED", | |
RATE_LIMIT_AFTER_INTERVAL: "RATE_LIMIT_AFTER_INTERVAL", | |
REMOTE_SERVICE_DOWN: "REMOTE_SERVICE_DOWN", | |
NOTIFICATION: "NOTIFICATION", | |
RELATIONS_SUBSCRIBE: "RELATIONS_SUBSCRIBE", | |
RELATIONS_UNSUBSCRIBE: "RELATIONS_UNSUBSCRIBE", | |
RELATIONS_DISMISS: "RELATIONS_DISMISS", | |
RELATIONS_UNDISMISS: "RELATIONS_UNDISMISS", | |
RELATIONS_BLOCK: "RELATIONS_BLOCK", | |
RELATIONS_UNBLOCK: "RELATIONS_UNBLOCK", | |
CHANGED: "CHANGED", | |
DURATION: "DURATION", | |
PLAYER_CREATED: "PLAYER_CREATED", | |
PLAYLIST_SUBSCRIBE: "PLAYLIST_SUBSCRIBE", | |
TIME_CAP: "TIME_CAP", | |
CHANGE: "CHANGE", | |
RECORD_AD_EVENT: "RECORD_AD_EVENT" | |
} | |
} | |
})(); | |
Spotify.Resolvers = { | |
STORAGE_RESOLVER: "STORAGE_RESOLVER", | |
AD_RESOLVER: "AD_RESOLVER", | |
PREVIEW_RESOLVER: "PREVIEW_RESOLVER" | |
}; | |
Spotify.Ajax = function (d) { | |
var g = Spotify.DebuggerJS, | |
d = d || {}, c = {}; | |
c.method = d.method || "GET"; | |
c.dataType = d.dataType || "text"; | |
c.url = d.url || void 0; | |
c.data = d.data || ""; | |
c.async = d.async !== void 0 ? d.async : !0; | |
c.success = d.success || void 0; | |
c.error = d.error || void 0; | |
c.context = d.context || void 0; | |
this.POST = "POST"; | |
this.GET = "GET"; | |
this.JSON = "json"; | |
this.XML = "xml"; | |
this.TEXT = "text"; | |
this.execute = function () { | |
var h, b = c.url, | |
a = "", | |
f, k = function (a) { | |
c.context !== void 0 ? c.error.call(c.context, a) : c.error(a) | |
}, m = function () { | |
if (typeof c.success !== | |
"undefined") { | |
if (c.dataType === "xml") try { | |
f = h.responseXML || Spotify.Utils.convertStringToXML(h.responseText) | |
} catch (a) { | |
k(a) | |
} | |
if (c.dataType === "json") try { | |
f = JSON.parse(h.responseText) | |
} catch (b) { | |
k(b) | |
} | |
c.dataType === "text" && (f = h.responseText); | |
c.context !== void 0 ? c.success.call(c.context, f, h) : c.success(f, h) | |
} | |
}, d = function () { | |
typeof c.error !== "undefined" && k() | |
}, p = function () { | |
m() | |
}, q = function (a) { | |
d(a) | |
}; | |
h = XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP"); | |
c.method === this.POST ? a = c.data : b += c.data !== "" ? | |
"?" + c.data : ""; | |
try { | |
try { | |
h.open(c.method, b, c.async) | |
} catch (n) { | |
if (XDomainRequest) g.log("Spotify.Ajax", ["Trying Cors"], "corejs"), h = new XDomainRequest, h.onprogress = function () {}, h.onload = p, h.onerror = q, h.open(c.method, b, c.async); | |
else throw Error("CORS not supported"); | |
} | |
h.send(a) | |
} catch (s) { | |
g.error("Spotify.Ajax", [s], "corejs"), k(s) | |
} | |
h.onreadystatechange = function () { | |
h.readyState === 4 && h.status >= 200 && h.status < 300 ? m() : h.status >= 400 && d() | |
}; | |
return h | |
} | |
}; | |
Spotify.Service = function () { | |
Spotify.EventTarget.call(this); | |
this.url = ""; | |
this.method = "GET"; | |
this.dataType = "text"; | |
this.data = ""; | |
this.async = !0; | |
this.fetch = function () { | |
(new Spotify.Ajax({ | |
method: this.method, | |
dataType: this.dataType, | |
url: this.url, | |
data: this.data, | |
success: d, | |
error: g, | |
context: this | |
})).execute() | |
}; | |
var d = function (c, h) { | |
this.trigger("onSuccess", { | |
result: c, | |
request: h | |
}) | |
}, g = function (c) { | |
this.trigger("onError", { | |
error: c | |
}) | |
} | |
}; | |
Spotify.Proto.Data = function (d, g) { | |
Spotify.EventTarget.call(this); | |
var c = this, | |
h, b = {}, a = new Spotify.Events; | |
this.initialize = function () { | |
var a = new Spotify.Service; | |
a.url = d + "data.xml" + g; | |
a.async = !1; | |
a.dataType = "text"; | |
a.bind("onSuccess", f, this); | |
a.bind("onError", k, this); | |
a.fetch() | |
}; | |
this.getDefinition = function (a) { | |
if (typeof b[a] !== "undefined") return b[a]; | |
var f = h.getElementsByTagName(a); | |
return typeof f !== "undefined" && f[0] && f[0].firstChild ? (b[a] = f[0].firstChild.data + "\n", b[a]) : "" | |
}; | |
this.getMultipleDefinitions = function (a) { | |
var f = | |
"", | |
k = 0, | |
c, d; | |
if (!Spotify.Utils.isArray(a)) throw Error("Definition identifiers must be an array with strings"); | |
for (; k < a.length; k++) d = a[k], typeof b[d] !== "undefined" ? f += b[d] : (c = h.getElementsByTagName(d), typeof c !== "undefined" && c[0] && c[0].firstChild && (b[d] = c[0].firstChild.data + "\n", f += b[d])); | |
return f | |
}; | |
var f = function (f) { | |
h = Spotify.Utils.convertStringToXML(f.params.result); | |
c.trigger(a.SUCCESS) | |
}, k = function (f) { | |
c.trigger(a.ERROR, f.params) | |
} | |
}; | |
(function () { | |
Spotify.Link = function (a, b) { | |
this.type = a; | |
for (var m in b) this[m] = b[m] | |
}; | |
var d = Spotify.Link; | |
d.Type = { | |
EMPTY: "empty", | |
ALBUM: "album", | |
AD: "ad", | |
APPLICATION: "application", | |
ARTIST: "artist", | |
ARTIST_TOPLIST: "artist-toplist", | |
AUDIO_FILE: "audiofile", | |
COLLECTION: "collection", | |
COLLECTION_ALBUM: "collection-album", | |
COLLECTION_MISSING_ALBUM: "collection-missing-album", | |
COLLECTION_ARTIST: "collection-artist", | |
CONTEXT_GROUP: "context-group", | |
FACEBOOK: "facebook", | |
FOLLOWERS: "followers", | |
FOLLOWING: "following", | |
IMAGE: "image", | |
INBOX: "inbox", | |
LOCAL_ARTIST: "local-artist", | |
LOCAL_ALBUM: "local-album", | |
LOCAL: "local", | |
LIBRARY: "library", | |
MOSAIC: "mosaic", | |
PLAYLIST: "playlist", | |
PROFILE: "profile", | |
PUBLISHED_ROOTLIST: "published-rootlist", | |
RADIO: "radio", | |
ROOTLIST: "rootlist", | |
COLLECTION_TRACK_LIST: "collectiontracklist", | |
SEARCH: "search", | |
STARRED: "starred", | |
TEMP_PLAYLIST: "temp-playlist", | |
TOPLIST: "toplist", | |
TRACK: "track", | |
TRACKSET: "trackset", | |
USER_TOPLIST: "user-toplist", | |
USET_TOP_TRACKS: "user-top-tracks" | |
}; | |
var g = function (a) { | |
return !!a | |
}, c = function (a, b) { | |
var m, c = 1; | |
if (a.indexOf("spotify:") == | |
0) m = a.slice(8).split(":"), c = 0; | |
else if (a.indexOf("http://play.spotify.com/") == 0) m = a.slice(24).split("/"); | |
else if (a.indexOf("https://play.spotify.com/") == 0) m = a.slice(25).split("/"); | |
else if (a.indexOf("http://open.spotify.com/") == 0) m = a.slice(24).split("/"); | |
else if (a.indexOf("https://open.spotify.com/") == 0) m = a.slice(25).split("/"); | |
else throw "Invalid Spotify URI!"; | |
Array.prototype.push.apply(b, m); | |
return c | |
}, h = function (a, b) { | |
a = encodeURIComponent(a); | |
return b == 0 ? a.replace(/%20/g, "+") : a | |
}, b = function (a, b) { | |
return decodeURIComponent(b == | |
0 ? a.replace(/\+/g, "%20") : a) | |
}, a = function (a, b) { | |
var m, c, g; | |
a.id && (m = Spotify.Utils.Base62.fromHex(a.id, 22)); | |
switch (a.type) { | |
case d.Type.ALBUM: | |
return c = ["album", m], a.disc && c.push(a.disc), c; | |
case d.Type.AD: | |
return ["ad", a.id]; | |
case d.Type.ARTIST: | |
return ["artist", m]; | |
case d.Type.ARTIST_TOPLIST: | |
return ["artist", m, "top", a.toplist]; | |
case d.Type.SEARCH: | |
return ["search", h(a.query, b)]; | |
case d.Type.TRACK: | |
return ["track", m]; | |
case d.Type.TRACKSET: | |
c = []; | |
for (m = 0, g = a.tracks.length; m < g; m++) c.push(Spotify.Utils.Base62.fromHex(a.tracks[m].id, | |
22)); | |
c = [c.join(",")]; | |
a.index !== null && c.push("#", a.index); | |
return ["trackset", h(a.name)].concat(c); | |
case d.Type.FACEBOOK: | |
return ["user", "facebook", a.uid]; | |
case d.Type.AUDIO_FILE: | |
return ["audiofile", a.extension, a.id]; | |
case d.Type.FOLLOWERS: | |
return ["user", h(a.username), "followers"]; | |
case d.Type.FOLLOWING: | |
return ["user", h(a.username), "following"]; | |
case d.Type.PLAYLIST: | |
return ["user", h(a.username), "playlist", m]; | |
case d.Type.STARRED: | |
return ["user", h(a.username), "starred"]; | |
case d.Type.TEMP_PLAYLIST: | |
return ["temp-playlist", | |
a.origin, a.data]; | |
case d.Type.CONTEXT_GROUP: | |
return ["context-group", a.origin, a.name]; | |
case d.Type.USER_TOPLIST: | |
return ["user", h(a.username), "top", a.toplist]; | |
case d.Type.USET_TOP_TRACKS: | |
return ["user", h(a.username), "toplist"]; | |
case d.Type.TOPLIST: | |
return ["top", a.toplist].concat(a.global ? ["global"] : ["country", a.country]); | |
case d.Type.INBOX: | |
return ["user", h(a.username), "inbox"]; | |
case d.Type.ROOTLIST: | |
return ["user", h(a.username), "rootlist"]; | |
case d.Type.PUBLISHED_ROOTLIST: | |
return ["user", h(a.username), "publishedrootlist"]; | |
case d.Type.COLLECTION_TRACK_LIST: | |
return ["user", h(a.username), "collectiontracklist", m]; | |
case d.Type.PROFILE: | |
return a.args && a.args.length > 0 ? ["user", h(a.username)].concat(a.args) : ["user", h(a.username)]; | |
case d.Type.LOCAL_ARTIST: | |
return ["local", h(a.artist, b)]; | |
case d.Type.LOCAL_ALBUM: | |
return ["local", h(a.artist, b), h(a.album, b)]; | |
case d.Type.LOCAL: | |
return ["local", h(a.artist, b), h(a.album, b), h(a.track, b), a.duration]; | |
case d.Type.LIBRARY: | |
return ["user", h(a.username), "library"].concat(a.category ? [a.category] : []); | |
case d.Type.IMAGE: | |
return ["image", | |
a.id]; | |
case d.Type.MOSAIC: | |
return c = a.ids.slice(0), c.unshift("mosaic"), c; | |
case d.Type.RADIO: | |
return ["radio", a.args]; | |
case d.Type.APPLICATION: | |
c = ["app", a.id]; | |
var q = a.args || []; | |
for (m = 0, g = q.length; m < g; ++m) c.push(h(q[m], b)); | |
return c; | |
case d.Type.COLLECTION_ALBUM: | |
return ["user", h(a.username), "collection", "album", m]; | |
case d.Type.COLLECTION_MISSING_ALBUM: | |
return ["user", h(a.username), "collection", "album", m, "missing"]; | |
case d.Type.COLLECTION_ARTIST: | |
return ["user", h(a.username), "collection", "artist", m]; | |
case d.Type.COLLECTION: | |
return ["user", | |
h(a.username), "collection"].concat(a.category ? [a.category] : []); | |
default: | |
throw "Invalid Spotify URI!"; | |
} | |
}; | |
d.prototype.toURI = function () { | |
return "spotify:" + a(this, 0).join(":") | |
}; | |
d.prototype.toAppLink = function () { | |
if (this.type == d.Type.APPLICATION) return d.applicationLink(this.id, this.args); | |
else { | |
var f = a(this, 1), | |
k = f.shift(); | |
f.length && (f = f.map(function (a) { | |
return b(a, 1) | |
})); | |
return d.applicationLink(k, this.type == d.Type.RADIO ? f.shift().split(":") : f) | |
} | |
}; | |
d.prototype.toAppURI = function () { | |
return this.type == d.Type.APPLICATION ? | |
this.toURI() : "spotify:" + ["app"].concat(a(this, 0)).join(":") | |
}; | |
d.prototype.toURLPath = function () { | |
var f = a(this, 1); | |
f[0] === "app" && f.shift(); | |
f[0] != "trackset" && (f = f.filter(g)); | |
return f.join("/") | |
}; | |
d.prototype.toURL = function (a) { | |
typeof a === "undefined" && (a = !0); | |
return a ? "http://play.spotify.com/" + this.toURLPath() : "/" + this.toURLPath() | |
}; | |
d.prototype.toSecureURL = function () { | |
return "https://play.spotify.com/" + this.toURLPath() | |
}; | |
d.prototype.toString = function () { | |
return this.toURI() | |
}; | |
d.prototype.idToByteString = function () { | |
for (var a = | |
Spotify.Utils.Base62.fromHex(this.id), a = Spotify.Utils.Base62.toBytes(a), a = a.map(function (a) { | |
return String.fromCharCode(a) | |
}).join(""); a.length < 16;) a = String.fromCharCode(0) + a; | |
return a | |
}; | |
d.fromString = function (a) { | |
var k = [], | |
m = c(a, k), | |
h = 0, | |
g = function () { | |
return k[h++] | |
}, a = function () { | |
var a = g(); | |
return a.length == 22 ? Spotify.Utils.Base62.toHex(a, 32) : a | |
}, q = function () { | |
return k.slice(h).join(m == 0 ? ":" : "/") | |
}, n = g(); | |
switch (n) { | |
case "album": | |
return d.albumLink(a(), parseInt(g(), 10)); | |
case "ad": | |
return d.adLink(a()); | |
case "artist": | |
return n = | |
a(), g() == "top" ? d.artistToplistLink(n, g()) : d.artistLink(n); | |
case "audiofile": | |
return d.audioFileLink(g(), g()); | |
case "temp-playlist": | |
return d.temporaryPlaylistLink(g(), q()); | |
case "search": | |
return d.searchLink(b(q(), m)); | |
case "track": | |
return d.trackLink(a()); | |
case "trackset": | |
var n = b(g()), | |
s = g(), | |
a = g(), | |
t = parseInt(g(), 10); | |
if (a !== "%23" || isNaN(t)) t = null; | |
var u = []; | |
if (s) { | |
s = b(s).split(","); | |
for (a = 0, q = s.length; a < q; a++) u.push(d.trackLink(Spotify.Utils.Base62.toHex(s[a], 32))) | |
} | |
return d.tracksetLink(u, n, t); | |
case "context-group": | |
return d.contextGroupLink(g(), | |
g()); | |
case "top": | |
return a = g(), g() == "global" ? d.toplistLink(a, null, !0) : d.toplistLink(a, g(), !1); | |
case "user": | |
q = b(g(), m); | |
n = g(); | |
if (q == "facebook" && n != null) return d.facebookLink(parseInt(n, 10)); | |
else if (n != null) switch (n) { | |
case "playlist": | |
return d.playlistLink(q, a()); | |
case "collectiontracklist": | |
return d.collectionTrackList(q, a()); | |
case "collection": | |
switch (n = g(), n) { | |
case "album": | |
return n = a(), g() === "missing" ? d.collectionMissingAlbumLink(q, n) : d.collectionAlbumLink(q, n); | |
case "artist": | |
return d.collectionArtistLink(q, | |
a()); | |
default: | |
return d.collectionLink(q, n) | |
} | |
case "starred": | |
return d.starredLink(q); | |
case "followers": | |
return d.followersLink(q); | |
case "following": | |
return d.followingLink(q); | |
case "top": | |
return d.userToplistLink(q, g()); | |
case "inbox": | |
return d.inboxLink(q); | |
case "rootlist": | |
return d.rootlistLink(q); | |
case "publishedrootlist": | |
return d.publishedRootlistLink(q); | |
case "toplist": | |
return d.userTopTracksLink(q); | |
case "library": | |
return d.libraryLink(q, g()) | |
} | |
a = k.slice(h); | |
return n != null && a.length > 0 ? d.profileLink(q, [n].concat(a)) : | |
n != null ? d.profileLink(q, [n]) : d.profileLink(q); | |
case "local": | |
return a = (a = g()) && b(a, m), n = (q = g()) && b(q, m), t = (s = g()) && b(s, m), u = g(), u = parseInt(u, 10), s !== void 0 ? d.localLink(a, n, t, u) : q !== void 0 ? d.localAlbumLink(a, n) : d.localArtistLink(a); | |
case "image": | |
return d.imageLink(a()); | |
case "mosaic": | |
return d.mosaicLink(k.slice(h)); | |
case "radio": | |
return d.radioLink(q()); | |
default: | |
n = n === "app" ? g() : n; | |
s = k.slice(h); | |
for (a = 0, q = s.length; a < q; ++a) s[a] = b(s[a], m); | |
return d.applicationLink(n, s) | |
} | |
throw "Invalid Spotify URI!"; | |
}; | |
d.emptyLink = | |
function () { | |
return new d(d.Type.EMPTY, {}) | |
}; | |
d.albumLink = function (a, b) { | |
return new d(d.Type.ALBUM, { | |
id: a, | |
disc: b | |
}) | |
}; | |
d.adLink = function (a) { | |
return new d(d.Type.AD, { | |
id: a | |
}) | |
}; | |
d.artistLink = function (a) { | |
return new d(d.Type.ARTIST, { | |
id: a | |
}) | |
}; | |
d.artistToplistLink = function (a, b) { | |
return new d(d.Type.ARTIST_TOPLIST, { | |
id: a, | |
toplist: b | |
}) | |
}; | |
d.searchLink = function (a) { | |
return new d(d.Type.SEARCH, { | |
query: a | |
}) | |
}; | |
d.trackLink = function (a) { | |
return new d(d.Type.TRACK, { | |
id: a | |
}) | |
}; | |
d.tracksetLink = function (a, b, m) { | |
return new d(d.Type.TRACKSET, { | |
tracks: a, | |
name: b || "", | |
index: isNaN(m) ? null : m | |
}) | |
}; | |
d.facebookLink = function (a) { | |
return new d(d.Type.FACEBOOK, { | |
uid: a | |
}) | |
}; | |
d.audioFileLink = function (a, b) { | |
return new d(d.Type.AUDIO_FILE, { | |
id: b, | |
extension: a | |
}) | |
}; | |
d.followersLink = function (a) { | |
return new d(d.Type.FOLLOWERS, { | |
username: a | |
}) | |
}; | |
d.followingLink = function (a) { | |
return new d(d.Type.FOLLOWING, { | |
username: a | |
}) | |
}; | |
d.playlistLink = function (a, b) { | |
return new d(d.Type.PLAYLIST, { | |
username: a, | |
id: b | |
}) | |
}; | |
d.collectionTrackList = function (a, b) { | |
return new d(d.Type.COLLECTION_TRACK_LIST, { | |
username: a, | |
id: b | |
}) | |
}; | |
d.starredLink = function (a) { | |
return new d(d.Type.STARRED, { | |
username: a | |
}) | |
}; | |
d.userToplistLink = function (a, b) { | |
return new d(d.Type.USER_TOPLIST, { | |
username: a, | |
toplist: b | |
}) | |
}; | |
d.userTopTracksLink = function (a) { | |
return new d(d.Type.USET_TOP_TRACKS, { | |
username: a | |
}) | |
}; | |
d.toplistLink = function (a, b, m) { | |
return new d(d.Type.TOPLIST, { | |
toplist: a, | |
country: b, | |
global: !! m | |
}) | |
}; | |
d.inboxLink = function (a) { | |
return new d(d.Type.INBOX, { | |
username: a | |
}) | |
}; | |
d.rootlistLink = function (a) { | |
return new d(d.Type.ROOTLIST, { | |
username: a | |
}) | |
}; | |
d.publishedRootlistLink = function (a) { | |
return new d(d.Type.PUBLISHED_ROOTLIST, { | |
username: a | |
}) | |
}; | |
d.localArtistLink = function (a) { | |
return new d(d.Type.LOCAL_ARTIST, { | |
artist: a | |
}) | |
}; | |
d.localAlbumLink = function (a, b) { | |
return new d(d.Type.LOCAL_ALBUM, { | |
artist: a, | |
album: b | |
}) | |
}; | |
d.localLink = function (a, b, m, c) { | |
return new d(d.Type.LOCAL, { | |
artist: a, | |
album: b, | |
track: m, | |
duration: c | |
}) | |
}; | |
d.libraryLink = function (a, b) { | |
return new d(d.Type.LIBRARY, { | |
username: a, | |
category: b | |
}) | |
}; | |
d.collectionLink = function (a, b) { | |
return new d(d.Type.COLLECTION, { | |
username: a, | |
category: b | |
}) | |
}; | |
d.temporaryPlaylistLink = function (a, b) { | |
return new d(d.Type.TEMP_PLAYLIST, { | |
origin: a, | |
data: b | |
}) | |
}; | |
d.contextGroupLink = function (a, b) { | |
return new d(d.Type.CONTEXT_GROUP, { | |
origin: a, | |
name: b | |
}) | |
}; | |
d.profileLink = function (a, b) { | |
return new d(d.Type.PROFILE, { | |
username: a, | |
args: b | |
}) | |
}; | |
d.imageLink = function (a) { | |
return new d(d.Type.IMAGE, { | |
id: a | |
}) | |
}; | |
d.mosaicLink = function (a) { | |
return new d(d.Type.MOSAIC, { | |
ids: a | |
}) | |
}; | |
d.radioLink = function (a) { | |
a = typeof a === "undefined" ? [] : a; | |
return new d(d.Type.RADIO, { | |
args: a | |
}) | |
}; | |
d.applicationLink = function (a, b) { | |
b = typeof b === "undefined" ? [] : b; | |
return new d(d.Type.APPLICATION, { | |
id: a, | |
args: b | |
}) | |
}; | |
d.collectionAlbumLink = function (a, b) { | |
return new d(d.Type.COLLECTION_ALBUM, { | |
username: a, | |
id: b | |
}) | |
}; | |
d.collectionMissingAlbumLink = function (a, b) { | |
return new d(d.Type.COLLECTION_MISSING_ALBUM, { | |
username: a, | |
id: b | |
}) | |
}; | |
d.collectionArtistLink = function (a, b) { | |
return new d(d.Type.COLLECTION_ARTIST, { | |
username: a, | |
id: b | |
}) | |
}; | |
d.fromByteString = function (a, b, m) { | |
for (var c = [], h = 0; h < b.length; h++) c.push(b.charCodeAt(h)); | |
b = Spotify.Utils.Base62.fromBytes(c, 22); | |
b = Spotify.Utils.Base62.toHex(b); | |
m = m || {}; | |
m.id = b; | |
return new d(a, m) | |
} | |
})(); | |
(function () { | |
var d; | |
Spotify.Logging.Types = function () { | |
return typeof d !== "undefined" ? d : d = { | |
TRACK_END: "TRACK_END", | |
PREVIEW_END: "PREVIEW_END", | |
TRACK_EVENT: "TRACK_EVENT", | |
TRACK_PROGRESS: "TRACK_PROGRESS", | |
REQUEST_TIME: "REQUEST_TIME", | |
AD_END: "EndAd" | |
} | |
} | |
})(); | |
Spotify.Logging.TrackEnd = function () { | |
Spotify.EventTarget.call(this); | |
var d, g = function () {}, c = function () {}; | |
this.serviceIsReady = !0; | |
this.log = function (h) { | |
d.rpc("track_end", [h.lid, h.ms_played, h.ms_played_union, h.n_seeks_forward, h.n_seeks_backward, h.ms_seeks_forward, h.ms_seeks_backward, h.ms_latency, h.display_track, h.play_context, h.source_start, h.source_end, h.reason_start, h.reason_end, h.referrer, h.referrer_version, h.referrer_vendor, h.max_continuous], g, c, this, !0, 2, "track_end") | |
}; | |
this.init = function (c) { | |
d = c | |
} | |
}; | |
Spotify.Logging.PreviewEnd = function () { | |
Spotify.EventTarget.call(this); | |
new Spotify.Logging.Logger; | |
this.serviceIsReady = !0; | |
this.log = function () {}; | |
this.init = function () {} | |
}; | |
Spotify.Logging.TrackEvent = function () { | |
Spotify.EventTarget.call(this); | |
var d, g = function () {}, c = function () {}; | |
this.serviceIsReady = !0; | |
this.log = function (h) { | |
d.rpc("track_event", [h.lid, h.event, h.ms_where], g, c, this, !0, 2, "track_event") | |
}; | |
this.init = function (c) { | |
d = c | |
} | |
}; | |
Spotify.Logging.TrackProgress = function () { | |
Spotify.EventTarget.call(this); | |
var d = Spotify.DebuggerJS, | |
g, c = function (b) { | |
d.log("Spotify.Logging.TrackProgress", ["Track progress success", b], "corejs") | |
}, h = function (b) { | |
d.error("Spotify.Logging.TrackProgress", ["On track progress error", b], "corejs") | |
}; | |
this.serviceIsReady = !0; | |
this.log = function (b) { | |
g.rpc("track_progress", [b.lid, b.source_start, b.reason_start, b.ms_played, b.ms_latency, b.play_context, b.display_track, b.referrer, b.referrer_version, b.referrer_vendor], c, h, this, !0, 2, "track_progress") | |
}; | |
this.init = function (b) { | |
g = b | |
} | |
}; | |
Spotify.Logging.ClientEvent = function () { | |
var d = function () {}, g = function () {}; | |
this.log = function (c) { | |
if (typeof c.source !== "string") throw Error("Source must be a string"); | |
if (typeof c.context !== "string") c.context = ""; | |
if (typeof c.event !== "string") throw Error("Event name must be a string"); | |
if (typeof c.event_version !== "string") c.event_version = ""; | |
if (typeof c.test_version !== "string") c.test_version = ""; | |
if (typeof c.source_version !== "string") throw Error("Source version name must be a string"); | |
if (typeof c.source_vendor !== | |
"string") throw Error("Source vendor name must be a string"); | |
if (typeof c.data !== "string") c.data = ""; | |
this.send(new Spotify.Calls.Simple({ | |
method: "log_ce", | |
payload: [c.source, c.context, c.event, c.event_version, c.test_version, c.source_version, c.source_vendor, c.data], | |
context: this, | |
persistent: !0, | |
retries: 2, | |
type: "log_ce" | |
}, d, g)) | |
} | |
}; | |
Spotify.Logging.AdEnd = function () { | |
Spotify.EventTarget.call(this); | |
var d, g = function () {}, c = function () {}; | |
this.serviceIsReady = !0; | |
this.log = function (h) { | |
d.rpc("log_ad", [String(h.file_id), String(h.ad_file_id), String(h.lid), String(h.source_start), String(h.reason_start), String(h.source_end), String(h.reason_end), String(h.bytes_played), String(h.content_length), String(h.ms_played), String(h.ms_played_union), String(h.ms_rcv_latency), String(h.n_seeks_backward), String(h.ms_seeks_backward), String(h.n_seeks_forward), | |
String(h.ms_seeks_forward), String(h.ms_latency), String(h.num_stutter), String(h.p_lowbuffer), String(h.skipped), String(h.clicked), String(h.token), String(h.last_stream_started_at), String(h["client-ad-count"]), String(h["client-campaign-count"]) | |
], g, c, this, !0, 2, "log_ad") | |
}; | |
this.init = function (c) { | |
d = c | |
} | |
}; | |
Spotify.Logging.View = function () { | |
var d = function () {}, g = function () {}; | |
this.log = function (c, h, b, a) { | |
if (typeof c !== "string") throw Error("Uri must be a string"); | |
if (typeof h !== "string") throw Error("View version must be a string"); | |
if (typeof b !== "string") throw Error("View vendor must be a string"); | |
if (typeof a !== "number") throw Error("Duration must be a number"); | |
this.send(new Spotify.Calls.Simple({ | |
method: "log_view", | |
payload: [c, h, b, a], | |
context: this, | |
persistent: !0, | |
retries: 2, | |
type: "log_view" | |
}, d, g)) | |
} | |
}; | |
(function () { | |
var d; | |
Spotify.Logging.Logger = function () { | |
if (typeof d !== "undefined") return d; | |
d = this; | |
var g = Spotify.DebuggerJS, | |
c = new Spotify.Events, | |
h = new Spotify.RateLimiter(3E4, 100), | |
b = {}, a = function (a) { | |
g.log("Spotify.Logging.Logger", ["Logging was successfull", a], "corejs") | |
}, f = function (a) { | |
g.error("Spotify.Logging.Logger", ["Logging was NOT successfull", a], "corejs") | |
}; | |
this.logJSExceptions = function (b, k, m, c) { | |
typeof b === "undefined" || typeof k === "undefined" || typeof m === "undefined" || typeof c === "undefined" || (this.send(new Spotify.Calls.Simple({ | |
method: "log", | |
payload: [202, 1, b, k, m, c], | |
context: this, | |
persistent: !0, | |
retries: 2, | |
type: "js_exceptions" | |
}, a, f)), g.log("Spotify.Logging.Logger", ["js_exceptions", arguments], "corejs")) | |
}; | |
this.logWindowSize = function (b, k) { | |
this.send(new Spotify.Calls.Simple({ | |
method: "log", | |
payload: [41, 1, b, k, 0, 0], | |
context: this, | |
persistent: !0, | |
retries: 0, | |
type: "window_size" | |
}, a, f)); | |
g.log("Spotify.Logging.Logger", ["window_size", arguments], "corejs") | |
}; | |
this.logRequestTime = function (b, k, m, c, h) { | |
typeof b === "undefined" || typeof k === "undefined" || typeof m === "undefined" || | |
typeof c === "undefined" || typeof h === "undefined" || (this.send(new Spotify.Calls.Simple({ | |
method: "log", | |
payload: [30, 1, b, k, m, c, h], | |
context: this, | |
persistent: !0, | |
retries: 2, | |
type: "request_time" | |
}, a, f)), g.log("Spotify.Logging.Logger", ["request_time", arguments], "corejs")) | |
}; | |
this.logEndPreview = function (b, k, m, c, h, d, u, w, v) { | |
this.send(new Spotify.Calls.Simple({ | |
method: "log", | |
payload: [216, 1, b, k, m, c, h, d, u, w, v], | |
context: this, | |
persistent: !0, | |
retries: 2, | |
type: "end_preview" | |
}, a, f)); | |
g.log("Spotify.Logging.Logger", ["end_preview", arguments], | |
"corejs") | |
}; | |
this.logAggregatedRequestTime = function (a, b) { | |
typeof a === "undefined" || typeof b === "undefined" || (h.addToBucket({ | |
messageType: 30, | |
messageVersion: 1, | |
type: a, | |
latency: b | |
}), h.isStarted() || h.start()) | |
}; | |
this.log = function (b, k) { | |
var m = Array.prototype.slice.call(arguments); | |
typeof b === "undefined" || typeof k === "undefined" || (this.send(new Spotify.Calls.Simple({ | |
method: "log", | |
payload: m, | |
context: this, | |
persistent: !0, | |
retries: 2, | |
type: "log" | |
}, a, f)), g.log("Spotify.Logging.Logger", ["Log", m], "corejs")) | |
}; | |
var k = function (a) { | |
a = a.params; | |
typeof b[a.type] === "undefined" && (b[a.type] = { | |
min: Number.MAX_VALUE, | |
max: 0, | |
sum: 0, | |
sumpow2: 0, | |
count: 0, | |
mean: 0, | |
std_deviation: 0 | |
}); | |
b[a.type].count++; | |
b[a.type].sum += a.latency; | |
b[a.type].sumpow2 += Math.pow(a.latency, 2); | |
if (b[a.type].min > a.latency) b[a.type].min = a.latency; | |
if (b[a.type].max < a.latency) b[a.type].max = a.latency | |
}, m = function () { | |
for (var k in b) { | |
var m = b[k]; | |
m.mean = Math.floor(m.sum / m.count); | |
m.std_deviation = Math.floor(Math.sqrt(m.sumpow2 - Math.pow(m.mean, 2), 2)); | |
this.send(new Spotify.Calls.Simple({ | |
method: "log", | |
payload: [232, | |
1, k, m.count, m.sum, m.sumpow2, m.min, m.max, m.mean, m.std_deviation | |
], | |
context: this, | |
persistent: !0, | |
retries: 2, | |
type: "aggregated_request_latencies" | |
}, a, f)) | |
} | |
g.log("Spotify.Logging.Logger", ["Aggregated Request Latencies", b], "corejs"); | |
b = {}; | |
h.isStarted() || h.start() | |
}; | |
this.setup = function () { | |
h.bind(c.RATE_LIMIT_CALL, k, this); | |
h.bind(c.RATE_LIMIT_AFTER_INTERVAL, m, this) | |
} | |
} | |
})(); | |
Spotify.PlayerTracker = function (d, g, c) { | |
Spotify.EventTarget.call(this); | |
this.id = d; | |
var h = Spotify.DebuggerJS, | |
b = !1, | |
a, f = new Spotify.Events, | |
k = {}, m, o = 0, | |
p = 0, | |
q = 0, | |
n = 0, | |
s = [], | |
t = 0, | |
u = 0, | |
w = 0, | |
v = 0, | |
A = 0, | |
x = 0, | |
F = "", | |
G = "unknown", | |
B = "unknown", | |
E = "unknown", | |
H = "unknown", | |
I = "unknown", | |
K = "unknown", | |
L = "unknown", | |
N = "unknown", | |
M = "", | |
z = new Spotify.Logging.Types, | |
C = new Spotify.Cache.Default(100, new Spotify.Cache.LocalStorage("tracker")), | |
y = !1, | |
D = !1, | |
P = !1, | |
O = {}, R = 0, | |
T = -1, | |
S = function (b) { | |
var c = k[b], | |
d = 0, | |
n = {}; | |
if (M !== "" || M === "" && P) { | |
q = y ? q : ca(s); | |
F = F || ""; | |
G = G || | |
"unknown"; | |
B = B || "unknown"; | |
H = H || "unknown"; | |
K = K || "unknown"; | |
L = L || "unknown"; | |
N = N || "unknown"; | |
if (t === 0 && u === 0 && (b === z.TRACK_END || b === z.AD_END)) o = p = q; | |
if (b === z.AD_END && g.ad !== void 0) n.ad_file_id = g.ad.file_id, n.lid = g.ad.ad_id, n.file_id = "5", n.bytes_played = 0, n.content_length = 0, n.ms_rcv_latency = 0, n.num_stutter = 0, n.p_lowbuffer = 0, n.skipped = 0, n.last_stream_started_at = (new Date(A)).toISOString(), n.token = g.ad.token, n.clicked = g.ad.has_been_clicked ? 1 : 0, n["client-ad-count"] = g.ad.adPlayCount, n["client-campaign-count"] = g.ad.campaignPlayCount, | |
n.source_start = "pendad", n.source_end = "trackdone", n.reason_end = "albumtrackdone"; | |
else if (b === z.TRACK_END) n.lid = M, n.source_start = B, n.source_end = E, n.reason_end = I; | |
else if (b === z.TRACK_PROGRESS) n.lid = M, n.play_track = m, n.source_start = B, n.bitrate = g.bitrate, n.audiocodec = g.audiocodec; | |
else if (b === z.PREVIEW_END) n.bitrate = g.bitrate, n.audiocodec = g.audiocodec, n.reason_end = I; | |
n.max_continuous = o; | |
n.ms_played = p; | |
n.ms_played_union = q; | |
n.n_seeks_forward = t; | |
n.n_seeks_backward = u; | |
n.ms_seeks_forward = w; | |
n.ms_seeks_backward = v; | |
n.ms_latency = | |
x; | |
n.display_track = F; | |
n.play_context = G; | |
n.reason_start = H; | |
n.referrer = K; | |
n.referrer_version = L; | |
for (n.referrer_vendor = N; d < c.length; d++) c[d].log(n); | |
b === z.AD_END && g.ad !== void 0 && (y || a.trigger(f.RECORD_AD_EVENT, { | |
playerId: g.id, | |
adUri: "spotify:ad:" + g.ad.file_id, | |
type: "impression" | |
}), delete g.ad); | |
y && (y = !1); | |
h.log("Spotify.PlayerTracker", ["Logging song data -> Type:", b, "-> Arguments:", n, " of player", g.id], "corejs") | |
} | |
}, J = function (a) { | |
var b = k[z.TRACK_EVENT], | |
f = 0; | |
if (M !== "") | |
for (a = { | |
lid: M, | |
event: a, | |
ms_where: g.position() | |
}; f < b.length; f++) b[f].log(a) | |
}, | |
V = function (a) { | |
p += a.params.interval; | |
n = g.getPlayerState().position; | |
a = Math.floor(p * 0.001) * 1E3; | |
if ((a % 15E3 === 0 || p < 1E3) && R < 4 && !D && T !== a) g.isPreview || S(z.TRACK_PROGRESS), R++, T = a | |
}, W = function (a) { | |
s.push({ | |
type: "START", | |
time: parseInt(a) | |
}); | |
b = !0 | |
}, Y = function (a) { | |
s.push({ | |
type: "END", | |
time: parseInt(a) | |
}); | |
b = !1 | |
}, Z = function () { | |
h.log("Spotify.PlayerTracker", ["Cache is initialized..."], "corejs"); | |
C.get(Spotify.Utils.Base64.encode(c) + ":stats:" + g.id, aa, a) | |
}, U = function () {}, Q = function (a) { | |
h.log("Spotify.PlayerTracker", ["endSongData are now stored", | |
arguments | |
], "corejs") | |
}, X = function (a) { | |
h.error("Spotify.PlayerTracker", ["endSongData are NOT stored", arguments], "corejs") | |
}, aa = function (b, f) { | |
if (f !== null) { | |
C.remove(b, ea, a); | |
var k; | |
k = JSON.parse(Spotify.Utils.Base64.decode(f)); | |
if (D = k.isAd) { | |
if (!g.ad) g.ad = {}; | |
g.ad.file_id = k.ad_file_id; | |
g.ad.ad_id = k.ad_id; | |
A = k.last_stream_started_at; | |
g.ad.token = k.token; | |
g.ad.has_been_clicked = k.clicked; | |
g.ad.adPlayCount = k["client-ad-count"]; | |
g.ad.campaignPlayCount = k["client-campaign-count"] | |
} | |
M = k.lid; | |
P = k.isPreview; | |
o = k.max_continuous; | |
q = | |
k.ms_played_union; | |
p = k.ms_played; | |
t = k.n_seeks_forward; | |
u = k.n_seeks_backward; | |
w = k.ms_seeks_forward; | |
v = k.ms_seeks_backward; | |
x = k.ms_latency; | |
F = k.display_track; | |
G = k.play_context; | |
B = k.source_start; | |
E = k.source_end; | |
H = k.reason_start; | |
I = k.reason_end; | |
K = k.referrer; | |
L = k.referrer_version; | |
N = k.referrer_vendor; | |
y = !0; | |
D ? S(z.AD_END) : P ? S(z.PREVIEW_END) : S(z.TRACK_END); | |
ba() | |
} | |
}, ea = function () {}, ba = function () { | |
P = D = !1; | |
M = ""; | |
p = 0; | |
m = ""; | |
q = o = 0; | |
s = []; | |
x = v = w = u = t = 0; | |
F = ""; | |
N = L = K = I = H = E = B = G = "unknown" | |
}, fa = function (a, b) { | |
return a.time - b.time | |
}, ca = function (a) { | |
for (var b = | |
0, f = 0, k = 0, m = 0, c = 0, d = 0; c < a.length; c++) c % 2 !== 0 && typeof a[c - 1] !== "undefined" && a[c - 1].type === "START" && (d = a[c].time - a[c - 1].time, o = d > o ? d : o); | |
h.log("Spotify.PlayerTracker", ["max continuous", o], "corejs"); | |
for (a.sort(fa); m < a.length; m++) a[m].type === "START" && (f === 0 && (k = m), ++f), a[m].type === "END" && (--f, f === 0 && (b += a[m].time - a[k].time)); | |
h.log("Spotify.PlayerTracker", ["Union calculated:", b, "Segments:", a], "corejs"); | |
return b | |
}, da = function () { | |
Y(n); | |
var a = {}; | |
D ? (a.ad_file_id = g.ad.file_id, a.lid = g.ad.ad_id, a.last_stream_started_at = | |
A, a.token = g.ad.token, a.clicked = g.ad.has_been_clicked, a["client-ad-count"] = g.ad.adPlayCount, a["client-campaign-count"] = g.ad.campaignPlayCount, a.source_start = "pendad") : (a.source_start = B || "unknown", a.lid = M); | |
a.isAd = D; | |
a.isPreview = P; | |
a.source_end = a.source_start; | |
a.max_continuous = o; | |
a.ms_played = p; | |
a.ms_played_union = ca(s); | |
a.n_seeks_forward = t; | |
a.n_seeks_backward = u; | |
a.ms_seeks_forward = w; | |
a.ms_seeks_backward = v; | |
a.ms_latency = x; | |
a.display_track = F || ""; | |
a.play_track = a.display_track; | |
a.play_context = G || "unknown"; | |
a.reason_start = | |
H || "unknown"; | |
a.reason_end = "reload"; | |
a.referrer = K || "unknown"; | |
a.referrer_version = L || "unknown"; | |
a.referrer_vendor = N || "unknown"; | |
C.put(Spotify.Utils.Base64.encode(c) + ":stats:" + g.id, Spotify.Utils.Base64.encode(JSON.stringify(a)), Q, X, null, this) | |
}, ga = function () { | |
if (M !== "") { | |
h.log("Spotify.PlayerTracker", ["Tracking the position changed event of player", g.id], "corejs"); | |
var a = parseInt(g.getPlayerState().position); | |
a !== n && (b && (h.log("Spotify.PlayerTracker", ["Union End from _onPositionChanged", n], "corejs"), Y(n)), a > | |
n ? (t++, w += a - n, h.log("Spotify.PlayerTracker", ["Went forward", a - n, "ms"], "corejs")) : a < n && (u++, v += n - a, h.log("Spotify.PlayerTracker", ["Went back", n - a, "ms"], "corejs")), n = a, h.log("Spotify.PlayerTracker", ["Union Start from _onPositionChanged", n], "corejs"), W(n)) | |
} | |
}; | |
this.onConnected = function () { | |
h.log("Spotify.PlayerTracker", ["Tracking the on connect event"], "corejs"); | |
M !== "" && (g.isPlaying ? (h.log("Spotify.PlayerTracker", ["Tracking the reconnect while playing event"], "corejs"), J(1)) : g.isPaused && (h.log("Spotify.PlayerTracker", ["Tracking the reconnect while being paused event"], "corejs"), J(2))) | |
}; | |
var ha = function (a) { | |
A = a.params.timestamp | |
}, ia = function (a) { | |
h.log("Spotify.PlayerTracker", ["Tracking the on song loaded event", a], "corejs") | |
}, ja = function () { | |
h.log("Spotify.PlayerTracker", ["Tracking the on load event of player", g.id], "corejs"); | |
M = g.lid; | |
m = g.trackUri; | |
D = g.isAd; | |
P = g.isPreview; | |
x = (new Date).getTime() - A; | |
F = O.display_track || ""; | |
G = O.play_context || "unknown"; | |
B = O.source_start || "unknown"; | |
H = O.reason_start || "unknown"; | |
K = O.referrer || "unknown"; | |
L = O.referrer_version || "unknown"; | |
N = O.referrer_vendor || "unknown"; | |
n = g.getPlayerState().position; | |
h.log("Spotify.PlayerTracker", ["Union Start from _onLoaded", n], "corejs"); | |
W(n) | |
}, ka = function () { | |
g.getPlayerState(); | |
J(3); | |
h.log("Spotify.PlayerTracker", ["Tracking the on play event of player", g.id], "corejs") | |
}, la = function () { | |
J(4); | |
h.log("Spotify.PlayerTracker", ["Tracking the on pause event of player", g.id], "corejs") | |
}, ma = function () { | |
h.log("Spotify.PlayerTracker", ["Tracking the invalid track uri event of player", g.id], | |
"corejs") | |
}, na = function () { | |
ba(); | |
h.log("Spotify.PlayerTracker", ["Tracking the playback failed event of player", g.id], "corejs") | |
}; | |
this.setEndSongStartLog = function (a) { | |
typeof a !== "undefined" && (O = a) | |
}; | |
this.setEndSongStopLog = function (a) { | |
typeof a !== "undefined" && (E = a.source_end || "unknown", I = a.reason_end || "unknown") | |
}; | |
this.stopTrackingAndLog = function () { | |
h.log("Spotify.PlayerTracker", ["Stopping tracking and logging", g.id], "corejs"); | |
R = 0; | |
T = -1; | |
h.log("Spotify.PlayerTracker", ["Union End from _logEndSongData", n], "corejs"); | |
Y(n); | |
D ? S(z.AD_END) : P ? S(z.PREVIEW_END) : S(z.TRACK_END); | |
ba() | |
}; | |
this.dispose = function (b) { | |
h.log("Spotify.PlayerTracker", ["Disposing tracker with id", this.id], "corejs"); | |
typeof b !== "undefined" && b || da(); | |
h.log("Spotify.PlayerTracker", ["Unbind event listeners"], "corejs"); | |
g.unbind(f.POSITION_CHANGED, ga, a); | |
g.unbind(f.PLAYING, ka, a); | |
g.unbind(f.PAUSED, la, a); | |
g.unbind(f.INVALID_TRACK_URI, ma, a); | |
g.unbind(f.PLAYBACK_FAILED, na, a); | |
g.unbind(f.TRACK_PLAY_REQUEST, ha, a); | |
g.unbind(f.SONG_LOADED, ia, a); | |
g.unbind(f.LOAD, ja, a); | |
g.unbind(f.PLAYER_STATE, | |
V, a) | |
}; | |
this.addLogger = function (a, b) { | |
typeof k[a] === "undefined" && (k[a] = []); | |
k[a].push(b) | |
}; | |
this.initialize = function () { | |
a = this; | |
C.initialize(Z, U, this); | |
h.log("Spotify.PlayerTracker", ["Binding event listeners"], "corejs"); | |
g.bind(f.POSITION_CHANGED, ga, a); | |
g.bind(f.PLAYING, ka, a); | |
g.bind(f.PAUSED, la, a); | |
g.bind(f.INVALID_TRACK_URI, ma, a); | |
g.bind(f.PLAYBACK_FAILED, na, a); | |
g.bind(f.TRACK_PLAY_REQUEST, ha, a); | |
g.bind(f.SONG_LOADED, ia, a); | |
g.bind(f.LOAD, ja, a); | |
g.bind(f.PLAYER_STATE, V, a) | |
} | |
}; | |
Spotify.Protobuf.Parser = function () { | |
function d() {} | |
function g(a) { | |
var b = f[a.current.value], | |
c = a.next().value, | |
h = a.next().value; | |
a.expectToken("="); | |
var d = ~~a.next().value; | |
a.skipUntil(";"); | |
return { | |
name: h, | |
number: d, | |
label: b, | |
type: k[c], | |
type_name: k[c] ? void 0 : c, | |
default_value: void 0 | |
} | |
} | |
function c(a, b) { | |
b = { | |
name: a.next().value, | |
field: [], | |
nested_type: [], | |
enum_type: [] | |
}; | |
for (a.expectToken("{"); a.next().type != "}";) switch (a.current.value) { | |
case "optional": | |
case "repeated": | |
case "required": | |
b.field.push(g(a)); | |
break; | |
case "message": | |
b.nested_type.push(c(a)); | |
break; | |
case "enum": | |
b.enum_type.push(h(a)); | |
break; | |
case "extensions": | |
a.skipUntil(";"); | |
break; | |
case ";": | |
break; | |
default: | |
a.fail("Unrecognized message token: " + a.current.value) | |
} | |
return b | |
} | |
function h(a) { | |
var b = a.next().value; | |
a.expectToken("{"); | |
for (var f = []; a.next().type != "}";) { | |
var k = a.current.value; | |
a.expectToken("="); | |
var c = ~~a.next().value; | |
f.push({ | |
name: k, | |
number: c | |
}); | |
a.skipUntil(";") | |
} | |
return { | |
name: b, | |
value: f | |
} | |
} | |
var b = {}; | |
d.Label = { | |
LABEL_OPTIONAL: 1, | |
LABEL_REQUIRED: 2, | |
LABEL_REPEATED: 3 | |
}; | |
d.Type = { | |
TYPE_DOUBLE: 1, | |
TYPE_FLOAT: 2, | |
TYPE_INT64: 3, | |
TYPE_UINT64: 4, | |
TYPE_INT32: 5, | |
TYPE_FIXED64: 6, | |
TYPE_FIXED32: 7, | |
TYPE_BOOL: 8, | |
TYPE_STRING: 9, | |
TYPE_MESSAGE: 11, | |
TYPE_BYTES: 12, | |
TYPE_UINT32: 13, | |
TYPE_ENUM: 14, | |
TYPE_SFIXED32: 15, | |
TYPE_SFIXED64: 16, | |
TYPE_SINT32: 17, | |
TYPE_SINT64: 18 | |
}; | |
var a = function (a) { | |
this.text = a; | |
this.ptr = 0; | |
this.current = { | |
value: "", | |
type: "", | |
ptr: 0 | |
} | |
}; | |
a.prototype = { | |
where: function (a) { | |
for (var a = a === void 0 ? this.current.ptr : a, b = 0, f = -1; f && f <= a;) f = this.text.indexOf("\n", f) + 1, ++b; | |
return "line: " + b | |
}, | |
fail: function (a, b) { | |
throw this.where(b) + ": " + a; | |
}, | |
skipWhitespace: function () { | |
for (var a = | |
this.text[this.ptr]; a && " \t\r\n".indexOf(a) != -1;) a = this.text[++this.ptr] | |
}, | |
skipLineComment: function () { | |
for (var a = this.text[this.ptr]; a && a !== "\r" && a !== "\n";) a = this.text[++this.ptr]; | |
a === "\r" && (a = this.text[++this.ptr]); | |
a === "\n" && ++this.ptr | |
}, | |
skipBlockComment: function () { | |
for (var a = this.ptr, b = this.text[this.ptr], f = !1; b && !(f && b === "/");) f = b === "*", b = this.text[++this.ptr]; | |
b || this.fail("Expected end of block comment", a); | |
++this.ptr | |
}, | |
skipUntil: function (a) { | |
for (var b = this.ptr; this.next().type !== a;) this.current.type === | |
"" && this.fail("Expected: " + a + "(Unexpected end of data)", b) | |
}, | |
expectToken: function (a) { | |
this.next().type !== a && this.fail("Expected: " + a) | |
}, | |
extractWord: function () { | |
for (var a = this.ptr, b = this.text[this.ptr]; b && "{}[]=; \t\r\n/".indexOf(b) === -1;) b = this.text[++this.ptr]; | |
this.current.type = "word"; | |
this.current.value = this.text.substring(a, this.ptr) | |
}, | |
extractString: function () { | |
var a = this.text.indexOf('"', this.ptr + 1); | |
this.current.type = "string"; | |
this.current.value = this.text.substring(this.ptr + 1, a - 1); | |
this.ptr = a + 1 | |
}, | |
next: function () { | |
this.skipWhitespace(); | |
for (var a = this.text[this.ptr]; a === "/";) a = this.text[++this.ptr], a === "/" ? (++this.ptr, this.skipLineComment()) : a === "*" ? (++this.ptr, this.skipBlockComment()) : this.fail("Expecting // or /*", this.ptr - 1), this.skipWhitespace(), a = this.text[this.ptr]; | |
this.current.ptr = this.ptr; | |
this.ptr >= this.text.length ? (this.current.value = "", this.current.type = "") : "{}[]=;".indexOf(a) !== -1 ? (this.current.value = this.current.type = a, ++this.ptr) : a === '"' ? this.extractString() : this.extractWord(); | |
return this.current | |
} | |
}; | |
var f = { | |
optional: "LABEL_OPTIONAL", | |
required: "LABEL_REQUIRED", | |
repeated: "LABEL_REPEATED" | |
}, k = { | |
"double": "TYPE_DOUBLE", | |
"float": "TYPE_FLOAT", | |
int64: "TYPE_INT64", | |
uint64: "TYPE_UINT64", | |
int32: "TYPE_INT32", | |
fixed64: "TYPE_FIXED64", | |
fixed32: "TYPE_FIXED32", | |
bool: "TYPE_BOOL", | |
string: "TYPE_STRING", | |
bytes: "TYPE_BYTES", | |
uint32: "TYPE_UINT32", | |
sfixed32: "TYPE_SFIXED32", | |
sfixed64: "TYPE_SFIXED64", | |
sint32: "TYPE_SINT32", | |
sint64: "TYPE_SINT64" | |
}; | |
b.parseFileDescriptor = function (b) { | |
for (var b = new a(b), f = { | |
message_type: [], | |
enum_type: [] | |
}; b.next().type != "";) switch (b.current.value) { | |
case "package": | |
case "option": | |
b.skipUntil(";"); | |
break; | |
case "message": | |
f.message_type.push(c(b)); | |
break; | |
case "enum": | |
f.enum_type.push(h(b)); | |
break; | |
default: | |
b.fail("Unrecognized proto token: " + b.current.value) | |
} | |
return f | |
}; | |
b.FieldDescriptorProto = d; | |
return b | |
}(); | |
Spotify.Protobuf.Serialization = function () { | |
function d() { | |
this._data = [] | |
} | |
function g(a, b, f) { | |
this._data = a; | |
this._ptr = b; | |
this._end = this._ptr + f | |
} | |
function c(a, b, f, k) { | |
switch (b.type) { | |
case "int32": | |
k.writeVarint(b.id << 3 | 0); | |
k.writeVarint(f); | |
break; | |
case "uint32": | |
k.writeVarint(b.id << 3 | 0); | |
k.writeVarint(~~f); | |
break; | |
case "sint32": | |
k.writeVarint(b.id << 3 | 0); | |
k.writeVarint(f << 1 ^ f >> 31); | |
break; | |
case "int64": | |
case "uint64": | |
k.writeVarint(b.id << 3 | 0); | |
k.writeVarint64(Math.floor(f / 4294967296), ~~f); | |
break; | |
case "sint64": | |
k.writeVarint(b.id << | |
3 | 0); | |
b = Math.abs(f) - (f < 0); | |
k.writeVarint64(Math.floor(b / 2147483648), (b << 1) + (f < 0)); | |
break; | |
case "bool": | |
k.writeVarint(b.id << 3 | 0); | |
k.writeVarint(f ? 1 : 0); | |
break; | |
case "string": | |
k.writeVarint(b.id << 3 | 2); | |
b = []; | |
for (a = 0; a < f.length; ++a) { | |
var m = f.charCodeAt(a); | |
if (m < 128) b.push(m); | |
else { | |
if ((m & 64512) === 55296) var h = f.charCodeAt(++a), | |
m = ((m & 1023) << 10 | h & 1023) + 65536; | |
m < 2048 ? b.push(192 | m >> 6) : (m < 65536 ? b.push(224 | m >> 12) : (b.push(240 | m >> 18), b.push(128 | m >> 12 & 63)), b.push(128 | m >> 6 & 63)); | |
b.push(128 | m & 63) | |
} | |
} | |
f = b; | |
k.writeVarint(f.length); | |
k.writeAll(f); | |
break; | |
case "bytes": | |
k.writeVarint(b.id << 3 | 2); | |
b = []; | |
for (a = 0; a < f.length; ++a) b.push(f.charCodeAt(a)); | |
f = b; | |
k.writeVarint(f.length); | |
k.writeAll(f); | |
break; | |
case "*": | |
for (m = 0; m < f.length; ++m) c(a, b.subField, f[m], k); | |
break; | |
case "#": | |
b.enumMap.toNumber.hasOwnProperty(f); | |
f = b.enumMap.toNumber[f]; | |
k.writeVarint(b.id << 3 | 0); | |
k.writeVarint(f); | |
break; | |
default: | |
if (a.hasOwnProperty(b.type)) m = new d, a[b.type].serializeToStream(f, m), k.writeVarint(b.id << 3 | 2), k.writeVarint(m._data.length), k.writeAll(m._data); | |
else throw "Unsupported type"; | |
} | |
} | |
function h(a) { | |
for (var b = [], f = 0; f < a.length;) { | |
var k = a.charCodeAt(f++); | |
if (k < 128) b.push(a[f - 1]); | |
else { | |
var c; | |
k < 224 ? (k &= -225, c = 2) : k < 240 ? (k &= -241, c = 3) : (k &= -249, c = 4); | |
for (; --c && f < a.length;) var m = a.charCodeAt(f++), | |
k = k << 6 | m & -193; | |
k < 65536 ? b.push(String.fromCharCode(k)) : (k -= 65536, b.push(String.fromCharCode(55296 | k >> 10, 56320 | k & 1023))) | |
} | |
} | |
return b.join("") | |
} | |
function b(a) { | |
return decodeURIComponent(escape(a)) | |
} | |
function a(b, f) { | |
var k = f.name; | |
switch (f.type) { | |
case "int32": | |
return function (a, b, f, c) { | |
return a === 0 ? (f[k || c] = ~~b.readVarint(), !0) : !1 | |
}; | |
case "uint32": | |
return function (a, b, f, c) { | |
return a === 0 ? (f[k || c] = b.readVarint(), !0) : !1 | |
}; | |
case "sint32": | |
return function (a, b, f, c) { | |
return a === 0 ? (a = k || c, b = b.readVarint(), f[a] = b >>> 1 ^ -(b & 1), !0) : !1 | |
}; | |
case "int64": | |
return function (a, b, f, c) { | |
return a === 0 ? (a = b.readVarint64(), f[k || c] = a.hi * 4294967296 + ((a.lo >>> 1) * 2 + (a.lo & 1)), !0) : !1 | |
}; | |
case "uint64": | |
return function (a, b, f, c) { | |
return a === 0 ? (a = b.readVarint64(), f[k || c] = ((a.hi >>> 1) * 2 + (a.hi & 1)) * 4294967296 + ((a.lo >>> 1) * 2 + (a.lo & 1)), !0) : !1 | |
}; | |
case "sint64": | |
return function (a, | |
b, f, c) { | |
return a === 0 ? (a = b.readVarint64(), b = ((a.hi >>> 1) * 2 + (a.hi & 1)) * 2147483648 + (a.lo >>> 1), f[k || c] = a.lo & 1 ? -1 - b : b, !0) : !1 | |
}; | |
case "bool": | |
return function (a, b, f, c) { | |
return a === 0 ? (f[k || c] = b.readVarint() !== 0, !0) : !1 | |
}; | |
case "string": | |
return function (a, b, f, c) { | |
return a === 2 ? (a = b.readVarint(), f[k || c] = t(b.bytes(a)), !0) : !1 | |
}; | |
case "bytes": | |
return function (a, b, f, c) { | |
return a === 2 ? (a = b.readVarint(), f[k || c] = b.bytes(a), !0) : !1 | |
}; | |
case "*": | |
var c = a(b, f.subField); | |
return k ? function (a, b, f) { | |
f = f[k] ? f[k] : f[k] = []; | |
return c(a, b, f, f.length) | |
} : | |
function (a, b, f, k) { | |
f = f[k] ? f[k] : f[k] = []; | |
return c(a, b, f, f.length) | |
}; | |
case "#": | |
var m = f.enumMap.toName; | |
return function (a, b, f, c) { | |
return a === 0 ? (a = b.readVarint(), f[k || c] = m.hasOwnProperty(a) ? m[a] : a, !0) : !1 | |
} | |
} | |
return function (a, c, m, h) { | |
return a === 2 ? (a = c.readVarint(), c = c.substream(a), b[f.type].parseFromStream(c, m[k || h] = {}), !0) : !1 | |
} | |
} | |
function f(b) { | |
for (var f = this, k = 0; k < b.length; ++k)(function (b) { | |
for (var k = [], m = {}, h = b.fields, o = 0; o < h.length; ++o) { | |
var p = h[o]; | |
if (p.type[0] === "*") var q = { | |
type: p.type.substr(1), | |
id: p.id, | |
enumMap: p.enumMap | |
}, | |
p = { | |
type: "*", | |
id: p.id, | |
name: p.name, | |
subField: q | |
}; | |
k[p.id] = a(f, p); | |
m[p.name] = p | |
} | |
f[b.name] = { | |
serializeToStream: function (a, b) { | |
for (var k in a) m.hasOwnProperty(k) && c(f, m[k], a[k], b) | |
}, | |
parseFromStream: function (a, f) { | |
for (; !a.empty();) { | |
var c = a.readVarint(), | |
m = c >>> 3; | |
c &= 7; | |
var h = k[m]; | |
try { | |
if (!h || !h(c, a, f)) switch (h = a, c) { | |
case 0: | |
h.skipVarint(); | |
break; | |
case 1: | |
h.skip(8); | |
break; | |
case 2: | |
var d = h.readVarint(); | |
h.skip(d); | |
break; | |
case 3: | |
case 4: | |
throw "Deprecated wire type"; | |
case 5: | |
h.skip(4); | |
break; | |
default: | |
throw "Unsupported wire type"; | |
} | |
} catch (g) { | |
throw n.error("Spotify.Protobuf.Serialization", ["Error in", b, m, c], "corejs"), g; | |
} | |
} | |
}, | |
serializeToString: function (a, b) { | |
b(serializeToStringSync(a)) | |
}, | |
serializeToStringSync: function (a) { | |
var k = new d; | |
f[b.name].serializeToStream(a, k); | |
return k.toString() | |
}, | |
parseFromString: function (a, b) { | |
b(parseFromStringSync(a)) | |
}, | |
parseFromStringSync: function (a) { | |
var a = new g(a, 0, a.length), | |
k = {}; | |
f[b.name].parseFromStream(a, k); | |
return k | |
} | |
} | |
})(b[k]) | |
} | |
function k(a, b, f, k) { | |
var c = null; | |
a.type_name ? (c = a.type_name, c = f.hasOwnProperty(k + c) ? f[k + c] : f.hasOwnProperty(c) ? f[c] : null, b = c ? b ? "int32" : "#" : | |
a.type_name) : b = u[a.type]; | |
return { | |
id: a.number, | |
type: (a.label === "LABEL_REPEATED" ? "*" : "") + b, | |
name: a.name, | |
typeName: a.type_name, | |
enumMap: c | |
} | |
} | |
function m(a, b, f, c) { | |
for (var m = { | |
name: a.name, | |
fields: [] | |
}, h = 0; h < a.field.length; ++h) m.fields.push(k(a.field[h], b, f, c + a.name + ".")); | |
return m | |
} | |
function o(a, b, f) { | |
for (var k = 0; k < a.length; ++k) { | |
for (var c = f + a[k].name, m = b, h = c, d = a[k].value, g = {}, o = {}, p = 0; p < d.length; ++p) { | |
var n = d[p]; | |
g[n.number] = n.name; | |
o[n.name] = n.number | |
} | |
m[h] = { | |
name: c, | |
toName: g, | |
toNumber: o | |
} | |
} | |
} | |
function p(a, b, f) { | |
for (var k = 0; k < a.length; ++k) { | |
var c = | |
f + a[k].name + "."; | |
p(a[k].nested_type, b, c); | |
o(a[k].enum_type, b, c) | |
} | |
} | |
var q = {}, n = Spotify.DebuggerJS; | |
d.prototype.write = function (a) { | |
this._data.push(a) | |
}; | |
d.prototype.writeAll = function (a) { | |
Array.prototype.push.apply(this._data, a) | |
}; | |
d.prototype.writeVarint = function (a) { | |
for (; a & -128;) this.write(a & 127 | 128), a >>>= 7; | |
this.write(a) | |
}; | |
d.prototype.writeVarint64 = function (a, b) { | |
a ? (this.write(b & 127 | 128), this.write(b >>> 7 & 127 | 128), this.write(b >>> 14 & 127 | 128), this.write(b >>> 21 & 127 | 128), a & -8 ? (this.write((a << 4 | b >>> 28) & 127 | 128), this.writeVarint(a >>> | |
3)) : this.write((a << 4 | b >>> 28) & 127)) : this.writeVarint(b) | |
}; | |
d.prototype.toString = function () { | |
var a; | |
a = this._data; | |
if (a.length < s) a = String.fromCharCode.apply(String, a); | |
else { | |
var b = 0, | |
f = []; | |
do f.push(String.fromCharCode.apply(String, a.slice(b, b + s))), b += s; while (b < a.length); | |
a = f.join("") | |
} | |
return a | |
}; | |
g.prototype.empty = function () { | |
return this._ptr >= this._end | |
}; | |
g.prototype.skipVarint = function () { | |
for (; this._data.charCodeAt(this._ptr++) >= 128;); | |
}; | |
g.prototype.readVarint = function () { | |
var a = 0, | |
b = 1; | |
do { | |
var f = this._data.charCodeAt(this._ptr++); | |
a += (f & 127) * b; | |
b *= 128 | |
} while (f >= 128); | |
return a | |
}; | |
g.prototype.readVarint64 = function () { | |
var a = 0, | |
b = 1 / 4294967296, | |
f = 0, | |
k = 1; | |
do { | |
var c = this._data.charCodeAt(this._ptr++); | |
a |= (c & 127) * b; | |
f |= (c & 127) * k; | |
b *= 128; | |
k *= 128 | |
} while (c >= 128); | |
return { | |
hi: a, | |
lo: f | |
} | |
}; | |
g.prototype.skip = function (a) { | |
this._ptr += a | |
}; | |
g.prototype.substream = function (a) { | |
var b = this._ptr; | |
this._ptr += a; | |
return new g(this._data, b, a) | |
}; | |
g.prototype.bytes = function (a) { | |
var b = this._ptr; | |
this._ptr += a; | |
return this._data.substr(b, a) | |
}; | |
var s = 4096, | |
t = decodeURIComponent && escape ? b : h, | |
u = { | |
TYPE_INT32: "int32", | |
TYPE_SINT32: "sint32", | |
TYPE_UINT32: "uint32", | |
TYPE_STRING: "string", | |
TYPE_BYTES: "bytes", | |
TYPE_BOOL: "bool", | |
TYPE_DOUBLE: "double", | |
TYPE_INT64: "int64", | |
TYPE_UINT64: "uint64", | |
TYPE_SINT64: "sint64" | |
}; | |
q.createFromJson = function (a) { | |
return new f(a) | |
}; | |
q.createFromFileDescriptor = function (a, b) { | |
var k = b === void 0 ? !1 : b, | |
c = [], | |
h = {}; | |
o(a.enum_type, h, ""); | |
p(a.message_type, h, ""); | |
for (var d = 0; d < a.message_type.length; ++d) c.push(m(a.message_type[d], k, h, "")); | |
return new f(c) | |
}; | |
return q | |
}(); | |
Spotify.Heartbeat = function () { | |
var d = new Spotify.Events, | |
g = null, | |
c = this; | |
this.start = function () { | |
this.stop(); | |
g = setInterval(a, 18E4) | |
}; | |
this.stop = function () { | |
g !== null && (clearInterval(g), g = null) | |
}; | |
var h = function () {}, b = function () {}, a = function () { | |
var a = new Spotify.Calls.Simple({ | |
method: "echo", | |
payload: ["h"], | |
context: c, | |
persistent: !1, | |
retries: 0, | |
type: "heartbeat" | |
}, h, b); | |
c.send(a) | |
}; | |
this.onNotify = function (a) { | |
switch (a.type) { | |
case d.DISCONNECTED: | |
this.stop(); | |
break; | |
case d.CONNECTED: | |
this.start() | |
} | |
} | |
}; | |
Spotify.Gateway = function (d) { | |
Spotify.EventTarget.call(this); | |
var g = Spotify.DebuggerJS, | |
c = new Spotify.Logging.Logger, | |
h = new Spotify.Events, | |
b = this; | |
this.isReady = !1; | |
this.bridge = null; | |
var a, f, k = !1, | |
m; | |
this.isConnected = !1; | |
this.rpc = function (b, c, h, d, o, p, n, q) { | |
h = a.addCall(b, c, h, d, o, p, n, q); | |
g.log("Spotify.Gateway", ["Call with method", b, "calltype", q, "params", c, "and request id", h, "was executed"], "corejs"); | |
this.isConnected ? k ? m.addToBucket(h) : this.bridge.rpc(b, c, h) : (p ? a.setPersistent(h, !0) : a.setPersistent(h, !1), f.reset()) | |
}; | |
this.disconnect = function () { | |
this.bridge.disconnect() | |
}; | |
this.connect = function (a, b) { | |
this.bridge.connect(b, a) | |
}; | |
var o = function () { | |
this.isConnected = !0 | |
}, p = function (a) { | |
g.log("Spotify.Gateway", ["onTimeout", a], "corejs") | |
}, q = function (a) { | |
b.trigger(h.HERMES_B64_MESSAGE, a.params) | |
}, n = function () { | |
b.trigger(h.USER_INFO_CHANGE) | |
}, s = function () { | |
try { | |
c.logWindowSize(window.innerWidth, window.innerHeight) | |
} catch (f) {} | |
for (var k = 0, m = a.getPersistentCalls(), d = m.length, g; k < d; k++) g = m[k], b.rpc(g.method, g.params, g.callback, g.errback, g.context, | |
g.persistent); | |
k = 0; | |
m = a.getCalls(); | |
for (d = m.length; k < d; k++) g = m[k], g.method !== "work_done" && b.rpc(g.method, g.params, g.callback, g.errback, g.context, g.persistent, g.retries--); | |
b.trigger(h.CONNECTED) | |
}, t = function () { | |
this.isConnected = !1 | |
}, u = function () { | |
b.trigger(h.ON_TRY_TO_CONNECT) | |
}, w = function (a) { | |
b.trigger(h.DISCONNECTED, a.params) | |
}, v = function (b) { | |
var f = a.getCall(b.params.requestId), | |
k; | |
typeof f !== "undefined" && (k = (new Date).getTime() - f.timestamp, g.log("Spotify.Gateway", ["Latency of call with request id", b.params.requestId, | |
"is", k, "ms" | |
], "corejs"), f.callback.call(f.context, b.params), f.callType !== "request_time" && f.callType !== "aggregated_request_latencies" && f.callType !== "userdata" && f.callType !== "log_view" && f.callType !== "track_end" && f.callType !== "track_progress" && f.callType !== "end_preview" && f.callType !== "log_ad" && f.callType !== "js_exceptions" && f.callType !== "log" && f.callType !== "log_ce" && c.logAggregatedRequestTime(f.callType, k)) | |
}, A = function (f) { | |
var h = [], | |
d = !0; | |
g.error("Spotify.Gateway", ["Got an RPC Error", f], "corejs"); | |
if (typeof f.params.response !== | |
"undefined") h = f.params.response; | |
if (h.length >= 3 && (h[0] === Spotify.Errors.Domains.HERMES_ERROR || h[0] === Spotify.Errors.Domains.HERMES_SERVICE_ERROR) && (h[1] === Spotify.Errors.Codes.HM_TOO_MANY_REQUESTS || h[1] === Spotify.Errors.Codes.HM_FAILED_TO_SEND_TO_BACKEND)) d = !1; | |
var d = a.getCall(f.params.requestId, d), | |
o; | |
typeof d !== "undefined" && (o = (new Date).getTime() - d.timestamp, g.log("Spotify.Gateway", ["Latency of call with request id", f.params.requestId, "is", o, "ms"], "corejs"), h.length >= 3 ? (h[0] === Spotify.Errors.Domains.HERMES_ERROR || | |
h[0] === Spotify.Errors.Domains.HERMES_SERVICE_ERROR) && h[1] === Spotify.Errors.Codes.HM_TOO_MANY_REQUESTS ? (k = !0, m.start(), m.addToBucket(f.params.requestId)) : (h[0] === Spotify.Errors.Domains.HERMES_ERROR || h[0] === Spotify.Errors.Domains.HERMES_SERVICE_ERROR) && (h[1] === Spotify.Errors.Codes.HM_TIMEOUT || h[1] === Spotify.Errors.Codes.HM_FAILED_TO_SEND_TO_BACKEND) && d.retries > 0 ? b.rpc(d.method, d.params, d.callback, d.errback, d.context, d.persistent, d.retries - 1, d.callType) : (h.push(f.params.method), d.errback.call(d.context, | |
new Spotify.Errors.Error(h))) : (g.log("Spotify.Gateway", ["RPC Error callback for method with id:", d.callType, d.params], "corejs"), d.errback.call(d.context, new Spotify.Errors.Error([1, 0, "", f.params]))), d.callType !== "request_time" && d.callType !== "aggregated_request_latencies" && d.callType !== "userdata" && d.callType !== "log_view" && d.callType !== "track_end" && d.callType !== "track_progress" && d.callType !== "end_preview" && d.callType !== "log_ad" && d.callType !== "js_exceptions" && d.callType !== "log" && d.callType !== "log_ce" && | |
c.logAggregatedRequestTime(d.callType, o)) | |
}, x = function () { | |
b.isReady = !0; | |
b.trigger(h.READY) | |
}, F = function (a) { | |
this.trigger(a.type, a.params) | |
}, G = function () { | |
b.trigger(h.TOKEN_LOST) | |
}, B = function (f) { | |
var f = f.params, | |
k = a.getCall(f, !1); | |
g.log("Spotify.Gateway", ["onRateLimitCall Will try run the callback with id", f, k], "corejs"); | |
k && b.bridge.rpc(k.method, k.params, f) | |
}, E = function () { | |
k = !1 | |
}, H = function (a) { | |
b.trigger(a.type, a.params) | |
}; | |
this.dispose = function () {}; | |
this.initialize = function (k, c) { | |
a = new Spotify.CallsManager; | |
m = new Spotify.RateLimiter(1E3, | |
90); | |
m.bind(h.RATE_LIMIT_CALL, B, this); | |
m.bind(h.RATE_LIMIT_DISABLED, E, this); | |
if (d === Spotify.GatewayTypes.FLASH) this.bridge = new Spotify.Flash.Bridge(k, c); | |
else if (d === Spotify.GatewayTypes.WEBSOCKETS) this.bridge = new Spotify.WebSockets.Bridge(k); | |
this.bridge.bind(h.CONNECTION_ESTABLISHED, o, this); | |
this.bridge.bind(h.FAILED_CONNECTING, t, this); | |
this.bridge.bind(h.RPC_CALLBACK, v, this); | |
this.bridge.bind(h.RPC_ERRBACK, A, this); | |
this.bridge.bind(h.TOKEN_LOST, G, this); | |
this.bridge.bind(h.HERMES_B64_MESSAGE, q, this); | |
this.bridge.bind(h.USER_INFO_CHANGE, | |
n, this); | |
this.bridge.bind(h.LOGIN_COMPLETE, s, this); | |
this.bridge.bind(h.TIMEOUT, p, this); | |
this.bridge.bind(h.READY, x, this); | |
this.bridge.bind(h.FLASH_AVAILABLE, F, b); | |
this.bridge.bind(h.FLASH_UNAVAILABLE, F, b); | |
this.bridge.bind(h.WORK, H, b); | |
this.bridge.bind(h.PING_FLASH, H, b); | |
f = new Spotify.ConnectionManager; | |
f.bind(h.ON_TRY_TO_CONNECT, u, this); | |
f.bind(h.NOTIFY_OF_DISCONNECT, w, this); | |
f.initialize(this.bridge); | |
this.bridge.initialize() | |
} | |
}; | |
Spotify.Audio.AudioStream = function (d, g, c) { | |
Spotify.EventTarget.call(this); | |
this.id = d; | |
this.lid = ""; | |
this.isReady = !0; | |
this.isPreview = this.isAd = !1; | |
this.trackUrl = this.trackUri = ""; | |
this.bitrate = 160; | |
this.audiocodec = "mp3"; | |
this.isPaused = this.isPlaying = !1; | |
this.isStopped = !0; | |
this.isActive = this.isLoaded = !1; | |
this.limit = -1; | |
var h = 0, | |
b = 0, | |
a = -1, | |
f, k = {}, m = 1, | |
o = this, | |
p = Spotify.DebuggerJS; | |
new Spotify.Logging.Logger; | |
var q = new Spotify.Events, | |
n = "", | |
s = 0, | |
t = !1, | |
u = 1, | |
w = 0, | |
v = 0, | |
A = !1, | |
x = function (a) { | |
p.log("Spotify.Audio.AudioStream", ["Player event:", | |
o.id, a | |
], "corejs"); | |
switch (a.type) { | |
case q.READY: | |
o.isReady = !0; | |
o.isLoaded && o.load(o.trackUri, v, !o.isPaused); | |
break; | |
case q.NOT_READY: | |
o.isReady = !1; | |
E(); | |
break; | |
case q.DURATION: | |
w = a.params; | |
p.log("Spotify.Audio.AudioStream", ["Got duration", a.params], "corejs"); | |
break; | |
case q.LOAD: | |
H(); | |
w = 0; | |
o.isPaused = !0; | |
o.isStopped = !1; | |
o.isPlaying = !1; | |
o.isLoaded = !0; | |
o.onLoad(a); | |
break; | |
case q.PLAYING: | |
E(); | |
f = setInterval(I, 500); | |
o.isPaused = !1; | |
o.isStopped = !1; | |
o.isPlaying = !0; | |
o.isActive || o.trigger(q.ACTIVE_PLAYER_CHANGED, { | |
id: o.id | |
}); | |
o.onPlay(a); | |
break; | |
case q.PAUSED: | |
E(); | |
o.isPaused = !0; | |
o.isStopped = !1; | |
o.isPlaying = !1; | |
o.onPause(a); | |
break; | |
case q.STOPPED: | |
o.isPaused = !1; | |
o.isStopped = !0; | |
o.isPlaying = !1; | |
o.isLoaded = !1; | |
o.onStop(a); | |
H(); | |
break; | |
case q.BEFORE_SEEK: | |
o.isPlaying && E(); | |
break; | |
case q.POSITION_CHANGED: | |
v = parseInt(a.params); | |
o.isPlaying && (E(), f = setInterval(I, 500)); | |
o.onPositionChanged(a); | |
break; | |
case q.TRACK_ENDED: | |
H(); | |
o.isPaused = !1; | |
o.isStopped = !0; | |
o.isPlaying = !1; | |
o.isLoaded = !0; | |
o.stop(); | |
o.onTrackEnded(a); | |
break; | |
case q.SONG_LOADED: | |
o.onSongLoaded(a); | |
break; | |
case q.PLAYBACK_FAILED: | |
H(); | |
o.isStopped = !0; | |
o.isPaused = !1; | |
o.isPlaying = !1; | |
o.isLoaded = !1; | |
o.onPlaybackFailed(a); | |
break; | |
case q.INVALID_TRACK_URI: | |
H(), o.onPlaybackFailed(a) | |
} | |
}, F = function (a) { | |
a.extra.id === o.id && o.trigger(a.type, a.params) | |
}; | |
this.load = function (b, f, c, m, h) { | |
(o.isPaused || o.isPlaying) && o.stop(); | |
p.log("Spotify.Audio.AudioStream", ["Load track", b], "corejs"); | |
var d, u = new Spotify.Link.fromString(b); | |
this.limit = typeof m !== "undefined" ? m : -1; | |
a = typeof h !== "undefined" ? h : -1; | |
this.isAd = this.isPreview = !1; | |
if (u.type === "audiofile") this.isPreview = !0, this.isAd = !1; | |
else if (u.type === "ad") this.isPreview = !1, this.isAd = !0; | |
this.trigger(q.TRACK_PLAY_REQUEST, { | |
timestamp: (new Date).getTime() | |
}); | |
s = this.isAd ? 0 : f || 0; | |
t = typeof c === "undefined" ? !1 : c; | |
n = b; | |
d = this.isAd ? k[Spotify.Resolvers.AD_RESOLVER] : this.isPreview ? k[Spotify.Resolvers.PREVIEW_RESOLVER] : k[Spotify.Resolvers.STORAGE_RESOLVER]; | |
d.onReady(function () { | |
try { | |
d.list(b, g === Spotify.PlayerTypes.FLASH_RTMPS ? "rtmp" : "", G, B) | |
} catch (a) { | |
p.error("Spotify.Audio.AudioStream", [a.message, a.stack], "corejs") | |
} | |
}, this) | |
}; | |
var G = | |
function (a) { | |
o.lid = a.lid; | |
o.trackUrl = a.uri; | |
o.trackUri = n; | |
p.log("Spotify.Audio.AudioStream", ["Got a result from the resolver", a], "corejs"); | |
c.load(o.id, o.trackUrl, { | |
autoplay: t, | |
startFrom: s, | |
server: a.server, | |
protocol: a.protocol | |
}); | |
v = s; | |
t = !1; | |
s = 0 | |
}, B = function (a) { | |
o.lid = ""; | |
o.trackUrl = ""; | |
n = o.trackUri = ""; | |
s = 0; | |
p.error("Spotify.Audio.AudioStream", ["Got an error from the storage resolver", a], "corejs"); | |
o.trigger(q.INVALID_TRACK_URI, a) | |
}, E = function () { | |
f && (clearInterval(f), f = null); | |
b = 0 | |
}, H = function () { | |
E(); | |
h = 0; | |
A = !1 | |
}, I = function () { | |
var f = | |
(new Date).getTime(), | |
k = f - (b === 0 ? f - 500 : b), | |
m = c.getPlayerState(o.id); | |
v = m.position; | |
w = m.duration; | |
m.isPlaying = o.isPlaying; | |
m.isStopped = o.isStopped; | |
m.isPaused = o.isPaused; | |
var d = m.duration; | |
b = f; | |
o.trigger(q.PLAYER_STATE, { | |
state: m, | |
interval: k | |
}); | |
p.log("Spotify.Audio.AudioStream", ["Tracking state:", m, k], "corejs"); | |
if (o.limit !== -1) d = o.limit; | |
v >= d - a - 500 && a !== -1 && !A && (p.log("Spotify.Audio.AudioStream", ["BEFORE_END event", m.position, m.duration], "corejs"), A = !0, o.trigger(q.BEFORE_END)); | |
h += k; | |
h >= o.limit && o.limit !== -1 && (o.trigger(q.TRACK_ENDED), | |
o.stop()) | |
}; | |
this.play = function (a, b) { | |
if (typeof b !== "undefined" && b !== -1) this.limit = b; | |
o.isReady && (h = 0, c.play(this.id, a)) | |
}; | |
this.pause = function () { | |
o.isPlaying && c.pause(this.id) | |
}; | |
this.resume = function () { | |
!o.isPlaying && o.isPaused && o.isLoaded && c.resume(this.id) | |
}; | |
this.stop = function () { | |
if (o.isLoaded) a = this.limit = -1, c.stop(this.id), this.trigger(q.STOPPED, {}, this.id) | |
}; | |
this.playpause = function () { | |
o.isPaused ? o.resume() : o.pause() | |
}; | |
this.position = function () { | |
return o.isLoaded ? v = c.position(this.id) : 0 | |
}; | |
this.getPlayerState = | |
function () { | |
var a = {}; | |
a.volume = u; | |
a.position = v; | |
a.duration = o.isLoaded ? w : 0; | |
a.isPlaying = this.isPlaying; | |
a.isStopped = this.isStopped; | |
a.isPaused = this.isPaused; | |
return a | |
}; | |
this.seek = function (a) { | |
return o.isLoaded ? (o.trigger(q.BEFORE_SEEK), v = a, c.seek(this.id, a)) : 0 | |
}; | |
this.setVolume = function (a) { | |
!isNaN(a) && a >= 0 && a <= 1 && (u = a, c.setVolume(this.id, a * m)) | |
}; | |
this.setMasterVolume = function (a) { | |
!isNaN(a) && a >= 0 && a <= 1 && (m = a, this.setVolume(u)) | |
}; | |
this.getVolume = function () { | |
return u | |
}; | |
this.getDuration = function () { | |
return w | |
}; | |
this.addFileResolver = | |
function (a, b) { | |
k[a] = b | |
}; | |
this.initialize = function () { | |
g === Spotify.PlayerTypes.HTML5_HTTP && (c.bind(q.TRACK_ENDED, F), c.bind(q.POSITION_CHANGED, F), c.bind(q.PLAYING, F), c.bind(q.PAUSED, F), c.bind(q.STOPPED, F), c.bind(q.LOAD, F)); | |
this.bind(q.TRACK_ENDED, x, this, 10); | |
this.bind(q.POSITION_CHANGED, x, this, 10); | |
this.bind(q.PLAYING, x, this, 10); | |
this.bind(q.PAUSED, x, this, 10); | |
this.bind(q.STOPPED, x, this, 10); | |
this.bind(q.PLAYBACK_FAILED, x, this, 10); | |
this.bind(q.SONG_LOADED, x, this, 10); | |
this.bind(q.INVALID_TRACK_URI, x, this, 10); | |
this.bind(q.LOAD, | |
x, this, 10); | |
this.bind(q.READY, x, this, 10); | |
this.bind(q.NOT_READY, x, this, 10); | |
this.bind(q.TRACK_PLAY_REQUEST, x, this, 10); | |
this.bind(q.DURATION, x, this, 10); | |
this.bind(q.BEFORE_SEEK, x, this, 10); | |
this.bind(q.FAILED_CONNECTING, x, this, 10); | |
c.initializePlayerById(this.id) | |
}; | |
this.dispose = function () { | |
g === Spotify.PlayerTypes.HTML5_HTTP && (c.unbind(q.TRACK_ENDED, F), c.unbind(q.POSITION_CHANGED, F), c.unbind(q.PLAYING, F), c.unbind(q.PAUSED, F), c.unbind(q.STOPPED, F), c.unbind(q.LOAD, F)); | |
this.unbind(q.TRACK_ENDED, x, this); | |
this.unbind(q.POSITION_CHANGED, | |
x, this); | |
this.unbind(q.PLAYING, x, this); | |
this.unbind(q.PAUSED, x, this); | |
this.unbind(q.STOPPED, x, this); | |
this.unbind(q.PLAYBACK_FAILED, x, this); | |
this.unbind(q.SONG_LOADED, x, this); | |
this.unbind(q.INVALID_TRACK_URI, x, this); | |
this.unbind(q.LOAD, x, this); | |
this.unbind(q.READY, x, this); | |
this.unbind(q.NOT_READY, x, this); | |
this.unbind(q.TRACK_PLAY_REQUEST, x, this); | |
this.unbind(q.DURATION, x, this); | |
this.unbind(q.BEFORE_SEEK, x, this); | |
this.unbind(q.FAILED_CONNECTING, x, this) | |
}; | |
this.onLoad = function () {}; | |
this.onPlay = function () {}; | |
this.onPause = | |
function () {}; | |
this.onStop = function () {}; | |
this.onTrackEnded = function () {}; | |
this.onSongLoaded = function () {}; | |
this.onPositionChanged = function () {}; | |
this.onInvalidTrackUri = function () {}; | |
this.onPlaybackFailed = function () {} | |
}; | |
Spotify.Audio.AudioManager = function (d, g, c) { | |
Spotify.EventTarget.call(this); | |
this.isInitialized = this.isReady = !1; | |
var h = this, | |
b = 1, | |
a = {}, f = Spotify.DebuggerJS, | |
k, m = new Spotify.Events, | |
o = new Spotify.Logging.Types, | |
p, q, n, s = [], | |
t = [], | |
u = 0, | |
w, v = "", | |
A = function (a) { | |
this.trigger(a.type, a.params) | |
}, x = function (a) { | |
v = a.user; | |
h.addPlayer("Player0"); | |
h.isReady = !0; | |
h.trigger(m.READY) | |
}, F = function () {}, G = function () { | |
this.hasSound() ? (h.isInitialized = !0, h.trigger(m.INITIALIZED), w.onReady(function () { | |
w.getUserInfo(x, F) | |
})) : this.trigger(m.NO_SOUND_CAPABILITIES) | |
}, | |
B = function (a) { | |
switch (a.type) { | |
case m.STOPPED: | |
case m.TRACK_END: | |
h.getTrackerForPlayerWithId(a.extra).stopTrackingAndLog(); | |
var b = h.getTrackerIndexWithId(a.extra); | |
t[b].dispose(!0); | |
t[b] = null; | |
f.log("Spotify.Audio.AudioManager", ["Stopped event capture", t], "corejs"); | |
I(a.extra, b, h.getPlayerAtIndex(b), v) | |
} | |
h.trigger(a.type, a.params, a.extra) | |
}, E = function (a) { | |
for (var b = 0, f = s.length; b < f; b += 1) { | |
var k = s[b]; | |
k.id === a.params.id ? (k.isActive = !0, p = k, h.trigger(a.type, a.params, a.extra)) : k.isActive = !1 | |
} | |
}; | |
this.onReady = function (a, | |
b) { | |
this.isReady ? a.call(b) : h.bind(m.READY, a, b) | |
}; | |
var H = function (a) { | |
h.trigger(a.type, a.params) | |
}, I = function (a, b, k, c) { | |
var d = new Spotify.Logging.TrackEnd; | |
d.init(q); | |
var g = new Spotify.Logging.PreviewEnd; | |
g.init(); | |
var p = new Spotify.Logging.TrackProgress; | |
p.init(q); | |
var n = new Spotify.Logging.TrackEvent; | |
n.init(q); | |
var s = new Spotify.Logging.AdEnd; | |
s.init(q); | |
a = t[b] = new Spotify.PlayerTracker(a, k, c); | |
a.bind(m.RECORD_AD_EVENT, H, h); | |
a.addLogger(o.TRACK_END, d); | |
a.addLogger(o.PREVIEW_END, g); | |
a.addLogger(o.TRACK_EVENT, n); | |
a.addLogger(o.AD_END, | |
s); | |
a.addLogger(o.TRACK_PROGRESS, p); | |
a.initialize(); | |
f.log("Spotify.Audio.AudioManager", ["Created a new tracker at index", b, t], "corejs") | |
}; | |
this.addPlayer = function (b, f) { | |
var k; | |
if (typeof b !== "string") throw Error("The id must be a string"); | |
typeof f === "undefined" && (f = c); | |
k = 0; | |
for (var d = s.length; k < d; k += 1) | |
if (s[k].id === b) throw Error("There is already a player with this id: " + b); | |
n.addPlayer(u, b, f); | |
k = s[u] = new Spotify.Audio.AudioStream(b, f, n); | |
k.addFileResolver(Spotify.Resolvers.STORAGE_RESOLVER, a[Spotify.Resolvers.STORAGE_RESOLVER]); | |
k.addFileResolver(Spotify.Resolvers.AD_RESOLVER, a[Spotify.Resolvers.AD_RESOLVER]); | |
k.addFileResolver(Spotify.Resolvers.PREVIEW_RESOLVER, a[Spotify.Resolvers.PREVIEW_RESOLVER]); | |
k.bind(m.ACTIVE_PLAYER_CHANGED, E, h); | |
k.bind(m.TRACK_ENDED, B, h); | |
k.bind(m.POSITION_CHANGED, B, h); | |
k.bind(m.PLAYING, B, h); | |
k.bind(m.PAUSED, B, h); | |
k.bind(m.STOPPED, B, h); | |
k.bind(m.INVALID_TRACK_URI, B, h); | |
k.bind(m.PLAYBACK_FAILED, B, h); | |
k.bind(m.TRACK_PLAY_REQUEST, B, h); | |
k.bind(m.SONG_LOADED, B, h); | |
k.bind(m.LOAD, B, h); | |
k.bind(m.FAILED_CONNECTING, B, | |
h); | |
k.initialize(); | |
I(b, u, k, v); | |
u++; | |
this.trigger(m.PLAYER_CREATED, { | |
id: b | |
}); | |
return k | |
}; | |
this.getPlayers = function () { | |
return s | |
}; | |
this.getActivePlayer = function () { | |
return p | |
}; | |
this.getPlayerById = function (a) { | |
var b; | |
if (typeof a === "string") | |
for (var f = 0, k = s.length; f < k; f += 1) | |
if (b = s[f], b.id === a) return b | |
}; | |
this.getTrackerIndexWithId = function (a) { | |
var b; | |
if (typeof a === "string") | |
for (var f = 0, k = t.length; f < k; f += 1) | |
if (b = t[f], b.id === a) return f | |
}; | |
this.getTrackerForPlayerWithId = function (a) { | |
var b; | |
if (typeof a === "string") | |
for (var f = 0, k = t.length; f < | |
k; f += 1) | |
if (b = t[f], b.id === a) return b | |
}; | |
this.getPlayerAtIndex = function (a) { | |
if (typeof a === "number" && s[a]) return s[a] | |
}; | |
this.getTrackerForPlayerAtIndex = function (a) { | |
if (typeof a === "number" && t[a]) return t[a] | |
}; | |
this.removePlayerById = function (a) { | |
var b; | |
if (typeof a === "string") { | |
if (a === "Player0") return !1; | |
for (var f = 0, k = s.length; f < k; f += 1) | |
if (b = s[f], b.id === a && f !== 0) return this.removePlayerAtIndex(f); | |
return !1 | |
} | |
}; | |
this.removePlayerAtIndex = function (a) { | |
if (typeof a !== "number") return !1; | |
if (a === 0) return !1; | |
return s[a] ? (s[a].isActive && | |
(p = s[0]), s[a].dispose(), t[a].dispose(!0), delete s[a], delete t[a], s[a] = null, t[a] = null, n.removePlayerAtIndex(a)) : !1 | |
}; | |
this.hasSound = function () { | |
return n.hasSound() | |
}; | |
this.setMasterVolume = function (a) { | |
b = a < 0 ? 0 : a > 1 ? 1 : a; | |
for (var f = 0, k = s.length; f < k; f += 1) a = s[f], a.setMasterVolume(b) | |
}; | |
this.getMasterVolume = function () { | |
return b | |
}; | |
this.crossfade = function (a, b, f, c) { | |
k || (k = new Spotify.Audio.Crossfader); | |
k.crossfade(this.getPlayerById(a), this.getPlayerById(b), f, c) | |
}; | |
this.dispose = function () { | |
for (var a, b = 0, f = s.length; b < f; b += 1) a = | |
s[b], a !== null && a !== void 0 && (a.dispose(), a.isActive && t[b].dispose()) | |
}; | |
this.addFileResolver = function (b, f) { | |
a[b] = f | |
}; | |
this.getInterface = function () { | |
return n | |
}; | |
this.initialize = function (a, b) { | |
w = b; | |
q = a; | |
c === Spotify.PlayerTypes.FLASH_HTTP || c === Spotify.PlayerTypes.FLASH_RTMPS || c === Spotify.PlayerTypes.FLASH_AAC ? (n = new Spotify.Flash.PlayerInterface(d, g), n.bind(m.FLASH_AVAILABLE, A, this), n.bind(m.FLASH_UNAVAILABLE, A, this)) : c === Spotify.PlayerTypes.HTML5_HTTP && (n = new Spotify.HTML5.PlayerInterface("html5audio")); | |
n.bind(m.READY, | |
G, this, 10); | |
n.initialize() | |
} | |
}; | |
Spotify.Audio.Crossfader = function () { | |
var d = this, | |
g = Spotify.DebuggerJS, | |
c, h, b = 1, | |
a = !1, | |
f = 0, | |
k = 0, | |
m, o; | |
this.crossfade = function (p, q, n, s) { | |
a ? (this.stop(), c(), c = null, o = m + (1 - (1 - f) + f) * n) : (q.setVolume(0), m = (new Date).getTime(), o = m + n, b = p.getVolume(), f = 0); | |
g.log("Spotify.Audio.Crossfader", ["Target volume", b], "corejs"); | |
a = !0; | |
c = s; | |
h = setInterval(function () { | |
var c = (new Date).getTime(); | |
k = (o - c) / n; | |
f = Math.floor((1 - k) * 100) / 100; | |
var c = Math.floor(b * (1 - f) * 100) / 100, | |
m = Math.floor(b * f * 100) / 100, | |
c = c > 1 ? 1 : c, | |
c = c < 0 ? 0 : c, | |
m = m > 1 ? 1 : m, | |
m = m < 0 ? 0 : m; | |
p.setVolume(c); | |
q.setVolume(m); | |
g.log("Spotify.Audio.Crossfader", [p.id, "will have volume", c, q.id, "will have volume", m], "corejs"); | |
f >= 1 && (a = !1, d.stop(), s()) | |
}, 100) | |
}; | |
this.stop = function () { | |
return h ? (clearInterval(h), h = null, !0) : !1 | |
} | |
}; | |
Spotify.Flash.Bridge = function (d, g) { | |
Spotify.EventTarget.call(this); | |
var c = Spotify.DebuggerJS, | |
h = new Spotify.Events; | |
this.id = d; | |
var b, a = function (a) { | |
this.trigger(a.type, a.params) | |
}; | |
this.rpc = function (a, k, m) { | |
typeof b !== void 0 ? b.isLoaded ? b.getSWF().sp_rpc.apply(b.getSWF(), [a, m].concat(k)) : c.error("Bridge", ["Core.Bridge:rpc: Bridge is not initialized"], "corejs") : c.error("Bridge", ["Core.Bridge:rpc: Bridge is not initialized"], "corejs") | |
}; | |
this.disconnect = function () { | |
typeof b !== void 0 ? b.isLoaded ? b.getSWF().sp_disconnect.apply(b.getSWF()) : | |
c.error("Bridge", ["Core.Bridge:Disconnect: Bridge is not initialized"], "corejs") : c.error("Bridge", ["Core.Bridge:Disconnect: Bridge is not initialized"], "corejs") | |
}; | |
this.connect = function (a, k) { | |
a = a || ""; | |
typeof b !== void 0 && b.isLoaded && b.getSWF().sp_connect.apply(b.getSWF(), [a, k]) | |
}; | |
this.initialize = function () { | |
b = new Spotify.Flash.SWFObject({ | |
SWFFlashId: d, | |
SWFContainerId: g.SWFContainerId, | |
SWFUrl: g.SWFUrl, | |
SWFMinVersion: g.SWFMinVersion, | |
instanceId: d, | |
logging: g.logging, | |
length: g.valid, | |
valid: 0 | |
}); | |
b.bind(h.FLASH_AVAILABLE, | |
a, this); | |
b.bind(h.FLASH_UNAVAILABLE, a, this); | |
b.initialize() | |
}; | |
this.getFlashObject = function () { | |
return b | |
} | |
}; | |
Spotify.WebSockets.Bridge = function (d, g) { | |
Spotify.EventTarget.call(this); | |
var c = Spotify.DebuggerJS; | |
this.id = d; | |
var g = g || {}, h = this, | |
b = new Spotify.Events, | |
a = g.connectionParams || "", | |
f, k = null, | |
m = function () { | |
this.activate = function () {}; | |
this.connect = function () {}; | |
this.disconnect = function () {}; | |
this.rpc = function () {}; | |
this.onConnect = function () {}; | |
this.onDisconnect = function () {}; | |
this.onMessage = function () {}; | |
this.onError = function () {} | |
}, o = null, | |
p = 0, | |
q = function (a) { | |
o = n[a]; | |
o.activate() | |
}, n = {}; | |
n[0] = new function () { | |
m.call(this); | |
this.activate = | |
function () { | |
clearInterval(p) | |
}; | |
this.connect = function () { | |
q(1) | |
} | |
}; | |
n[1] = new function () { | |
m.call(this); | |
this.activate = function () { | |
clearInterval(p); | |
k.connect(f) | |
}; | |
this.onConnect = function () { | |
c.log("Spotify.WebSockets.Bridge", ["[State.connecting] Socket connected"], "corejs"); | |
q(2) | |
}; | |
this.onDisconnect = function (a) { | |
c.log("Spotify.WebSockets.Bridge", ["[State.connecting] Socket disconnected"], "corejs"); | |
h.trigger(b.FAILED_CONNECTING, a.params || []); | |
q(0) | |
}; | |
this.disconnect = function () { | |
k.disconnect() | |
}; | |
this.onError = function (a) { | |
c.error("Spotify.WebSockets.Bridge", ["[State.connecting] Error", a], "corejs"); | |
h.trigger(b.FAILED_CONNECTING, {}); | |
q(0) | |
} | |
}; | |
n[2] = new function () { | |
m.call(this); | |
this.activate = function () { | |
c.log("Spotify.WebSockets.Bridge", ["[State.authorizing] Sending auth object"], "corejs"); | |
clearInterval(p); | |
var b = a.split(":"); | |
if (parseInt(b[0], 10) > 200) var f = b.shift(), | |
m = b.shift(), b = b.join(":"), b = [f, m, b]; | |
k.sendObject({ | |
name: "connect", | |
id: "0", | |
args: b | |
}) | |
}; | |
this.disconnect = function () { | |
k.disconnect(!1) | |
}; | |
this.onDisconnect = function (a) { | |
c.log("Spotify.WebSockets.Bridge", ["[State.authorizing] Socket disconnected"], | |
"corejs"); | |
h.trigger(b.FAILED_CONNECTING, a.params || []); | |
q(0) | |
}; | |
this.onMessage = function (a) { | |
c.log("Spotify.WebSockets.Bridge", ["[State.authorizing] Got message", a], "corejs"); | |
try { | |
var f = JSON.parse(a); | |
f.result === "ok" ? (h.trigger(b.AUTHENTICATED, {}), h.trigger(b.CONNECTION_ESTABLISHED, {}), q(3)) : f.error && (h.trigger(b.FAILED_CONNECTING, f.error), h.disconnect(), q(0)) | |
} catch (k) {} | |
} | |
}; | |
n[3] = new function () { | |
m.call(this); | |
this.activate = function () { | |
clearInterval(p); | |
p = setInterval(function () { | |
k.isConnected() || (clearInterval(p), | |
k.trigger("ondisconnect", [])) | |
}, 1E3) | |
}; | |
this.onMessage = function (a) { | |
c.log("Spotify.WebSockets.Bridge", ["[State.authorized] Got message", a], "corejs"); | |
try { | |
var f = JSON.parse(a) | |
} catch (k) { | |
h.trigger(b.ERROR, { | |
message: "Response not a JSON object" | |
}); | |
return | |
} | |
a = f.message ? f.message[0] : null; | |
a === "token_lost" ? h.trigger(b.TOKEN_LOST, {}) : a === "do_work" ? h.trigger(b.WORK, f.message[1]) : a === "ping_flash" ? h.trigger(b.PING_FLASH, f.message[1]) : a === "login_complete" ? h.trigger(b.LOGIN_COMPLETE) : a === "hm_b64" ? h.trigger(b.HERMES_B64_MESSAGE, | |
f.message) : a === "user_info_change" ? h.trigger(b.USER_INFO_CHANGE) : f.id ? f.error ? h.trigger(b.RPC_ERRBACK, { | |
requestId: f.id, | |
response: f.error | |
}) : h.trigger(b.RPC_CALLBACK, { | |
requestId: f.id, | |
response: f.result | |
}) : h.trigger(b.ERROR, { | |
error: "Response object invalid" | |
}) | |
}; | |
this.disconnect = function () { | |
k.disconnect() | |
}; | |
this.onDisconnect = function () { | |
c.log("Spotify.WebSockets.Bridge", ["[State.authorized] Socket disconnected"], "corejs"); | |
h.trigger(b.FAILED_CONNECTING, {}); | |
q(0) | |
}; | |
this.rpc = function (a, b, f) { | |
c.log("Spotify.WebSockets.Bridge", ["[State.authorized] Doing an RPC call", a, b], "corejs"); | |
k.sendObject({ | |
id: f, | |
name: "sp/" + a, | |
args: b | |
}) | |
}; | |
this.onError = function (a) { | |
c.error("Spotify.WebSockets.Bridge", ["[State.authorized] onerror", a], "corejs") | |
} | |
}; | |
this.rpc = function (a, b, f) { | |
o.rpc(a, b, f) | |
}; | |
this.connect = function (b, k) { | |
b && (a = b); | |
k && (f = k); | |
o.connect() | |
}; | |
this.disconnect = function () { | |
o.disconnect() | |
}; | |
this.initialize = function () { | |
if (f === "") throw Error("Spotify.WebSockets.Bridge connectionUri cannot be empty"); | |
k = new Spotify.WebSockets.Client; | |
k.bind("onconnect", | |
function () { | |
o.onConnect() | |
}); | |
k.bind("ondisconnect", function (a) { | |
o.onDisconnect(a) | |
}); | |
k.bind("onmessage", function (a) { | |
o.onMessage(a.params.message) | |
}); | |
k.bind("onerror", function (a) { | |
o.onError(a.params.message) | |
}); | |
h.trigger(b.READY, {}); | |
q(0) | |
} | |
}; | |
Spotify.WebSockets.Client = function () { | |
Spotify.EventTarget.call(this); | |
var d = Spotify.DebuggerJS, | |
g = null, | |
c = this; | |
this.connect = function (h) { | |
if (h === "") throw Error("Spotify.WebSockets.Client connection Uri was not set"); | |
if (this.isConnected()) return !1; | |
if (WebSocket === void 0) throw Error("Spotify.WebSockets.Client WebSocket interface not supported"); | |
var b = this.currentConnection = (this.currentConnection || 0) + 1; | |
g = new WebSocket(h); | |
g.onopen = function () { | |
d.log("Spotify.WebSockets.Client", ["onopen", b], "corejs"); | |
b == c.currentConnection && | |
c.trigger("onconnect", {}) | |
}; | |
g.onclose = function (a) { | |
d.log("Spotify.WebSockets.Client", ["onclose", b, a], "corejs"); | |
b == c.currentConnection && c.trigger("ondisconnect", [0, a.code, a.reason]) | |
}; | |
g.onmessage = function (a) { | |
d.log("Spotify.WebSockets.Client", ["onmessage", a, b], "corejs"); | |
b == c.currentConnection && c.trigger("onmessage", { | |
message: a.data | |
}) | |
}; | |
g.onerror = function (a) { | |
d.error("Spotify.WebSockets.Client", ["onerror", a, b], "corejs"); | |
b == c.currentConnection && c.trigger("onerror", { | |
message: a | |
}) | |
} | |
}; | |
this.disconnect = function (h) { | |
typeof h === | |
"undefined" && (h = !0); | |
this.isConnected() ? (g.close(), g = null, h && c.trigger("ondisconnect", [0, 0, ""])) : d.error("Spotify.WebSockets.Client", ["Client not connected"], "corejs") | |
}; | |
this.isConnected = function () { | |
return g && g.readyState === 1 | |
}; | |
this.send = function (h) { | |
this.isConnected() ? g.send(h) : (c.trigger("ondisconnect", [0, 0, ""]), d.error("Spotify.WebSockets.Client", ["Client not connected"], "corejs")) | |
}; | |
this.sendObject = function (h) { | |
var b = JSON.stringify(h); | |
b.length > 32768 ? c.trigger("onmessage", { | |
message: JSON.stringify({ | |
id: h.id, | |
error: [16, 1, "PACKET_SIZE_EXCEEDED"] | |
}) | |
}) : this.send(b) | |
} | |
}; | |
Spotify.EventTarget = function () { | |
this._listeners = {}; | |
this.bind = this.addEventListener = function (g, c, h, b) { | |
typeof b === "undefined" && (b = 0); | |
if (typeof c !== "undefined" && c !== null) { | |
var b = { | |
callback: c, | |
context: h, | |
priority: b | |
}, a = !1, | |
f; | |
this._listeners[g] === void 0 && (this._listeners[g] = []); | |
f = this._listeners[g]; | |
for (var k = 0; k < f.length; k++) | |
if (f[k].callback === c && f[k].context === h) { | |
a = !0; | |
break | |
} | |
a === !1 && (this._listeners[g].push(b), this._listeners[g].sort(d)) | |
} | |
}; | |
this.bindOnce = function (d, c, h, b) { | |
var a = this, | |
f; | |
f = function () { | |
a.unbind(d, | |
f); | |
c.apply(h, arguments) | |
}; | |
this.bind(d, f, void 0, b) | |
}; | |
var d = function (d, c) { | |
return c.priority - d.priority | |
}; | |
this.trigger = this.dispatchEvent = function (d, c, h) { | |
var b = this._listeners[d], | |
c = c || {}; | |
if (typeof b !== "undefined") | |
for (var b = b.concat(), a = 0, f = b.length; a < f; a++) { | |
var k = b[a]; | |
k.context ? k.callback.call(k.context, { | |
type: d, | |
params: c, | |
extra: h || {} | |
}) : k.callback({ | |
type: d, | |
params: c, | |
extra: h || {} | |
}) | |
} | |
}; | |
this._triggerDeferred = function (d, c, h) { | |
var b = this._listeners[d], | |
c = c || {}; | |
if (typeof b !== "undefined") | |
for (var a = 0; a < b.length; a++) { | |
var f = | |
b[a]; | |
setTimeout(f.callback.bind(f.context, { | |
type: d, | |
params: c, | |
extra: h || {} | |
}), 0) | |
} | |
}; | |
this.unbind = this.removeEventListener = function (d, c, h) { | |
var b = -1, | |
a = this._listeners[d]; | |
if (typeof c !== "undefined") { | |
if (typeof a !== "undefined") { | |
for (var f = 0; f < a.length; f++) | |
if (a[f].callback === c && a[f].context === h) { | |
b = f; | |
break | |
} | |
b !== -1 && this._listeners[d].splice(b, 1) | |
} | |
} else this._listeners[d] = [] | |
} | |
}; | |
Spotify.Protobuf.Schema = function (d, g, c, h) { | |
Spotify.EventTarget.call(this); | |
var b, a = 0, | |
f = []; | |
this.id = ""; | |
this.PROTO = "proto"; | |
this.type = this.JSON = "json"; | |
this.load = function () { | |
var b, f; | |
if (this.type === this.JSON) f = "json"; | |
else if (this.type === this.PROTO) f = "text"; | |
else throw Error("Not a valid descriptor file for the protobuf schema"); | |
for (b = a = 0; b < d.length; b++) | |
if (typeof d[b] === "string") { | |
a++; | |
var c = new Spotify.Service; | |
c.url = d[b]; | |
c.dataType = f; | |
c.bind("onSuccess", this.done, this); | |
c.bind("onError", this.error, this); | |
c.fetch() | |
} | |
}; | |
this.reset = function () { | |
f = null | |
}; | |
this.getSchema = function () { | |
return b | |
}; | |
this.msg = function (a) { | |
return b[a] | |
}; | |
this.parse = function (a) { | |
f = f === null ? a : f.concat(a) | |
}; | |
this.encode = function () { | |
var a; | |
this.type == this.JSON ? b = Spotify.Protobuf.Serialization.createFromJson(f) : (a = Spotify.Protobuf.Parser.parseFileDescriptor(f), b = Spotify.Protobuf.Serialization.createFromFileDescriptor(a)) | |
}; | |
this.done = function (b) { | |
this.parse(b.params.result); | |
a--; | |
a === 0 && (this.encode(), typeof h !== "undefined" ? typeof g !== "undefined" && g.call(h, this.id) : | |
typeof g !== "undefined" && g(this.id)) | |
}; | |
this.setData = function (a) { | |
f = a | |
}; | |
this.error = function (a) { | |
typeof h !== "undefined" ? typeof c !== "undefined" && c.call(h, a) : typeof c !== "undefined" && c(a) | |
} | |
}; | |
Spotify.HermesCache = function () { | |
var d = Spotify.Cache.Default, | |
g = ["GET", "HEAD"], | |
c = this, | |
h = [null, null], | |
b = new Spotify.Events, | |
a = function () { | |
return h[Spotify.Cache.Types.TEMPORARY] != null && h[Spotify.Cache.Types.PERSISTENT] != null | |
}, f = function (f) { | |
return function (k) { | |
var m = "com.spotify.cache." + (f || "generic") + ".version", | |
d = function () { | |
localStorage.setItem(m, (5).toString()); | |
h[f] = k; | |
a() && c.trigger(b.READY) | |
}; | |
parseInt(localStorage.getItem(m)) != 5 ? k.clear(d) : d() | |
} | |
}, k = function () { | |
throw Error("Failed creating caches!"); | |
}, m = function (a) { | |
return a.indexOf("hm://playlist/") >= | |
0 ? h[Spotify.Cache.Types.PERSISTENT] : h[Spotify.Cache.Types.TEMPORARY] | |
}, o = function (a, b, f, k, c, h) { | |
var d = m(a); | |
d.get(b, function (a, b) { | |
b == null ? k.call(h) : b.expires < (new Date).getTime() ? b.etag ? c.call(h, b.frames, b.etag) : (d.remove(a), k.call(h)) : f.call(h, b.frames) | |
}) | |
}; | |
c.onReady = function (f, k) { | |
a() ? f.call(k) : c.bind(b.READY, f, k) | |
}; | |
c.isRequestCacheable = function (a) { | |
return g.indexOf(a.getMethod()) != -1 | |
}; | |
c.getCacheKey = function (a) { | |
for (var b = [a.getMethod(), a.getURI()], f = 0, k = a.getRequestFrameCount(); f < k; ++f) b.push(a.getRequestFrame(f)); | |
return b.join("") | |
}; | |
c.getCachedFrames = function (b, f, k, c, m, h) { | |
a() ? o(b, f, k, c, m, h) : c.call(h) | |
}; | |
c.setCachedFrames = function (b, f, k, h, d, g) { | |
if (a() && h && (k == "CACHE_PRIVATE" || k == "CACHE_PUBLIC")) { | |
k = { | |
frames: g, | |
expires: (new Date).getTime() + h * 1E3 | |
}; | |
if (d) k.etag = d; | |
m(b).put(f, k, null, null, c.onfull) | |
} | |
}; | |
c.removeAllContaining = function (a, b) { | |
m(a).removeAllContaining(a, b) | |
}; | |
c.onfull = function () {}; | |
c.migrateToIndexedDB = function (a, b, f) { | |
if (JSON.parse(localStorage.getItem("indexeddb") || !1)) a.call(f); | |
else { | |
var k = h[Spotify.Cache.Types.PERSISTENT], | |
c = new d(5E3, new Spotify.Cache.IndexedDBStorage("Spotify.Mercury.Cache")); | |
delete h[Spotify.Cache.Types.PERSISTENT]; | |
var m = function (a, b) { | |
c.put(a, b) | |
}, g = function () { | |
h[Spotify.Cache.Types.PERSISTENT] = c; | |
k.clear(); | |
localStorage.setItem("indexeddb", "true"); | |
a.call(f, this) | |
}; | |
c.initialize(function () { | |
k._storage.each(m, g, this) | |
}, b, f) | |
} | |
}; | |
(function () { | |
Spotify.EventTarget.call(c); | |
var a = new d(500, new Spotify.Cache.MemoryStorage("Spotify.Mercury.Cache")); | |
a.initialize(f(Spotify.Cache.Types.TEMPORARY), k); | |
a = JSON.parse(localStorage.getItem("indexeddb") || !1) ? new d(5E3, new Spotify.Cache.IndexedDBStorage("Spotify.Mercury.Cache")) : new d(5E3, new Spotify.Cache.LocalStorage("Spotify.Mercury.Cache")); | |
a.initialize(f(Spotify.Cache.Types.PERSISTENT), k) | |
})() | |
}; | |
(function () { | |
if (typeof window.btoa !== "function") window.btoa = Spotify.Utils.Base64.encode; | |
if (typeof window.atob !== "function") window.atob = Spotify.Utils.Base64.decode; | |
var d = Spotify.DebuggerJS, | |
g = Spotify.Protobuf.Serialization.createFromJson([{ | |
name: "Header", | |
fields: [{ | |
id: 1, | |
type: "string", | |
name: "uri" | |
}, { | |
id: 2, | |
type: "string", | |
name: "content_type" | |
}, { | |
id: 3, | |
type: "string", | |
name: "method" | |
}, { | |
id: 4, | |
type: "sint32", | |
name: "status_code" | |
}, { | |
id: 5, | |
type: "string", | |
name: "source" | |
}, { | |
id: 6, | |
type: "*UserField", | |
name: "user_fields" | |
}] | |
}, { | |
name: "UserField", | |
fields: [{ | |
id: 1, | |
type: "string", | |
name: "name" | |
}, { | |
id: 2, | |
type: "bytes", | |
name: "value" | |
}] | |
}]).Header; | |
Spotify.Hermes.Header = g; | |
Spotify.Hermes.Request = function (c) { | |
if (c.uri == void 0) throw Error("URI not specified!"); | |
var h = Spotify.Hermes.Cache; | |
this.getMethod = function () { | |
return c.method | |
}; | |
this.getURI = function () { | |
return c.uri | |
}; | |
this.getRequestFrameCount = function () { | |
return 0 | |
}; | |
this.getRequestFrameData = function () { | |
return null | |
}; | |
this.setRequestFrameData = function () {}; | |
this.getRequestFrame = function () { | |
return null | |
}; | |
this.parseResponseFrame = | |
function (a, b) { | |
return b | |
}; | |
var b = function (a) { | |
for (var b = [], f = (new Date).getTime(), k = 1, c = a.length; k < c; ++k) b.push(this.parseResponseFrame(k - 1, a[k])); | |
d.log("Spotify.Hermes.Request", ["It took", (new Date).getTime() - f, "ms to parse the frames"], "parsing_times"); | |
return b | |
}, a = function (a) { | |
for (var b = [], f = 0, k = a.length; f < k; ++f) b.push(window.atob(a[f])); | |
return b | |
}, f = function (a) { | |
var b = {}; | |
if (a.user_fields) | |
for (var f = 0, k = a.user_fields.length; f < k; ++f) { | |
var c = a.user_fields[f]; | |
switch (c.name) { | |
case "MC-Cache-Policy": | |
if (c.value == | |
"private") b.cache_policy = "CACHE_PRIVATE"; | |
else if (c.value == "public") b.cache_policy = "CACHE_PUBLIC"; | |
break; | |
case "MC-TTL": | |
b.ttl = c.value; | |
break; | |
case "MC-ETag": | |
b.etag = c.value | |
} | |
} | |
return b | |
}, k = function (a, b, f) { | |
a.user_fields = a.user_fields || []; | |
a.user_fields.push({ | |
name: b, | |
value: f | |
}) | |
}, m = function (a) { | |
switch (a) { | |
case "SUB": | |
return 1; | |
case "UNSUB": | |
return 2 | |
} | |
return 0 | |
}, o = function (k, o, p, n, q, A, x) { | |
n != null && q != null ? c.user_fields = [{ | |
name: "MC-ETag", | |
value: q | |
}] : delete c.user_fields; | |
for (var F = m(this.getMethod()), q = (new Date).getTime(), F = [F, window.btoa(g.serializeToStringSync(c))], G = 0, B = this.getRequestFrameCount(); G < B; ++G) F.push(window.btoa(this.getRequestFrame(G))); | |
d.log("Spotify.Hermes.Request", ["It took", (new Date).getTime() - q, "ms to serialize the request"], "parsing_times"); | |
k.rpc("hm_b64", F, function (k) { | |
var k = a(k.response), | |
c = g.parseFromStringSync(k[0]), | |
m = c.status_code; | |
if (m >= 200 && m <= 299) { | |
var d = f(c); | |
h.setCachedFrames(this.getURI(), h.getCacheKey(this), d.cache_policy, d.ttl, d.etag, k); | |
o(b.call(this, k), m, c) | |
} else m == 304 ? o(b.call(this, n), | |
m, c) : p(new Spotify.Errors.Error([13, m, null, c])) | |
}, p, this, A || !1, 2, x) | |
}, p = function (a) { | |
if (a.length != 2) throw Error("Invalid number of frames!"); | |
var b = g.parseFromStringSync(a[0]), | |
a = { | |
content_type: b.content_type, | |
status_code: b.status_code, | |
body: a[1] | |
}, b = f(b), | |
k; | |
for (k in b) a[k] = b[k]; | |
return a | |
}, q = function (a, b) { | |
var f = { | |
uri: b, | |
content_type: a.content_type, | |
status_code: a.status_code | |
}; | |
a.cache_policy == "CACHE_PUBLIC" ? k(f, "MC-Cache-Policy", "public") : a.cache_policy == "CACHE_PRIVATE" && k(f, "MC-Cache-Policy", "private"); | |
a.ttl !== | |
void 0 && k(f, "MC-TTL", a.ttl); | |
a.etag !== void 0 && k(f, "MC-ETag", a.etag); | |
return [g.serializeToStringSync(f), a.body] | |
}, n = function (b, f, k, m, o, n) { | |
o = typeof o !== "undefined" ? o : !1; | |
if (this.getRequestFrameCount() != 1) throw Error("Invalid number of request frames!"); | |
var x = this.getRequestFrameData(0).request, | |
F = x.length, | |
G = [], | |
B = [], | |
E = Array(F), | |
H = function (b) { | |
var c = a(b.response), | |
m = g.parseFromStringSync(c[0]), | |
b = m.status_code; | |
if (Spotify.Hermes.Request.isSuccess(b)) | |
if (m.content_type != "vnd.spotify/mercury-mget-reply") k(new Spotify.Errors.Error([Spotify.Errors.Domains.HERMES_ERROR, | |
500, "Server didn't send a multi-GET reply!" | |
])); | |
else if (c.length != 2) k(new Spotify.Errors.Error([Spotify.Errors.Domains.HERMES_ERROR, 500, "Invalid number of frames in multi-GET reply!"])); | |
else { | |
for (var c = this.parseResponseFrame(0, c[1]).reply, m = (new Date).getTime(), o = 0, n = c.length; o < n; ++o) { | |
var s = G[o], | |
v = c[o], | |
w = B.shift(); | |
v.status_code == 304 ? (E[w] = p(s.cachedFrames), E[w].status_code = 200) : Spotify.Hermes.Request.isSuccess(v.status_code) ? (E[w] = v, h.setCachedFrames(s.uri, "GET" + s.uri + (s.body || ""), v.cache_policy, v.ttl, | |
v.etag, q(v, s.uri))) : delete E[w] | |
} | |
d.log("Spotify.Hermes.Request", ["It took", (new Date).getTime() - m, "ms to parse the frames"], "parsing_times"); | |
f([{ | |
reply: E | |
}], b) | |
} else k(new Spotify.Errors.Error([Spotify.Errors.Domains.HERMES_ERROR, b])) | |
}, I = function () { | |
if (G.length == 0) f([{ | |
reply: E | |
}], 200); | |
else { | |
var a = (new Date).getTime(), | |
h = [0, window.btoa(g.serializeToStringSync(c))]; | |
this.setRequestFrameData(0, { | |
request: G | |
}); | |
h.push(window.btoa(this.getRequestFrame(0))); | |
d.log("Spotify.Hermes.Request", ["It took", (new Date).getTime() - | |
a, "ms to serialize the request" | |
], "parsing_times"); | |
b.rpc("hm_b64", h, H, k, this, m || !1, 2, n) | |
} | |
}, K = function (a) { | |
return function (b) { | |
E[a] = p(b); | |
--F <= 0 && I.call(this) | |
} | |
}, L = function (a) { | |
return function () { | |
G.push(x[a]); | |
B.push(a); | |
--F <= 0 && I.call(this) | |
} | |
}, N = function (a) { | |
return function (b, f) { | |
x[a].etag = f; | |
x[a].cachedFrames = b; | |
G.push(x[a]); | |
B.push(a); | |
--F <= 0 && I.call(this) | |
} | |
}; | |
if (o) | |
for (var o = 0, M = x.length; o < M; ++o) L(o).call(this); | |
else { | |
o = 0; | |
for (M = x.length; o < M; ++o) { | |
var z = x[o]; | |
h.getCachedFrames(z.uri, "GET" + z.uri + (z.body || ""), K(o), L(o), | |
N(o), this) | |
} | |
} | |
}; | |
this.send = function (a, f, k, m, d, g) { | |
d = typeof d !== "undefined" ? d : !1; | |
if (c.content_type == "vnd.spotify/mercury-mget-request") n.call(this, a, f, k, m, d, g); | |
else { | |
var p = function (a) { | |
f(b.call(this, a), 200) | |
}, q = function () { | |
o.call(this, a, f, k, null, null, m, g) | |
}, G = function (b, c) { | |
o.call(this, a, f, k, b, c, m, g) | |
}; | |
d || !h.isRequestCacheable(this) ? q.call(this) : h.getCachedFrames(this.getURI(), h.getCacheKey(this), p, q, G, this) | |
} | |
} | |
}; | |
Spotify.Hermes.Request.isSuccess = function (c) { | |
return c >= 200 && c < 300 | |
}; | |
Spotify.Hermes.Request.isRedirect = | |
function (c) { | |
return c >= 300 && c < 400 | |
}; | |
Spotify.Hermes.Request.isClientError = function (c) { | |
return c >= 400 && c < 500 | |
}; | |
Spotify.Hermes.Request.isServerError = function (c) { | |
return c >= 500 && c < 600 | |
}; | |
Spotify.Hermes.StringRequest = function (c, h) { | |
var b = new Spotify.Hermes.Request(c); | |
b.getRequestFrameCount = function () { | |
return h.length | |
}; | |
b.getRequestFrameData = function (a) { | |
return h[a] | |
}; | |
b.setRequestFrameData = function (a, b) { | |
h[a] = b | |
}; | |
b.getRequestFrame = function (a) { | |
return h[a] | |
}; | |
b.parseResponseFrame = function (a, b) { | |
return b | |
}; | |
return b | |
}; | |
Spotify.Hermes.ProtobufRequest = | |
function (c, h, b, a) { | |
c = new Spotify.Hermes.Request(c); | |
c.getRequestFrameCount = function () { | |
return h.length | |
}; | |
c.getRequestFrameData = function (a) { | |
return h[a] | |
}; | |
c.setRequestFrameData = function (a, b) { | |
h[a] = b | |
}; | |
c.getRequestFrame = function (a) { | |
return b[a] ? b[a].serializeToStringSync(h[a]) : h[a] | |
}; | |
c.parseResponseFrame = function (b, k) { | |
return b < a.length ? a[b].parseFromStringSync(k) : k | |
}; | |
return c | |
} | |
})(); | |
Spotify.Hermes.Handler = function () { | |
Spotify.EventTarget.call(this); | |
var d = {}, g, c = function (c) { | |
var b; | |
if (typeof c !== void 0 && (b = c.split("#"), Spotify.Utils.isArray(b) && b.length == 2)) return c = b[0], b = b[1], typeof d[c] !== "undefined" ? d[c].msg(b) : null; | |
throw Error("Not a valid message!"); | |
}; | |
this.send = function (h, b, a, f, k, m, d, p, q) { | |
var p = p || !1, | |
n = [], | |
s = []; | |
if (!Spotify.Utils.isArray(a) && !Spotify.Utils.isArray(f)) throw "Hermes:send Wrong arguments"; | |
for (var t = 0; t < a.length; t++) n.push(c(a[t])); | |
for (t = 0; t < f.length; t++) s.push(c(f[t])); | |
(new Spotify.Hermes.ProtobufRequest({ | |
uri: h, | |
method: b | |
}, k, n, s)).send(g, m, d, p, q, "hermes") | |
}; | |
this.loadSchemas = function (c, b, a, f) { | |
var k; | |
if (Spotify.Utils.isArray(c)) | |
if (k = Spotify.Utils.Base64.encode(c.join("_")) + "_", typeof d[k] !== "undefined") a(k); | |
else try { | |
var m = new Spotify.Protobuf.Schema(c, a, f, null); | |
d[k] = m; | |
if (b !== m.PROTO && b !== m.JSON) b = m.JSON; | |
m.id = k; | |
m.type = b; | |
m.reset(); | |
m.load() | |
} catch (g) { | |
throw typeof f !== "undefined" && f(g), g; | |
} else f(Error("Schemas is not an array")) | |
}; | |
this.loadSchemaData = function (c, b, a) { | |
var f = | |
(new Date).getTime() + Math.floor(Math.random() * 1E3), | |
f = Spotify.Utils.Base64.encode(f.toString()) + "_", | |
k, m; | |
if (Spotify.Utils.isArray(c)) { | |
c = c.join("\n"); | |
for (k in d) a = d[k], a === c[0] && (m = a, f = k); | |
if (typeof m === "undefined") m = new Spotify.Protobuf.Schema([], null, null, null), m.id = f, m.type = "proto", m.setData(c), m.encode(), d[f] = m; | |
b(f) | |
} else a(Error("Schemas is not an array")) | |
}; | |
this.init = function (c) { | |
g = c | |
} | |
}; | |
Spotify.GatewayTypes = { | |
FLASH: "FLASH", | |
WEBSOCKETS: "WEBSOCKETS" | |
}; | |
Spotify.PlayerTypes = { | |
FLASH_RTMPS: "FLASH_RTMPS", | |
FLASH_HTTP: "FLASH_HTTP", | |
FLASH_AAC: "FLASH_AAC", | |
WEBSOCKETS_STREAMING: "WEBSOCKETS_STREAMING", | |
HTML5_HTTP: "HTML5_HTTP" | |
}; | |
Spotify.Protocols = { | |
RTMPS: "RTMPS", | |
RTMP: "RTMP", | |
HTTP: "HTTP", | |
HTTPS: "HTTPS" | |
}; | |
Spotify.Instances = function () { | |
var d = {}; | |
return { | |
add: function (g) { | |
g.id = "SPFBIn_" + Math.floor(Math.random() * 1E4); | |
d[g.id] = g; | |
return !0 | |
}, | |
get: function (g) { | |
if (typeof d[g] !== void 0) return d[g] | |
} | |
} | |
}(); | |
Spotify.Features = function (d) { | |
var g = d || {}; | |
this.isEnabled = function (c) { | |
return !!g[c] | |
}; | |
this.getAll = function () { | |
return g | |
} | |
}; | |
Spotify.Flash.SWFObject = function (d) { | |
Spotify.EventTarget.call(this); | |
var g = Spotify.DebuggerJS, | |
c = this; | |
this.isLoaded = !1; | |
var h = new Spotify.Events; | |
this.getSWF = function () { | |
if (this.isLoaded) { | |
if (window.document[d.SWFFlashId]) return window.document[d.SWFFlashId]; | |
if (navigator.appName.indexOf("Microsoft Internet") === -1) { | |
if (document.embeds && document.embeds[d.SWFFlashId]) return document.embeds[d.SWFFlashId] | |
} else return document.getElementById(d.SWFFlashId) | |
} else g.error("Spotify.Flash.SWFObject", ["SWF Object is not loaded...."], | |
"corejs") | |
}; | |
this.initialize = function () { | |
swfobject.hasFlashPlayerVersion("11.0.0") ? swfobject.embedSWF(d.SWFUrl, d.SWFContainerId, "1", "1", "11.0.0", "", { | |
playerType: d.playerType || "", | |
valid: 0, | |
id: d.SWFFlashId || "", | |
length: 0, | |
instanceId: d.instanceId, | |
logging: d.logging | |
}, { | |
quality: "high", | |
allowscriptaccess: "always", | |
wmode: "window", | |
bgcolor: "#2c2c2d" | |
}, { | |
id: d.SWFFlashId, | |
name: d.SWFFlashId, | |
align: "middle" | |
}, b) : (c.trigger(h.FLASH_UNAVAILABLE), g.error("Spotify.Flash.SWFObject", ["Your Flash is not up to date: 11.0.0"], "corejs")) | |
}; | |
var b = function (a) { | |
!1 === a.success ? (c.trigger(h.FLASH_UNAVAILABLE), g.error("Spotify.Flash.SWFObject", ["Cannot load SWF object"], "corejs")) : (c.trigger(h.FLASH_AVAILABLE), c.isLoaded = !0) | |
} | |
}; | |
Spotify.Flash.PlayerInterface = function (d, g) { | |
Spotify.EventTarget.call(this); | |
var c = this, | |
h = new Spotify.Events, | |
b; | |
this.hasSoundCapabilities = !0; | |
var a = function (a) { | |
this.trigger(a.type, a.params) | |
}; | |
this.run = function (a) { | |
return typeof b !== "undefined" && b.isLoaded ? b.getSWF().sp_run(a) : !1 | |
}; | |
this.playpause = function (a) { | |
return typeof b !== "undefined" && b.isLoaded && this.hasSoundCapabilities ? b.getSWF().sp_playpause(a) : !1 | |
}; | |
this.position = function (a) { | |
try { | |
if (typeof b !== "undefined" && b.isLoaded && this.hasSoundCapabilities) return b.getSWF().sp_time(a) | |
} catch (k) { | |
return 0 | |
} | |
}; | |
this.getPlayerState = function (a) { | |
typeof b !== "undefined" && b.isLoaded && this.hasSoundCapabilities && (response = b.getSWF().sp_playerState(a)); | |
return response | |
}; | |
this.seek = function (a, k) { | |
if (typeof b !== "undefined" && b.isLoaded && this.hasSoundCapabilities) return b.getSWF().sp_seek(a, k) | |
}; | |
this.pause = function (a) { | |
typeof b !== "undefined" && b.isLoaded && this.hasSoundCapabilities && b.getSWF().sp_pause(a) | |
}; | |
this.resume = function (a) { | |
typeof b !== "undefined" && b.isLoaded && this.hasSoundCapabilities && b.getSWF().sp_resume(a) | |
}; | |
this.stop = | |
function (a) { | |
typeof b !== "undefined" && b.isLoaded && this.hasSoundCapabilities && b.getSWF().sp_stop(a) | |
}; | |
this.load = function (a, k, m) { | |
m = m || {}; | |
typeof b !== "undefined" && b.isLoaded && c.hasSoundCapabilities && b.getSWF().sp_load(a, k, m) | |
}; | |
this.play = function (a, k) { | |
typeof b !== "undefined" && b.isLoaded && c.hasSoundCapabilities && b.getSWF().sp_play(a, k) | |
}; | |
this.setVolume = function (a, k) { | |
if (typeof b !== "undefined" && b.isLoaded && this.hasSoundCapabilities) try { | |
b.getSWF().sp_setVolume(a, k) | |
} catch (c) {} | |
}; | |
this.getVolume = function (a) { | |
if (typeof b !== | |
"undefined" && b.isLoaded && this.hasSoundCapabilities) try { | |
return b.getSWF().sp_getVolume(a) | |
} catch (k) {} | |
return 1 | |
}; | |
this.getDuration = function (a) { | |
if (typeof b !== "undefined" && b.isLoaded && this.hasSoundCapabilities) try { | |
return b.getSWF().sp_getDuration(a) | |
} catch (k) {} | |
return 0 | |
}; | |
this.hasSound = function () { | |
return typeof b !== "undefined" && b.isLoaded ? this.hasSoundCapabilities = b.getSWF().sp_hasSound() : !1 | |
}; | |
this.addPlayer = function (a, k, m) { | |
if (typeof b !== "undefined" && b.isLoaded && c.hasSoundCapabilities) return b.getSWF().sp_addPlayer(a, | |
k, m) | |
}; | |
this.removePlayerAtIndex = function (a) { | |
return typeof b !== "undefined" && b.isLoaded && c.hasSoundCapabilities ? (b.getSWF().sp_removePlayerAtIndex(a), !0) : !1 | |
}; | |
this.initializePlayerById = function (a) { | |
typeof b !== "undefined" && b.isLoaded && c.hasSoundCapabilities && b.getSWF().sp_initializePlayerById(a) | |
}; | |
this.initialize = function () { | |
b = new Spotify.Flash.SWFObject({ | |
playerType: g.playerType, | |
SWFFlashId: d + "_player", | |
SWFContainerId: g.SWFPlayerContainerId, | |
SWFUrl: g.SWFPlayerUrl, | |
SWFMinVersion: g.SWFMinVersion, | |
instanceId: d, | |
logging: g.logging, | |
length: g.valid, | |
valid: 0 | |
}); | |
b.bind(h.FLASH_AVAILABLE, a, this); | |
b.bind(h.FLASH_UNAVAILABLE, a, this); | |
b.initialize() | |
}; | |
this.onLoad = function () {}; | |
this.onPlay = function () {}; | |
this.onPause = function () {}; | |
this.onStop = function () {}; | |
this.onTrackEnded = function () {}; | |
this.onSongLoaded = function () {}; | |
this.onPositionChanged = function () {}; | |
this.onInvalidTrackUri = function () {}; | |
this.onPlaybackFailed = function () {} | |
}; | |
Spotify.HTML5.PlayerInterface = function (d) { | |
Spotify.EventTarget.call(this); | |
document.getElementById(d); | |
var g = new Spotify.Events; | |
this.hasSoundCapabilities = !0; | |
this.playpause = function () {}; | |
this.position = function () { | |
return 0 | |
}; | |
this.getPlayerState = function () { | |
return { | |
position: 0, | |
duration: 0, | |
isPaused: !1, | |
isPlaying: !1, | |
isStopped: !0 | |
} | |
}; | |
this.seek = function () {}; | |
this.pause = function () {}; | |
this.resume = function () {}; | |
this.stop = function () {}; | |
this.load = function () {}; | |
this.play = function () {}; | |
this.setVolume = function () {}; | |
this.getVolume = | |
function () { | |
return 0 | |
}; | |
this.getDuration = function () { | |
return 0 | |
}; | |
this.hasSound = function () { | |
return !0 | |
}; | |
this.addPlayer = function () {}; | |
this.removePlayerAtIndex = function () {}; | |
this.initializePlayerById = function () {}; | |
this.initialize = function () { | |
this.trigger(g.READY) | |
}; | |
this.onLoad = function () {}; | |
this.onPlay = function () {}; | |
this.onPause = function () {}; | |
this.onStop = function () {}; | |
this.onTrackEnded = function () {}; | |
this.onSongLoaded = function () {}; | |
this.onPositionChanged = function () {}; | |
this.onInvalidTrackUri = function () {}; | |
this.onPlaybackFailed = | |
function () {} | |
}; | |
Spotify.Parsers.Facebook = function () { | |
this.makeCredential = function (d, g) { | |
var c = {}; | |
if (d || g) { | |
var h = c.credential = {}; | |
if (d) h.facebook_uid = d; | |
if (g) h.access_token = g | |
} | |
return c | |
}; | |
this.parseConfig = function (d) { | |
return d[0] | |
}; | |
this.parseCredential = function (d, g) { | |
var c, h = null, | |
b = null; | |
g || (g = "credential"); | |
d && d[0] && (c = d[0][g]); | |
if (c) { | |
if (c.facebook_uid) h = c.facebook_uid; | |
if (c.access_token) b = c.access_token | |
} | |
return { | |
facebookUid: h, | |
accessToken: b | |
} | |
}; | |
this.parseCredentialInspection = function (d) { | |
var g = d[0], | |
c = null; | |
g.alternative_credential && (c = | |
this.parseCredential(d, "alternative_credential")); | |
return { | |
alternativeCredential: c, | |
appUser: g.app_user || null, | |
permanentError: g.permanent_error || !1, | |
transientError: g.transient_error || !1 | |
} | |
}; | |
this.parseFriend = function (d) { | |
return { | |
facebookUid: d.facebook_uid, | |
appUser: d.app_user || null, | |
username: d.spotify_username || null, | |
name: d.display_name || null, | |
picture: d.picture_large || null | |
} | |
}; | |
this.parseFriendList = function (d) { | |
for (var g = [], d = d[0].friends, c = 0; c < d.length; c++) g.push(this.parseFriend(d[c])); | |
return g | |
}; | |
this.parsePermissions = | |
function (d) { | |
return d[0].permissions | |
}; | |
this.parsePostId = function (d) { | |
return d[0].post_id | |
} | |
}; | |
Spotify.Parsers.Metadata = function () { | |
var d = Spotify.Utils, | |
g = ["album_group", "single_group", "compilation_group", "appears_on_group"], | |
c = function (c, b) { | |
for (var a = 0, f = b.length; a < f; a += 2) | |
if (c[0] == b[a] && c[1] == b[a + 1]) return !0; | |
return !1 | |
}; | |
this.isPlayable = function (c, b) { | |
return c == "premium" && b.catalogue == "premium" ? !0 : c == "available" | |
}; | |
this.parseAlbum = function (c, b) { | |
if (c.gid != void 0) c.id = d.str2hex(c.gid), delete c.gid; | |
if (c.artist != void 0) | |
for (var a = 0, f = c.artist.length; a < f; ++a) c.artist[a] = this.parseArtist(c.artist[a], null); | |
if (c.disc != void 0) { | |
a = 0; | |
for (f = c.disc.length; a < f; ++a) c.disc[a] = this.parseDisc(c.disc[a]) | |
} | |
if (b != null) c.availability = this.parseRestrictions(c.restriction, b), c.playable = this.isPlayable(c.availability, b); | |
c.restriction != void 0 && delete c.restriction; | |
if (c.related != void 0) { | |
a = 0; | |
for (f = c.related.length; a < f; ++a) c.related[a] = this.parseAlbum(c.related[a], null) | |
} | |
c.cover != void 0 && delete c.cover; | |
return c | |
}; | |
this.parseAlbumGroup = function (c, b) { | |
var a = []; | |
if (c.album != void 0) | |
for (var a = c.album, f = 0, k = a.length; f < k; ++f) a[f] = this.parseAlbum(a[f], | |
b); | |
return a | |
}; | |
this.parseArtist = function (c, b) { | |
if (c.gid != void 0) c.id = d.str2hex(c.gid), delete c.gid; | |
if (c.top_track != void 0) c.top_track = this.parseTopTracks(c.top_track, b); | |
for (var a = 0, f = g.length; a < f; ++a) { | |
var k = g[a]; | |
if (c[k] != void 0) { | |
for (var m = c[k], o = 0, p = m.length; o < p; ++o) m[o] = this.parseAlbumGroup(m[o], b); | |
c[k] = m | |
} | |
} | |
if (c.biography != void 0) { | |
a = 0; | |
for (f = c.biography.length; a < f; ++a) k = c.biography, m = a, o = c.biography[a], o.portrait != void 0 && delete o.portrait, k[m] = o | |
} | |
if (b != null) c.availability = this.parseRestrictions(c.restriction, | |
b), c.playable = this.isPlayable(c.availability, b); | |
c.restriction != void 0 && delete c.restriction; | |
if (c.related != void 0) { | |
a = 0; | |
for (f = c.related.length; a < f; ++a) c.related[a] = this.parseArtist(c.related[a], null) | |
} | |
c.portrait != void 0 && delete c.portrait; | |
return c | |
}; | |
this.parseDisc = function (c) { | |
if (c.track != void 0) | |
for (var b = 0, a = c.track.length; b < a; ++b) c.track[b] = this.parseTrack(c.track[b], null); | |
return c | |
}; | |
this.parseRestrictions = function (d, b) { | |
var a = {}, f = !1; | |
if (typeof d === "undefined" || d.length == 0) return "available"; | |
for (var k = | |
0, m = d.length; k < m; ++k) { | |
var g = d[k], | |
p, q = !0; | |
g.countries_allowed != void 0 ? (q = g.countries_allowed.length != 0, p = c(b.country, g.countries_allowed)) : p = g.countries_forbidden !== void 0 ? !c(b.country, g.countries_forbidden) : !1; | |
if (p && g.catalogue != void 0) | |
for (p = 0; p < g.catalogue.length; ++p) { | |
var n = g.catalogue[p]; | |
if (n.toLowerCase() == "ad" || n.toLowerCase() == "free") a.free = !0; | |
else if (n.toLowerCase() == "subscription" || n.toLowerCase() == "premium") a.premium = !0 | |
} | |
if (g.type == void 0 || g.type.toLowerCase() == "streaming") f |= q | |
} | |
return f && b.catalogue == | |
"all" ? "available" : a[b.catalogue] ? b.catalogue == "premium" ? "premium" : "available" : a.premium ? "premium" : f ? "regional" : "unavailable" | |
}; | |
this.parseTopTracks = function (c, b) { | |
for (var a = [], f = 0, k = c.length; f < k; ++f) { | |
var m = c[f]; | |
if (m.country != void 0 && m.country == b.country) { | |
if (m.track != void 0) a = c[f].track; | |
break | |
} | |
} | |
f = 0; | |
for (k = a.length; f < k; ++f) a[f] = this.parseTrack(a[f], null); | |
return a | |
}; | |
this.parseTrack = function (c, b) { | |
if (c.gid != void 0) c.id = d.str2hex(c.gid), delete c.gid; | |
if (c.album != void 0) c.album = this.parseAlbum(c.album, null); | |
if (c.artist != | |
void 0) | |
for (var a = 0, f = c.artist.length; a < f; ++a) c.artist[a] = this.parseArtist(c.artist[a], null); | |
if (b != null) { | |
var a = this.parseRestrictions(c.restriction, b), | |
f = this.isPlayable(a, b), | |
k; | |
if (k = f) { | |
a: { | |
if (c.file != void 0) { | |
k = 0; | |
for (var m = c.file.length; k < m; ++k) | |
if (c.file[k].format == "MP3_160") { | |
k = !0; | |
break a | |
} | |
delete c.file | |
} | |
k = !1 | |
} | |
k = !k | |
} | |
k && (a = "unavailable", f = !1); | |
c.availability = a; | |
c.playable = f | |
} | |
c.restriction != void 0 && delete c.restriction; | |
if (c.playable) c.playableId = c.id; | |
else if (c.alternative != void 0) { | |
a = 0; | |
for (f = c.alternative.length; a < | |
f; ++a) | |
if (k = this.parseTrack(c.alternative[a], b), k.playable) { | |
c.availability = k.availability; | |
c.playable = k.playable; | |
c.playableId = k.id; | |
break | |
} | |
delete c.alternative | |
} | |
return c | |
} | |
}; | |
Spotify.Parsers.AdMetadata = function () { | |
this.toTrackMetadata = function (d) { | |
return { | |
__pid: d.file_id, | |
name: d.title, | |
disc: 1, | |
duration: parseInt(d.duration * 1E3, 10), | |
number: 1, | |
popularity: d.tracking_url, | |
availability: "available", | |
playable: !0, | |
explicit: !1, | |
image: Spotify.SourceURLs.normal + d.image_id, | |
starred: !1, | |
advertisement: !0, | |
ad_metadata: { | |
type: d.ad_type, | |
embed: { | |
width: d.embed ? d.embed.width : 100, | |
height: d.embed ? d.embed.height : 100, | |
background_image: d.embed ? Spotify.SourceURLs.original + d.embed.background_image : "" | |
}, | |
targetUrl: d.target_url | |
}, | |
artists: [{ | |
uri: d.target_url, | |
name: d.advertiser | |
}] | |
} | |
} | |
}; | |
Spotify.Parsers.Search = function () { | |
var d = Spotify.DebuggerJS, | |
g = new Spotify.Parsers.Metadata, | |
c = function (a) { | |
return a ? Spotify.Utils.isArray(a) ? a : [a] : [] | |
}, h = function (b, f) { | |
if (!b.id) return {}; | |
if (b["album-type"]) b.type = b["album-type"].toUpperCase(); | |
if (b["artist-id"] && b["artist-name"]) { | |
var c = b.artists = []; | |
if (Spotify.Utils.isArray(b["artist-id"]) && Spotify.Utils.isArray(b["artist-name"])) | |
for (var m = Math.min(b["artist-id"].length, b["artist-name"].length), d = 0; d < m; ++d) c.push({ | |
id: b["artist-id"][d], | |
name: b["artist-name"][d] | |
}); | |
else c.push({ | |
id: b["artist-id"], | |
name: b["artist-name"] | |
}) | |
} | |
b.cover = a(b); | |
if (b.popularity) b.popularity = Math.round(parseFloat(b.popularity) * 100); | |
if (b.restrictions) b.restrictions = k(b.restrictions.restriction); | |
b.availability = g.parseRestrictions(b.restrictions, f); | |
b.playable = g.isPlayable(b.availability, f); | |
delete b.restrictions; | |
delete b["album-type"]; | |
delete b["artist-id"]; | |
delete b["artist-name"]; | |
delete b["external-ids"]; | |
delete b["cover-small"]; | |
delete b["cover-large"]; | |
return b | |
}, b = function (a, b) { | |
if (!a.id) return {}; | |
if (a.portrait) { | |
var f = a.portrait, | |
c = []; | |
f.id && c.push({ | |
size: "DEFAULT", | |
file_id: f.id, | |
width: parseInt(f.width), | |
height: parseInt(f.height) | |
}); | |
f.small && c.push({ | |
size: "SMALL", | |
file_id: f.small | |
}); | |
f.large && c.push({ | |
size: "LARGE", | |
file_id: f.large | |
}); | |
a.portrait = c | |
} | |
if (a.popularity) a.popularity = Math.round(parseFloat(a.popularity) * 100); | |
if (a.restrictions) a.restrictions = k(a.restrictions.restriction); | |
a.availability = g.parseRestrictions(a.restrictions, b); | |
a.playable = g.isPlayable(a.availability, b); | |
delete a.restrictions; | |
return a | |
}, a = | |
function (a) { | |
var b = []; | |
a.cover && (b.push({ | |
size: "DEFAULT", | |
file_id: a.cover | |
}), delete a.cover); | |
a["cover-small"] && (b.push({ | |
size: "SMALL", | |
file_id: a["cover-small"] | |
}), delete a["cover-small"]); | |
a["cover-large"] && (b.push({ | |
size: "LARGE", | |
file_id: a["cover-large"] | |
}), delete a["cover-large"]); | |
return b | |
}, f = function (a) { | |
return !a.uri ? {} : a | |
}, k = function (a) { | |
for (var a = c(a), b = 0, f = a.length; b < f; ++b) { | |
var k = a[b]["@attributes"], | |
m = {}; | |
if (k.allowed !== void 0) m.countries_allowed = k.allowed.replace(/,/g, ""); | |
if (k.forbidden !== void 0) m.countries_forbidden = | |
k.forbidden.replace(/,/g, ""); | |
if (k.catalogues !== void 0) m.catalogue = k.catalogues.split(","); | |
a[b] = m | |
} | |
return a | |
}, m = function (b, f) { | |
if (!b.id) return {}; | |
if (b.album && b["album-id"]) b.album = { | |
name: b.album, | |
id: b["album-id"], | |
artist: { | |
name: b["album-artist"], | |
id: b["album-artist-id"] | |
}, | |
cover: a(b) | |
}; | |
if (b["album-artist"] && b["album-artist-id"]) { | |
b.album = b.album || {}; | |
var d = b.album.artists = []; | |
if (Spotify.Utils.isArray(b["album-artist"]) && Spotify.Utils.isArray(b["album-artist-id"])) | |
for (var h = Math.min(b["album-artist"].length, b["album-artist-id"].length), | |
o = 0; o < h; ++o) d.push({ | |
id: b["album-artist-id"][o], | |
name: b["album-artist"][o] | |
}); | |
else d.push({ | |
id: b["album-artist-id"], | |
name: b["album-artist"] | |
}) | |
} | |
if (b.artist && b["artist-id"]) | |
if (d = b.artists = [], Spotify.Utils.isArray(b.artist) && Spotify.Utils.isArray(b["artist-id"])) { | |
h = Math.min(b.artist.length, b["artist-id"].length); | |
for (o = 0; o < h; ++o) d.push({ | |
id: b["artist-id"][o], | |
name: b.artist[o] | |
}) | |
} else d.push({ | |
id: b["artist-id"], | |
name: b.artist | |
}); | |
if (b.length) b.length = parseInt(b.length); | |
if (b.popularity) b.popularity = Math.round(parseFloat(b.popularity) * | |
100); | |
if (b.number) b.number = parseInt(b["track-number"]); | |
if (b.year) b.year = parseInt(b.year); | |
if (b.title) b.name = b.title; | |
if (b.restrictions) b.restrictions = k(b.restrictions.restriction); | |
b.availability = g.parseRestrictions(b.restrictions, f); | |
b.playable = g.isPlayable(b.availability, f); | |
if (b.playable) b.playableId = b.id; | |
else if (b.alternatives) { | |
d = c(b.alternatives.track); | |
o = 0; | |
for (h = d.length; o < h; ++o) { | |
var u = m(d[o], f); | |
if (u.playable) { | |
b.availability = u.availability; | |
b.playable = u.playable; | |
b.playableId = u.id; | |
break | |
} | |
} | |
} | |
delete b.alternatives; | |
delete b.restrictions; | |
delete b["album-id"]; | |
delete b["album-artist"]; | |
delete b["album-artist-id"]; | |
delete b.artist; | |
delete b.cover; | |
delete b["cover-small"]; | |
delete b["cover-large"]; | |
delete b["artist-id"]; | |
delete b["external-ids"]; | |
delete b.files; | |
delete b["track-number"]; | |
delete b.title; | |
return b | |
}, o = function (a, b, f) { | |
for (var a = c(a), k = 0, m = a.length; k < m; ++k) a[k] = f(a[k], b); | |
return a | |
}; | |
this.parse = function (a, k) { | |
var c = (new Date).getTime(), | |
g = Spotify.Utils.convertStringToXML(a), | |
g = Spotify.Utils.convertXMLToJSON(g.documentElement); | |
if (g.albums) g.albums = o(g.albums.album, k, h); | |
if (g.artists) g.artists = o(g.artists.artist, k, b); | |
if (g.tracks) g.tracks = o(g.tracks.track, k, m); | |
if (g.playlists) g.playlists = o(g.playlists.playlist, k, f); | |
if (g["did-you-mean"]) g.didYouMean = g["did-you-mean"], delete g["did-you-mean"]; | |
g.total = { | |
albums: parseInt(g["total-albums"]), | |
artists: parseInt(g["total-artists"]), | |
tracks: parseInt(g["total-tracks"]), | |
playlists: parseInt(g["total-playlists"]) | |
}; | |
delete g["total-albums"]; | |
delete g["total-artists"]; | |
delete g["total-tracks"]; | |
delete g["total-playlists"]; | |
delete g.version; | |
d.log("Spotify.Parsers.Search", ["It took", (new Date).getTime() - c, "ms to parse the search result"], "parsing_times"); | |
return g | |
} | |
}; | |
Spotify.Parsers.Suggest = function () { | |
var d = Spotify.Link, | |
g = Spotify.Utils, | |
c = function (c) { | |
for (var b = 0, a = c.length; b < a; ++b) { | |
var f = c[b]; | |
if (f.gid) f.id = g.str2hex(f.gid), delete f.gid; | |
if (f.image) f.image = g.str2hex(f.image); | |
if (f.image_uri) { | |
var k = d.fromString(f.image_uri); | |
f.image = k.id || k.ids[0]; | |
delete f.image_uri | |
} | |
k = f.artists = []; | |
if (Spotify.Utils.isArray(f.artist_gid) && Spotify.Utils.isArray(f.artist_name)) | |
for (var m = Math.min(f.artist_name.length, f.artist_gid.length), o = 0; o < m; ++o) k.push({ | |
id: g.str2hex(f.artist_gid[o]), | |
name: f.artist_name[o] | |
}); | |
delete f.artist_gid; | |
delete f.artist_name; | |
if (f.owner_uri && f.owner_name) f.user = { | |
uri: f.owner_uri, | |
name: f.owner_name | |
}; | |
delete f.owner_name; | |
delete f.owner_uri; | |
if (f.rank) f.popularity = Math.round(f.rank * 100 / 2147483647), delete f.rank | |
} | |
return c | |
}; | |
this.parse = function (d) { | |
return { | |
artists: c(d.artist || []), | |
albums: c(d.album || []), | |
tracks: c(d.track || []), | |
playlist: c(d.playlist || []) | |
} | |
} | |
}; | |
Spotify.Parsers.Playlist = function () { | |
var d = function (d, c) { | |
var h = [], | |
b = {}; | |
if (typeof d !== "undefined" && typeof d.items !== "undefined") | |
for (var a = 0; a < d.items.length; a++) { | |
var f; | |
f = d.items[a]; | |
var k = c, | |
m = null, | |
o = {}; | |
if (typeof f !== "undefined" && typeof f.uri !== "undefined") try { | |
m = Spotify.Link.fromString(f.uri); | |
m.type === "collectiontracklist" && (m = Spotify.Link.starredLink(m.username)); | |
if (f.attributes) o = f.attributes; | |
if (!o.added_by) o.added_by = decodeURIComponent(k); | |
if (!o.timestamp) o.timestamp = 0; | |
if (m.username && encodeURIComponent(m.username) == | |
m.username) m.username = decodeURIComponent(m.username) | |
} catch (p) { | |
m = Spotify.Link.emptyLink() | |
} | |
f = { | |
link: m || Spotify.Link.emptyLink(), | |
attributes: o | |
}; | |
if (f.link.type === "starred") | |
if (typeof b[f.link.username] === "undefined") b[f.link.username] = !0; | |
else continue; | |
f !== null && h.push({ | |
uri: f.link, | |
attributes: f.attributes | |
}) | |
} | |
return { | |
contents: h | |
} | |
}; | |
this.parsePlaylist = function (g, c) { | |
if (typeof g.contents !== "undefined") { | |
var h = d(g.contents, c); | |
g.contents = h.contents | |
} | |
if (typeof g.revision !== "undefined") g.revision = Spotify.Utils.str2hex(g.revision); | |
return g | |
}; | |
this.parsePublishedPlaylist = function (g, c) { | |
if (typeof g.contents !== "undefined") { | |
var h = d(g.contents, c); | |
g.contents = h.contents; | |
g.length = g.contents.length | |
} | |
if (typeof g.revision !== "undefined") g.revision = Spotify.Utils.str2hex(g.revision); | |
return g | |
}; | |
this.parseMetadata = function (d) { | |
return d.attributes | |
} | |
}; | |
Spotify.Parsers.AdChooser = function () { | |
this.parseServerResponse = function (d) { | |
d = Spotify.Utils.convertStringToXML(d); | |
return Spotify.Utils.convertXMLToJSON(d.documentElement) | |
}; | |
this.parseAudioAdsVersion1 = function (d) { | |
var g = { | |
"audio-ad-break": {}, | |
AdQueueEntry: [] | |
}, c = {}; | |
try { | |
if (typeof d.rules.rule !== "undefined") | |
for (var h = 0, b = d.rules.rule.length; h < b; h += 1) { | |
var a = d.rules.rule[h]; | |
c[a.id] = a | |
} | |
g["audio-ad-break"] = d["audio-ad-break"]; | |
if (typeof d.ads["audio-ad"] !== "undefined") { | |
var f = []; | |
d.ads["audio-ad"].length > 0 ? f = d.ads["audio-ad"] : | |
typeof d.ads["audio-ad"].ad_version !== "undefined" && f.push(d.ads["audio-ad"]); | |
h = 0; | |
for (b = f.length; h < b; h += 1) { | |
for (var k = f[h], d = [], m = 0, o = k.rules.id.length; m < o; m += 1) a = k.rules.id[m], d.push(c[a]); | |
for (var m = null, p = 0, q = k.files.file.length; p < q; p += 1) { | |
var n = k.files.file[p]; | |
if (n["@attributes"].format === "MPEG 1 layer 3,160000,0,1,1") { | |
m = n["@attributes"].id; | |
break | |
} | |
} | |
var s = { | |
ad_type: typeof k["embed-width"] === "string" ? "lightbox" : "audio", | |
has_been_played: !1, | |
has_been_clicked: !1, | |
adPlayCount: 0, | |
campaignPlayCount: 0, | |
ids_valid: !0, | |
non_explicit: k["non-explicit-only"] || 0, | |
is_test_ad: !1, | |
priority: parseFloat(k.priority), | |
duration: parseInt(k.duration, 10), | |
min_duration: 0, | |
ad_version: k.ad_version || 1, | |
start_time_earliest: parseInt(k.starttime), | |
start_time_latest: parseInt(k.endtime), | |
campaign_expiry: parseInt(k.expiry), | |
adclass: 0, | |
adchooserkind: null, | |
adkind: "ENC_AD_AUDIO", | |
rules: d, | |
ad_id: k.id, | |
campaign_id: k.campaign, | |
advertiser: k.advertiser, | |
target_url: k.url, | |
token: k.token, | |
tracking_url: typeof k["tracking-url"] === "string" ? k["tracking-url"] : null, | |
files: k.files, | |
image_id: k.image, | |
embed: { | |
width: k["embed-width"], | |
height: k["embed-height"], | |
background_image: typeof k["embed-background-image"] === "string" ? k["embed-background-image"] : "" | |
}, | |
banner_size: null, | |
banner_type: null, | |
html: null, | |
title: k.title, | |
caption: k.caption, | |
file_id: m, | |
large_bgcolor: null, | |
large_image_id: null, | |
fullscreen_delay: null, | |
fullscreen_inactivity_timeout: null, | |
background_target_url: null, | |
message: null, | |
level: null | |
}; | |
g.AdQueueEntry.push(s) | |
} | |
} | |
} catch (t) {} | |
return g | |
} | |
}; | |
Spotify.Parsers.Social = function () { | |
var d = Spotify.DebuggerJS; | |
this.parse = function (g) { | |
var c = (new Date).getTime(); | |
if (!g.username) g.username = ""; | |
if (!g.full_name) g.full_name = ""; | |
if (!g.image_url) g.image_url = ""; | |
if (!g.large_image_url) g.large_image_url = ""; | |
if (!g.first_name) g.first_name = ""; | |
if (!g.last_name) g.last_name = ""; | |
if (!g.facebook_uid) g.facebook_uid = ""; | |
d.log("Spotify.Parsers.Social", ["It took", (new Date).getTime() - c, "ms to parse the social result"], "parsing_times"); | |
return g | |
} | |
}; | |
Spotify.Parsers.URL = function () { | |
this.parseRTMPUrl = function (d) { | |
var g = Spotify.Utils.parseURL(d); | |
return { | |
server: g.protocol + "://" + g.host + (g.port !== "" ? ":" + g.port : "") + "/cfx/st", | |
protocol: g.protocol, | |
url: d, | |
file: "mp3:" + g.relative.replace("/cfx/st/", "") | |
} | |
}; | |
this.parseHTTPUrl = function (d) { | |
var g = Spotify.Utils.parseURL(d); | |
return { | |
server: g.protocol + "://" + g.host + (g.port !== "" ? ":" + g.port : ""), | |
protocol: g.protocol, | |
url: d, | |
file: g.relative | |
} | |
} | |
}; | |
Spotify.Services.Base = function (d) { | |
Spotify.EventTarget.call(this); | |
this.id = ""; | |
this.serviceIsReady = !1; | |
this.services = {}; | |
this._totalDependenciesReady = 0; | |
this._dependencies = []; | |
var g = new Spotify.Events; | |
this._onServiceReady = function () { | |
this._totalDependenciesReady++; | |
if (this._totalDependenciesReady >= this._dependencies.length) delete this._dependencies, delete this._totalDependenciesReady, this.serviceIsReady = !0, this.setup(), this.trigger(g.READY) | |
}; | |
this.setup = function () {}; | |
this.onReady = function (c, d) { | |
this.serviceIsReady ? | |
c.call(d) : this.bind(g.READY, c, d) | |
}; | |
this._initialize = function (c) { | |
c.length === 0 && this._onServiceReady(); | |
for (var d = 0, b = c.length; d < b; d += 1) this.services[c[d].id] = c[d], c[d].onReady(this._onServiceReady, this) | |
}; | |
this.send = function (c) { | |
c.calleeId = this.id; | |
this.trigger(g.REQUEST, c) | |
}; | |
this.onNotify = function () {}; | |
this.getProtobufMsgParser = d.getProtobufMsgParser; | |
this.dispose = function () {} | |
}; | |
Spotify.Services.Time = function () { | |
var d; | |
this.getServerTime = function (g, c, h) { | |
this.serviceIsReady ? (typeof h === "undefined" && (h = !1), typeof d !== "undefined" && !h ? g(Math.floor((new Date).getTime() / 1E3) + d) : this.send(new Spotify.Calls.Simple({ | |
method: "time", | |
payload: [], | |
context: this, | |
persistent: !1, | |
retries: 2, | |
type: "time" | |
}, function (b) { | |
var a = Math.floor((new Date).getTime() / 1E3); | |
d = b.response - a; | |
g(b.response) | |
}, c))) : c(new Spotify.Errors.Error([503, 0, "Time service not ready!"])) | |
} | |
}; | |
Spotify.Services.Suggest = function () { | |
var d = this, | |
g = new Spotify.Parsers.Suggest; | |
this.suggest = function (c, h, b) { | |
this.serviceIsReady ? this.services.user.getUserInfo(function (a) { | |
a = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://searchsuggest/suggest/" + encodeURIComponent(c) + "?country=" + a.country + "&catalogues=" + a.catalogue, | |
method: "GET" | |
}, | |
responseSchemas: ["suggest#Suggestions"], | |
type: "searchsuggest" | |
}, function (a, k) { | |
if (k == 200) { | |
var c = g.parse(a[0]); | |
h(c, k) | |
} else b(new Spotify.Errors.Error([13, k, ""])) | |
}, b); | |
d.send(a) | |
}, function (a) { | |
b(a) | |
}) : | |
b(new Spotify.Errors.Error([13, 503, "Suggest service not ready!"])) | |
} | |
}; | |
Spotify.Services.AppStore = function () { | |
this.list = function (d, g, c) { | |
this.serviceIsReady ? this.send(new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://appstore/app/list", | |
method: "GET" | |
}, | |
payload: d, | |
payloadSchemas: ["appstore#RequestHeader"], | |
responseSchemas: ["appstore#AppList"], | |
type: "appstore" | |
}, g, c)) : c(new Spotify.Errors.Error([13, 503, "Appstore service not ready!"])) | |
} | |
}; | |
Spotify.Services.PopCount = function () { | |
this.get = function (d, g, c, h, b, a) { | |
this.serviceIsReady ? (g = typeof g === "number" ? g : 100, c = typeof c === "boolean" ? "&friendsFirst=" + c : "", h = typeof h === "string" ? "&afterUser=" + h : "", d = Spotify.Link.fromString(d).toURLPath(), this.send(new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://popcount/" + d + "?maxUsers=" + g + c + h, | |
method: "GET" | |
}, | |
payload: [], | |
payloadSchemas: [], | |
responseSchemas: ["popcount#PopcountResult"], | |
type: "PopCount" | |
}, b, a))) : a(new Spotify.Errors.Error([13, 503, "PopCount service not ready!"])) | |
} | |
}; | |
Spotify.Services.Metadata = function () { | |
var d = Spotify.Link, | |
g = this, | |
c = new Spotify.Parsers.Metadata; | |
new Spotify.Events; | |
var h = function (a) { | |
switch (a.type) { | |
case d.Type.TRACK: | |
return "hm://metadata/track/" + a.id; | |
case d.Type.ALBUM: | |
return "hm://metadata/album/" + a.id; | |
case d.Type.ARTIST: | |
return "hm://metadata/artist/" + a.id; | |
default: | |
throw Error("Unsupported link type!"); | |
} | |
}, b = function (a) { | |
switch (a) { | |
case d.Type.TRACK: | |
return "metadata#Track"; | |
case d.Type.ALBUM: | |
return "metadata#Album"; | |
case d.Type.ARTIST: | |
return "metadata#Artist"; | |
default: | |
throw Error("Unsupported link type!"); | |
} | |
}, a = function (a) { | |
switch (a) { | |
case d.Type.TRACK: | |
return c.parseTrack.bind(c); | |
case d.Type.ALBUM: | |
return c.parseAlbum.bind(c); | |
case d.Type.ARTIST: | |
return c.parseArtist.bind(c); | |
default: | |
throw Error("Unsupported link type!"); | |
} | |
}, f = function (f, k, c) { | |
var m = function (b, m) { | |
if (Spotify.Hermes.Request.isSuccess(m)) { | |
var d = b[0], | |
h = a(f.type); | |
g.services.user.getUserInfo(function (a) { | |
d = h(d, a); | |
k(d, m) | |
}, function (a) { | |
c(a) | |
}) | |
} else c(m) | |
}; | |
this.send = function () { | |
var a = new Spotify.Calls.Hermes({ | |
header: { | |
uri: h(f), | |
method: "GET" | |
}, | |
payload: [], | |
payloadSchemas: [], | |
responseSchemas: [b(f.type)], | |
type: "metadata", | |
persistent: !1, | |
bypassCache: !1 | |
}, m, c); | |
g.send(a) | |
} | |
}, k = function (f, k, c) { | |
var m = f[0].type, | |
s = a(m), | |
t = function (a, b) { | |
var f = []; | |
g.services.user.getUserInfo(function (c) { | |
for (var m = 0, d = a.length; m < d; m += 1) | |
if (a[m]) { | |
var h = s(a[m], c); | |
f.push(h) | |
} | |
k(f, b) | |
}, function (a) { | |
c(a) | |
}) | |
}; | |
this.send = function () { | |
for (var a = [], k = 0, p = f.length; k < p; ++k) a.push({ | |
uri: h(f[k]) | |
}); | |
k = Spotify.Calls.Hermes; | |
a: switch (m) { | |
case d.Type.TRACK: | |
p = "hm://metadata/tracks"; | |
break a; | |
case d.Type.ALBUM: | |
p = | |
"hm://metadata/albums"; | |
break a; | |
case d.Type.ARTIST: | |
p = "hm://metadata/artists"; | |
break a; | |
default: | |
throw Error("Unsupported link type!"); | |
} | |
a = new k({ | |
header: { | |
uri: p, | |
method: "GET" | |
}, | |
payload: [{ | |
request: a | |
}], | |
payloadSchemas: [], | |
responseSchemas: [b(m)], | |
type: "metadata", | |
isMultiGet: !0, | |
persistent: !1, | |
bypassCache: !1 | |
}, t, c); | |
g.send(a) | |
} | |
}, m = function (a) { | |
if (a instanceof Spotify.Link) return a; | |
else if (typeof a === "string" || a instanceof String) return d.fromString(a); | |
else throw Error("Invalid argument!"); | |
}; | |
this.lookup = function (a, b, c) { | |
if (g.serviceIsReady) | |
if (Spotify.Utils.isArray(a)) | |
if (a.length > | |
1) { | |
for (var d = Math.ceil(a.length / 100), h = !1, t = [], u = Array(d), w = function (a) { | |
return function (f) { | |
h || (u[a] = f, --d == 0 && b(Array.prototype.concat.apply([], u), 200)) | |
} | |
}, v = function (a) { | |
h = !0; | |
c(a) | |
}, A = 0, x = a.length; A < x; ++A) t.push(m(a[A])); | |
a = 0; | |
do(new k(t.splice(0, 100), w(a++), v)).send(); while (t.length > 0) | |
} else a.length == 1 ? (new f(m(a[0]), function (a, f) { | |
b([a], f) | |
}, c)).send() : c(Error("Array does not contain any items!")); | |
else(new f(m(a), b, c)).send(); | |
else c(Error("Service not ready!")) | |
} | |
}; | |
Spotify.Services.Search = function () { | |
var d = this, | |
g = new Spotify.Parsers.Search; | |
this.DEFAULT_TOTAL_RESULTS = 50; | |
this.TRACKS = 1; | |
this.ALBUMS = 2; | |
this.ARTISTS = 4; | |
this.PLAYLISTS = 8; | |
this.ALL = this.TRACKS | this.ALBUMS | this.ARTISTS | this.PLAYLISTS; | |
this.search = function (c, h, b, a) { | |
if (this.serviceIsReady) | |
if (typeof c === "undefined" || c === "") a(new Spotify.Errors.Error([403, 0, "You haven't provided a valid query"])); | |
else { | |
h = h || {}; | |
h.type = h.type || this.ALL; | |
h.total = h.total || this.DEFAULT_TOTAL_RESULTS; | |
h.offset = h.offset || 0; | |
if (h.total > this.DEFAULT_TOTAL_RESULTS) h.total = | |
this.DEFAULT_TOTAL_RESULTS; | |
this.send(new Spotify.Calls.Simple({ | |
method: "search", | |
payload: [c, h.type, h.total, h.offset], | |
context: this, | |
persistent: !1, | |
retries: 2, | |
type: "search" | |
}, function (f) { | |
d.services.user.getUserInfo(function (a) { | |
a = g.parse(f.response, a); | |
b(a) | |
}, function (b) { | |
a(b) | |
}) | |
}, a)) | |
} else a(new Spotify.Errors.Error([503, 0, "Search service not ready!"])) | |
} | |
}; | |
Spotify.Services.SearchHermes = function () { | |
this.TRACKS = "TRACK"; | |
this.ALBUMS = "ALBUM"; | |
this.ARTISTS = "ARTIST"; | |
this.PLAYLISTS = "PLAYLIST"; | |
this.USERS = "USER"; | |
this.DEFAULT_TOTAL_RESULTS = 200; | |
this.search = function (d, g, c, h) { | |
this.serviceIsReady ? typeof d === "undefined" || d === "" ? h(new Spotify.Errors.Error([403, 0, "You haven't provided a valid query"])) : (g = g || {}, g.query = d, g.type = g.type || this.TRACKS, g.limit = g.total || this.DEFAULT_TOTAL_RESULTS, delete g.total, g.offset = g.offset || 0, this.send(new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://search/search", | |
method: "GET" | |
}, | |
payload: [g], | |
payloadSchemas: ["searchHermes_FULL#SearchRequest"], | |
responseSchemas: ["searchHermes_FULL#SearchReply"], | |
type: "search_hermes" | |
}, c, h))) : h(new Spotify.Errors.Error([503, 0, "Search service not ready!"])) | |
} | |
}; | |
Spotify.Services.Toplist = function () { | |
var d = this, | |
g = {}; | |
this.TRACK = "track"; | |
this.ALBUM = "album"; | |
this.ARTIST = "artist"; | |
this.PLAYLIST = "playlist"; | |
this.GLOBAL = "global"; | |
var c = { | |
track: Spotify.Link.trackLink, | |
album: Spotify.Link.albumLink, | |
artist: Spotify.Link.artistLink, | |
playlist: Spotify.Link.playlistLink | |
}, h = function (b, a, f, k, m, h, p) { | |
var q = function (a) { | |
if (a[0].items != void 0) { | |
for (var a = a[0].items, m = 0, d = a.length; m < d; ++m) a[m] = c[f](a[m]); | |
g[b] = a; | |
k(a, f, 200) | |
} else if (a[0].uris != void 0) { | |
a = a[0].uris; | |
m = 0; | |
for (d = a.length; m < d; ++m) a[m] = | |
Spotify.Link.fromString(a[m]); | |
g[b] = a; | |
k(a, f, 200) | |
} else g[b] = [], k([], f, 200) | |
}, n = function (b, c) { | |
if (c != null) k(c, f, 200); | |
else { | |
var h = [], | |
g = [], | |
o = []; | |
f === "playlist" ? (h = ["socialgraph#TopPlaylistsRequest"], g = ["socialgraph#TopPlaylistsReply"], o.push({ | |
username: p | |
})) : g = ["toplist#Toplist"]; | |
h = new Spotify.Calls.Hermes({ | |
header: { | |
uri: a, | |
method: "GET" | |
}, | |
payload: o, | |
payloadSchemas: h, | |
responseSchemas: g, | |
type: "toplist" | |
}, q, m); | |
d.send(h) | |
} | |
}; | |
h ? n(b, null) : n(b, g[b]) | |
}; | |
this.lookupForUser = function (b, a, f, k, c) { | |
this.serviceIsReady ? this.services.user.getUserInfo(function (d) { | |
b = | |
b ? b : d.user; | |
var d = Spotify.Link.userToplistLink(b, a).toURI(), | |
g = "hm://toplist/toplist/user/" + encodeURIComponent(b) + "?type=" + a; | |
a === "playlist" && (g = "hm://socialgraph/suggestions/topplaylists"); | |
h(d, g, a, f, k, c, b) | |
}, k) : k(new Spotify.Errors.Error([13, 503, "Toplist service not ready!"])) | |
}; | |
this.lookupForRegion = function (b, a, f, k, c) { | |
this.serviceIsReady ? this.services.user.getUserInfo(function (d) { | |
b = b ? b : d.country; | |
var d = b == "global", | |
g = Spotify.Link.toplistLink(a, d ? null : b, d).toURI(); | |
h(g, d ? "hm://toplist/toplist/region?type=" + | |
a : "hm://toplist/toplist/region/" + b + "?type=" + a, a, f, k, c) | |
}, k) : k(new Spotify.Errors.Error([13, 503, "Toplist service not ready!"])) | |
} | |
}; | |
Spotify.Services.Playlist = function () { | |
this.DEFAULT_TOTAL_RESULTS = 200; | |
var d = Spotify.Utils.isArray, | |
g = Spotify.DebuggerJS, | |
c = this, | |
h = new Spotify.Events, | |
b = new Spotify.Parsers.Playlist, | |
a = [], | |
f = null, | |
k = {}, m = function (a, b) { | |
b = typeof b !== "undefined" && b.length ? "?" + b.join("&") : ""; | |
return "hm://playlist/" + a.split(":").join("/").substr(8) + b | |
}, o = function (a) { | |
return function () { | |
for (var b = 0; b < a.length; b++) typeof a[b] === "function" && a[b].apply(this, arguments) | |
} | |
}, p = function (a, b, f, d, h, g) { | |
var o = []; | |
a === "ADD" && o.push("add_first=true"); | |
a = "APPEND" === a ? "ADD" : a; | |
(a === "REMOVE" || a === "MODIFY") && Spotify.Link.fromString(b).type !== "inbox" && o.push("syncpublished=true"); | |
var q = [], | |
q = a === "REMOVE" || a === "ADD" || a === "APPEND" ? [] : ["playlist_FULL#OpList"], | |
p = []; | |
a === "MODIFY" ? p = ["playlist_FULL#ModifyReply"] : a === "PUT" && (p = ["playlist_FULL#CreateListReply"]); | |
f && a === "MODIFY" && (f = w(f.revision), o.push("revision=" + f)); | |
var s = 0, | |
t = 0, | |
u = function () { | |
var f = new Spotify.Calls.Hermes({ | |
header: { | |
uri: m(b, o), | |
method: a | |
}, | |
payload: [d], | |
payloadSchemas: q, | |
responseSchemas: p, | |
type: "playlist", | |
persistent: !1, | |
bypassCache: !1 | |
}, function (m) { | |
c.services.user.getUserInfo(function (c) { | |
k[b] = w(Spotify.Utils.str2hex(m[0].revision || m[0])); | |
var g = [], | |
o = []; | |
typeof d === "string" && (g = d.split(",")); | |
for (var q = 0, p = g.length; q < p; q += 1) { | |
var s = { | |
uri: Spotify.Link.fromString(g[q]) | |
}; | |
a === "ADD" && b !== Spotify.Link.publishedRootlistLink(c.user).toURI() && s.uri.type === "playlist" && o.push(s) | |
} | |
o.length > 0 && n(o); | |
typeof h === "function" && (a === "PUT" ? h(m, { | |
revision: k[b] | |
}) : h(!0, { | |
revision: k[b] | |
})); | |
c = f.header.uri.split("?")[0]; | |
g = "GET"; | |
if (a === | |
"MODIFY" && d.ops.length && (d.ops[0].kind === "UPDATE_LIST_ATTRIBUTES" || d.ops[0].kind === "UPDATE_ITEM_ATTRIBUTES")) g = "HEAD"; | |
Spotify.Hermes.Cache.removeAllContaining(g + c) | |
}, g) | |
}, M); | |
c.send(f) | |
}, M = function () { | |
t >= 4 ? typeof g === "function" && g.apply(this, arguments) : (s = Math.floor(2 * t * Math.random()) * 500, t++, setTimeout(u, s)) | |
}; | |
return u | |
}, q = function () { | |
var a; | |
c.serviceIsReady ? c.services.user.getUserInfo(function (b) { | |
a = Spotify.Link.profileLink(b.user); | |
g.log("Spotify.Services.Playlist", ["Will try to subscribe to", a.username], | |
"corejs"); | |
n([{ | |
uri: a | |
}]); | |
c.rootlist({ | |
total: -1, | |
offset: 0 | |
}, function (a) { | |
for (var f = [], c = 0, k = a.contents.length; c < k; c += 1) { | |
var m = a.contents[c]; | |
m.username !== b.user && f.push(m) | |
} | |
f.length > 0 && (g.log("Spotify.Services.Playlist", ["Will try to subscribe to", f], "corejs"), n(f)) | |
}, t) | |
}, t) : g.error("Spotify.Services.Playlist", ["Playlist service not ready"], "corejs") | |
}, n = function (a) { | |
var b = []; | |
if (!Spotify.Utils.isArray(a)) throw "Playlists argument must be an array"; | |
if (a.length !== 0) { | |
for (var f = 0, k = a.length; f < k; f += 1) typeof a[f] !== | |
"undefined" && typeof a[f].uri !== "undefined" && b.push("hm://playlist/" + a[f].uri.toURLPath()); | |
c.services.pubsub.subscribe("hm://playlist/", [{ | |
uris: b | |
}], ["playlist_FULL#SubscribeRequest"], s, t, u, c) | |
} | |
}, s = function (a) { | |
g.log("Spotify.Services.Playlist", ["Subscription was a success", a], "corejs") | |
}, t = function (a) { | |
g.error("Spotify.Services.Playlist", ["Subscription failed", a], "corejs") | |
}, u = function (a) { | |
if (a.length > 0) { | |
a = c.getProtobufMsgParser("playlist4service", "PlaylistModificationInfo").parseFromStringSync(Spotify.Utils.Base64.decode(a[3])); | |
if (typeof a.new_revision !== "undefined") a.new_revision = w(Spotify.Utils.str2hex(a.new_revision)); | |
g.log("Spotify.Services.Playlist", ["Got a notification", a], "corejs"); | |
typeof a.uri !== "undefined" && (Spotify.Link.fromString(a.uri).type === "collectiontracklist" ? g.log("Spotify.Services.Playlist", ["The notification is about the starred list but by using the legacy object collectiontracklist"], "corejs") : (c.trigger(h.CHANGE, { | |
localRevision: k[a.uri], | |
revision: a.new_revision, | |
uri: a.uri | |
}), g.log("Spotify.Services.Playlist", ["Triggered change event for ", a.uri, " with new revision: ", a.new_revision], "corejs"))) | |
} | |
}, w = function (a) { | |
var b = parseInt(a.substr(0, 8), 16), | |
a = a.substr(8); | |
return b + "," + a | |
}; | |
this.metadata = function (a, f, k) { | |
c.serviceIsReady ? (typeof a == "string" && (a = Spotify.Link.fromString(a)), this.send(new Spotify.Calls.Hermes({ | |
header: { | |
uri: m(a.toURI()), | |
method: "HEAD" | |
}, | |
payload: [], | |
payloadSchemas: [], | |
responseSchemas: ["playlist_FULL#SelectedListContent"], | |
type: "playlist", | |
persistent: !1, | |
bypassCache: !1 | |
}, function (c) { | |
var m = a.toURI(); | |
if (typeof c == | |
"undefined" || typeof c[0] == "undefined") k(new Spotify.Errors.Error([13, 404, "No results", m])); | |
else { | |
var d = b.parseMetadata(c[0]); | |
d.owner = Spotify.Link.fromString(m).username; | |
d.uri = m; | |
d.revision = w(Spotify.Utils.str2hex(c[0].revision)); | |
f(d) | |
} | |
}, function (b) { | |
b.data = a.toURI(); | |
k(b) | |
}))) : k(new Spotify.Errors.Error([13, 503, "Playlist service not ready!"])) | |
}; | |
this.getChangesBetweenRevisionAndHead = function (a, b, f, d) { | |
b = new Spotify.Calls.Hermes({ | |
header: { | |
uri: m(a) + "?revision=" + b, | |
method: "DIFF" | |
}, | |
payload: [], | |
payloadSchemas: [], | |
responseSchemas: ["playlist_FULL#SelectedListContent"], | |
type: "playlist", | |
persistent: !1, | |
bypassCache: !1 | |
}, function (b) { | |
var c = {}; | |
c.operations = b[0].diff.ops; | |
c.uri = a; | |
c.revision = w(Spotify.Utils.str2hex(b[0].revision)); | |
k[a] = c.revision; | |
f(c) | |
}, d); | |
c.send(b) | |
}; | |
this.subscribe = function (b, k, m) { | |
clearTimeout(f); | |
if (c.serviceIsReady) { | |
if (typeof b.publish === "undefined") b.publish = !1; | |
for (var n = d(b.uri) ? b.uri : [b.uri], q = n.length; q--;) { | |
var s = Spotify.Link.fromString(n[q]); | |
n[q] = s.toURI() | |
} | |
a.push({ | |
username: b.username, | |
uri: n, | |
callback: k, | |
errback: m | |
}); | |
var t = this, | |
u; | |
f = setTimeout(function () { | |
u = a.slice(0); | |
f = null; | |
a = []; | |
for (var k = {}, m = {}, d = {}, n = {}, q = 0; q < u.length; q++) n = u[q], k[n.username] = k[n.username] || [], m[n.username] = m[n.username] || [], d[n.username] = d[n.username] || [], k[n.username] = k[n.username].concat(n.uri), m[n.username].push(n.callback), d[n.username].push(n.errback); | |
for (var s in k) { | |
var w = k[n.username], | |
A = o(m[n.username]), | |
x = o(d[n.username]), | |
F = Spotify.Link.rootlistLink(b.username).toURI(); | |
t.list({ | |
uri: F, | |
total: -1 | |
}, function (a) { | |
for (var b = F, f = A, | |
k = x, m = w.slice(0), d = 0; d < a.contents.length; d++) { | |
var g = a.contents[d].uri; | |
if (g.type != "empty") | |
for (var o = 0; o < m.length; o++) g.toURI() == m[o] && delete m[o] | |
} | |
a = []; | |
for (d = 0; d < m.length; d++) m[d] && a.push(m[d]); | |
a.length > 0 ? (p("ADD", b, null, a.join(","), f, k)(), c.trigger(h.PLAYLIST_SUBSCRIBE, { | |
uris: a | |
})) : typeof f === "function" && f(!0) | |
}, x); | |
b.publish && setTimeout(function () { | |
t.publishPlaylists(w, function () { | |
g.log("Spotify.Services.Playlist", ["Playlists were published too", w], "corejs") | |
}, function () { | |
g.error("Spotify.Services.Playlist", ["Playlists couldn't be published", w], "corejs") | |
}) | |
}, 2E3) | |
} | |
}, 100) | |
} else m(new Spotify.Errors.Error([13, 503, "Playlist service not ready!"])) | |
}; | |
this.list = function (a, f, d) { | |
if (c.serviceIsReady) { | |
if (a.total > this.DEFAULT_TOTAL_RESULTS) a.total = this.DEFAULT_TOTAL_RESULTS; | |
else if (!a.total) a.total = -1; | |
if (typeof a.offset === "undefined") a.offset = 0; | |
var h = Spotify.Link.fromString(a.uri), | |
g = { | |
uri: m(h.toURI()), | |
method: "GET" | |
}; | |
typeof a.offset !== "undefined" && typeof a.total !== "undefined" && (g.uri += "?from=" + a.offset, a.total !== -1 && | |
(g.uri += "&length=" + a.total)); | |
this.send(new Spotify.Calls.Hermes({ | |
header: g, | |
payload: [], | |
payloadSchemas: [], | |
responseSchemas: ["playlist_FULL#SelectedListContent"], | |
type: "playlist", | |
persistent: !1, | |
bypassCache: !1 | |
}, function (a) { | |
if (typeof a == "undefined" || typeof a[0] == "undefined") d(new Spotify.Errors.Error([13, 404, "No results"])); | |
else { | |
var c; | |
c = h.type === "published-rootlist" ? b.parsePublishedPlaylist(a[0], h.username) : b.parsePlaylist(a[0], h.username); | |
k[h.toURI()] = w(a[0].revision) || ""; | |
h.type == "starred" && c.contents.reverse(); | |
f(c, { | |
revision: k[h.toURI()] | |
}) | |
} | |
}, d)) | |
} else d(new Spotify.Errors.Error([13, 503, "Playlist service not ready!"])) | |
}; | |
this.rootlist = function (a, b, f) { | |
this.services.user.getUserInfo(function (k) { | |
a.username = k.user; | |
a.uri = Spotify.Link.rootlistLink(a.username).toURI(); | |
c.list(a, b, f) | |
}, f) | |
}; | |
this.publishedRootlist = function (a, b, f) { | |
a.offset && delete a.offset; | |
a.total = -1; | |
a.uri = Spotify.Link.publishedRootlistLink(a.username).toURI(); | |
this.list(a, b, f) | |
}; | |
this.starredPlaylist = function (a, b, f) { | |
a.uri = Spotify.Link.starredLink(a.username).toURI(); | |
this.list(a, b, f) | |
}; | |
this.publishPlaylists = function (a, b, f) { | |
this.services.user.getUserInfo(function (c) { | |
c = Spotify.Link.publishedRootlistLink(c.user).toURI(); | |
p("ADD", c, null, a.join(","), b, f)() | |
}, f) | |
}; | |
this.unpublishPlaylists = function (a, b, f) { | |
this.services.user.getUserInfo(function (k) { | |
k = Spotify.Link.publishedRootlistLink(k.user).toURI(); | |
c.removeFromPlaylistByUri(k, a, b, f) | |
}, f) | |
}; | |
this.addToPlaylist = function (a, b, f, c) { | |
p("APPEND", a, null, b.join(","), f, c)() | |
}; | |
this.addToPlaylistWithAttributes = function (a, b, f, c) { | |
for (var k = [], m = 0, d = b.length; m < d; m += 1) { | |
var h = b[m]; | |
k.push({ | |
uri: h.uri, | |
attributes: { | |
added_by: h.addedBy || "", | |
message: h.message || "" | |
} | |
}) | |
} | |
p("MODIFY", a, null, { | |
ops: [{ | |
kind: "ADD", | |
add: { | |
addLast: !0, | |
items: k | |
} | |
}] | |
}, f, c)() | |
}; | |
this.addTracksInPlaylist = function (a, b, f, k) { | |
c.addToPlaylist(a, b, f, k) | |
}; | |
this.removeFromPlaylistByUri = function (a, b, f, k) { | |
p("REMOVE", a, null, b.join(","), f, k)() | |
}; | |
this.removeFromPlaylist = function (a, b, f, k, c) { | |
this.list({ | |
uri: a, | |
total: -1 | |
}, function (m) { | |
p("MODIFY", a, m, { | |
ops: [{ | |
kind: "REM", | |
rem: { | |
fromIndex: b, | |
length: f | |
} | |
}] | |
}, k, c)() | |
}, function (a) { | |
c(a) | |
}) | |
}; | |
this.starTracks = function (a, b, f) { | |
this.services.user.getUserInfo(function (k) { | |
k = Spotify.Link.starredLink(k.user).toURI(); | |
c.addToPlaylist(k, a, b, f) | |
}, f) | |
}; | |
this.unstarTracks = function (a, b, f) { | |
this.services.user.getUserInfo(function (k) { | |
k = Spotify.Link.starredLink(k.user).toURI(); | |
c.removeFromPlaylistByUri(k, a, b, f) | |
}, f) | |
}; | |
this.createPlaylist = function (a, b, f) { | |
this.services.user.getUserInfo(function (k) { | |
var m = Spotify.Link.profileLink(k.user).toURI(); | |
p("PUT", m, null, { | |
ops: [{ | |
kind: "UPDATE_LIST_ATTRIBUTES", | |
update_list_attributes: { | |
new_attributes: { | |
values: { | |
name: a.name | |
} | |
} | |
} | |
}] | |
}, | |
function (m, d) { | |
c.subscribe({ | |
username: k.user, | |
uri: m[0].uri, | |
publish: a.publish | |
}, function () { | |
b(m[0].uri, { | |
revision: w(d.revision) | |
}) | |
}, f) | |
}, f)() | |
}, f) | |
}; | |
this.renamePlaylist = function (a, b, f, k) { | |
p("MODIFY", a, null, { | |
ops: [{ | |
kind: "UPDATE_LIST_ATTRIBUTES", | |
update_list_attributes: { | |
new_attributes: { | |
values: { | |
name: b | |
} | |
} | |
} | |
}] | |
}, function (a, b) { | |
f(!0, b) | |
}, k)() | |
}; | |
this.updateItemAttributes = function (a, b, f, k, c) { | |
var m = { | |
ops: [{ | |
kind: "UPDATE_ITEM_ATTRIBUTES", | |
update_item_attributes: { | |
index: b, | |
new_attributes: { | |
values: f | |
} | |
} | |
}] | |
}; | |
this.list({ | |
uri: a, | |
total: -1 | |
}, function (b) { | |
p("MODIFY", | |
a, b, m, function (a, b) { | |
k(!0, b) | |
}, c)() | |
}, c) | |
}; | |
this.synchronize = function (a, b, f, k) { | |
this.send(new Spotify.Calls.Hermes({ | |
header: { | |
uri: m(a), | |
method: "CALL" | |
}, | |
payload: requestData, | |
payloadSchemas: ["playlist_FULL#Playlist4ServiceCall"], | |
responseSchemas: ["playlist_FULL#Playlist4ServiceReturn"], | |
type: "playlist", | |
persistent: !1, | |
bypassCache: !1 | |
}, f, k)) | |
}; | |
this.onNotify = function (a) { | |
switch (a.type) { | |
case h.CONNECTED: | |
q() | |
} | |
} | |
}; | |
Spotify.Services.User = function () { | |
var d = this, | |
g = new Spotify.Events, | |
c = null, | |
h = !1, | |
b = []; | |
this.getUserInfo = function (a, f, k) { | |
typeof k === "undefined" && (k = !1); | |
c !== null && !k ? a(c) : (b.push({ | |
onSuccess: a, | |
onError: f | |
}), h || (h = !0, this.send(new Spotify.Calls.Simple({ | |
method: "user_info", | |
payload: [], | |
context: this, | |
persistent: !1, | |
retries: 2, | |
type: "userdata" | |
}, function (a) { | |
c = a.response; | |
h = !1; | |
for (var a = 0, f = b.length; a < f; a += 1) b[a].onSuccess(c); | |
b = [] | |
}, function (a) { | |
h = !1; | |
for (var f = 0, k = b.length; f < k; f += 1) b[f].onError(a); | |
b = [] | |
})))) | |
}; | |
this.setUserAttribute = | |
function (a, b, k, m) { | |
this.send(new Spotify.Calls.Simple({ | |
method: "set_ua", | |
payload: [a, b], | |
context: this, | |
persistent: !1, | |
retries: 2, | |
type: "userdata" | |
}, function () { | |
c[a] = b; | |
k(!0, 200); | |
d.trigger(g.USER_INFO_CHANGE) | |
}, m)) | |
}; | |
this.onNotify = function (a) { | |
switch (a.type) { | |
case g.USER_INFO_CHANGE: | |
this.trigger(g.USER_INFO_CHANGE) | |
} | |
} | |
}; | |
Spotify.Services.Social = function () { | |
new Spotify.Parsers.Social; | |
this.getUsers = function (d, g, c, h) { | |
var b = 0, | |
a = [], | |
f = 0; | |
typeof g === "undefined" ? g = "fast" : g !== "fast" && g !== "complete" && (g = "fast"); | |
for (b = d.length; f < b; ++f) a.push({ | |
uri: "hm://social/decoration/user/" + encodeURIComponent(d[f]) | |
}); | |
this.send(new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://social/decorations/" + g, | |
method: "GET" | |
}, | |
isMultiGet: !0, | |
payload: [{ | |
request: a | |
}], | |
responseSchemas: ["social#DecorationData"], | |
type: "social" | |
}, c, h)) | |
} | |
}; | |
Spotify.SourceURLs = { | |
normal: "https://d3rt1990lpmkn.cloudfront.net/300/", | |
original: "https://d3rt1990lpmkn.cloudfront.net/unbranded/" | |
}; | |
Spotify.Services.SongUriResolver = function () { | |
var d = Spotify.DebuggerJS, | |
g = new Spotify.Events, | |
c = this, | |
h = new Spotify.Parsers.URL, | |
b, a = !1; | |
this.IN_CDN = 0; | |
this.ONLY_ON_STORAGE = 1; | |
this.RATE_LIMIT_REACHED = 2; | |
this.TRACK_RESTRICTED = 3; | |
var f = function (a) { | |
var b = a.params.trackUri, | |
f = a.params.callback, | |
k = a.params.errback, | |
a = a.params.schema; | |
d.log("Spotify.Services.SongUriResolver", ["Rate limit is calling again:", b], "corejs"); | |
c.list(b, a, f, k) | |
}, k = function () { | |
d.log("Spotify.Services.SongUriResolver", ["Rate limit is disabled"], "corejs"); | |
a = !1 | |
}; | |
this.list = function (f, k, p, q) { | |
var n = Spotify.Link.fromString(f); | |
if (this.serviceIsReady) { | |
if (!(n instanceof Spotify.Link)) return d.error("Spotify.Services.SongUriResolver", ["Invalid arguments"], "corejs"), q(Error("Services:SongUriResolver:list Invalid arguments")), !1; | |
if (a && b.totalPendingRequests() !== 0) { | |
n = b.getItemAtIndex(0); | |
if (n !== null && typeof n !== "undefined") { | |
var s = new Spotify.Errors.Error([Spotify.Errors.Domains.TRACK_ERROR, Spotify.Errors.Codes.TRACK_REQUEST_RATE_LIMITED, ""]); | |
n.errback(s) | |
} | |
b.addToBucket({ | |
trackUri: f, | |
schema: k, | |
callback: p, | |
errback: q | |
}, !1) | |
} else n = new Spotify.Calls.Simple({ | |
method: "track_uri", | |
payload: ["mp3160", n.id, k], | |
context: c, | |
persistent: !0, | |
retries: 2, | |
type: "track_uri" | |
}, function (a) { | |
if (a.response !== null) { | |
var b = a.response.type; | |
if (b === c.IN_CDN) k === "rtmp" ? (b = h.parseRTMPUrl(a.response.uri), a.response.uri = b.file) : b = h.parseHTTPUrl(a.response.uri), a.response.server = b.server, a.response.protocol = b.protocol, p(a.response, 200), d.log("Spotify.Services.SongUriResolver", ["Song can be loaded", a.response], "corejs"); | |
else { | |
a = | |
new Spotify.Errors.Error([Spotify.Errors.Domains.TRACK_ERROR, 0, ""]); | |
a.code = b; | |
if (b === c.ONLY_ON_STORAGE) a.description = "Song only on storage"; | |
else if (b === c.RATE_LIMIT_REACHED) a.description = "Rate limit reached"; | |
else if (b === c.TRACK_RESTRICTED) a.description = "Track restricted"; | |
a.data = f; | |
q(a); | |
d.error("Spotify.Services.SongUriResolver", ["I could not load the song", a], "corejs") | |
} | |
} else a = new Spotify.Errors.Error([Spotify.Errors.Domains.TRACK_ERROR, 0, "Response was null"]), a.data = f, q(a), d.error("Spotify.Services.SongUriResolver", ["I could not load the song", a], "corejs") | |
}, function (k) { | |
k.data = f; | |
k.domain === Spotify.Errors.Domains.TRACK_ERROR && k.code === Spotify.Errors.Codes.TRACK_REQUEST_RATE_LIMITED ? (d.warn("Spotify.Services.SongUriResolver", ["Rate limit is enabled"], "corejs"), a = !0, b.start(), b.addToBucket({ | |
trackUri: f, | |
callback: p, | |
errback: q | |
}, !1)) : (k.domain === Spotify.Errors.Domains.TRACK_ERROR && k.code === Spotify.Errors.Codes.TIME_CAP && c.trigger(g.TIME_CAP, k), q(k)); | |
d.error("Spotify.Services.SongUriResolver", ["I could not load the song", | |
k | |
], "corejs") | |
}), c.send(n) | |
} else d.error("Spotify.Services.SongUriResolver", ["Service is not ready"], "corejs"), q(Error("Services.SongUriResolver:list Service is not ready")) | |
}; | |
this.initialize = function () { | |
b = new Spotify.RateLimiter(1E4, 1); | |
b.bind(g.RATE_LIMIT_CALL, f, this); | |
b.bind(g.RATE_LIMIT_DISABLED, k, this) | |
}; | |
this.initialize.call(this) | |
}; | |
Spotify.Services.AdUriResolver = function () { | |
var d = Spotify.DebuggerJS, | |
g = new Spotify.Parsers.URL, | |
c = this; | |
this.list = function (h, b, a, f) { | |
var k = Spotify.Link.fromString(h); | |
if (this.serviceIsReady) { | |
if (!(k instanceof Spotify.Link)) return f(new Spotify.Errors.Error([15, 400, "Invalid arguments"])), !1; | |
(function (k) { | |
var o = k.response.type; | |
if (o === 0) b === "rtmp" ? (o = g.parseRTMPUrl(k.response.uri), k.response.uri = o.file) : o = g.parseHTTPUrl(k.response.uri), k.response.server = o.server, k.response.protocol = o.protocol, a(k.response, | |
200); | |
else { | |
k = { | |
method: "ad_uri", | |
response: k | |
}; | |
if (o === c.ONLY_ON_STORAGE) k.response = "Song only on storage"; | |
else if (o === c.RATE_LIMIT_REACHED) k.response = "Rate limit reached"; | |
else if (o === c.TRACK_RESTRICTED) k.response = "Track restricted"; | |
k.adUri = h; | |
d.error("Spotify.Services.AdUriResolver", ["Error with track", k], "corejs"); | |
f(k) | |
} | |
})({ | |
method: "ad_uri", | |
response: { | |
type: 0, | |
uri: b === "rtmp" ? "rtmp://saa23rvd7l5c6.cloudfront.net/cfx/st/mp3-ad/" + k.id : "http://d7zatysqm84hv.cloudfront.net/mp3-ad/" + k.id | |
} | |
}) | |
} else f(new Spotify.Errors.Error([15, | |
503, "AdUriResolver service not ready!" | |
])) | |
} | |
}; | |
Spotify.Services.PreviewsUriResolver = function () { | |
var d = new Spotify.Parsers.URL; | |
new Spotify.Events; | |
this.list = function (g, c, h) { | |
var b = {}, g = Spotify.Link.fromString(g).id; | |
c === "rtmp" ? (c = d.parseRTMPUrl("rtmp://soamh0g9lumcr.cloudfront.net/cfx/st/mp3-preview/" + g), b.uri = c.file) : (c = d.parseHTTPUrl("http://d318706lgtcm8e.cloudfront.net/mp3-preview/" + g), b.uri = "http://d318706lgtcm8e.cloudfront.net/mp3-preview/" + g); | |
b.server = c.server; | |
b.protocol = c.protocol; | |
b.lid = ""; | |
b.type = 0; | |
h(b) | |
} | |
}; | |
Spotify.Services.AdChooser = function () { | |
Spotify.EventTarget.call(this); | |
var d = Spotify.DebuggerJS, | |
g = this, | |
c = new Spotify.Parsers.AdChooser, | |
h = new Spotify.Parsers.AdMetadata, | |
b, a = [], | |
f, k = new Spotify.Events, | |
m = !1, | |
o = null, | |
p = null, | |
q = 0, | |
n = null, | |
s = null, | |
t = null, | |
u = [0, 60], | |
w = 35, | |
v = 0, | |
A = 0, | |
x = 600, | |
F = 0, | |
G = [], | |
B = {}, E = [], | |
H = null, | |
I = null; | |
this.serviceIsReady = !1; | |
var K = function (a) { | |
d.error("Spotify.Services.AdChooser", ["AdChooser Error.. " + ["Domain: " + a.domain, "Code: " + a.code, "Description: " + a.description, "Data: " + a.data].join(",")], "corejs") | |
}, | |
L = function (a, b) { | |
if (typeof a === "function" && typeof b === "function") { | |
var k = E.slice(0); | |
k.slice(0, 1021); | |
var c = [0, 1, k.length]; | |
c.push.apply(c, k); | |
try { | |
f.rpc("ads", c, a, b, this) | |
} catch (m) { | |
R({ | |
serverError: !0 | |
}), K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Exception thrown communicating with ad server", { | |
extra: m | |
}])) | |
} | |
} else K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Invalid callbacks specified for _retrieveAudioAdsFromServer", { | |
extra: e | |
}])) | |
}, N = function (a) { | |
var b = null; | |
R(); | |
z(function (a) { | |
a = a.response; | |
parseInt(a) > 0 ? F = O() - a : K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Invalid server time specified", { | |
extra: e | |
}])) | |
}, function (a) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Exception thrown retrieving server time", { | |
extra: a | |
}])) | |
}); | |
b = c.parseServerResponse(a.response); | |
return C(b) | |
}, M = function (a, b, k) { | |
if (typeof b === "function" && typeof k === | |
"function") { | |
a = [a]; | |
try { | |
f.rpc("get_ad", a, b, k, this) | |
} catch (c) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Exception thrown communicating with ad metadata server", { | |
extra: c | |
}])) | |
} | |
} else K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Invalid callbacks specified for _retrieveAudioAdMetadataFromServer", { | |
extra: e | |
}])) | |
}, z = function (a, b) { | |
typeof a === "function" && typeof b === "function" ? f.rpc("time", [0], a, b, this) : K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, | |
Spotify.Errors.Codes.ADS_SERVER_ERROR, "Invalid callbacks for retrieveAdServerTime" | |
])) | |
}, C = function (a) { | |
var b = parseInt(a["@attributes"].version, 10) | 0, | |
f = null, | |
k = null, | |
m = f = null, | |
d = null; | |
if (b === 0) K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Missing version attribute from audio queue data structure", { | |
extra: e | |
}])); | |
else if (f = c["parseAudioAdsVersion" + b], typeof f === "function") { | |
f = f(a); | |
a = parseInt(f["audio-ad-break"].length); | |
try { | |
w = a, I.setItem("defaultAdBreakLength", | |
w) | |
} catch (h) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Unable to set audio ad break length", { | |
extra: h | |
}])) | |
} | |
a = parseInt(f["audio-ad-break"].time_between); | |
try { | |
x = a, I.setItem("timeBetweenAdBreak", x) | |
} catch (g) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Unable to set audio ad break time between", { | |
extra: g | |
}])) | |
} | |
if (typeof (f.AdQueueEntry !== "undefined" && f.AdQueueEntry.length > 0)) { | |
for (m = 0, d = f.AdQueueEntry.length; m < | |
d; m += 1) k = f.AdQueueEntry[m], G.push(k), typeof B[k.ad_id] === "undefined" && J(k.ad_id); | |
y(); | |
I.setItem("audioQueue", JSON.stringify(G)) | |
} else R({ | |
serverError: !0 | |
}), K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "No ads received from the ad server"])) | |
} else K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "No parser exists for audio queue version " + b])) | |
}, y = function (a) { | |
try { | |
typeof a === "undefined" ? G.sort(function (a, b) { | |
return b.priority - | |
a.priority | |
}) : G.sort(a) | |
} catch (b) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Unable to prioritize ad queue", { | |
extra: b | |
}])) | |
} | |
}, D = function (a) { | |
try { | |
E.indexOf(a) === -1 && (E.push(a), I.setItem("forbiddenAds", JSON.stringify(E))) | |
} catch (b) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Unable to add forbidden ad", { | |
extra: b | |
}])) | |
} | |
}, P = function (a) { | |
try { | |
v += a, v > w * 2 && (v = w * 2), I.setItem("audioAdBreakAvailableTime", v) | |
} catch (b) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, | |
Spotify.Errors.Codes.ADS_SERVER_ERROR, "Unable to set audio ad break available time", { | |
extra: b | |
} | |
])) | |
} | |
}, O = function () { | |
return Math.round((new Date).getTime() / 1E3) | |
}, R = function (a) { | |
var b = !1, | |
f = O(), | |
k = Math.floor(Math.random() * u[1] + u[0]); | |
typeof a !== "undefined" && a.serverError === !0 && (b = !0); | |
A = b === !1 ? f + 600 + k : f + 3600 + k; | |
I.setItem("timeOfNextAdServerRequest", A) | |
}, T = function (a) { | |
var b = [], | |
f = B[a.ad_id], | |
k = O() + F, | |
c = { | |
max_campaign_repeats_within: function (b, f) { | |
var c = k - b, | |
m = [], | |
d = a.campaign_id, | |
h = null; | |
for (h in B) B.hasOwnProperty(h) && | |
B[h].campaign_id === d && m.concat(B[h].event_history.map(function (a) { | |
if (a.event === "impression" && a.timestamp >= c) return a | |
})); | |
return m.length < f | |
}, | |
max_repeats_within: function (a, b) { | |
var c = k - a; | |
return f.event_history.map(function (a) { | |
if (a.event === "impression" && a.timestamp >= c) return a | |
}).length < b | |
}, | |
max_attempts_within: function (a, b) { | |
var c = k - a; | |
return f.event_history.map(function (a) { | |
if (a.event === "attempt" && a.timestamp >= c) return a | |
}).length < b | |
}, | |
max_clicks_within: function (a, b) { | |
var c = k - a; | |
return f.event_history.map(function (a) { | |
if (a.event === | |
"click" && a.timestamp >= c) return a | |
}).length < b | |
} | |
}; | |
if (f.rules.length > 0) | |
for (r in f.rules) | |
if (f.rules.hasOwnProperty(r)) { | |
var m = f.rules[r]; | |
b.push(c[m.type](parseInt(m.interval), parseInt(m.times))) | |
} | |
return b.indexOf(!1) === -1 | |
}, S = function () { | |
try { | |
var a = [], | |
b = null, | |
f = null, | |
k = null; | |
for (f = 0, k = G.length; f < k; f += 1) b = G[f], b.start_time_latest <= O() + F ? (d.log("Spotify.Services.AdChooser", ["Removing expired ad", result], "corejs"), D(b.ad_id)) : T(b) === !1 ? (d.log("Spotify.Services.AdChooser", ["Removing ad with expired rules"], "corejs"), | |
D(b.ad_id)) : a.push(b); | |
G = a; | |
I.setItem("audioQueue", JSON.stringify(G)); | |
return G.length - a.length | |
} catch (c) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Unable to clear invalid ads in audio ad queue", { | |
extra: c | |
}])) | |
} | |
}, J = function (a, b) { | |
var f; | |
a: { | |
var k = f = null, | |
c = null; | |
for (f = 0, k = G.length; f < k; f += 1) | |
if (c = G[f], c.ad_id === a) { | |
f = c; | |
break a | |
} | |
f = null | |
} | |
f !== null ? (typeof B[a] === "undefined" && (B[a] = { | |
campaign_id: f.campaign_id, | |
expiry_time: f.campaign_expiry, | |
rules: f.rules, | |
event_history: [] | |
}), | |
typeof b !== "undefined" && B[a].event_history.push({ | |
timestamp: O() + F, | |
event: b | |
}), I.setItem("adHistory", JSON.stringify(B))) : K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Unable to locate ad queue entry", { | |
extra: b | |
}])) | |
}, V = function (a, b) { | |
var f; | |
f = a.split("spotify:ad:")[1]; | |
f = X(f); | |
var k = null; | |
if (f === null) K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_NOT_FOUND, "Unable to locate ad to record ad event", { | |
extra: a | |
}])); | |
else { | |
a: { | |
var c = | |
k = null, | |
m = null; | |
for (k = 0, c = G.length; k < c; k += 1) | |
if (m = G[k], m.ad_id === f.ad_id) break a; | |
k = null | |
} | |
k === null && K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_NOT_FOUND, "Unable to locate ad queue index", { | |
extra: f | |
}])); | |
switch (b) { | |
case "click": | |
G[k].has_been_clicked = !0; | |
J(f.ad_id, "click"); | |
break; | |
case "attempt": | |
J(f.ad_id, "attempt"); | |
break; | |
case "impression": | |
G[k].has_been_played = !0; | |
G[k].adPlayCount += 1; | |
G[k].campaignPlayCount += 1; | |
J(f.ad_id, "impression"); | |
break; | |
default: | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, | |
Spotify.Errors.Codes.ADS_SERVER_ERROR, "Invalid ad event", { | |
extra: b | |
} | |
])) | |
} | |
} | |
}, W = function (a) { | |
V(a.params.adUri, a.params.type) | |
}, Y = function () { | |
m === !1 && (o = setInterval(function () { | |
m = !0; | |
t.isPlaying === !0 && t.isAd === !1 && q++ | |
}, 1E3), p = setInterval(function () { | |
I.setItem("streamTimeSinceLastAdBreak", q); | |
d.log("Spotify.Services.AdChooser", ["Stream time: ", q], "corejs") | |
}, 1E4)) | |
}, Z = function () { | |
clearInterval(o); | |
clearInterval(p); | |
m = !1 | |
}, U = function (f) { | |
f = b.getPlayerById(f.params.id); | |
f.bind(k.PLAYING, Y, g); | |
f.bind(k.PAUSED, Z, g); | |
a.push(f) | |
}, | |
Q = function (a) { | |
g.trigger(a.type, a.params) | |
}, X = function (a) { | |
var b = null, | |
f = null, | |
k = null; | |
for (b = 0, f = G.length; b < f; b += 1) | |
if (k = G[b], k.file_id === a) return k; | |
return null | |
}; | |
this.onReady = function (a, b) { | |
this.serviceIsReady ? a.call(b) : this.bind(k.READY, a, b) | |
}; | |
this.recordAdEvent = function (a, b) { | |
V(a, b) | |
}; | |
this.getNextAd = function () { | |
var a = null, | |
b = null; | |
var a = Object.keys(B), | |
f; | |
try { | |
for (var b = 0, k = a.length; b < k; b++)(f = B[a[b]]) && f.expiry_time <= O() + F && (f.event_history = []); | |
I.setItem(_AD_HISTORY_KEY, JSON.stringify(B)) | |
} catch (c) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, | |
Spotify.Errors.Codes.ADS_SERVER_ERROR, "Unable to purge expired ad history", { | |
extra: c | |
} | |
])) | |
} | |
if (q >= x && t.isAd === !1) { | |
d.log("Spotify.Services.AdChooser", ["Injecting ad!"], "corejs"); | |
P(w); | |
f = []; | |
var k = !1, | |
m = b = a = null; | |
S(); | |
for (y(); v > 0 && k === !1;) | |
for (a = 0, b = G.length, k = !0; a < b; a += 1) m = G[a], m.duration < v && (f.push(m), P(m.duration * -1), k = !1); | |
a = f; | |
if (a.length > 0) s.setIntercept(H), b = h.toTrackMetadata(a[0]), H.appendWithMeta("spotify:ad:" + a[0].file_id, b), H.setOwner(b.artists[0].uri), s.intercept(), t.ad = a[0] | |
} else d.log("Spotify.Services.AdChooser", [x - q + " seconds left until ad..."], "corejs") | |
}; | |
this.lookup = function (a, b) { | |
var f = [], | |
k = null, | |
m = null; | |
Spotify.Utils.isArray(a) && a.length === 1 ? (m = Spotify.Link.fromString(a[0]), k = X(m.id), k !== null ? (f.push(h.toTrackMetadata(k)), b(f, 200)) : M(m.id, function (a) { | |
var a = c.parseServerResponse(a.response), | |
k = parseInt(a["@attributes"].version, 10) | 0, | |
a = (0, c["parseAudioAdsVersion" + k])(a); | |
f.push(h.toTrackMetadata(a.AdQueueEntry[0])); | |
b(f, 200) | |
}, function (a) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, | |
a | |
])) | |
})) : K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_NOT_FOUND, "Array does not contain any items!"])) | |
}; | |
this.maybeRetrieveAds = function () { | |
A <= O() && (d.log("Spotify.Services.AdChooser", ["Retrieving ads from server."], "corejs"), L(N, function () { | |
R({ | |
serverError: !0 | |
}) | |
})) | |
}; | |
this.init = function (a, c, m) { | |
f = a; | |
b = c; | |
b.bind(k.PLAYER_CREATED, U, g); | |
b.bind(k.RECORD_AD_EVENT, W, g); | |
b.onReady(function () { | |
t = c.getPlayerAtIndex(0); | |
m.onReady(function () { | |
m.getUserInfo(function (a) { | |
I = new Spotify.Cache.PackageStore({ | |
storageKey: Spotify.Utils.Base64.encode(a.user + | |
"-" + a.catalogue) | |
}); | |
I.getItem("timeBetweenAdBreak") !== null && (x = parseInt(I.getItem("timeBetweenAdBreak"), 10)); | |
I.getItem("defaultAdBreakLength") !== null && (w = parseInt(I.getItem("defaultAdBreakLength"), 10)); | |
I.getItem("timeOfNextAdServerRequest") !== null && (A = parseInt(I.getItem("timeOfNextAdServerRequest"), 10)); | |
I.getItem("streamTimeSinceLastAdBreak") !== null && (q = parseInt(I.getItem("streamTimeSinceLastAdBreak"), 0)); | |
I.getItem("audioQueue") !== null && (G = JSON.parse(I.getItem("audioQueue"))); | |
I.getItem("adHistory") !== | |
null && (B = JSON.parse(I.getItem("adHistory"))); | |
I.getItem("forbiddenAds") !== null && (E = JSON.parse(I.getItem("forbiddenAds"))); | |
S(); | |
g.maybeRetrieveAds(); | |
g.serviceIsReady = !0; | |
g.trigger(k.READY) | |
}, function (a) { | |
K(new Spotify.Errors.Error([Spotify.Errors.Codes.ADS_ERROR, Spotify.Errors.Codes.ADS_SERVER_ERROR, "Exception thrown gathering user info", { | |
extra: a | |
}])) | |
}) | |
}, this) | |
}, this) | |
}; | |
this.initializeContext = function (a, b) { | |
n = a; | |
s = b; | |
s.addEvent(k.INTERCEPTED, Q); | |
H = n.create("spotify:ads"); | |
H.setRule("intercept"); | |
s.addEvents({ | |
beforeContextChange: g.getNextAd, | |
beforeNext: g.getNextAd, | |
beforePrevious: g.getNextAd, | |
ended: function () { | |
t.trackUri.indexOf("spotify:ad:") > -1 && (q = 0) | |
} | |
}) | |
} | |
}; | |
Spotify.Services.Pubsub = function () { | |
var d = this, | |
g = new Spotify.Events, | |
c = {}; | |
this.subscribe = function (h, b, a, f, k, m, g) { | |
function p(a) { | |
k.call(g, a) | |
} | |
typeof h === "undefined" || typeof m === "undefined" || typeof f === "undefined" || typeof k === "undefined" || typeof g === "undefined" ? k.call(g, new Spotify.Errors.Error([0, 16, "Not all argments are provided"])) : (Spotify.Utils.isArray(b) || (b = []), Spotify.Utils.isArray(a) || (a = []), this.serviceIsReady ? this.send(new Spotify.Calls.Hermes({ | |
header: { | |
uri: h, | |
method: "SUB" | |
}, | |
payload: b, | |
payloadSchemas: a, | |
responseSchemas: [], | |
type: "pubsub", | |
persistent: !1, | |
bypassCache: !0 | |
}, function (a) { | |
var b = d.getProtobufMsgParser("pubsub", "Subscription"), | |
k = []; | |
if (a) { | |
for (var h = !1, u = 0; u < a.length; ++u) { | |
var w = b.parseFromStringSync(a[u]); | |
if (w.status_code === 200) h = w.uri, k.push(h), typeof c[h] === "undefined" && (c[h] = []), c[h].push({ | |
callback: m, | |
context: g, | |
uri: h, | |
arguments: [] | |
}), h = !0 | |
} | |
if (!h) { | |
p(); | |
return | |
} | |
} | |
f.call(g, k) | |
}, p)) : k.call(g, new Spotify.Errors.Error([13, 503, "Suggest service not ready!"]))) | |
}; | |
this.onNotify = function (d) { | |
switch (d.type) { | |
case g.HERMES_B64_MESSAGE: | |
var b = | |
Spotify.Hermes.Header.parseFromStringSync(Spotify.Utils.Base64.decode(d.params[2])); | |
if (b) { | |
var a = c[b.uri], | |
f; | |
if (b.status_code === 200) | |
for (var k = 0, m = a.length; k < m; k += 1) f = a[k], f.callback.call(f.context, d.params); | |
else { | |
k = 0; | |
for (m = a.length; k < m; k += 1) f = a[k], f.errorCallback.call(f.context, b) | |
} | |
} | |
} | |
} | |
}; | |
Spotify.Services.Presence = function () { | |
var d = Spotify.DebuggerJS, | |
g = this, | |
c = new Spotify.Events, | |
h = { | |
PLAYLIST_PUBLISHED: { | |
name: "playlist_published", | |
id: 1, | |
decorator: function (a, b) { | |
a.item_uri = b.uri | |
} | |
}, | |
PLAYLIST_TRACK_ADDED: { | |
name: "playlist_track_added", | |
id: 2, | |
decorator: function (a, b) { | |
a.item_uri = b.playlist_uri; | |
a.context_uri = b.track_uri | |
} | |
}, | |
TRACK_FINISHED_PLAYING: { | |
name: "track_finished_playing", | |
id: 3, | |
decorator: function (a, b) { | |
a.item_uri = b.uri; | |
a.context_uri = b.context_uri; | |
a.referrer_uri = b.referrer_uri | |
} | |
}, | |
FAVORITE_APP_ADDED: { | |
name: "favorite_app_added", | |
id: 4, | |
decorator: function (a, b) { | |
a.item_uri = b.app_uri | |
} | |
}, | |
TRACK_STARTED_PLAYING: { | |
name: "track_started_playing", | |
id: 5, | |
decorator: function (a, b) { | |
a.item_uri = b.uri; | |
a.context_uri = b.context_uri; | |
a.referrer_uri = b.referrer_uri | |
} | |
}, | |
URI_SHARED: { | |
name: "uri_shared", | |
id: 6, | |
decorator: function (a, b) { | |
a.item_uri = b.uri; | |
a.message = b.message | |
} | |
}, | |
ARTIST_FOLLOWED: { | |
name: "artist_followed", | |
id: 7, | |
decorator: function (a, b) { | |
a.item_uri = b.uri; | |
a.item_name = b.artist_name; | |
a.item_image = b.artist_cover_uri | |
} | |
}, | |
GENERIC: { | |
name: "generic", | |
id: 11, | |
decorator: function (a, | |
b) { | |
a.type = b.type; | |
a.timestamp = b.timestamp; | |
a.item_uri = b.item_uri; | |
a.item_name = b.item_name; | |
a.item_image = b.item_image; | |
a.context_uri = b.context_uri; | |
a.context_name = b.context_name; | |
a.context_image = b.context_image; | |
a.referrer_uri = b.referrer_uri; | |
a.referrer_name = b.referrer_name; | |
a.referrer_image = b.referrer_image; | |
a.message = b.message; | |
a.device_information = b.device_information | |
} | |
} | |
}, b = function (a) { | |
a.length > 0 && (a = g.getProtobufMsgParser("presence", "State").parseFromStringSync(Spotify.Utils.Base64.decode(a[3])), g.trigger(c.NOTIFICATION, | |
a)) | |
}, a = function (a) { | |
d.log("Spotify.Services.Presence", ["Broadcast success", a], "corejs") | |
}, f = function (a) { | |
d.error("Spotify.Services.Presence", ["Broadcast error", a], "corejs") | |
}, k = function (a) { | |
d.error("Spotify.Services.Presence", ["Statuses error", a], "corejs") | |
}, m = function (b, k) { | |
g.services.user.getUserInfo(function (c) { | |
c = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://presence/user/" + encodeURIComponent(c.user), | |
method: "SET" | |
}, | |
payload: [b], | |
payloadSchemas: ["presence#State"], | |
responseSchemas: [], | |
type: "Presence", | |
bypassCache: !1, | |
persistent: !1 | |
}, k || a, f); | |
g.send(c) | |
}, f) | |
}, o = function (a, b) { | |
var f = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://presence/user/", | |
method: "GET" | |
}, | |
payload: [a], | |
payloadSchemas: [], | |
responseSchemas: ["presence#State"], | |
type: "Presence", | |
bypassCache: !1, | |
persistent: !1 | |
}, function (f, k) { | |
var c = [], | |
m = f[0]; | |
if (!m || typeof m !== "object") b([]); | |
else { | |
for (var d in m) | |
if (m.hasOwnProperty(d)) { | |
var g = m[d], | |
o = h[d.toUpperCase()], | |
n = { | |
timestamp: g.timestamp, | |
type: o.id, | |
username: a | |
}; | |
o.decorator(n, g); | |
n.device_information || c.push(n) | |
} | |
b(c, k) | |
} | |
}, k); | |
g.send(f) | |
}; | |
this.subscribe = function (a, f, k, c) { | |
this.serviceIsReady ? typeof a === "undefined" ? k.call(c, new Spotify.Errors.Error([0, 16, "Not all argments are provided"])) : Spotify.Utils.isArray(a) ? this.services.pubsub.subscribe("hm://presence/user/", a, [], f, k, b, g) : k.call(c, new Spotify.Errors.Error([0, 16, "Users arguments must be an array"])) : k.call(c, new Spotify.Errors.Error([13, 503, "Presence service not ready!"])) | |
}; | |
this.broadcastPlaylistPublished = function (a, b) { | |
var f = { | |
generic: { | |
type: h.PLAYLIST_PUBLISHED.id, | |
item_uri: a, | |
timestamp: (new Date).getTime() / 1E3 | |
} | |
}; | |
m(f, b) | |
}; | |
this.broadcastTrackAdded = function (a, b, f) { | |
a = { | |
generic: { | |
type: h.PLAYLIST_TRACK_ADDED.id, | |
context_uri: a, | |
item_uri: b, | |
timestamp: (new Date).getTime() / 1E3 | |
} | |
}; | |
m(a, f) | |
}; | |
this.broadcastTrackStartedPlaying = function (a, b, f, k) { | |
a = { | |
generic: { | |
type: h.TRACK_STARTED_PLAYING.id, | |
item_uri: a, | |
context_uri: b, | |
referrer_uri: f, | |
timestamp: (new Date).getTime() / 1E3 | |
} | |
}; | |
m(a, k) | |
}; | |
this.broadcastTrackFinishedPlaying = function (a, b, f, k) { | |
a = { | |
generic: { | |
type: h.TRACK_FINISHED_PLAYING.id, | |
item_uri: a, | |
context_uri: b, | |
referrer_uri: f, | |
timestamp: (new Date).getTime() / 1E3 | |
} | |
}; | |
m(a, k) | |
}; | |
this.broadcastFavoriteAppAdded = function (a, b) { | |
var f = { | |
generic: { | |
type: h.FAVORITE_APP_ADDED.id, | |
item_uri: a, | |
timestamp: (new Date).getTime() / 1E3 | |
} | |
}; | |
m(f, b) | |
}; | |
this.broadcastUriShared = function (a, b, f) { | |
a = { | |
generic: { | |
type: h.URI_SHARED.id, | |
item_uri: a, | |
message: b, | |
timestamp: (new Date).getTime() / 1E3 | |
} | |
}; | |
m(a, f) | |
}; | |
this.broadcastArtistFollowed = function (a, b, f, k) { | |
a = { | |
generic: { | |
type: h.ARTIST_FOLLOWED.id, | |
item_uri: a, | |
item_name: b, | |
item_image: f, | |
timestamp: (new Date).getTime() / 1E3 | |
} | |
}; | |
m(a, k) | |
}; | |
this.getStatuses = function (a, b, f) { | |
o(a, | |
b, f) | |
} | |
}; | |
Spotify.Services.SocialGraph = function () { | |
var d = Spotify.DebuggerJS, | |
g = this, | |
c = new Spotify.Events, | |
h = { | |
subscriptions: { | |
add: c.RELATIONS_SUBSCRIBE, | |
remove: c.RELATIONS_UNSUBSCRIBE | |
}, | |
dismissed: { | |
add: c.RELATIONS_DISMISS, | |
remove: c.RELATIONS_UNDISMISS | |
}, | |
blocked: { | |
add: c.RELATIONS_BLOCK, | |
remove: c.RELATIONS_UNBLOCK | |
} | |
}, b = function (a, k) { | |
var k = k || 0, | |
c = function (c) { | |
if (c = c[0].users) { | |
for (var m = 0, d = c.length; m < d; m++) f[a][c[m].username] = m; | |
c.length === 1E3 && (k += c.length, b(a, k)) | |
} | |
}, h = function () { | |
d.error("Spotify.Services.SocialGraph", ["We failed to cache the user's " + | |
a, arguments | |
], "corejs") | |
}; | |
g.services.user.getUserInfo(function (b) { | |
m(a, b.user, 1E3, k, c, h) | |
}, h) | |
}, a = { | |
subscribers: {}, | |
subscriptions: {}, | |
dismissed: {}, | |
blocked: {} | |
}, f = { | |
subscribers: {}, | |
subscriptions: {}, | |
dismissed: {}, | |
blocked: {} | |
}, k = function (b, f) { | |
var k = a[b], | |
c = ""; | |
if (k[f] && k[f].lastResult) c = k[f].lastResult; | |
return c | |
}, m = function (b, f, c, m, d, h, o) { | |
g.services.user.getUserInfo(function (n) { | |
var q = []; | |
if (!f) f = n.user; | |
n = "hm://socialgraph/" + b + "/user/" + encodeURIComponent(f); | |
o && (n += "/relevant"); | |
var p = [{ | |
count: c, | |
include_length: !0 | |
}]; | |
o ? p = [] : (q = ["socialgraph#UserListRequest"], p[0].last_result = m === 0 ? "" : k(b, f)); | |
q = new Spotify.Calls.Hermes({ | |
header: { | |
uri: n, | |
method: "GET" | |
}, | |
payload: p, | |
payloadSchemas: q, | |
responseSchemas: ["socialgraph#UserListReply"], | |
type: "socialgraph" | |
}, function (k, c) { | |
var m = k[0].users; | |
if (m) { | |
var h = f, | |
m = m[m.length - 1].username, | |
g = a[b]; | |
g[h] = g[h] || {}; | |
g[h].lastResult = m | |
} | |
d(k, c) | |
}, h); | |
g.send(q) | |
}, h) | |
}, o = function (a, b, f, k) { | |
g.services.user.getUserInfo(function (c) { | |
b || (b = [c.user]); | |
c = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://socialgraph/" + a + "/count/", | |
method: "GET" | |
}, | |
payload: [{ | |
args: b | |
}], | |
payloadSchemas: ["socialgraph#StringListRequest"], | |
responseSchemas: ["socialgraph#CountReply"], | |
type: "socialgraph" | |
}, f, k); | |
g.send(c) | |
}, k) | |
}, p = function (a, b, k, c, m) { | |
m = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://socialgraph/" + a, | |
method: b ? "DELETE" : "POST" | |
}, | |
payload: [{ | |
args: k | |
}], | |
payloadSchemas: ["socialgraph#StringListRequest"], | |
responseSchemas: ["socialgraph#StringListReply"], | |
type: "socialgraph" | |
}, function (m, d) { | |
c(m, d); | |
var o = h[a]; | |
g.trigger(b ? o.remove : o.add, { | |
users: k | |
}); | |
for (var o = 0, n = k.length; o < | |
n; o++) b ? delete f[a][k[o]] : f[a][k[o]] = o | |
}, m); | |
g.send(m) | |
}, q = function (a) { | |
for (var a = a.params.uris, b = {}, k = 0, c = a.length; k < c; k++) { | |
var m = Spotify.Link.fromString(a[k]).username; | |
m in f.subscriptions || (b[m] = !0) | |
} | |
p("subscriptions", !1, Object.keys(b), function () {}, function () { | |
d.error("Spotify.Services.SocialGraph", ["We failed to subscribe to the following playist owners", b], "corejs") | |
}) | |
}, n = function (a, b, f, k, c) { | |
a = "hm://socialgraph/" + a + "/user/" + encodeURIComponent(b) + "/exists"; | |
f = new Spotify.Calls.Hermes({ | |
header: { | |
uri: a, | |
method: "GET" | |
}, | |
payload: [{ | |
args: f | |
}], | |
payloadSchemas: ["socialgraph#StringListRequest"], | |
responseSchemas: ["socialgraph#StringListReply"], | |
type: "socialgraph" | |
}, k, c); | |
g.send(f) | |
}; | |
this.setup = function () { | |
this.services.playlist.bind(c.PLAYLIST_SUBSCRIBE, q, this) | |
}; | |
this.getSubscribers = function (a, b, f, k, c) { | |
m("subscribers", a, b, f, k, c) | |
}; | |
this.getRelevantSubscribers = function (a, b, f, k, c) { | |
m("subscribers", a, b, f, k, c, !0) | |
}; | |
this.getSubscriptions = function (a, b, f, k, c) { | |
m("subscriptions", a, b, f, k, c) | |
}; | |
this.getRelevantSubscriptions = function (a, b, f, k, c) { | |
m("subscriptions", | |
a, b, f, k, c, !0) | |
}; | |
this.getDismissed = function (a, b, f, k, c) { | |
m("dismissed", a, b, f, k, c) | |
}; | |
this.getBlocked = function (a, b, f, k, c) { | |
m("blocked", a, b, f, k, c) | |
}; | |
this.getSubscribersCount = function (a, b, f) { | |
o("subscribers", a, b, f) | |
}; | |
this.getSubscriptionsCount = function (a, b, f) { | |
o("subscriptions", a, b, f) | |
}; | |
this.subscribeTo = function (a, b, f) { | |
p("subscriptions", !1, a, b, f) | |
}; | |
this.unsubscribeFrom = function (a, b, f) { | |
p("subscriptions", !0, a, b, f) | |
}; | |
this.dismiss = function (a, b, f) { | |
p("dismissed", !1, a, b, f) | |
}; | |
this.undismiss = function (a, b, f) { | |
p("dismissed", !0, | |
a, b, f) | |
}; | |
this.block = function (a, b, f) { | |
p("blocked", !1, a, b, f) | |
}; | |
this.unblock = function (a, b, f) { | |
p("blocked", !0, a, b, f) | |
}; | |
this.isSubscribed = function (a) { | |
for (var b = [], k = 0, c = a.length; k < c; k++) b.push(a[k] in f.subscriptions); | |
return b | |
}; | |
this.hasSubscribers = function (a, b, f, k) { | |
n("subscribers", a, b, f, k) | |
}; | |
this.hasSubscriptions = function (a, b, f, k) { | |
n("subscriptions", a, b, f, k) | |
}; | |
this.hasDismissed = function (a, b, f, k) { | |
n("dismissed", a, b, f, k) | |
}; | |
this.hasBlocked = function (a, b, f, k) { | |
n("blocked", a, b, f, k) | |
}; | |
this.hasHidden = function (a, b, f, k) { | |
n("hidden", | |
a, b, f, k) | |
}; | |
this.preloadCurrentUserRelations = function () { | |
for (var a in f) b(a) | |
} | |
}; | |
Spotify.Services.MergedProfile = function () { | |
var d = this, | |
g = function (c, h, b, a) { | |
d.serviceIsReady ? (c = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://mergedprofile/mergedprofile/" + c + "/" + encodeURIComponent(h), | |
method: "GET" | |
}, | |
payload: [], | |
payloadSchemas: [], | |
responseSchemas: ["mergedprofile#MergedProfileReply"], | |
type: "mergedprofile" | |
}, function (a) { | |
for (var k, c = 0, d = a.length; c < d; c += 1) k = a[c], k.artist = typeof k.artistid !== "undefined" ? "spotify:artist:" + k.artistid : null, k.user = typeof k.username !== "undefined" ? Spotify.Link.profileLink(k.username).toURI() : | |
null, delete k.artistid, delete k.username; | |
b(a, 200) | |
}, a), d.send(c)) : a(new Spotify.Errors.Error([13, 503, "MergedProfile service not ready!"])) | |
}; | |
this.forUser = function (c, d, b) { | |
g("user", c, d, b) | |
}; | |
this.forArtist = function (c, d, b) { | |
g("artist", c, d, b) | |
} | |
}; | |
Spotify.Services.Inbox = function () { | |
this.getInbox = function (d, g, c) { | |
this.serviceIsReady ? this.services.playlist.list({ | |
uri: Spotify.Link.inboxLink(d.username).toURI(), | |
offset: d.offset, | |
total: d.total | |
}, g, c) : c(new Spotify.Errors.Error([13, 503, "Inbox service not ready!"])) | |
}; | |
this.addToInbox = function (d, g, c) { | |
if (this.serviceIsReady) | |
if (typeof d.items === "undefined") c(new Spotify.Errors.Error([13, 503, "You need to provide at least one item to send"])); | |
else if (d.recipient) | |
if (d.sender) { | |
for (var h = 0, b = d.items.length; h < b; h += | |
1) d.items[h].addedBy = d.sender || ""; | |
this.services.playlist.addToPlaylistWithAttributes(Spotify.Link.inboxLink(d.recipient).toURI(), d.items, g, c) | |
} else c(new Spotify.Errors.Error([13, 503, "You need to provide a sender"])); | |
else c(new Spotify.Errors.Error([13, 503, "You need to provide a recipient"])); | |
else c(new Spotify.Errors.Error([13, 503, "Inbox service not ready!"])) | |
}; | |
this.deleteFromInbox = function (d, g, c) { | |
if (typeof d.username === "undefined") c(new Spotify.Errors.Error([13, 503, "You need to provide a username"])); | |
else { | |
var h = d.offset || 0, | |
b = d.total || 1; | |
this.services.playlist.removeFromPlaylist(Spotify.Link.inboxLink(d.username).toURI(), h, b, g, c) | |
} | |
}; | |
this.markAsRead = function (d, g, c) { | |
typeof d.username === "undefined" ? c(new Spotify.Errors.Error([13, 503, "You need to provide a username"])) : typeof d.itemIndex === "undefined" ? c(new Spotify.Errors.Error([13, 503, "You need to provide an index for the item you want to mark as read"])) : this.services.playlist.updateItemAttributes(Spotify.Link.inboxLink(d.username).toURI(), d.itemIndex, { | |
seen: 1 | |
}, g, c) | |
} | |
}; | |
Spotify.InstanceFactory = function (d) { | |
this.createInstance = d.createInstance; | |
this.waitReady = d.waitReady || function (d, c) { | |
if (d.onReady) d.onReady(c.bind(void 0, d)); | |
else c(d) | |
}; | |
this.destroyInstance = d.destroyInstance || function () {} | |
}; | |
Spotify.InstanceFactory.fromService = function (d, g) { | |
return new Spotify.InstanceFactory({ | |
createInstance: function (c) { | |
var h = new d; | |
h.init && h.init.apply(h, (g || []).concat(c || [])); | |
return h | |
}, | |
waitReady: function (c, d) { | |
if (c.onReady) c.onReady(d.bind(void 0, c)); | |
else d(c) | |
}, | |
destroyInstance: function (c) { | |
c.shutdown && c.shutdown() | |
} | |
}) | |
}; | |
Spotify.InstanceFactory.fromFactoryMethod = function (d, g, c) { | |
return new Spotify.InstanceFactory({ | |
createInstance: d, | |
destroyInstance: g, | |
waitReady: c | |
}) | |
}; | |
Spotify.InstanceCache = function (d) { | |
var g = {}, c = d; | |
this.reset = function (d, b) { | |
d && (c = d); | |
if (!b) { | |
for (var a in g) { | |
var f = g[a]; | |
f.factory.destroyInstance(f.instance) | |
} | |
g = {} | |
} | |
}; | |
this.createAwaitReady = function (c, b, a) { | |
var f = b.createInstance(c), | |
c = g[c] = { | |
instance: f, | |
factory: b | |
}; | |
c.factory.waitReady(c.instance, a.bind(void 0, c.instance)) | |
}; | |
this.get = function (d) { | |
var b = g[d]; | |
if (b) return b.instance; | |
else if (c) return b = c.createInstance(d), g[d] = { | |
instance: b, | |
factory: c | |
}, b; | |
else throw "No such key and no default factory specified"; | |
}; | |
this.getAwaitReady = | |
function (d, b, a) { | |
var f = g[d]; | |
if (f) f.factory.waitReady(f.instance, b.bind(void 0, f.instance)); | |
else if (c) this.createAwaitReady(d, c, b, a); | |
else if (a) a("No such key and no default factory specified"); | |
else throw "No such key and no default factory specified"; | |
} | |
}; | |
Spotify.DependencyObject = function () { | |
Spotify.EventTarget.call(this); | |
var d = this, | |
g = new Spotify.Events; | |
this.serviceIsReady = !1; | |
this.onReady = function (c, d) { | |
this.serviceIsReady ? c.call(d) : this.bind(g.READY, c, d) | |
}; | |
this.markReady = function () { | |
d.serviceIsReady = !0; | |
d.trigger(g.READY) | |
}; | |
this.dependsOn = function (c, h) { | |
if (!c || c.length == 0) return d.markReady(); | |
var b = 0, | |
a = function () { | |
b++; | |
b == c.length && (h ? h.length == 0 ? (h(), d.markReady()) : h(function () { | |
d.markReady() | |
}) : d.markReady()) | |
}; | |
c.forEach(function (b) { | |
if (typeof b == "function") b(a); | |
else b.onReady(a) | |
}) | |
} | |
}; | |
Spotify.Services.Collection2Cache = function () { | |
Spotify.DependencyObject.call(this); | |
new Spotify.Events; | |
var d, g, c; | |
this.init = function (h, b, a) { | |
c = a; | |
if (!a) throw "Username must be defined"; | |
g = new Spotify.Protobuf.Schema([], null, null, null); | |
g.id = "collection2cache"; | |
g.type = "proto"; | |
g.setData(h); | |
g.encode(); | |
d = b; | |
this.markReady() | |
}; | |
this.getTracks = function (h, b, a) { | |
(new Spotify.Hermes.ProtobufRequest({ | |
uri: "hm://collection-cache/tracks/" + encodeURIComponent(c) + "?union=" + !! h, | |
method: "GET" | |
}, [], [], [g.msg("CollectionTracks")])).send(d, function (a) { | |
b(a[0].track || []) | |
}, a, !1, !1, "collection2cache") | |
}; | |
this.getAlbums = function (h, b, a) { | |
(new Spotify.Hermes.ProtobufRequest({ | |
uri: "hm://collection-cache/albums/" + encodeURIComponent(c) + "?union=" + !! h, | |
method: "GET" | |
}, [], [], [g.msg("CollectionAlbums")])).send(d, function (a) { | |
b(a[0].album || []) | |
}, a, !1, !1, "collection2cache") | |
}; | |
this.getArtists = function (h, b, a) { | |
(new Spotify.Hermes.ProtobufRequest({ | |
uri: "hm://collection-cache/artists/" + encodeURIComponent(c) + "?union=" + !! h, | |
method: "GET" | |
}, [], [], [g.msg("CollectionArtists")])).send(d, function (a) { | |
b(a[0].artist || []) | |
}, a, !1, !1, "collection2cache") | |
} | |
}; | |
Spotify.Services.CollectionStorageImplementation.Backend = function () { | |
Spotify.DependencyObject.call(this); | |
var d = this, | |
g = new Spotify.Events, | |
c, h, b, a, f = Spotify.DebuggerJS, | |
k = function (a) { | |
return a.map(function (a) { | |
a.type == "TRACK" ? a.uri = Spotify.Link.fromByteString(Spotify.Link.Type.TRACK, a.identifier).toURI() : a.type == "ALBUM" ? a.uri = Spotify.Link.fromByteString(Spotify.Link.Type.ALBUM, a.identifier).toURI() : (f.error("Spotify.Services.CollectionStorageImplementation.Backend", ["Not supported type: ", a.type], "corejs"), | |
a = void 0); | |
return a | |
}).filter(function (a) { | |
return a | |
}) | |
}, m = function (a) { | |
a.length > 0 && (a = b.msg("CollectionItems").parseFromStringSync(Spotify.Utils.Base64.decode(a[3])), a.item && (a = k(a.item), d.trigger(g.CHANGED, { | |
items: a | |
}))) | |
}, o = function (b) { | |
c.subscribe("hm://collection/collection/" + encodeURIComponent(a), [], [], b, function () {}, m, d) | |
}; | |
this.init = function (f, k, m, d) { | |
c = f; | |
a = d; | |
if (!d) throw "Username must be defined"; | |
b = new Spotify.Protobuf.Schema([], null, null, null); | |
b.id = "collection2"; | |
b.type = "proto"; | |
b.setData(k); | |
b.encode(); | |
h = m; | |
h.bind(g.CONNECTED, function () { | |
o(function () {}) | |
}, this); | |
this.dependsOn([f], o) | |
}; | |
this.get = function (f, c) { | |
(new Spotify.Hermes.ProtobufRequest({ | |
uri: "hm://collection/collection/" + encodeURIComponent(a) + "?sort=descending", | |
method: "GET", | |
content_type: "vnd.spotify/collection-items" | |
}, [], [], [b.msg("CollectionItems")])).send(h, function (a) { | |
a = a[0].item || []; | |
a = k(a); | |
f(a) | |
}, c, !1, !1, "collection") | |
}; | |
this.change = function (f, k, c) { | |
f.forEach(function (a) { | |
a.type = "TRACK"; | |
a.identifier = Spotify.Link.fromString(a.uri).idToByteString() | |
}); | |
(new Spotify.Hermes.ProtobufRequest({ | |
uri: "hm://collection/collection/" + encodeURIComponent(a), | |
method: "PATCH", | |
content_type: "vnd.spotify/collection-items" | |
}, [{ | |
item: f | |
}], [b.msg("CollectionItems")], [])).send(h, function (a) { | |
k(a) | |
}, c, !0, !1, "collection") | |
} | |
}; | |
Spotify.Services.CollectionStorageImplementation.Mock = function () { | |
Spotify.DependencyObject.call(this); | |
var d = this, | |
g = {}; | |
[{ | |
uri: "spotify:track:7pYInkuxFsh625wA82Uf8W", | |
name: "Away From The Sun - 17 Days Acoustic Version" | |
}, { | |
uri: "spotify:track:7i6x7pxU92f9Lazp4Y1dbZ", | |
name: "Warsaw Or The First Breath You Take After You Give Up" | |
}, { | |
uri: "spotify:track:7e5B4aloHuniGxtxSV83g0", | |
name: "Vem" | |
}, { | |
uri: "spotify:track:7bTiNxyu4FlHwBes8eG8sE", | |
name: "Jag tror p?? dig" | |
}, { | |
uri: "spotify:track:7KonowmHhdoW6gn0ZNvgOn", | |
name: "Spinning In Daffodils" | |
}, { | |
uri: "spotify:track:7E680BITbk5khHVIE0DrIV", | |
name: "Sober - Bimbo Jones Radio Edit" | |
}, { | |
uri: "spotify:track:7980zwuuUReCHIjSVcItPy", | |
name: "Big Pimpin' - Live" | |
}, { | |
uri: "spotify:track:6pi0NzmQkouL2R5EDIV7YH", | |
name: "Bonito" | |
}, { | |
uri: "spotify:track:6kmewkv1yTxyUD963qiEbQ", | |
name: "Linger" | |
}, { | |
uri: "spotify:track:6ZqvAJ2SBUqscWtqjZr0EA", | |
name: "Criminal Intent" | |
}, { | |
uri: "spotify:track:6T1Xc4BNJO7bkgiEyH7vCm", | |
name: "For an Angel - Radio Mix '09" | |
}, { | |
uri: "spotify:track:65lMlV6eqqFQ9Eskj0f9Me", | |
name: "Caligulove" | |
}, { | |
uri: "spotify:track:62duQFVb51gug9ajR6Qdiz", | |
name: "Gangsta Rap Made Me Do It" | |
}, { | |
uri: "spotify:track:5qXxGJlfiAh0aKCRYHL2V0", | |
name: "Up Where We Belong" | |
}, { | |
uri: "spotify:track:5hIjE1vig7y1rb2LRLgRfp", | |
name: "The Crying Light" | |
}, { | |
uri: "spotify:track:5TTiXxO7SPIYHulRCSyYzR", | |
name: "Harder Now That It's Over" | |
}, { | |
uri: "spotify:track:5NaV3m1KmpygBsCUkaVIK0", | |
name: "How To Save A Life (made famous by The Fray)" | |
}, { | |
uri: "spotify:track:4ni0Vt7dQev9fS1O97a7jw", | |
name: "Wonderful Tonight" | |
}, { | |
uri: "spotify:track:4ibFD6UnSsExXMV0Ptycsq", | |
name: "Smells Like Teen Spirit (made famous by Nirvana)" | |
}, { | |
uri: "spotify:track:4dhAjyKOEc5YPIk6tTY3Q8", | |
name: "Interlude With Ludes" | |
}, { | |
uri: "spotify:track:4VBmMhjrJ1Bu7ebnl0Gbmj", | |
name: "The Lovers Are Losing" | |
}, { | |
uri: "spotify:track:48s2DVrUoICD8B37y6H06g", | |
name: "Show Me What You Got - Album Version (Edited)" | |
}, { | |
uri: "spotify:track:3f5BGbxhywHIV7gVrqtVqI", | |
name: "Sail Away (made famous by Enya)" | |
}, { | |
uri: "spotify:track:3NT4deyIUzzqL63rNHgYNM", | |
name: "Foolish - Mainstream Edit" | |
}, { | |
uri: "spotify:track:3I8dxmjvDQNyiWXMcScsCv", | |
name: "Secret Smile - Album Edit" | |
}, { | |
uri: "spotify:track:3DjPNEk6Yd5xhXs6RGNKNs", | |
name: "No Diggity" | |
}, { | |
uri: "spotify:track:2udjspYLl1PvGV7gERAuxg", | |
name: "That Ole Devil Called Love - Single Version" | |
}, { | |
uri: "spotify:track:2l5k6k0XYdjtZslUibsPeA", | |
name: "Show Me Heaven" | |
}, { | |
uri: "spotify:track:2aRnHc1Q8ydUOSEYo68ztS", | |
name: "Hot N Cold (Manhattan Clique Remix Radio Edit)" | |
}, { | |
uri: "spotify:track:2DemiHqRL0bAa0e3JEnaW8", | |
name: "Congratulations - Revisited" | |
}, { | |
uri: "spotify:track:18HLZDh4NyDHcAn7gwZrb2", | |
name: "Black Girls (feat. Travis Barker)" | |
}, { | |
uri: "spotify:track:15Cl88mjOLGp3uM2Opm5iT", | |
name: "On The Wings Of Love" | |
}, { | |
uri: "spotify:track:0oHKGL4obpVZlFxZb5AeKW", | |
name: "Include Me Out" | |
}, { | |
uri: "spotify:track:7oSwuLOwlCMqTQi30ME0zR", | |
name: "Unchained Melody" | |
}, { | |
uri: "spotify:track:7nNTYx6f54SUPX2GaTUcf7", | |
name: "5th Avenue Bar" | |
}].forEach(function (c) { | |
g[c.uri] = { | |
uri: c.uri, | |
starred: !1, | |
unheard: !0, | |
added_at: Math.floor(Date.now() / 1E3), | |
starred_at: Math.floor(Date.now() / 1E3) | |
} | |
}); | |
var c = new Spotify.Events; | |
this.init = function () { | |
this.markReady() | |
}; | |
this.get = function (c) { | |
var b = [], | |
a; | |
for (a in g) b.push(g[a]); | |
c(b) | |
}; | |
this.change = function (h, b) { | |
h.forEach(function (a) { | |
if (a.removed) delete g[a.uri]; | |
else { | |
if (a.added_at === void 0) a.added_at = Math.floor(Date.now() / 1E3); | |
g[a.uri] = a | |
} | |
}); | |
b(); | |
d.trigger(c.CHANGED, { | |
items: h | |
}) | |
} | |
}; | |
Spotify.Services.CollectionStorageImplementation.CacheAttributes = function () { | |
Spotify.DependencyObject.call(this); | |
var d = this, | |
g = {}, c = new Spotify.Events, | |
h = function (a) { | |
var b = [], | |
m = !1; | |
a.forEach(function (a) { | |
var f = g[a.uri]; | |
b.push(f); | |
if (a.removed) delete g[a.uri], f && (m = !0); | |
else if (g[a.uri] = a, !f || a.unheard != f.unheard) m = !0 | |
}); | |
m && d.trigger(c.CHANGED, { | |
items: a, | |
oldItems: b | |
}) | |
}, b, a = function (a) { | |
h(a.params.items) | |
}; | |
this.init = function (f) { | |
b = f; | |
b.bind(c.CHANGED, a); | |
this.dependsOn([b], function (a) { | |
b.get(function (b) { | |
b.forEach(function (a) { | |
g[a.uri] = | |
a | |
}); | |
a() | |
}, function () { | |
a() | |
}) | |
}) | |
}; | |
this.get = function (a) { | |
var b = [], | |
c; | |
for (c in g) b.push(JSON.parse(JSON.stringify(g[c]))); | |
a(b) | |
}; | |
this.change = function (a, k, c) { | |
a = a.map(function (a) { | |
var b = g[a.uri]; | |
if (b) { | |
if (a.unheard === void 0) a.unheard = b.unheard; | |
a.added_at = b.added_at | |
} else { | |
if (a.unheard === void 0) a.unheard = !0; | |
if (a.removed === void 0) a.removed = !1; | |
a.added_at = Math.floor(Date.now() / 1E3) | |
} | |
return a | |
}); | |
h(a); | |
b.change(a, function () {}, c); | |
k() | |
} | |
}; | |
Spotify.Services.CollectionStorage = function (d, g) { | |
Spotify.DependencyObject.call(this); | |
var c = d || {}; | |
c.implementation = c.implementation || "backend"; | |
var h = {}, b; | |
this.config = function (a) { | |
c = a; | |
b.reset(h[c.implementation]) | |
}; | |
this.init = function (a, f) { | |
h.mock = new Spotify.InstanceFactory({ | |
createInstance: function () { | |
var a = new Spotify.Services.CollectionStorageImplementation.Mock; | |
a.init(); | |
var b = new Spotify.Services.CollectionStorageImplementation.CacheAttributes; | |
b.init(a); | |
return b | |
} | |
}); | |
h.backend = new Spotify.InstanceFactory({ | |
createInstance: function (b) { | |
var c = | |
new Spotify.Services.CollectionStorageImplementation.Backend; | |
c.init(f, g, a, b); | |
b = new Spotify.Services.CollectionStorageImplementation.CacheAttributes; | |
b.init(c); | |
return b | |
} | |
}); | |
b = new Spotify.InstanceCache; | |
this.config(c); | |
this.markReady() | |
}; | |
this.getInstance = function (a, f, k) { | |
b.getAwaitReady(a, function (a) { | |
f(a) | |
}, k) | |
} | |
}; | |
Spotify.Services.CollectionViewImplementation.CollectionViewForUser = function () { | |
Spotify.DependencyObject.call(this); | |
var d = this, | |
g; | |
this.init = function (a, f, k, c, d, n, s) { | |
g = n; | |
q = new Spotify.Services.Collection2Cache; | |
q.init(c, d, n); | |
m = a; | |
o = k; | |
this.dependsOn([q, a, f, k], function (a) { | |
k.bind(h.CHANGE, A); | |
f.getInstance(n, function (f) { | |
p = f; | |
p.bind(h.CHANGED, x); | |
K(s, a, function () { | |
b.error("Spotify.Services.CollectionViewImplementation.CollectionViewForUser", ["Load data failed"], "corejs") | |
}) | |
}) | |
}) | |
}; | |
this.artistsSnapshot = function (a, | |
b, f, k) { | |
B("artists", a, b, f, k) | |
}; | |
this.albumsSnapshot = function (a, b, f, k) { | |
B("albums", a, b, f, k) | |
}; | |
this.tracksSnapshot = function (a, b, f, k) { | |
B("tracks", a, b, f, k) | |
}; | |
var c = function (b, f, k) { | |
var c = []; | |
f.forEach(function (f) { | |
c.push( !! a[b][f]) | |
}); | |
k(c) | |
}; | |
this.tracksContains = function (a, b, f) { | |
c("tracks", a, b, f) | |
}; | |
this.albumsContains = function (a, b, f) { | |
c("albums", a, b, f) | |
}; | |
this.tracksAdd = function (a, b, f) { | |
s(a, function (k) { | |
var c = [], | |
m = []; | |
a.forEach(function (a) { | |
c.push({ | |
uri: a, | |
sources: { | |
collection: !0, | |
playlists: {} | |
} | |
}); | |
m.push({ | |
uri: a | |
}) | |
}); | |
w(c, k); | |
p.change(m, | |
b, f) | |
}, f) | |
}; | |
this.albumsAdd = function (a, b, f) { | |
m.lookup(a, function (a) { | |
var k = {}; | |
a.forEach(function (a) { | |
a && a.disc.forEach(function (a) { | |
a.track.forEach(function (a) { | |
a = Spotify.Link.trackLink(a.id).toURI(); | |
k[a] = a | |
}) | |
}) | |
}); | |
k = Object.keys(k); | |
d.tracksAdd(k, b, f) | |
}, f) | |
}; | |
this.tracksRemove = function (b, f, k) { | |
s(b, function (c) { | |
var m = [], | |
d = [], | |
h = []; | |
b.forEach(function (b) { | |
var f = a.tracks[b]; | |
h.push({ | |
uri: b, | |
sources: f.sources | |
}); | |
f.sources.collection && d.push({ | |
uri: b, | |
removed: !0 | |
}); | |
for (var k in f.sources.playlists) m.push(o.removeFromPlaylistByUri.bind(o, | |
k, [b])) | |
}); | |
v(h, c); | |
d.length > 0 && m.push(p.change.bind(p, d)); | |
F(m, f, k) | |
}, k) | |
}; | |
this.albumsRemove = function (b, f, k) { | |
m.lookup(b, function (b) { | |
var c = {}; | |
b.forEach(function (b) { | |
b && b.disc.forEach(function (b) { | |
b.track.forEach(function (b) { | |
b = Spotify.Link.trackLink(b.id).toURI(); | |
a.tracks[b] && (c[b] = b) | |
}) | |
}) | |
}); | |
c = Object.keys(c); | |
d.tracksRemove(c, f, k) | |
}, k) | |
}; | |
this.tracksClear = function (b, f) { | |
var c = a; | |
a = { | |
tracks: {}, | |
albums: {}, | |
artists: {} | |
}; | |
k = {}; | |
p.get(function (a) { | |
a = a.map(function (a) { | |
return { | |
uri: a.uri, | |
removed: !0 | |
} | |
}); | |
a.length == 0 ? b() : p.change(a, | |
b, f); | |
a = { | |
source: "all", | |
removed: { | |
artists: { | |
uris: Object.keys(c.artists), | |
indices: Object.keys(c.artists).map(function (a, b) { | |
return b | |
}) | |
}, | |
albums: { | |
uris: Object.keys(c.albums), | |
indices: Object.keys(c.albums).map(function (a, b) { | |
return b | |
}) | |
}, | |
tracks: { | |
uris: Object.keys(c.tracks), | |
indices: Object.keys(c.tracks).map(function (a, b) { | |
return b | |
}) | |
} | |
} | |
}; | |
d.trigger(h.CHANGED, a) | |
}, f) | |
}; | |
this.getSources = function (b, f, k) { | |
var c = Spotify.Link.fromString(b); | |
c.type === Spotify.Link.Type.ALBUM ? m.lookup(b, function (b) { | |
var k = { | |
collection: !1, | |
playlists: {} | |
}; | |
b.disc.forEach(function (b) { | |
b.track.forEach(function (b) { | |
b = Spotify.Link.trackLink(b.id).toURI(); | |
if (b = a.tracks[b]) { | |
if (b.sources.collection) k.collection = !0; | |
if (b.sources.playlists) | |
for (var f in b.sources.playlists) k.playlists[f] = (k.playlists[f] || 0) + b.sources.playlists[f] | |
} | |
}) | |
}); | |
f(k) | |
}, k) : c.type === Spotify.Link.Type.TRACK ? (b = a.tracks[b]) ? f(b.sources) : f({ | |
collection: !1, | |
playlists: {} | |
}) : k("Unsupported type: " + c.type) | |
}; | |
var h = new Spotify.Events, | |
b = Spotify.DebuggerJS, | |
a = { | |
tracks: {}, | |
albums: {}, | |
artists: {} | |
}, f = {}, k = {}, m, o, | |
p, q, n = { | |
tracks: function (a) { | |
var b = [], | |
f; | |
for (f in a) b.push(a[f]); | |
return b.sort(function (a, b) { | |
var f = (b.added_at || 0) - (a.added_at || 0); | |
return f === 0 ? a.uri > b.uri ? 1 : -1 : f > 0 ? 1 : -1 | |
}).map(function (a) { | |
return a.uri | |
}) | |
}, | |
albums: function (a) { | |
var b = [], | |
f; | |
for (f in a) b.push(a[f]); | |
return b.sort(function (a, b) { | |
return a.artistNames[0] == b.artistNames[0] && a.name === b.name ? a.uri > b.uri ? 1 : -1 : a.artistNames[0] == b.artistNames[0] ? a.name > b.name ? 1 : -1 : a.artistNames[0] > b.artistNames[0] ? 1 : -1 | |
}).map(function (a) { | |
return a.uri | |
}) | |
}, | |
artists: function (a) { | |
var b = [], | |
f; | |
for (f in a) b.push(a[f]); | |
return b.sort(function (a, b) { | |
return a.name === b.name ? a.uri > b.uri : a.name > b.name ? 1 : -1 | |
}).map(function (a) { | |
return a.uri | |
}) | |
} | |
}, s = function (a, b, f) { | |
m.lookup(a, function (a) { | |
var f = {}; | |
a.forEach(function (a) { | |
f[Spotify.Link.trackLink(a.id).toURI()] = a | |
}); | |
b(f) | |
}, f) | |
}, t = function (a, b) { | |
return b.map(function (b) { | |
return a.indexOf(b) | |
}) | |
}, u = function (a, b) { | |
var f = { | |
uris: [], | |
indices: [] | |
}; | |
t(G(a), b).map(function (a, f) { | |
return { | |
index: a, | |
uri: b[f] | |
} | |
}).sort(function (a, b) { | |
return a.index - b.index | |
}).map(function (a, b) { | |
f.uris.push(a.uri); | |
f.indices.push(a.index - b) | |
}); | |
return f | |
}, w = function (b, f) { | |
k = {}; | |
var c = []; | |
b.forEach(function (b) { | |
var k = a.tracks[b.uri]; | |
if (k) { | |
if (b.sources.collection === !0) k.sources.collection = !0; | |
for (var m in b.sources.playlists) k.sources.playlists[m] = (k.sources.playlists[m] || 0) + b.sources.playlists[m] | |
} else a.tracks[b.uri] = k = { | |
uri: b.uri, | |
added_at: Math.floor(Date.now() / 1E3), | |
name: f[b.uri].name, | |
sources: { | |
collection: b.sources.collection, | |
playlists: b.sources.playlists || {} | |
} | |
}, c.push(k.uri) | |
}); | |
if (c.length > 0) { | |
var m = [], | |
g = []; | |
c.forEach(function (b) { | |
var b = | |
f[b], | |
k = Spotify.Link.albumLink(b.album.id).toURI(), | |
c = a.albums[k]; | |
c || (c = { | |
uri: k, | |
name: b.album.name, | |
artistNames: b.album.artist ? b.album.artist.map(function (a) { | |
return a.name | |
}) : [], | |
count: 0 | |
}, a.albums[k] = c, m.push(k)); | |
c.count++; | |
k = Spotify.Link.artistLink(b.artist[0].id).toURI(); | |
c = a.artists[k]; | |
c || (c = { | |
uri: k, | |
name: b.artist[0].name, | |
count: 0 | |
}, a.artists[k] = c, g.push(k)); | |
c.count++ | |
}); | |
var o = { | |
source: "all", | |
inserted: { | |
artists: u("artists", g), | |
albums: u("albums", m), | |
tracks: u("tracks", c) | |
} | |
}; | |
d.trigger(h.CHANGED, o) | |
} | |
}, v = function (b, f) { | |
var c = | |
k; | |
k = {}; | |
var m = []; | |
b.forEach(function (b) { | |
var f = a.tracks[b.uri]; | |
if (f) { | |
if (b.sources.collection === !0) f.sources.collection = !1; | |
for (var k in b.sources.playlists) f.sources.playlists[k] -= b.sources.playlists[k] || 0, f.sources.playlists[k] === 0 && delete f.sources.playlists[k]; | |
!f.sources.collection && Object.keys(f.sources.playlists).length === 0 && (delete a.tracks[f.uri], m.push(f.uri)) | |
} | |
}); | |
if (m.length > 0) { | |
var g = [], | |
o = []; | |
m.forEach(function (b) { | |
var b = f[b], | |
k = Spotify.Link.albumLink(b.album.id).toURI(), | |
c = a.albums[k]; | |
c && (c.count--, | |
c.count <= 0 && (delete a.albums[k], g.push(k))); | |
b = Spotify.Link.artistLink(b.artist[0].id).toURI(); | |
if (k = a.artists[b]) k.count--, k.count <= 0 && (delete a.artists[b], o.push(b)) | |
}); | |
c = { | |
source: "all", | |
removed: { | |
artists: { | |
uris: o, | |
indices: t(c.artists || [], o) | |
}, | |
albums: { | |
uris: g, | |
indices: t(c.albums || [], g) | |
}, | |
tracks: { | |
uris: m, | |
indices: t(c.tracks || [], m) | |
} | |
} | |
}; | |
d.trigger(h.CHANGED, c) | |
} | |
}, A = function (a) { | |
var k = f[a.params.uri] || a.params.localRevision; | |
f[a.params.uri] = a.params.revision; | |
o.getChangesBetweenRevisionAndHead(a.params.uri, k, function (k) { | |
var c = | |
k.operations; | |
if (c) f[a.params.uri] = k.revision, c.forEach(function (f) { | |
var k = []; | |
if (f.kind == "ADD") { | |
var c = []; | |
f.add.items.forEach(function (b) { | |
if (Spotify.Link.fromString(b.uri).type == Spotify.Link.Type.TRACK) { | |
var f = { | |
uri: b.uri, | |
sources: { | |
collection: !1, | |
playlists: {} | |
} | |
}; | |
f.sources.playlists[a.params.uri] = 1; | |
c.push(f); | |
k.push(b.uri) | |
} | |
}); | |
s(k, function (a) { | |
w(c, a) | |
}, function () { | |
b.error("Spotify.Services.CollectionViewImplementation.CollectionViewForUser", ["Playlist changed: Can't load metadata"], "corejs") | |
}) | |
} else if (f.kind == | |
"REM") { | |
var m = []; | |
f.rem.items.forEach(function (b) { | |
if (Spotify.Link.fromString(b.uri).type == Spotify.Link.Type.TRACK) { | |
var f = { | |
uri: b.uri, | |
sources: { | |
playlists: {} | |
} | |
}; | |
f.sources.playlists[a.params.uri] = 1; | |
m.push(f); | |
k.push(b.uri) | |
} | |
}); | |
s(k, function (a) { | |
v(m, a) | |
}, function () { | |
b.error("Spotify.Services.CollectionViewImplementation.CollectionViewForUser", ["Playlist changed: Can't load metadata"], "corejs") | |
}) | |
} | |
}) | |
}, function () { | |
b.error("Spotify.Services.CollectionViewImplementation.CollectionViewForUser", ["Playlist changed: Can't get changes"], | |
"corejs") | |
}) | |
}, x = function (a) { | |
var f = [], | |
k = []; | |
a.params.items.forEach(function (b, c) { | |
b.type == "TRACK" && (b.removed ? k.push(b.uri) : a.params.oldItems[c] === void 0 && f.push(b.uri)) | |
}); | |
if (f.length > 0) { | |
var c = f.map(function (a) { | |
return { | |
uri: a, | |
sources: { | |
collection: !0, | |
playlists: {} | |
} | |
} | |
}); | |
s(f, function (a) { | |
w(c, a) | |
}, function () { | |
b.error("Spotify.Services.CollectionViewImplementation.CollectionViewForUser", ["Collection changed: Can't load metadata"], "corejs") | |
}) | |
} | |
if (k.length > 0) { | |
var m = k.map(function (a) { | |
return { | |
uri: a, | |
sources: { | |
collection: !0, | |
playlists: {} | |
} | |
} | |
}); | |
s(k, function (a) { | |
v(m, a) | |
}, function () { | |
b.error("Spotify.Services.CollectionViewImplementation.CollectionViewForUser", ["Collection changed: Can't load metadata"], "corejs") | |
}) | |
} | |
}, F = function (a, b, f) { | |
var k = 0, | |
c = Array(a.length); | |
a.forEach(function (m, d) { | |
m(function (f) { | |
c[d] = f; | |
k++; | |
k == a.length && b(c) | |
}, function () { | |
f() | |
}) | |
}) | |
}, G = function (b) { | |
k[b] || (k[b] = n[b](a[b])); | |
return k[b] | |
}, B = function (a, b, f, k) { | |
a = G(a); | |
b = b >= 0 && f >= 0 ? a.slice(b, b + f) : b >= 0 ? a.slice(b) : a; | |
k(b, a.length) | |
}, E = function (a, b, f) { | |
q.getTracks(a, function (a) { | |
var f = {}, k = {}; | |
a.forEach(function (a) { | |
var b = {}; | |
b.uri = Spotify.Link.fromByteString(Spotify.Link.Type.TRACK, a.identifier).toURI(); | |
b.added_at = a.added_at; | |
b.name = a.name; | |
b.sources = { | |
collection: a.in_collection === void 0 ? !0 : a.in_collection, | |
playlists: {} | |
}; | |
a.playlists && a.playlists.forEach(function (a) { | |
var f = Spotify.Link.fromByteString(Spotify.Link.Type.PLAYLIST, a.identifier, { | |
username: g | |
}).toURI(); | |
b.sources.playlists[f] = a.count || 1; | |
k[f] = a.revision | |
}); | |
f[b.uri] = b | |
}); | |
b(f, k) | |
}, f) | |
}, H = function (a, b, f) { | |
q.getAlbums(a, function (a) { | |
var f = {}; | |
a.forEach(function (a) { | |
var b = {}; | |
b.uri = Spotify.Link.fromByteString(Spotify.Link.Type.ALBUM, a.identifier).toURI(); | |
b.count = a.track_count; | |
b.artistNames = a.artist_names; | |
b.name = a.name; | |
f[b.uri] = b | |
}); | |
b(f) | |
}, f) | |
}, I = function (a, b, f) { | |
q.getArtists(a, function (a) { | |
var f = {}; | |
a.forEach(function (a) { | |
var b = {}; | |
b.uri = Spotify.Link.fromByteString(Spotify.Link.Type.ARTIST, a.identifier).toURI(); | |
b.count = a.track_count; | |
b.name = a.name; | |
f[b.uri] = b | |
}); | |
b(f) | |
}, f) | |
}, K = function (b, k, c) { | |
F([ | |
function (k) { | |
E(b, function (b, c) { | |
a.tracks = b; | |
f = c; | |
k() | |
}, c) | |
}, | |
function (f) { | |
H(b, function (b) { | |
a.albums = b; | |
f() | |
}, c) | |
}, | |
function (f) { | |
I(b, function (b) { | |
a.artists = b; | |
f() | |
}, c) | |
} | |
], k, c) | |
} | |
}; | |
Spotify.Services.CollectionView = function (d) { | |
Spotify.DependencyObject.call(this); | |
var g = d || {}; | |
if (g.union === void 0) g.union = !0; | |
var c, h, b, a, f; | |
this.config = function (b) { | |
g = b; | |
f.reset(a) | |
}; | |
this.init = function (k, m, d, p, q, n) { | |
c = k; | |
h = m; | |
b = d; | |
a = Spotify.InstanceFactory.fromFactoryMethod(function (a) { | |
var b = new Spotify.Services.CollectionViewImplementation.CollectionViewForUser; | |
b.init(m, k, d, n, q, a, g.union); | |
return b | |
}); | |
f = new Spotify.InstanceCache; | |
this.config(g); | |
this.dependsOn([c, h, b, p], function (a) { | |
p.getUserInfo(function (b) { | |
f.getAwaitReady(b.user, | |
function () {}, function () { | |
throw arguments; | |
}); | |
a() | |
}) | |
}) | |
}; | |
this.getInstance = function (a, b, c) { | |
f.getAwaitReady(a, function (a) { | |
b(a) | |
}, c) | |
} | |
}; | |
Spotify.Services.CollectionUnplayed = function () { | |
Spotify.DependencyObject.call(this); | |
var d = this, | |
g, c, h = {}, b, a, f, k, m = new Spotify.Events, | |
o = function () { | |
var a = k.getState().track.uri, | |
b; | |
b = a ? Spotify.Link.fromString(a).type == Spotify.Link.Type.TRACK ? !0 : !1 : !1; | |
if (b) d.onReady(function () { | |
g.get(function (b) { | |
for (var f, k = 0, c = b.length; k < c; k++) | |
if (b[k].uri === a) { | |
f = b[k]; | |
break | |
} | |
f ? f.unheard !== !1 && g.change([{ | |
uri: a, | |
unheard: !1 | |
}], function () {}) : h[a] = !0 | |
}) | |
}) | |
}, p = function (b) { | |
g.get(function (k) { | |
a = k; | |
f = {}; | |
for (k = 0; k < a.length; k++) f[a[k].uri] = | |
a[k].unheard; | |
b() | |
}) | |
}, q = function (a) { | |
var b = a.params.oldItems, | |
f = [], | |
k = !1, | |
c = { | |
inserted: [], | |
removed: [] | |
}; | |
a.params.items.forEach(function (a, m) { | |
var d = !b[m], | |
g = d || a.unheard != b[m].unheard; | |
if (a.unheard && h[a.uri]) a.unheard = !1, delete h[a.uri], f.push({ | |
uri: a.uri, | |
unheard: !1 | |
}); | |
else if (d || g) k = !0, d ? c.inserted.push(a.uri) : g && c[a.unheard ? "inserted" : "removed"].push(a.uri) | |
}); | |
f.length > 0 && g.change(f, function () {}); | |
k && p(function () { | |
d.trigger(m.CHANGED, { | |
insertedItems: c.inserted, | |
removedItems: c.removed | |
}) | |
}) | |
}; | |
this.init = function (a, f) { | |
c = | |
f; | |
this.dependsOn([a, c], function (f) { | |
c.getUserInfo(function (k) { | |
b = k.user; | |
a.getInstance(b, function (a) { | |
g = a; | |
a.bind(m.CHANGED, q); | |
p(f) | |
}) | |
}) | |
}) | |
}; | |
this.initializeContext = function (a) { | |
k = a; | |
k.addEvent("play", o) | |
}; | |
this.isUnplayed = function (a, k, c) { | |
if (a != b) throw Error("Only supported for current user"); | |
var m = []; | |
k.forEach(function (a) { | |
m.push(f[a]) | |
}); | |
c(m) | |
} | |
}; | |
Spotify.Services.Facebook = function () { | |
function d(b) { | |
return function (a) { | |
a = h.parseCredential(a); | |
b(a) | |
} | |
} | |
var g = this, | |
c = Spotify.DebuggerJS, | |
h = new Spotify.Parsers.Facebook; | |
this.enable = function (b, a, f) { | |
this.services.user.getUserInfo(function (k) { | |
k = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook/user/" + encodeURIComponent(k.user), | |
method: "CREATE" | |
}, | |
payload: [h.makeCredential(null, b)], | |
payloadSchemas: ["facebook#EnableRequest"], | |
responseSchemas: ["facebook#EnableReply"], | |
type: "facebook", | |
bypassCache: !0, | |
persistent: !1 | |
}, | |
d(a), f); | |
g._sendRetry(k) | |
}, f) | |
}; | |
this.disable = function (b, a, f, k) { | |
this.services.user.getUserInfo(function (c) { | |
c = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook/user/" + encodeURIComponent(c.user), | |
method: "DELETE" | |
}, | |
payload: [h.makeCredential(b, a)], | |
payloadSchemas: ["facebook#DisableRequest"], | |
responseSchemas: [], | |
type: "facebook", | |
bypassCache: !0, | |
persistent: !1 | |
}, f, k); | |
g._sendRetry(c) | |
}, k) | |
}; | |
this.getState = function (b, a, f, k) { | |
this.services.user.getUserInfo(function (c) { | |
c = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook/user/" + encodeURIComponent(c.user), | |
method: "GET" | |
}, | |
payload: [h.makeCredential(b, a)], | |
payloadSchemas: ["facebook#UserState"], | |
responseSchemas: ["facebook#UserState"], | |
type: "facebook", | |
bypassCache: !0, | |
persistent: !1 | |
}, d(f), k); | |
g._sendRetry(c) | |
}, k) | |
}; | |
this.updateState = function (b, a, f, k) { | |
this.services.user.getUserInfo(function (c) { | |
c = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook/user/" + encodeURIComponent(c.user), | |
method: "GET" | |
}, | |
payload: [h.makeCredential(b, a)], | |
payloadSchemas: ["facebook#UpdateUserStateRequest"], | |
responseSchemas: ["facebook#UserState"], | |
type: "facebook", | |
bypassCache: !0, | |
persistent: !1 | |
}, d(f), k); | |
g._sendRetry(c) | |
}, k) | |
}; | |
this.getFriends = function (b, a) { | |
this.services.user.getUserInfo(function (f) { | |
f = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook/user/" + encodeURIComponent(f.user) + "/friends", | |
method: "GET" | |
}, | |
payload: [{ | |
fields: { | |
app_user: !0, | |
display_name: !0, | |
picture_large: !0 | |
} | |
}], | |
payloadSchemas: ["facebook#FriendsRequest"], | |
responseSchemas: ["facebook#FriendsReply"], | |
type: "facebook" | |
}, function (a) { | |
a = h.parseFriendList(a); | |
b(a) | |
}, a); | |
g._sendRetry(f) | |
}, a) | |
}; | |
this.getConfig = | |
function (b, a) { | |
var f = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook/config", | |
method: "GET" | |
}, | |
responseSchemas: ["facebook#ConfigReply"], | |
type: "facebook" | |
}, function (a) { | |
a = h.parseConfig(a); | |
b(a) | |
}, a); | |
g._sendRetry(f) | |
}; | |
this.share = function (b, a, f, k, c, d) { | |
this.services.user.getUserInfo(function (p) { | |
var q = h.makeCredential(b, a); | |
q.uri = f; | |
if (k) q.message_text = k; | |
p = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook/user/" + encodeURIComponent(p.user) + "/share", | |
method: "POST" | |
}, | |
payload: [q], | |
payloadSchemas: ["facebook#ShareRequest"], | |
responseSchemas: ["facebook#ShareReply"], | |
type: "facebook", | |
bypassCache: !0 | |
}, function (a) { | |
a = h.parsePostId(a); | |
c(a) | |
}, d); | |
g._sendRetry(p) | |
}, d) | |
}; | |
this.getPermissions = function (b, a, f, k) { | |
this.services.user.getUserInfo(function (c) { | |
var d = h.makeCredential(b, a); | |
d.options = { | |
cache_is_king: !1 | |
}; | |
c = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook/user/" + encodeURIComponent(c.user) + "/permissions", | |
method: "GET" | |
}, | |
payload: [d], | |
payloadSchemas: ["facebook#PermissionsRequest"], | |
responseSchemas: ["facebook#PermissionsReply"], | |
type: "facebook", | |
bypassCache: !0 | |
}, function (a) { | |
a = h.parsePermissions(a); | |
f(a) | |
}, k); | |
g._sendRetry(c) | |
}, k) | |
}; | |
this._sendRetry = function (b, a) { | |
var f = 0, | |
k = b.error, | |
a = a || 3, | |
m = function () { | |
g.send(b) | |
}; | |
b.error = function (d) { | |
var h; | |
f + 1 < a && (statusCode = d.code || 0, Spotify.Hermes.Request.isServerError(statusCode) && (h = Math.pow(f, 2) + Math.random(), f++)); | |
h !== void 0 ? (c.log("Spotify.Services.Facebook", ["Scheduling retry to request", b.header.method, b.header.uri, "in", h, "second(s) due to error", d], "corejs"), setTimeout(m, h * 1E3)) : k(d) | |
}; | |
m() | |
}; | |
this.inspectCredential = | |
function (b, a, f, k) { | |
this.services.user.getUserInfo(function (c) { | |
c = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook/user/" + encodeURIComponent(c.user) + "/inspect", | |
method: "POST" | |
}, | |
payload: [h.makeCredential(b, a)], | |
payloadSchemas: ["facebook#InspectCredentialRequest"], | |
responseSchemas: ["facebook#InspectCredentialReply"], | |
type: "facebook", | |
bypassCache: !0 | |
}, function (a) { | |
a = h.parseCredentialInspection(a); | |
f(a) | |
}, k); | |
g._sendRetry(c) | |
}, k) | |
} | |
}; | |
Spotify.Services.FacebookPublish = function () { | |
var d = this, | |
g = new Spotify.Events, | |
c, h = [], | |
b = function (a, b, f, k, h, g) { | |
d.serviceIsReady ? (c.addToBucket({ | |
uri: a, | |
startTime: b, | |
eventName: f, | |
event: k, | |
callback: h, | |
errback: g | |
}), c.isStarted() || c.start()) : g(new Spotify.Errors.Error([13, 503, "Facebook-publish service not ready!"])) | |
}, a = function (a) { | |
d.services.user.getUserInfo(function (b) { | |
for (var f = [], k = [], c = [], h = 0; h < a.length; h++) { | |
var g = a[h], | |
u = { | |
id: { | |
uri: g.uri, | |
startTime: g.startTime | |
} | |
}; | |
u[g.eventName] = g.event; | |
f.push(u); | |
k.push("facebook-publish#Event"); | |
c.push("facebook-publish#EventReply") | |
} | |
b = new Spotify.Calls.Hermes({ | |
header: { | |
uri: "hm://facebook-publish/user/" + encodeURIComponent(b.user) + "/music/listen", | |
method: "POST" | |
}, | |
payload: f, | |
payloadSchemas: k, | |
responseSchemas: c, | |
type: "facebook-publish", | |
bypassCache: !1, | |
persistent: !1 | |
}, function () { | |
for (var b = 0; b < a.length; b++) a[b].callback.apply(this, arguments) | |
}, function () { | |
for (var b = 0; b < a.length; b++) a[b].errback.apply(this, arguments) | |
}); | |
d.send(b) | |
}, function () {}) | |
}, f = function (a) { | |
h.push(a.params) | |
}, k = function () { | |
a(h); | |
h = [] | |
}; | |
this.scrobbleStart = | |
function (a, f, k, c, d, h, g) { | |
c = { | |
length: d, | |
end_time: c | |
}; | |
if (f) c.context_uri = f; | |
b(a, k, "start", c, h, g) | |
}; | |
this.scrobbleSeek = function (a, f, k, c, d) { | |
b(a, f, "seek", { | |
end_time: k | |
}, c, d) | |
}; | |
this.scrobblePause = function (a, f, k, c, d, h) { | |
b(a, f, "pause", { | |
seconds_played: k, | |
end_time: c | |
}, d, h) | |
}; | |
this.scrobbleResume = function (a, f, k, c, d, h) { | |
b(a, f, "resume", { | |
seconds_played: k, | |
end_time: c | |
}, d, h) | |
}; | |
this.scrobbleEnd = function (a, f, k, c, d, h) { | |
b(a, f, "end", { | |
seconds_played: k, | |
end_time: c | |
}, d, h) | |
}; | |
this.setup = function () { | |
c = new Spotify.RateLimiter(1E3, 25); | |
c.bind(g.RATE_LIMIT_CALL, | |
f); | |
c.bind(g.RATE_LIMIT_AFTER_INTERVAL, k) | |
} | |
}; | |
Spotify.Core = function (d, g) { | |
Spotify.EventTarget.call(this); | |
Spotify.DebuggerJS.register("console", new Spotify.DebuggerJS.Loggers.Console, new Spotify.DebuggerJS.Parsers.Default); | |
Spotify.Hermes.Cache = new Spotify.HermesCache; | |
var c = this, | |
h = Spotify.DebuggerJS, | |
b, a, f = !1, | |
k = typeof swfobject !== "undefined" ? Spotify.PlayerTypes.FLASH_RTMPS : Spotify.PlayerTypes.HTML5_HTTP, | |
m = { | |
playerType: k, | |
SWFContainerId: g.SWFContainerId || "", | |
SWFPlayerContainerId: g.SWFPlayerContainerId || "", | |
SWFPlayerUrl: g.SWFPlayerUrl || "player.swf", | |
SWFUrl: g.SWFUrl || "bridge.swf", | |
SWFMinVersion: g.SWFMinVersion || "10.2.0", | |
logging: g.logging || 0, | |
length: g.length || 0, | |
valid: g.valid || 0, | |
cdn: g.cdn || "", | |
protoSchemasLocation: g.protoSchemasLocation || "proto/", | |
protoSchemasLocationRandomizer: g.protoSchemasLocationRandomizer || "", | |
services: g.services || {} | |
}; | |
this.id = ""; | |
var o = d || Spotify.GatewayTypes.FLASH, | |
p, q = new Spotify.Events, | |
n, s = {}, t = new Spotify.Managers.ProtobufSchemasManager; | |
this.services = {}; | |
this.previewUriResolver = this.adUriResolver = this.storageResolver = this._bridge = this.facebookPublish = | |
this.mergedProfile = this.adChooser = this.presence = this.hermes = this.collectionUnplayed = this.collectionView = this.collectionStorage = this.facebook = this.socialGraph = this.social = this.toplist = this.user = this.search = this.popcount = this.appstore = this.playlist = this.metadata = this.pubsub = this.time = this.suggest = this.player = null; | |
this.logging = {}; | |
this.isReady = !1; | |
this.onConnect = function () {}; | |
this.onDisconnect = function () {}; | |
this.onTokenLost = function () {}; | |
this.connect = function (a, b) { | |
p.connect(a, b) | |
}; | |
this.connectWithToken = function (a, | |
b) { | |
p.connect(a, b) | |
}; | |
this.connectWithCredentials = function (a, b, f) { | |
p.connect(a, "1:" + b + ":" + f) | |
}; | |
this.disconnect = function () { | |
p.disconnect() | |
}; | |
this.migrateToIndexedDBStorage = function (a, b, f) { | |
Spotify.Hermes.Cache.migrateToIndexedDB(a, b, f) | |
}; | |
this.initialize = function () { | |
n = new Spotify.Proto.Data(m.protoSchemasLocation, m.protoSchemasLocationRandomizer); | |
n.bind(q.SUCCESS, F); | |
n.bind(q.ERROR, H); | |
n.initialize() | |
}; | |
var u = function (a) { | |
var b = a.params; | |
if (b instanceof Spotify.Calls.Hermes) { | |
for (var a = b.success, f = b.isMultiGet ? b.mercuryMultiGetPayloadSchemas : | |
b.payloadSchemas, k = b.isMultiGet ? b.mercuryMultiGetResponseSchemas : b.responseSchemas, m = [], d = [], h = 0, g = f.length; h < g; h += 1) m.push(t.getProtobufMsgParser.apply(c, f[h].split("#"))); | |
f = 0; | |
for (g = k.length; f < g; f += 1) d.push(t.getProtobufMsgParser.apply(c, k[f].split("#"))); | |
b.isMultiGet && (a = function (a, f) { | |
for (var k = 0; k < a.length; k += 1) { | |
var m = a[k], | |
d = []; | |
if (typeof m.reply === "undefined") { | |
b.error(new Spotify.Errors.Error([13, 400])); | |
return | |
} | |
if (b.responseSchemas[k]) var h = t.getProtobufMsgParser.apply(c, b.responseSchemas[k].split("#")); | |
for (var m = m.reply, g = 0, o = m.length; g < o; g += 1) { | |
var n = m[g], | |
n = n && n.status_code ? n.status_code >= 200 && n.status_code < 300 ? h ? h.parseFromStringSync(n.body) : n : null : null; | |
d.push(n) | |
} | |
} | |
b.success(d, f) | |
}); | |
(new Spotify.Hermes.ProtobufRequest(b.header, b.payload, m, d)).send(p, a, b.error, b.persistent, b.bypassCache, b.type) | |
} else b instanceof Spotify.Calls.Simple && p.rpc(b.method, b.payload, b.success, b.error, b.context, b.persistent, b.retries, b.type) | |
}; | |
this.registerService = function (a, b, f, k, c) { | |
if (typeof this.services[a] !== "undefined") return h.error("Spotify.Core", ["A service with id", a, "already exists"], "corejs"), null; | |
if (typeof c === "undefined") c = Spotify.Services.Base; | |
k = Spotify.Utils.inherit(c.bind(this, t), k); | |
s[a] = f; | |
f = new k; | |
this.services[a] = f; | |
f._dependencies = b; | |
f.id = a; | |
f.bind(q.REQUEST, u, this); | |
return this.services[a] | |
}; | |
this.dispose = function () { | |
for (var a in this.services) { | |
try { | |
this.services[a].dispose() | |
} catch (b) {} | |
this.services[a] = null | |
} | |
this.audioManager.dispose(); | |
p.dispose() | |
}; | |
this.onReady = function (a, b) { | |
this.isReady ? a.call(b) : this.bind(q.READY, a, b) | |
}; | |
var w = function (a) { | |
var b = | |
c.audioManager.getActivePlayer(); | |
b && b.pause(); | |
c.onTokenLost(a) | |
}, v = function (a) { | |
A(a) | |
}, A = function (a) { | |
for (var b in c.services) try { | |
c.services[b].onNotify(a) | |
} catch (f) {} | |
}, x = function (a) { | |
A(a) | |
}, F = function () { | |
Spotify.Instances.add(c); | |
t.registerSchema("mercury", n.getDefinition("mercury")); | |
t.registerSchema("pubsub", n.getDefinition("pubsub")); | |
c.registerService("user", [], [], Spotify.Services.User); | |
c.user = c.services.user; | |
c.registerService("logging_clientEvent", [], [], Spotify.Logging.ClientEvent); | |
c.logging.clientEvent = | |
c.services.logging_clientEvent; | |
c.registerService("logging_view", [], [], Spotify.Logging.View); | |
c.logging.view = c.services.logging_view; | |
c.registerService("logging_logger", [], [], Spotify.Logging.Logger); | |
c.logging.logger = c.services.logging_logger; | |
c.registerService("heartbeat", [], [], Spotify.Heartbeat); | |
c.registerService("storageResolver", [], [], Spotify.Services.SongUriResolver); | |
c.storageResolver = c.services.storageResolver; | |
c.storageResolver.bind(q.TIME_CAP, G, c); | |
c.registerService("adResolver", [], [], Spotify.Services.AdUriResolver); | |
c.adUriResolver = c.services.adResolver; | |
c.registerService("previewResolver", [], [], Spotify.Services.PreviewsUriResolver); | |
c.previewUriResolver = c.services.previewResolver; | |
c.registerService("pubsub", [], ["pubsub"], Spotify.Services.Pubsub); | |
c.pubsub = c.services.pubsub; | |
p = new Spotify.Gateway(o); | |
p.bind(q.READY, z, c); | |
p.bind(q.ON_TRY_TO_CONNECT, y, c); | |
p.bind(q.CONNECTED, L, c); | |
p.bind(q.DISCONNECTED, c.onDisconnect, c); | |
p.bind(q.TOKEN_LOST, w, c); | |
p.bind(q.FLASH_AVAILABLE, E, c); | |
p.bind(q.FLASH_UNAVAILABLE, E, c); | |
p.bind(q.HERMES_B64_MESSAGE, | |
v, c); | |
p.bind(q.USER_INFO_CHANGE, B, c); | |
Spotify.Hermes.Cache.onfull = K; | |
c.features = new Spotify.Features(g.features); | |
c.hermes = new Spotify.Hermes.Handler; | |
c.hermes.init(p); | |
c.audioManager = new Spotify.Audio.AudioManager(c.id, m, k); | |
c.audioManager.bind(q.FLASH_AVAILABLE, E, c); | |
c.audioManager.bind(q.FLASH_UNAVAILABLE, E, c); | |
c.audioManager.bind(q.NO_SOUND_CAPABILITIES, I); | |
c.audioManager.bind(q.INITIALIZED, C, c); | |
c.audioManager.bind(q.TRACK_ENDED, x, c); | |
c.audioManager.bind(q.POSITION_CHANGED, x, c); | |
c.audioManager.bind(q.PLAYING, | |
x, c); | |
c.audioManager.bind(q.PAUSED, x, c); | |
c.audioManager.bind(q.STOPPED, x, c); | |
c.audioManager.bind(q.LOAD, x, c); | |
c.audioManager.addFileResolver(Spotify.Resolvers.STORAGE_RESOLVER, c.services.storageResolver); | |
c.audioManager.addFileResolver(Spotify.Resolvers.AD_RESOLVER, c.services.adResolver); | |
c.audioManager.addFileResolver(Spotify.Resolvers.PREVIEW_RESOLVER, c.services.previewResolver); | |
c.audioManager.initialize(p, c.user); | |
b = new Spotify.Worker; | |
b.initialize(p, c.audioManager); | |
p.initialize(c.id, m); | |
c._bridge = p.bridge | |
}, | |
G = function (a) { | |
c.trigger(q.TIME_CAP, a.params) | |
}, B = function (a) { | |
A(a) | |
}, E = function (b) { | |
b.type === q.UNAVAILABLE ? c.trigger(q.FLASH_UNAVAILABLE) : (a && clearTimeout(a), a = setTimeout(function () { | |
p.isReady && c.audioManager.isInitialized ? h.log("Spotify.Core", ["Flash is available"], "corejs") : (h.error("Spotify.Core", ["Flash is NOT available"], "corejs"), c.trigger(q.FLASH_UNAVAILABLE)) | |
}, 1E4)) | |
}, H = function (a) { | |
c.trigger(q.DATA_ERROR, a) | |
}, I = function () { | |
c.trigger(q.NO_SOUND_CAPABILITIES) | |
}, K = function () { | |
c.trigger(q.STORAGE_FULL) | |
}, | |
L = function (a) { | |
if (!f) { | |
f = !0; | |
c.registerService("appstore", [], ["appstore"], Spotify.Services.AppStore); | |
c.appstore = c.services.appstore; | |
c.registerService("mergedProfile", [], ["mergedprofile"], Spotify.Services.MergedProfile); | |
c.mergedProfile = c.services.mergedProfile; | |
c.registerService("popcount", [], ["popcount"], Spotify.Services.PopCount); | |
c.popcount = c.services.popcount; | |
c.registerService("social", [], ["social"], Spotify.Services.Social); | |
c.social = c.services.social; | |
c.registerService("searchHermes", [], ["metadata", | |
"search" | |
], Spotify.Services.SearchHermes); | |
c.registerService("suggest", ["user"], ["suggest"], Spotify.Services.Suggest); | |
c.suggest = c.services.suggest; | |
c.registerService("toplist", ["user"], ["toplist", "socialgraph"], Spotify.Services.Toplist); | |
c.toplist = c.services.toplist; | |
c.registerService("search", ["user"], [], Spotify.Services.Search); | |
c.search = c.services.search; | |
c.registerService("playlist", ["user", "toplist", "pubsub"], "playlist4changes,playlist4content,playlist4issues,playlist4meta,playlist4ops,playlist4service".split(","), | |
Spotify.Services.Playlist); | |
c.playlist = c.services.playlist; | |
c.registerService("presence", ["pubsub", "user"], ["presence"], Spotify.Services.Presence); | |
c.presence = c.services.presence; | |
c.registerService("socialGraph", ["user", "playlist"], ["socialgraph"], Spotify.Services.SocialGraph); | |
c.socialGraph = c.services.socialGraph; | |
c.registerService("facebook", ["user"], ["facebook"], Spotify.Services.Facebook); | |
c.facebook = c.services.facebook; | |
c.registerService("facebookPublish", ["user"], ["facebook-publish"], Spotify.Services.FacebookPublish); | |
c.facebookPublish = c.services.facebookPublish; | |
c.registerService("metadata", ["user"], ["metadata"], Spotify.Services.Metadata); | |
c.metadata = c.services.metadata; | |
c.registerService("time", [], [], Spotify.Services.Time); | |
c.registerService("inbox", ["playlist"], [], Spotify.Services.Inbox); | |
c.adChooser = new Spotify.Services.AdChooser; | |
c.services.adChooser = c.adChooser; | |
c.adChooser.bind(q.INTERCEPTED, N); | |
c.adChooser.init(p, c.audioManager, c.user); | |
c.collectionStorage = new Spotify.Services.CollectionStorage(m.services.collection_storage, | |
n.getDefinition("collection2")); | |
c.services.collectionStorage = c.collectionStorage; | |
c.collectionStorage.init(p, c.pubsub); | |
c.collectionView = new Spotify.Services.CollectionView(m.services.collection_view); | |
c.services.collectionView = c.collectionView; | |
c.collectionView.init(c.collectionStorage, c.metadata, c.playlist, c.user, p, n.getDefinition("collection2cache")); | |
c.collectionUnplayed = new Spotify.Services.CollectionUnplayed(m.services.collection_unplayed); | |
c.collectionUnplayed.init(c.collectionStorage, c.user); | |
for (var b in c.services) { | |
var k = !1, | |
d = []; | |
if (c.services[b]._dependencies) { | |
for (var h = 0, g = c.services[b]._dependencies.length; h < g; h += 1) { | |
var o = c.services[c.services[b]._dependencies[h]]; | |
if (typeof o === "undefined") { | |
k = !0; | |
break | |
} | |
d.push(o) | |
} | |
if (!k) { | |
k = 0; | |
for (h = s[b].length; k < h; k += 1) g = s[b][k], t.registerSchema(g, n.getMultipleDefinitions([g])); | |
s[b].length > 1 && t.registerSchema(b + "_FULL", n.getMultipleDefinitions(s[b])); | |
c.services[b]._initialize.call(c.services[b], d) | |
} | |
} | |
} | |
} | |
A(a); | |
c.onConnect(a) | |
}, N = function () { | |
c.trigger(q.WAIT_FOR_COMMERCIAL_TO_FINISH) | |
}, M = function () { | |
if (!c.isReady && | |
p.isReady && c.audioManager.isInitialized) c.isReady = !0, c.trigger(q.READY) | |
}, z = function () { | |
M() | |
}, C = function () { | |
M() | |
}, y = function (a) { | |
A({ | |
type: q.DISCONNECTED, | |
params: {}, | |
extra: {} | |
}); | |
c.trigger(a.type) | |
}; | |
this.initialize.call(this) | |
}; | |
(function () { | |
Spotify.Shell = {} | |
})(); | |
(function () { | |
function d(c) { | |
var d = c.data; | |
if (typeof d == "string") try { | |
d = JSON.parse(d) | |
} catch (b) { | |
return | |
} | |
var a = g[d.type]; | |
a && a.call(this, c, d) | |
} | |
var g = {}; | |
window.attachEvent && !window.addEventListener ? window.attachEvent("onmessage", d) : window.addEventListener("message", d, !1); | |
Spotify.addMessageHandler = function (c, d) { | |
if (g[c]) throw Error('Rehandling of message "' + c + '" not allowed.'); | |
g[c] = d | |
}; | |
Spotify.removeMessageHandler = function (c, d) { | |
return g[c] == d ? (g[c] = null, !0) : !1 | |
} | |
})(); | |
(function () { | |
var d = [], | |
g = window.postMessage.bind(window, '{"type": "execute_deferreds"}', window.location.origin || [window.location.protocol, window.location.hostname].join("//")); | |
Spotify.addMessageHandler("execute_deferreds", function () { | |
var c = d.splice(0); | |
if (c.length) | |
for (var h = 0, b = c.length; h < b; h++) { | |
var a = !0; | |
try { | |
c[h](), a = !1 | |
} finally { | |
a && (a = !d.length, d = c.slice(++h).concat(d), a && g()) | |
} | |
} | |
}); | |
Spotify.defer = function (c) { | |
var h = !d.length; | |
d.push(c); | |
h && g() | |
} | |
})(); | |
(function () { | |
var d; | |
function g(b, a) { | |
b.then(function (b) { | |
a.fulfill(b) | |
}, function (b) { | |
a.fail(b) | |
}) | |
} | |
function c() { | |
this._state = d; | |
this._value = null; | |
this._handlers = []; | |
this._deferred = !1 | |
} | |
var h = Array.prototype.slice; | |
d = 0; | |
Spotify.Promise = c; | |
c.defer = typeof setImmediate == "function" ? function (b) { | |
setImmediate(b) | |
} : Spotify.defer; | |
c.prototype.isUnfulfilled = function () { | |
return this._state == d | |
}; | |
c.prototype.isFulfilled = function () { | |
return this._state == 1 | |
}; | |
c.prototype.isFailed = function () { | |
return this._state == 2 | |
}; | |
c.prototype.fulfill = function (b) { | |
var a = | |
this; | |
if (this._state === d && (this._value = b, this._state = 1, !this._deferred)) c.defer(function () { | |
a._runHandlers() | |
}), this._deferred = !0 | |
}; | |
c.prototype.fail = function (b) { | |
var a = this; | |
if (this._state === d && (this._value = b, this._state = 2, !this._deferred)) c.defer(function () { | |
a._runHandlers() | |
}), this._deferred = !0 | |
}; | |
c.prototype.then = function (b, a) { | |
var f = this, | |
k = new c; | |
this._handlers.push({ | |
fulfilled: b, | |
failed: a, | |
promise: k | |
}); | |
if (this._state !== d && !this._deferred) c.defer(function () { | |
f._runHandlers() | |
}), this._deferred = !0; | |
return k | |
}; | |
c.prototype.pipe = | |
function (b) { | |
this.then(function (a) { | |
b.fulfill(a) | |
}, function (a) { | |
b.fail(a) | |
}) | |
}; | |
c.prototype._runHandlers = function () { | |
this._deferred = !1; | |
var b = this._value; | |
if (this._state != d) | |
for (var a = this._state === 1, f = this._handlers.splice(0), k = 0, c = f.length; k < c; k++) { | |
var h = f[k], | |
p = h[a ? "fulfilled" : "failed"], | |
h = h.promise; | |
if (!p || typeof p != "function") b && typeof b.then == "function" ? g(b, h) : a ? h.fulfill(b) : h.fail(b); | |
else { | |
try { | |
var q = p(b) | |
} catch (n) { | |
h.fail(n); | |
continue | |
} | |
q && typeof q.then == "function" ? g(q, h) : h.fulfill(q) | |
} | |
} | |
}; | |
c.prototype.catchError = | |
function (b) { | |
return this.then(null, b) | |
}; | |
c.prototype.get = function (b) { | |
var a = new c; | |
this.then(function (f) { | |
a.fulfill(f[b]) | |
}, function (b) { | |
a.fail(b) | |
}); | |
return a | |
}; | |
c.prototype.call = function (b, a) { | |
var f = h.call(arguments, 1), | |
k = new c; | |
this.then(function (a) { | |
try { | |
k.fulfill(a[b].apply(a, f)) | |
} catch (c) { | |
k.fail(c) | |
} | |
}, function (a) { | |
k.fail(a) | |
}); | |
return k | |
}; | |
c.prototype.thenSpread = function (b, a) { | |
return this.then(function (a) { | |
return Array.isArray(a) ? b.apply(this, a) : b.call(this, a) | |
}, a) | |
}; | |
c.join = function (b) { | |
for (var b = Array.isArray(b) ? b : h.call(arguments), | |
a = new c, f = b.length, k = [], m = !1, d = function (b, c) { | |
m || (k[b] = c, f--, f || a.fulfill(k)) | |
}, g = function (b) { | |
m || (m = !0, a.fail(b)) | |
}, q = 0, n = f; q < n; q++) b[q].then(d.bind(null, q), g); | |
return a | |
}; | |
c.group = function (b) { | |
for (var b = Array.isArray(b) ? b : h.call(arguments), a = new c, f = 0, k = b.length; f < k; f++) a.pipe(b[f]); | |
return a | |
} | |
})(); | |
(function () { | |
var d = Array.prototype.slice, | |
g = Object.prototype.toString, | |
c = Spotify.Link; | |
if (!Array.isArray) Array.isArray = function (c) { | |
return g.call(c) == "[object Array]" | |
}; | |
Array.prototype.spliceWith || Object.defineProperty(Array.prototype, "spliceWith", { | |
configurable: !0, | |
enumerable: !1, | |
writeable: !0, | |
value: function (c, b, a) { | |
if (a == void 0) return this.splice(c, b); | |
Array.isArray(a) || (a = [a]); | |
return this.splice.apply(this, [c, b].concat(a)) | |
} | |
}); | |
Array.prototype.insertFrom || Object.defineProperty(Array.prototype, "insertFrom", { | |
configurable: !0, | |
enumerable: !1, | |
writeable: !0, | |
value: function (c, b) { | |
if (b == void 0) return this; | |
Array.isArray(b) || (b = [b]); | |
for (var a = b.length; a--;) this[a + c] = b[a]; | |
return this | |
} | |
}); | |
Spotify.inherit = function (c, b) { | |
function a() {} | |
var f = b.prototype; | |
a.prototype = c._super = f; | |
a.prototype.constructor = b; | |
c.prototype = new a; | |
c.prototype._super = function (a, b) { | |
b = typeof b == "arguments" || Array.isArray(b) ? b : d.call(arguments, 1); | |
return f[a].apply(this, b) | |
} | |
}; | |
Spotify.LinkHelper = {}; | |
Spotify.LinkHelper.from = function (d) { | |
try { | |
return d instanceof c ? d : c.fromString(d.toString()) | |
} catch (b) { | |
return null | |
} | |
} | |
})(); | |
(function () { | |
function d() { | |
this._ids = []; | |
this._values = {} | |
} | |
Spotify.Shell.RequestQueue = d; | |
d.prototype.push = function (d, c) { | |
var h = this._ids, | |
b = this._values, | |
d = d.toString(); | |
b[d] || h.push(d); | |
(b[d] || (b[d] = [])).push(c); | |
return this | |
}; | |
d.prototype.takeIds = function (d) { | |
var c = this._ids, | |
d = d != void 0 ? d : c.length; | |
return c.splice(0, d) | |
}; | |
d.prototype.takeValues = function (d, c) { | |
var h = this._values[d]; | |
if (!h) return []; | |
var c = c != void 0 ? c : h.length, | |
b = h.splice(0, c); | |
h.length || (this._values[d] = null); | |
return b | |
} | |
})(); | |
(function () { | |
function d() { | |
this._events = {} | |
} | |
var g = Spotify.defer; | |
Spotify.Shell.EventEmitter = d; | |
d.prototype.addEvent = function (c, d) { | |
var b = this._events[c] || (this._events[c] = []); | |
if (b.indexOf(d) != -1) return this; | |
b.push(d); | |
return this | |
}; | |
d.prototype.addEvents = function (c) { | |
for (var d in c) c.hasOwnProperty(d) && this.addEvent(d, c[d]) | |
}; | |
d.prototype.addOnceEvent = function (c, d) { | |
var b = this, | |
a = function () { | |
var f = d.apply(this, arguments); | |
b.removeEvent(c, a); | |
return f | |
}; | |
return this.addEvent(c, a) | |
}; | |
d.prototype.removeEvent = function (c, | |
d) { | |
var b = this._events[c]; | |
if (!b || !b.length) return this; | |
var a = b.indexOf(d); | |
if (a == -1) return this; | |
b.splice(a, 1); | |
return this | |
}; | |
d.prototype.fireEvent = function (c, d, b) { | |
var a = this, | |
c = this._events[c]; | |
if (!c || !c.length) return this; | |
c = c.slice(0); | |
Array.isArray(d) || (d = [d]); | |
for (var f = c.length; f--;)(function (f) { | |
b ? f.apply(a, d) : g(function () { | |
f.apply(a, d) | |
}) | |
})(c[f]); | |
return this | |
}; | |
d.prototype.fireEventSync = function (c, d) { | |
var b = this._events[c]; | |
if (!b || !b.length) return this; | |
b = b.slice(0); | |
Array.isArray(d) || (d = [d]); | |
for (var a = b.length; a--;) b[a].apply(this, | |
d); | |
return this | |
} | |
})(); | |
(function () { | |
function d(c, h, b) { | |
if (!(this instanceof d)) return new d(c, h, b); | |
var c = c != null ? c : 0, | |
h = h != null ? h : -1, | |
b = b != null ? b : Infinity, | |
a = h == -1 ? b : h; | |
this.length = h = h == -1 ? b : Math.min(h, b); | |
this.expectedLength = a; | |
this.begin = c; | |
this.last = c + h; | |
this.end = c + h - 1 | |
} | |
var g = Array.prototype.slice; | |
Spotify.Shell.Range = d; | |
d.prototype.contains = function (c) { | |
return !(c.begin < this.begin || c.begin > this.end || c.end > this.end || c.end < this.begin) | |
}; | |
d.prototype.has = function (c) { | |
return c >= this.begin && c <= this.end | |
}; | |
d.prototype.equals = function (c) { | |
return this.begin == | |
c.begin && this.end == c.end | |
}; | |
d.prototype.intersects = function (c) { | |
return this.begin <= c.end && c.begin <= this.end | |
}; | |
d.prototype.contiguous = function (c) { | |
return this.last == c.begin || c.last == this.begin | |
}; | |
d.prototype.intersect = function (c) { | |
if (this.end < c.begin || c.end < this.begin) return new d(NaN, 0); | |
var h = Math.max(c.begin, this.begin), | |
c = Math.min(c.end, this.end) - h + 1; | |
return new d(h, c) | |
}; | |
d.prototype.add = function (c) { | |
var h = Math.min(c.begin, this.begin), | |
c = Math.max(c.end, this.end) - h + 1; | |
return new d(h, c) | |
}; | |
d.prototype.subtract = function (c) { | |
if (this.equals(c)) return []; | |
if (this.contains(c)) { | |
var h = [], | |
b = new d(this.begin, c.begin - this.begin), | |
c = new d(c.end + 1, this.end - c.end); | |
b.length && h.push(b); | |
c.length && h.push(c); | |
return h | |
} else if (c.contains(this)) return c.subtract(this); | |
else if (this.intersects(c)) return this.add(c).subtract(this.intersect(c)); | |
return [this, c] | |
}; | |
d.prototype.subtractMany = function (c) { | |
for (var c = Array.isArray(c) ? c : g.call(arguments), d = [], b = this, a = 0, f = c.length; a < f; a++) { | |
var k = c[a]; | |
if (!b.intersects(k)) break; | |
b = b.subtract(b.intersect(k)); | |
switch (b.length) { | |
case 2: | |
d.push(b[0]); | |
b = b[1]; | |
break; | |
case 1: | |
b = b[0]; | |
break; | |
default: | |
return [] | |
} | |
} | |
d.push(b); | |
return d | |
}; | |
d.prototype.fill = function (c) { | |
if (this.intersects(c)) return new d(NaN, 0); | |
var h; | |
Math.min(this.begin, c.begin) == this.begin ? h = this : (h = c, c = this); | |
return new d(h.end + 1, c.begin - h.end - 1) | |
}; | |
d.prototype.split = function (c) { | |
if (c >= this.length) return [new d(this.begin, this.length)]; | |
for (var h = [], b = this.begin, a = this.length; a;) { | |
if (a < c) { | |
h.push(new d(b, a)); | |
break | |
} else h.push(new d(b, c)); | |
a -= c; | |
b += c | |
} | |
return h | |
}; | |
d.prototype.findContainer = function (c) { | |
for (var c = | |
Array.isArray(c) ? c : g.call(arguments), d = 0, b = c.length; d < b; d++) | |
if (c[d].contains(this)) return c[d]; | |
return null | |
}; | |
d.simplify = function (c) { | |
var c = Array.isArray(c) ? c : g.call(arguments), | |
d = [], | |
b = null; | |
c.sort(function (a, b) { | |
return a.begin - b.begin | |
}); | |
for (var a = 0, f = c.length; a < f; a++) { | |
var k = c[a]; | |
!isNaN(k.begin) && !isNaN(k.length) && k.length && (b && (b.intersects(k) || b.contiguous(k) ? k = b.add(k) : d.push(b)), b = k) | |
} | |
b && d.push(b); | |
return d | |
} | |
})(); | |
(function () { | |
Spotify.ItemList = {}; | |
Spotify.ItemList.LIST_START = new function () {}; | |
Spotify.ItemList.LIST_END = new function () {}; | |
Spotify.ItemList.NULL_VALUE = new function () {}; | |
Spotify.ItemList.LoadedState = { | |
UNLOADED: "unloaded", | |
LOADING: "loading", | |
PARTIAL: "partial", | |
COMPLETE: "complete" | |
} | |
})(); | |
(function () { | |
function d(a, b) { | |
return a - b | |
} | |
function g(a, b) { | |
return b - a | |
} | |
function c(a, b) { | |
return a > b ? 1 : a == b ? 0 : -1 | |
} | |
function h(a, b) { | |
return a > b ? -1 : a == b ? 0 : 1 | |
} | |
Spotify.ItemList.SortingOrder = { | |
ASC: "asc", | |
DESC: "desc" | |
}; | |
Spotify.ItemList.ComparisonResult = { | |
GREATER: 1, | |
EQUAL: 0, | |
LESS: -1 | |
}; | |
var b = Spotify.ItemList.Comparators = {}; | |
b.forNumber = function () { | |
return d | |
}; | |
b.forNumberReversed = function () { | |
return g | |
}; | |
b.forString = function () { | |
return c | |
}; | |
b.forStringReversed = function () { | |
return h | |
}; | |
var a = {}, f = {}; | |
b.forNumberProperty = function (b) { | |
return a[b] || | |
(a[b] = function (a, f) { | |
a = a[b]; | |
f = f[b]; | |
return a - f | |
}) | |
}; | |
b.forNumberPropertyReversed = function (b) { | |
var f = b + "_reverse"; | |
return a[f] || (a[f] = function (a, f) { | |
a = a[b]; | |
f = f[b]; | |
return f - a | |
}) | |
}; | |
b.forStringProperty = function (a) { | |
return f[a] || (f[a] = function (b, f) { | |
b = (b[a] || "").toString(); | |
f = (f[a] || "").toString(); | |
return b > f ? 1 : b == f ? 0 : -1 | |
}) | |
}; | |
b.forStringPropertyReversed = function (a) { | |
var b = a + "_reverse"; | |
return f[b] || (f[b] = function (b, f) { | |
b = (b[a] || "").toString(); | |
f = (f[a] || "").toString(); | |
return b > f ? -1 : b == f ? 0 : 1 | |
}) | |
}; | |
b.forProperty = function (a, b) { | |
return function (f, | |
c) { | |
return b(f[a], c[a]) | |
} | |
} | |
})(); | |
(function () { | |
Spotify.ItemList.PredicateOperator = { | |
EQUAL: "=", | |
NOT_EQUAL: "!=", | |
GREATER_THAN: ">", | |
LESS_THAN: "<", | |
GREATER_THAN_OR_EQUAL: ">=", | |
LESS_THAN_OR_EQUAL: "<=", | |
STARTS_WITH: "startswith", | |
CONTAINS: "contains" | |
}; | |
var d = Spotify.ItemList.Predicates = {}; | |
d.forOperator = function (d, c) { | |
switch (d) { | |
case "=": | |
return this.forEqual(c); | |
case "!=": | |
return this.forNotEqual(c); | |
case ">": | |
return this.forGreaterThan(c); | |
case "<": | |
return this.forLessThan(c); | |
case ">=": | |
return this.forGreaterThanOrEqual(c); | |
case "<=": | |
return this.forLessThanOrEqual(c); | |
case "startswith": | |
return this.forBeginsWith(c); | |
case "contains": | |
return this.forContains(c); | |
default: | |
return null | |
} | |
}; | |
d.forPropertyOperator = function (d, c, h) { | |
switch (c) { | |
case "=": | |
return this.forPropertyEqual(d, h); | |
case "!=": | |
return this.forPropertyNotEqual(d, h); | |
case ">": | |
return this.forPropertyGreaterThan(d, h); | |
case "<": | |
return this.forPropertyLessThan(d, h); | |
case ">=": | |
return this.forPropertyGreaterThanOrEqual(d, h); | |
case "<=": | |
return this.forPropertyLessThanOrEqual(d, h); | |
case "startswith": | |
return this.forPropertyBeginsWith(d, h); | |
case "contains": | |
return this.forPropertyContains(d, | |
h); | |
default: | |
return null | |
} | |
}; | |
d.forNotNull = function () { | |
return function (d) { | |
return d != null | |
} | |
}; | |
d.forEqual = function (d) { | |
return function (c) { | |
return c === d | |
} | |
}; | |
d.forGreaterThan = function (d) { | |
return function (c) { | |
return c > d | |
} | |
}; | |
d.forLessThan = function (d) { | |
return function (c) { | |
return c < d | |
} | |
}; | |
d.forGreaterThanOrEqual = function (d) { | |
return function (c) { | |
return c >= d | |
} | |
}; | |
d.forLessThanOrEqual = function (d) { | |
return function (c) { | |
return c <= d | |
} | |
}; | |
d.forNotEqual = function (d) { | |
return function (c) { | |
return c != d | |
} | |
}; | |
d.forBeginsWith = function (d) { | |
return function (c) { | |
return !c ? !1 : c.toString().indexOf(d) == 0 | |
} | |
}; | |
d.forContains = function (d) { | |
return function (c) { | |
return !c ? !1 : c.toString().indexOf(d) != -1 | |
} | |
}; | |
d.forPropertyNotNull = function (d) { | |
return function (c) { | |
return c[d] != null | |
} | |
}; | |
d.forPropertyEqual = function (d, c) { | |
return function (h) { | |
return h[d] == c | |
} | |
}; | |
d.forPropertyGreaterThan = function (d, c) { | |
return function (h) { | |
return h[d] > c | |
} | |
}; | |
d.forPropertyLessThan = function (d, c) { | |
return function (h) { | |
return h[d] < c | |
} | |
}; | |
d.forPropertyGreaterThanOrEqual = function (d, c) { | |
return function (h) { | |
return h[d] >= c | |
} | |
}; | |
d.forPropertyLessThanOrEqual = | |
function (d, c) { | |
return function (h) { | |
return h[d] <= c | |
} | |
}; | |
d.forPropertyNotEqual = function (d, c) { | |
return function (h) { | |
return h[d] != c | |
} | |
}; | |
d.forPropertyBeginsWith = function (d, c) { | |
return function (h) { | |
return !h || !h[d] ? !1 : h[d].toString().indexOf(c) == 0 | |
} | |
}; | |
d.forPropertyContains = function (d, c) { | |
return function (h) { | |
return !h || !h[d] ? !1 : h[d].toString().indexOf(c) != -1 | |
} | |
} | |
})(); | |
(function () { | |
function d(a) { | |
if (!(this instanceof d)) return new d(a); | |
if (!a) return this; | |
for (var b in a) this[b] = a[b] | |
} | |
function g(a) { | |
if (!(this instanceof g)) return new g(a); | |
d.call(this, a) | |
} | |
function c(a, b, k, d, h) { | |
if (!(this instanceof c)) return new c(a, b, k, d, h); | |
this._applied = !1; | |
this._applyMutation = a; | |
this._checkVersion = b; | |
this._ruleset = k; | |
this._version = d; | |
this._length = h; | |
this._changes = [] | |
} | |
var h = Spotify.Promise; | |
Spotify.ItemList.MutationResult = { | |
SUCCESS: "success", | |
ALLOWED: "allowed", | |
FORBIDDEN: "forbidden", | |
LIST_FULL: "listFull", | |
OUT_OF_BOUNDS: "outOfBounds", | |
EXPIRED: "expired" | |
}; | |
var b = Spotify.ItemList.MutationResult; | |
Spotify.ItemList.MutationRuleset = d; | |
d.prototype.add = b.ALLOWED; | |
d.prototype.insert = b.ALLOWED; | |
d.prototype.remove = b.ALLOWED; | |
d.prototype.move = b.ALLOWED; | |
Spotify.inherit(g, d); | |
Spotify.ItemList.MutationRuleset.Immutable = g; | |
g.prototype.add = b.FORBIDDEN; | |
g.prototype.insert = b.FORBIDDEN; | |
g.prototype.remove = b.FORBIDDEN; | |
g.prototype.move = b.FORBIDDEN; | |
Spotify.ItemList.Mutator = c; | |
c.prototype.isApplied = function () { | |
return !!this._applied | |
}; | |
c.prototype.isExpired = | |
function () { | |
return !this._checkVersion(this._version) | |
}; | |
c.prototype.canInsert = function (a) { | |
return this._ruleset.insert == b.FORBIDDEN ? b.FORBIDDEN : this._applied || !this._checkVersion(this._version) ? b.EXPIRED : a < 0 || a > this._length ? b.OUT_OF_BOUNDS : b.ALLOWED | |
}; | |
c.prototype.canAdd = function () { | |
return this._ruleset.add == b.FORBIDDEN ? b.FORBIDDEN : this._applied || !this._checkVersion(this._version) ? b.EXPIRED : b.ALLOWED | |
}; | |
c.prototype.canRemove = function (a, f) { | |
return this._ruleset.remove == b.FORBIDDEN ? b.FORBIDDEN : this._applied || !this._checkVersion(this._version) ? b.EXPIRED : a < 0 || a > this._length ? b.OUT_OF_BOUNDS : a + f > this._length ? b.OUT_OF_BOUNDS : b.ALLOWED | |
}; | |
c.prototype.canMove = function (a, f, k) { | |
return this._ruleset.move == b.FORBIDDEN ? b.FORBIDDEN : this._applied || !this._checkVersion(this._version) ? b.EXPIRED : a < 0 || a > this._length ? b.OUT_OF_BOUNDS : f < 0 || f > this._length ? b.OUT_OF_BOUNDS : a + k > this._length ? b.OUT_OF_BOUNDS : b.ALLOWED | |
}; | |
c.prototype.apply = function () { | |
var a = new h; | |
if (this._applied) return a.fulfill(b.EXPIRED), a; | |
this._applied = !0; | |
this._applyMutation(this._version, | |
this._changes).pipe(a); | |
return a | |
}; | |
c.prototype.insert = function (a, f, k) { | |
var c = this.canInsert(a, f.length); | |
if (c != b.ALLOWED) return c; | |
if (!f.length) return b.SUCCESS; | |
this._length += f.length; | |
a = { | |
type: "insert", | |
begin: a, | |
items: f.slice(0) | |
}; | |
this._changes.push(a); | |
k && k.push(a); | |
return b.SUCCESS | |
}; | |
c.prototype.add = function (a, f) { | |
var k = this.canAdd(a.length); | |
return k != b.ALLOWED ? k : !a.length ? b.SUCCESS : this.insert(this._length, a, f) | |
}; | |
c.prototype.remove = function (a, f, k) { | |
var c = this.canRemove(a, f); | |
if (c != b.ALLOWED) return c; | |
if (f == 0) return b.SUCCESS; | |
this._length -= f; | |
a = { | |
type: "remove", | |
begin: a, | |
length: f | |
}; | |
this._changes.push(a); | |
k && k.push(a); | |
return b.SUCCESS | |
}; | |
c.prototype.move = function (a, f, k, c) { | |
var d = this.canMove(a, f, k); | |
if (d != b.ALLOWED) return d; | |
if (a == f || k == 0) return b.SUCCESS; | |
a = { | |
type: "move", | |
begin: a, | |
end: f, | |
length: k | |
}; | |
this._changes.push(a); | |
c && c.push(a); | |
return b.SUCCESS | |
} | |
})(); | |
(function () { | |
function d(c, h, b, a) { | |
if (!(this instanceof d)) return new d(c, h, b); | |
this._version = c; | |
this._versionedAccessor = h; | |
this._range = b; | |
this._listLength = a | |
} | |
var g = Spotify.ItemList; | |
Spotify.ItemList.Snapshot = d; | |
d.prototype.getOffset = function () { | |
return this._range.begin | |
}; | |
d.prototype.getLength = function () { | |
return this._range.length | |
}; | |
d.prototype.getListLength = function () { | |
return this._listLength | |
}; | |
d.prototype.getVersion = function () { | |
return this._version | |
}; | |
d.prototype.get = function (c) { | |
var d = this._range, | |
b = d.begin + c; | |
return b < | |
0 || b < d.begin || b > d.end ? g.NULL_VALUE : this._versionedAccessor(this._version, b, c) | |
}; | |
d.prototype.toArray = function () { | |
for (var c = [], d = 0, b = this._range.length; d < b; d++) { | |
var a = this.get(d); | |
a != g.NULL_VALUE && c.push(a) | |
} | |
return c | |
}; | |
d.prototype.toFullArray = function () { | |
for (var c = [], d = 0, b = this._range.length; d < b; d++) { | |
var a = this.get(d); | |
c.push(a) | |
} | |
return c | |
} | |
})(); | |
(function () { | |
function d(a) { | |
if (!(this instanceof d)) return new d(a); | |
this._base = a || null; | |
this._descriptor = null; | |
this._observers = []; | |
this._version = 0; | |
this._list = []; | |
this._length = null; | |
this._snapshotLimit = 1E3; | |
this._loadLimit = 200; | |
this._loadedState = f.UNLOADED; | |
this._loadedRanges = []; | |
this._snapshotQueue = []; | |
this.makeMutable() | |
} | |
var g = Spotify.Promise, | |
c = Spotify.Shell.Range, | |
h = Spotify.ItemList, | |
b = Spotify.ItemList.Comparators, | |
a = Spotify.ItemList.Predicates, | |
f = h.LoadedState, | |
k = h.MutationRuleset, | |
m = h.MutationResult, | |
o = h.Mutator, | |
p = h.Snapshot; | |
Spotify.ItemList.Base = d; | |
d.prototype.setDescriptor = function (a) { | |
this._descriptor = a; | |
return this | |
}; | |
d.prototype.getDescriptor = function () { | |
return this._descriptor | |
}; | |
d.prototype.makeMutable = function () { | |
this._ruleset = new k | |
}; | |
d.prototype.makeImmutable = function () { | |
this._ruleset = new k.Immutable; | |
return this | |
}; | |
d.prototype.getVersion = function () { | |
return this._version | |
}; | |
d.prototype.getBaseList = function () { | |
return this._base || null | |
}; | |
d.prototype.getRootBaseList = function () { | |
if (!this._base) return this; | |
for (var a = this, | |
b = this; a = a._base;) b = a; | |
return b | |
}; | |
d.prototype.layersList = function (a) { | |
if (!this._base) return this == a; | |
for (var b = this; b = b._base;) | |
if (b == a) return !0; | |
return !1 | |
}; | |
d.prototype.layersListType = function (a) { | |
if (!this._base) return this instanceof a; | |
for (var b = this; b = b._base;) | |
if (b instanceof a) return !0; | |
return !1 | |
}; | |
d.prototype.createComparator = function (a, f) { | |
return f == "asc" ? b.forString() : b.forStringReversed() | |
}; | |
d.prototype.createPredicate = function () { | |
return a.forNotNull() | |
}; | |
d.prototype.observe = function (a) { | |
this._observers.push(a); | |
return this | |
}; | |
d.prototype.unobserve = function (a) { | |
a = this._observers.indexOf(a); | |
a != -1 && this._observers.splice(a, 1); | |
return this | |
}; | |
d.prototype.notify = function (a, b) { | |
for (var f = this._observers.slice(0), c = 0, k = f.length; c < k; c++) { | |
var d = f[c], | |
m = d[a]; | |
m && m.call(d, b, this) | |
} | |
return this | |
}; | |
d.prototype.onBeforeMutate = function () {}; | |
d.prototype.onMutate = function () {}; | |
d.prototype.createMutator = function () { | |
if (this._loadedState != f.COMPLETE) return null; | |
var a = this._createMutationApplicator(), | |
b = this._createVersionComparator(); | |
return new o(a, | |
b, this._ruleset, this._version, this._length) | |
}; | |
d.prototype._createMutationApplicator = function () { | |
var a = this; | |
return function (b, f) { | |
var k = new g; | |
if (a._version != b) return k.fulfill(m.EXPIRED), k; | |
a.notify("onBeforeMutate", new p(a._version, a._createVersionedAccessor(), new c(0, a._length), a._length)); | |
for (var d = [], h = 0, o = f.length; h < o; h++) { | |
var A = f[h], | |
x = null; | |
switch (A.type) { | |
case "insert": | |
x = a._applyInsertMutation(A); | |
break; | |
case "remove": | |
x = a._applyRemoveMutation(A); | |
break; | |
case "move": | |
x = a._applyMoveMutation(A) | |
} | |
x && d.push(x) | |
} | |
a._version++; | |
a.notify("onMutate", d); | |
k.fulfill(m.SUCCESS); | |
return k | |
} | |
}; | |
d.prototype._applyInsertMutation = function (a) { | |
var b = a.items; | |
this._list.spliceWith(a.begin, 0, b); | |
this._length += b.length; | |
return a | |
}; | |
d.prototype._applyRemoveMutation = function (a) { | |
var b = a.length; | |
this._list.splice(a.begin, b); | |
this._length -= b; | |
return a | |
}; | |
d.prototype._applyMoveMutation = function (a) { | |
var b = a.end, | |
f = this._list, | |
k = f.splice(a.begin, a.length); | |
f.spliceWith(b, 0, k); | |
return a | |
}; | |
d.prototype._unqueueSnapshots = function () { | |
for (var a = this._snapshotQueue, b = 0, f = | |
a.length; b < f; b++) { | |
var k = a[b]; | |
this.snapshot(k[0], k[1]).pipe(k[2]) | |
} | |
}; | |
d.prototype._queueSnapshot = function (a, b, f) { | |
this._snapshotQueue.push([a, b, f]); | |
return this | |
}; | |
d.prototype._fill = function (a) { | |
var b = this._loadedState, | |
k = this._loadLimit, | |
d = new g; | |
if (b == f.COMPLETE) d.fulfill(this); | |
else { | |
for (var b = Math.floor(a.begin * (1 / k)) * k, a = Math.ceil(a.last * (1 / k)) * k, a = new c(b, a - b), b = a.subtractMany(this._loadedRanges), a = [], m = 0, h = b.length; m < h; m++) a.push.apply(a, b[m].split(k)); | |
if (!a.length) return d.fulfill(this), d; | |
k = []; | |
b = 0; | |
for (m = | |
a.length; b < m; b++) k.push(this._load(a[b]).then(this._insertLoadedData.bind(this))); | |
g.join(k).pipe(d) | |
} | |
return d | |
}; | |
d.prototype._insertLoadedData = function (a) { | |
var b = a.range; | |
this._list.insertFrom(b.begin, a.items); | |
this._updateRanges(b); | |
this._updateState(); | |
return a | |
}; | |
d.prototype._updateRanges = function (a) { | |
var b = this._loadedRanges; | |
b.push(a); | |
this._loadedRanges = c.simplify(b) | |
}; | |
d.prototype._updateState = function () { | |
var a = this._loadedRanges; | |
this._loadedState = a.length == 1 && a[0].length >= this._length ? f.COMPLETE : f.PARTIAL | |
}; | |
d.prototype._load = function () { | |
var a = new g; | |
a.fulfill({ | |
state: f.COMPLETE, | |
range: new c(0, 0), | |
items: [] | |
}); | |
return a | |
}; | |
d.prototype._loadLength = function () { | |
var a = new g, | |
b = this._length = 0; | |
a.fulfill({ | |
length: b | |
}); | |
return a | |
}; | |
d.prototype.fillFromArray = function (a, b, k) { | |
this._list.spliceWith(k.begin, k.length, a); | |
this._length = b; | |
a = this._loadedRanges; | |
a.push(k); | |
this._loadedRanges = a = c.simplify(a); | |
this._loadedState = a.length == 1 && a[0].length == b ? f.COMPLETE : f.PARTIAL | |
}; | |
d.prototype.fillFullFromArray = function (a) { | |
this._list.spliceWith(0, | |
0, a); | |
this._length = a.length; | |
this._loadedRanges = [new c(0, a.length)]; | |
this._loadedState = f.COMPLETE | |
}; | |
d.prototype._createVersionComparator = function () { | |
var a = this; | |
return function (b) { | |
return a._version == b | |
} | |
}; | |
d.prototype._createVersionedAccessor = function () { | |
var a = this, | |
b = this._list; | |
return function (f, k) { | |
if (a._version != f) throw Error("Cannot access item with an expired snapshot."); | |
return k in b ? b[k] : h.NULL_VALUE | |
} | |
}; | |
d.prototype.snapshot = function (a, b) { | |
var k = this, | |
d = this._version, | |
m = new g, | |
h; | |
if (b == 0 && this._length != null) return m.fulfill(new p(d, | |
this._createVersionedAccessor(), new c(a, 0), this._length)), m; | |
switch (this._loadedState) { | |
case f.COMPLETE: | |
h = new c(a, b, Math.max(this._length - a, 0)); | |
m.fulfill(new p(d, this._createVersionedAccessor(), h, this._length)); | |
break; | |
case f.PARTIAL: | |
h = new c(a, b, Math.max(this._length - a, 0)); | |
h.findContainer(this._loadedRanges) ? m.fulfill(new p(d, this._createVersionedAccessor(), h, this._length)) : this._fill(h).then(function () { | |
k.snapshot(a, b).pipe(m) | |
}).catchError(function (a) { | |
m.fail(a) | |
}); | |
break; | |
case f.UNLOADED: | |
this._loadLength().then(function (d) { | |
d.length ? | |
this._fill(new c(a, b, Math.min(this._snapshotLimit, this._length))).then(function () { | |
k.snapshot(a, b).pipe(m) | |
}).catchError(function (a) { | |
m.fail(a) | |
}) : (this._loadedState = f.COMPLETE, this.snapshot(a, b).pipe(m)) | |
}.bind(this)) | |
} | |
return m | |
}; | |
d.prototype.snapshotRange = function (a) { | |
return this.snapshot(a.begin, a.length) | |
}; | |
d.prototype.getLength = function () { | |
return this.snapshot(0, 0).call("getListLength") | |
} | |
})(); | |
(function () { | |
function d(c, h) { | |
if (!(this instanceof d)) return new d(c, h); | |
g.call(this, h); | |
this.fillFullFromArray(c || []) | |
} | |
var g = Spotify.ItemList.Base; | |
Spotify.inherit(d, g); | |
Spotify.ItemList.Array = d | |
})(); | |
(function () { | |
function d(a) { | |
if (!(this instanceof d)) return new d(list); | |
if (!a || !a.length) throw new TypeError("ConcatenatedItemList: Argument `lists` cannot be empty."); | |
b.call(this); | |
this._sublists = a.slice(0); | |
this._offsets = []; | |
this._ruleset = new f.Immutable | |
} | |
var g = Spotify.Promise, | |
c = Spotify.Shell.Range, | |
h = Spotify.ItemList, | |
b = h.Base, | |
a = h.Snapshot, | |
f = h.MutationRuleset; | |
Spotify.inherit(d, b); | |
Spotify.ItemList.Concatenated = d; | |
d.prototype._load = function (a) { | |
for (var b = this._sublists, f = this._offsets, d = [], h = 0, n = f.length; h < | |
n; h++) { | |
var s = f[h], | |
s = new c(s, (h + 1 in f ? f[h + 1] : this._length) - s); | |
s.intersects(a) && (s = s.intersect(a), d.push(b[h].snapshot(s.begin, s.length))) | |
} | |
return g.join(d).then(function (b) { | |
for (var f = [], c = 0, d = b.length; c < d; c++) f.push.apply(f, b[c].toArray()); | |
return { | |
range: a, | |
items: f | |
} | |
}) | |
}; | |
d.prototype._loadLength = function () { | |
for (var a = this._sublists, b = [], f = 0, c = a.length; f < c; f++) { | |
var d = a[f]; | |
d.observe(this); | |
b.push(d.snapshot(0, -1)) | |
} | |
return g.join(b).then(this._processInitialSnapshots.bind(this)) | |
}; | |
d.prototype._processInitialSnapshots = | |
function (a) { | |
for (var b = this._list, f = this._offsets, d = this._length = 0, h = a.length; d < h; d++) { | |
var g = a[d], | |
s = g.toFullArray(), | |
t = new c(g.getOffset() + this._length, s.length); | |
b.insertFrom(t.begin, s); | |
f[d] = this._length; | |
this._length += g.getListLength(); | |
this._updateRanges(t); | |
this._updateState() | |
} | |
return { | |
length: this._length | |
} | |
}; | |
d.prototype.onMutate = function (a, b) { | |
a.length && this._applyMutations(a, b) | |
}; | |
d.prototype._applyMutations = function (b, f) { | |
this.notify("onBeforeMutate", new a(this._version, this._createVersionedAccessor(), new c(0, | |
this._length), this._length)); | |
var d = this._sublists.indexOf(f); | |
if (d != -1) { | |
var h = this._offsets[d]; | |
if (h != null) { | |
for (var g = [], n = 0, s = b.length; n < s; n++) { | |
var t = b[n], | |
u = null; | |
switch (t.type) { | |
case "insert": | |
if (u = this._applyInsertMutation({ | |
type: "insert", | |
begin: h + t.begin, | |
items: t.items | |
})) this._incrementOffsets(d + 1, u.items.length), g.push(u); | |
break; | |
case "remove": | |
if (u = this._applyRemoveMutation({ | |
type: "remove", | |
begin: h + t.begin, | |
length: t.length | |
})) this._decrementOffsets(d + 1, u.length), g.push(u); | |
break; | |
case "move": | |
(u = this._applyMoveMutation({ | |
type: "move", | |
begin: h + t.begin, | |
end: h + t.end, | |
length: t.length | |
})) && g.push(u) | |
} | |
} | |
this._version++; | |
this.notify("onMutate", g); | |
return g | |
} | |
} | |
}; | |
d.prototype._incrementOffsets = function (a, b) { | |
for (var f = this._offsets, c = a, d = f.length; c < d; c++) f[c] += b; | |
return this | |
}; | |
d.prototype._decrementOffsets = function (a, b) { | |
for (var f = this._offsets, c = a, d = f.length; c < d; c++) f[c] -= b; | |
return this | |
} | |
})(); | |
(function () { | |
function d(c) { | |
if (!(this instanceof d)) return new d(c); | |
if (!c) throw Error("Required base argument must not be undefined"); | |
g.call(this, c); | |
this._base.observe(this) | |
} | |
var g = Spotify.ItemList.Base; | |
Spotify.inherit(d, g); | |
Spotify.ItemList.Layered = d; | |
d.prototype.createComparator = function (c, d) { | |
return this._base.createComparator(c, d) | |
}; | |
d.prototype.createPredicate = function (c, d, b) { | |
return this._base.createPredicate(c, d, b) | |
}; | |
d.prototype.onBeforeMutate = function (c) { | |
this.notify("onBeforeMutate", c) | |
}; | |
d.prototype.onMutate = | |
function (c) { | |
for (var d = 0, b = c.length; d < b; d++) { | |
var a = c[d]; | |
switch (a.type) { | |
case "insert": | |
this._length += a.items.length; | |
break; | |
case "remove": | |
this._length -= a.length | |
} | |
} | |
this._version++; | |
this.notify("onMutate", c); | |
return c | |
}; | |
d.prototype.createMutator = function () { | |
return this._base.createMutator() | |
}; | |
d.prototype.snapshot = function (c, d) { | |
return this._base.snapshot(c, d) | |
}; | |
d.prototype.getLength = function () { | |
var c = this; | |
return this.snapshot(0, 1).call("getListLength").then(function (d) { | |
return c._length = d | |
}) | |
} | |
})(); | |
(function () { | |
function d(a, b, c) { | |
h.call(this, a); | |
this._range = new g(b, c); | |
this._baseListLength = 0; | |
this.makeImmutable() | |
} | |
var g = Spotify.Shell.Range, | |
c = Spotify.ItemList, | |
h = c.Layered, | |
b = c.Snapshot; | |
Spotify.inherit(d, h); | |
c.Ranged = d; | |
d.prototype.onBeforeMutate = function (a) { | |
this._list = a.toArray() | |
}; | |
d.prototype.onMutate = function (a) { | |
var b = this; | |
this.snapshot(0, -1).then(function (c) { | |
b._applyMutations(a, c) | |
}) | |
}; | |
d.prototype._applyMutations = function (a, f) { | |
var c = this._version; | |
this.notify("onBeforeMutate", new b(c, this._createVersionedAccessor(c, | |
0, f), new g(0, this._range.length), this._range.length)); | |
for (var c = [], d = 0, h = a.length; d < h; d++) { | |
var p = a[d], | |
q = null; | |
switch (p.type) { | |
case "insert": | |
q = this._applyInsertMutation(p); | |
break; | |
case "remove": | |
q = this._applyRemoveMutation(p); | |
break; | |
case "move": | |
q = this._applyMoveMutation(p) | |
} | |
q.length && c.push.apply(c, q) | |
} | |
this._version++; | |
this.notify("onMutate", c); | |
return c | |
}; | |
d.prototype._applyInsertMutation = function (a) { | |
var b = this._range, | |
c = []; | |
if (a.begin >= b.last) return this._list.spliceWith(a.begin, 0, a.items), c; | |
var d = new g(a.begin, | |
a.items.length), | |
h = this._list.length, | |
p = Math.max(0, Math.min(b.length, b.last - h)), | |
d = (new g(0, b.last)).intersect(d).length, | |
h = Math.max(0, b.begin - h), | |
h = Math.min(b.length, d - h), | |
d = Math.max(0, h - p), | |
p = b.last - d - p; | |
d > 0 && c.push({ | |
type: "remove", | |
begin: p - b.begin, | |
length: d | |
}); | |
this._list.spliceWith(a.begin, 0, a.items); | |
h > 0 && (a = Math.max(0, a.begin - b.begin), b = a + b.begin, c.push({ | |
type: "insert", | |
begin: a, | |
items: this._list.slice(b, b + h) | |
})); | |
return c | |
}; | |
d.prototype._applyRemoveMutation = function (a) { | |
var b = this._range, | |
c = null, | |
d = []; | |
if (a.begin >= | |
a.last) return this._list.spliceWith(a.begin, a.length), d; | |
var c = this._list.length, | |
h = c - a.length, | |
g = Math.max(0, c - b.begin), | |
h = Math.max(0, h - b.begin), | |
c = Math.max(0, a.begin - b.begin), | |
c = Math.min(g - h, b.length - c), | |
q = Math.min(b.length, g) - c, | |
g = b.length - q, | |
h = Math.min(g, h - q); | |
c > 0 && (c = { | |
type: "remove", | |
begin: Math.max(0, a.begin - b.begin), | |
length: c | |
}, d.push(c)); | |
this._list.spliceWith(a.begin, a.length); | |
h > 0 && (a = b.length - g, b = a + b.begin, c = { | |
type: "insert", | |
begin: a, | |
items: this._list.slice(b, b + h) | |
}, d.push(c)); | |
return d | |
}; | |
d.prototype._applyMoveMutation = | |
function (a) { | |
var b = [], | |
c = { | |
type: "remove", | |
begin: a.begin, | |
length: a.length | |
}, d = a.end; | |
d > a.begin && (d -= a.length); | |
a = { | |
type: "insert", | |
begin: d, | |
items: this._list.slice(a.begin, a.begin + a.length) | |
}; | |
d = null; | |
d = this._applyRemoveMutation(c); | |
d.length && b.push.apply(b, d); | |
d = this._applyInsertMutation(a); | |
d.length && b.push.apply(b, d); | |
return b | |
}; | |
d.prototype.snapshot = function (a, f) { | |
var c = this, | |
d = this._base, | |
h = this._range, | |
p = this._version, | |
q = new g(h.begin + (a || 0), f, h.length - a); | |
return d.snapshot(q.begin, q.length).then(function (d) { | |
var m = c._createVersionedAccessor(p, | |
a, d), | |
q = new g(a, f, Math.min(h.length, d.getLength())), | |
d = Math.min(d.getListLength(), h.length); | |
return new b(p, m, q, d) | |
}) | |
}; | |
d.prototype._createVersionedAccessor = function (a, b, c) { | |
var d = this; | |
return function (a, h) { | |
if (d._version != a) throw Error("Cannot access item with an expired snapshot."); | |
return c.get(h - b) | |
} | |
} | |
})(); | |
(function () { | |
function d(a, b) { | |
m.call(this, a); | |
this._baseList = []; | |
this._sortedList = null; | |
this._rawComparator = b || k.forString(); | |
this._comparator = this._wrapComparator(this._rawComparator); | |
this._ruleset = new p({ | |
insert: q.FORBIDDEN, | |
move: q.FORBIDDEN | |
}); | |
this._init() | |
} | |
function g(a, b, f) { | |
this._baseList = a.slice(0); | |
this._sortedList = b.slice(0); | |
this._length = a.length; | |
this._rawComparator = this._comparator = f; | |
this._version = 0 | |
} | |
function c(a, b, f, k, d, m, h) { | |
if (!(this instanceof c)) return new c(a); | |
n.call(this, null, k, d, m, h); | |
this._baseMutator = | |
a; | |
this._resolveIndex = f; | |
this._mutationMock = b | |
} | |
var h = Array.prototype.slice, | |
b = Spotify.Promise, | |
a = Spotify.Shell.Range, | |
f = Spotify.ItemList, | |
k = f.Comparators, | |
m = f.Layered, | |
o = f.LoadedState, | |
p = f.MutationRuleset, | |
q = f.MutationResult, | |
n = f.Mutator, | |
s = f.Snapshot; | |
Spotify.inherit(d, m); | |
Spotify.ItemList.Sorted = d; | |
d.prototype._init = function () { | |
this._base.snapshot(0, -1).then(this._buildInitial.bind(this)).catchError(function () {}) | |
}; | |
d.prototype._wrapComparator = function (a) { | |
var b = this._baseList; | |
return function (f, c) { | |
var k = a(b[f], b[c]); | |
return k == 0 ? f - c : k | |
} | |
}; | |
d.prototype._buildInitial = function (a) { | |
this._length = a.getListLength(); | |
this._baseList.spliceWith(0, 0, a.toArray()); | |
this._sortInitial(); | |
this._unqueueSnapshots() | |
}; | |
d.prototype._sortInitial = function () { | |
for (var a = this._baseList.length, b = this._sortedList = Array(a); a--;) b[a] = a; | |
b.sort(this._comparator); | |
this._loadedState = o.COMPLETE | |
}; | |
d.prototype.snapshot = function (f, c) { | |
var k = new b, | |
d = new a(f, c, Math.max(this._length - f, 0)); | |
this._loadedState != o.COMPLETE ? this._queueSnapshot(f, c, k) : (d = new s(this._version, | |
this._createVersionedAccessor(), d, this._length), k.fulfill(d)); | |
return k | |
}; | |
d.prototype._createVersionedAccessor = function () { | |
var a = this, | |
b = this._baseList, | |
c = this._sortedList; | |
return function (k, d) { | |
if (a._version != k) throw Error("Cannot access item with an expired snapshot."); | |
return d in c ? b[c[d]] : f.NULL_VALUE | |
} | |
}; | |
d.prototype._createIndexResolver = function () { | |
var a = this._sortedList; | |
return function (b) { | |
return b in a ? a[b] : f.NULL_VALUE | |
} | |
}; | |
d.prototype._createMutationMock = function () { | |
return new g(this._baseList, this._sortedList, | |
this._rawComparator) | |
}; | |
d.prototype.createMutator = function () { | |
var a = this._base.createMutator(); | |
if (!a) return null; | |
var b = this._createMutationMock(), | |
f = this._createIndexResolver(), | |
k = this._createVersionComparator(); | |
return new c(a, b, f, k, this._ruleset, this._version, this._length) | |
}; | |
d.prototype.onMutate = function (a) { | |
a.length && this._applyMutations(a) | |
}; | |
d.prototype._applyMutations = function (b) { | |
this.notify("onBeforeMutate", new s(this._version, this._createVersionedAccessor(), new a(0, this._length), this._length)); | |
for (var f = [], c = 0, k = b.length; c < k; c++) { | |
var d = b[c], | |
m = null, | |
h, g, o; | |
switch (d.type) { | |
case "remove": | |
h = d.begin; | |
g = d.length; | |
for (d = 0, o = g; d < o; d++) m = { | |
type: "remove", | |
begin: h, | |
length: 1 | |
}, (m = this._applyRemoveMutation(m)) && f.push(m); | |
break; | |
case "move": | |
m = this._applyMoveMutation(d); | |
m.length && f.push.apply(f, m); | |
break; | |
case "insert": | |
h = d.begin; | |
g = d.items; | |
for (d = 0, o = g.length; d < o; d++) m = h + d, m = { | |
type: "insert", | |
begin: m, | |
items: [g[d]] | |
}, (m = this._applyInsertMutation(m)) && f.push(m) | |
} | |
} | |
this._version++; | |
this.notify("onMutate", f); | |
return f | |
}; | |
d.prototype._getInsertionIndex = | |
function (a, b) { | |
var f = this._baseList, | |
c = this._sortedList, | |
k = this._length, | |
d = this._rawComparator, | |
m = 0, | |
h = k - 1, | |
g = a, | |
o = 0; | |
if (k == 0) return 0; | |
if (k == 1) return k = d(b, f[0]), k == 0 ? a > 0 ? 1 : -1 : k > 0 ? 1 : 0; | |
for (; m <= h;) | |
if (g = Math.floor((m + h) / 2), k = d(b, f[c[g]]), k > 0) m = g + 1, o = 1; | |
else if (k < 0) h = g - 1, o = 0; | |
else { | |
if (a == c[g]) break; | |
else a > c[g] ? g += 1 : g -= 1, o = 1; | |
break | |
} | |
return g + o | |
}; | |
d.prototype._applyInsertMutation = function (a) { | |
var b = a.begin, | |
a = a.items[0], | |
f = this._baseList, | |
c = this._sortedList, | |
k = { | |
type: "insert", | |
begin: b, | |
items: [a] | |
}, d = this._getInsertionIndex(b, a); | |
this._incrementSortedIndices(b); | |
c.splice(d, 0, b); | |
k.begin = d; | |
f.splice(b, 0, a); | |
this._length++; | |
return k | |
}; | |
d.prototype._incrementSortedIndices = function (a) { | |
for (var a = a || 0, b = this._sortedList, f = 0, c = b.length; f < c; f++) b[f] >= a && b[f]++ | |
}; | |
d.prototype._decrementSortedIndices = function (a) { | |
for (var a = a || 0, b = this._sortedList, f = 0, c = b.length; f < c; f++) b[f] >= a && b[f]-- | |
}; | |
d.prototype._applyRemoveMutation = function (a) { | |
var a = a.begin, | |
b = this._baseList, | |
f = this._sortedList, | |
c = f.indexOf(a); | |
f.splice(f.indexOf(a), 1); | |
this._decrementSortedIndices(a); | |
b.splice(a, 1); | |
this._length--; | |
return { | |
type: "remove", | |
begin: c, | |
length: 1 | |
} | |
}; | |
d.prototype._applyMoveMutation = function (a) { | |
for (var b = this._baseList, f = this._sortedList, c = a.begin, k = a.end, d = [], m = 0, a = a.length; m < a; m++) { | |
var h = f.indexOf(c), | |
g = b[c], | |
o = h; | |
k < c ? (b.splice(c, 1), b.splice(k, 0, g), this._decrementSortedIndices(c), this._incrementSortedIndices(k), f.splice(h, 1), o = this._getInsertionIndex(k, g), f.splice(o, 0, k), k++, c++) : k > c && (b.splice(k, 0, g), b.splice(c, 1), this._incrementSortedIndices(k), this._decrementSortedIndices(c), | |
f.splice(h, 1), o = this._getInsertionIndex(k - 1, g), f.splice(o, 0, k - 1)); | |
o > h && o++; | |
h != o && d.push({ | |
type: "move", | |
begin: h, | |
end: o, | |
length: 1 | |
}) | |
} | |
return d | |
}; | |
g.prototype.applyMutations = function (a) { | |
a = Array.isArray(a) ? a : h.call(arguments); | |
return this._applyMutations(a) | |
}; | |
g.prototype.notify = function () {}; | |
g.prototype._createVersionedAccessor = function () {}; | |
g.prototype._applyMutations = d.prototype._applyMutations; | |
g.prototype._getInsertionIndex = d.prototype._getInsertionIndex; | |
g.prototype._incrementSortedIndices = d.prototype._incrementSortedIndices; | |
g.prototype._decrementSortedIndices = d.prototype._decrementSortedIndices; | |
g.prototype._applyInsertMutation = d.prototype._applyInsertMutation; | |
g.prototype._applyRemoveMutation = d.prototype._applyRemoveMutation; | |
Spotify.inherit(c, n); | |
c.prototype.apply = function () { | |
return this._baseMutator.apply() | |
}; | |
c.prototype.add = function (a, b) { | |
var f = this.canAdd(a.length); | |
if (f != q.ALLOWED) return f; | |
if (!a.length) return q.SUCCESS; | |
var f = this._baseMutator, | |
c = f.canAdd(a.length); | |
if (c != q.ALLOWED) return c; | |
c = []; | |
f.add(a, c); | |
f = this._mutationMock.applyMutations(c); | |
b && b.push.apply(b, f); | |
return q.SUCCESS | |
}; | |
c.prototype.remove = function (a, b, f) { | |
var c = this.canRemove(a, b); | |
if (c != q.ALLOWED) return c; | |
if (b == 0) return q.SUCCESS; | |
for (var c = this._baseMutator, d = [], m = 0; m < b; m++) { | |
var h = this._resolveIndex(a + m), | |
g = c.canRemove(h, 1); | |
if (g != q.ALLOWED) return g; | |
d.push(h) | |
} | |
d.sort(k.forNumber()); | |
m = []; | |
for (h = 0; h < b; h++) c.remove(d[h] - h, 1, m); | |
this._length -= b; | |
this._mutationMock.applyMutations(m); | |
a = { | |
type: "remove", | |
begin: a, | |
length: b | |
}; | |
f && f.push(a); | |
return q.SUCCESS | |
} | |
})(); | |
(function () { | |
function d(a, b) { | |
f.call(this, a); | |
this._baseList = []; | |
this._loadedBaseRanges = []; | |
this._predicate = b | |
} | |
function g(a, b, f, c) { | |
this._baseList = a.slice(0); | |
this._list = b.slice(0); | |
this._length = f; | |
this._predicate = c; | |
this._version = 0 | |
} | |
function c(a, b, f, k, d, m, h) { | |
if (!(this instanceof c)) return new c(a); | |
o.call(this, null, k, d, m, h); | |
this._baseMutator = a; | |
this._resolveIndex = f; | |
this._mutationMock = b | |
} | |
var h = Spotify.Promise, | |
b = Spotify.Shell.Range, | |
a = Spotify.ItemList, | |
f = a.Layered, | |
k = a.LoadedState, | |
m = a.MutationResult, | |
o = a.Mutator, | |
p = a.Snapshot; | |
Spotify.inherit(d, f); | |
Spotify.ItemList.Filtered = d; | |
d.prototype._buildList = function (f, c) { | |
for (var d = this._list, m = d.length, h = 0, g = this._predicate, o = 0, p = c.length; o < p; o++) { | |
var x = c[o]; | |
x != a.NULL_VALUE && g(x) && (d.push(f.begin + o), h++) | |
} | |
h && this._updateRanges(new b(m, h)); | |
this._baseList.insertFrom(f.begin, c); | |
m = this._loadedBaseRanges; | |
m.push(f); | |
this._loadedBaseRanges = m = b.simplify(m); | |
m.length == 1 && m[0].length >= this._baseLength ? (this._length = d.length, this._loadedState = k.COMPLETE) : this._loadedState = k.PARTIAL; | |
return this | |
}; | |
d.prototype._createVersionedAccessor = function (b, f) { | |
var c = this, | |
k = this._list; | |
return function (d, m) { | |
return c._version != d ? a.NULL_VALUE : m in k ? f[k[m] - b] : a.NULL_VALUE | |
} | |
}; | |
d.prototype._snapshot = function (a, f, c) { | |
var d = this, | |
m = new h, | |
g = new b(a, f), | |
o, A; | |
switch (this._loadedState) { | |
case k.COMPLETE: | |
if (f == -1) f = this._length; | |
o = this._list.slice(a, a + f); | |
A = (new b(o[0], 0)).add(new b(o[o.length - 1], 1)); | |
this._base.snapshotRange(A).then(function (f) { | |
f = new p(d._version, d._createVersionedAccessor(A.begin, f.toFullArray()), new b(a, o.length), | |
d._length); | |
m.fulfill(f) | |
}); | |
break; | |
case k.PARTIAL: | |
if (g.findContainer(this._loadedRanges)) { | |
if (f == -1) f = this._length; | |
o = this._list.slice(a, a + f); | |
A = (new b(o[0], 0)).add(new b(o[o.length - 1], 1)); | |
this._base.snapshotRange(A).then(function (f) { | |
f = new p(d._version, d._createVersionedAccessor(A.begin, f.toFullArray()), new b(a, o.length), o.length); | |
m.fulfill(f) | |
}) | |
} else f = this._loadedBaseRanges[this._loadedBaseRanges.length - 1], f = new b(f.last, 10 * c), this._base.snapshotRange(f).then(function (a) { | |
d._buildList(new b(a.getOffset(), | |
a.getLength()), a.toFullArray()); | |
d._snapshot(g.begin, g.length, ++c).pipe(m) | |
}); | |
break; | |
case k.UNLOADED: | |
this._base.snapshotRange(new b(0, g.last - g.begin + 10 * c)).then(function (a) { | |
d._length = d._baseLength = a.getListLength(); | |
d._buildList(new b(a.getOffset(), a.getLength()), a.toFullArray()); | |
d._snapshot(g.begin, g.length, ++c).pipe(m) | |
}) | |
} | |
return m | |
}; | |
d.prototype.snapshot = function (a, b) { | |
return this._snapshot(a, b, 1) | |
}; | |
d.prototype.onBeforeMutate = function (a) { | |
this._baseList = a.toFullArray() | |
}; | |
d.prototype.onMutate = function (a) { | |
a.length && | |
this._applyMutations(a) | |
}; | |
d.prototype._applyMutations = function (a) { | |
this.notify("onBeforeMutate", new p(this._version, this._createVersionedAccessor(0, this._baseList), new b(0, this._length), this._length)); | |
for (var f = [], c = 0, k = a.length; c < k; c++) { | |
var d = a[c], | |
m = null; | |
switch (d.type) { | |
case "insert": | |
m = this._applyInsertMutation(d); | |
break; | |
case "remove": | |
m = this._applyRemoveMutation(d); | |
break; | |
case "move": | |
m = this._applyMoveMutation(d) | |
} | |
m && f.push(m) | |
} | |
this._version++; | |
this.notify("onMutate", f); | |
return f | |
}; | |
d.prototype._applyInsertMutation = | |
function (a) { | |
var b = this._list, | |
f = a.begin, | |
c = a.items; | |
if (!c.length) return null; | |
var k = this._filterMutationItems(c), | |
a = k.items, | |
k = k.indices, | |
d = this._findInsertionIndex(f); | |
this._updateIndices(d, b.length, c.length); | |
for (var c = 0, m = k.length; c < m; c++) b.splice(d + c, 0, f + k[c]); | |
this._length += k.length; | |
return { | |
type: "insert", | |
begin: d, | |
items: a | |
} | |
}; | |
d.prototype._applyRemoveMutation = function (a) { | |
var b = this._list, | |
f = a.begin, | |
a = a.length, | |
c = f + a; | |
if (!a) return null; | |
for (var k = -1, d = 0, m = 0, h = b.length; m < h; m++) { | |
var g = b[m]; | |
g >= c ? b[m] -= a : g >= f && (k == -1 && | |
(k = m), d++) | |
} | |
b.splice(k, d); | |
this._length -= d; | |
return { | |
type: "remove", | |
begin: k, | |
length: d | |
} | |
}; | |
d.prototype._applyMoveMutation = function (a) { | |
var f = this._list, | |
c = a.begin, | |
k = a.end, | |
a = a.length; | |
if (c == k) return null; | |
var d = this._getIndicesInRange(new b(c, a)), | |
m = this._findInsertionIndex(c), | |
h = this._findInsertionIndex(k); | |
c < k ? (c = k - c - a, this._updateIndices(m + d.length, h, -a), f.spliceWith(h, 0, d), f.splice(m, d.length), this._updateIndices(h - d.length, h, c)) : (c = k - c, this._updateIndices(h, m, a), f.splice(m, d.length), f.spliceWith(h, 0, d), this._updateIndices(h, | |
h + d.length, c)); | |
return m == h ? null : { | |
type: "move", | |
begin: m, | |
end: h, | |
length: d.length | |
} | |
}; | |
d.prototype._filterMutationItems = function (a) { | |
for (var b = [], f = [], c = this._predicate, k = 0, d = a.length; k < d; k++) { | |
var m = a[k]; | |
c(m) && (b.push(m), f.push(k)) | |
} | |
return { | |
items: b, | |
indices: f | |
} | |
}; | |
d.prototype._findInsertionIndex = function (a) { | |
for (var b = this._list, f = 0, c = b.length; f < c; f++) | |
if (b[f] >= a) return f; | |
return c | |
}; | |
d.prototype._getIndicesInRange = function (a) { | |
for (var b = this._list, f = [], c = 0, k = b.length; c < k; c++) { | |
var d = b[c]; | |
a.has(d) && f.push(d) | |
} | |
return f | |
}; | |
d.prototype._createMutationMock = | |
function () { | |
return new g(this._baseList, this._list, this._length, this._predicate) | |
}; | |
d.prototype.createMutator = function () { | |
var a = this._base.createMutator(); | |
if (!a) return null; | |
var b = this._createMutationMock(), | |
f = this._createIndexResolver(), | |
k = this._createVersionComparator(); | |
return new c(a, b, f, k, this._ruleset, this._version, this._length) | |
}; | |
d.prototype._createIndexResolver = function () { | |
var b = this._list; | |
return function (f) { | |
return f in b ? b[f] : a.NULL_VALUE | |
} | |
}; | |
d.prototype._updateIndices = function (a, b, f) { | |
for (var c = this._list; a < | |
b; a++) c[a] += f | |
}; | |
g.prototype.applyMutations = function (a) { | |
a = Array.isArray(a) ? a : slice.call(arguments); | |
return this._applyMutations(a) | |
}; | |
g.prototype.notify = function () {}; | |
g.prototype._createVersionedAccessor = function () {}; | |
g.prototype._applyMutations = d.prototype._applyMutations; | |
g.prototype._applyInsertMutation = d.prototype._applyInsertMutation; | |
g.prototype._applyRemoveMutation = d.prototype._applyRemoveMutation; | |
g.prototype._applyMoveMutation = d.prototype._applyMoveMutation; | |
g.prototype._filterMutationItems = d.prototype._filterMutationItems; | |
g.prototype._findInsertionIndex = d.prototype._findInsertionIndex; | |
g.prototype._getIndicesInRange = d.prototype._getIndicesInRange; | |
g.prototype._updateIndices = d.prototype._updateIndices; | |
Spotify.inherit(c, o); | |
Spotify.ItemList.Mutator.Filtered = c; | |
c.prototype.apply = function () { | |
return this._baseMutator.apply() | |
}; | |
c.prototype.add = function (a, b) { | |
var f = this.canAdd(a.length); | |
if (f != m.ALLOWED) return f; | |
if (!a.length) return m.SUCCESS; | |
var f = this._baseMutator, | |
c = f.canAdd(a.length); | |
if (c != m.ALLOWED) return c; | |
c = []; | |
f.add(a, c); | |
f = | |
this._mutationMock.applyMutations(c); | |
b && b.push.apply(b, f); | |
return m.SUCCESS | |
}; | |
c.prototype.insert = function (a, b, f) { | |
var c = this.canInsert(a, b.length); | |
if (c != m.ALLOWED) return c; | |
if (!b.length) return m.SUCCESS; | |
var a = this._resolveIndex(a), | |
c = this._baseMutator, | |
k = c.canInsert(a, b.length); | |
if (k != m.ALLOWED) return k; | |
k = []; | |
c.insert(a, b, k); | |
b = this._mutationMock.applyMutations(k); | |
this._length = this._mutationMock._length; | |
f && f.push.apply(f, b); | |
return m.SUCCESS | |
}; | |
c.prototype.remove = function (a, b, f) { | |
var c = this.canRemove(a, b); | |
if (c != | |
m.ALLOWED) return c; | |
if (b == 0) return m.SUCCESS; | |
for (var c = this._baseMutator, k = [], d = 0; d < b; d++) { | |
var h = this._resolveIndex(a + d), | |
g = c.canRemove(h, 1); | |
if (g != m.ALLOWED) return g; | |
k.push(h) | |
} | |
k.sort(function (a, b) { | |
return a - b | |
}); | |
d = []; | |
for (h = 0; h < b; h++) c.remove(k[h] - h, 1, d); | |
this._length -= b; | |
this._mutationMock.applyMutations(d); | |
a = { | |
type: "remove", | |
begin: a, | |
length: b | |
}; | |
f && f.push(a); | |
return m.SUCCESS | |
}; | |
c.prototype.move = function (a, b, f, c) { | |
var k = this.canMove(a, b, f); | |
if (k != m.ALLOWED) return k; | |
if (a == b || f == 0) return m.SUCCESS; | |
for (var k = this._baseMutator, | |
d = [], h = 0; h < f; h++) { | |
var g = this._resolveIndex(a + h), | |
o = k.canMove(g, a, 1); | |
if (o != m.ALLOWED) return o; | |
d.push(g) | |
} | |
for (var h = this._resolveIndex(b), g = [], o = 0, p = d.length; o < p; o++) k.move(d[o] - o, h, 1, g); | |
this._mutationMock.applyMutations(g); | |
a = { | |
type: "move", | |
begin: a, | |
end: b, | |
length: f | |
}; | |
c && c.push(a); | |
return m.SUCCESS | |
} | |
})(); | |
(function () { | |
function d() { | |
this.type = null | |
} | |
function g(a) { | |
if (!(this instanceof g)) return new g(a); | |
if (!a) throw Error("Invalid arguments."); | |
this.type = "list"; | |
this.uri = a | |
} | |
function c(a) { | |
if (!(this instanceof c)) return new c(uri); | |
if (!a) throw Error("Invalid arguments."); | |
this.lists = a; | |
this.type = "concatenate" | |
} | |
function h(a, b, f) { | |
if (!(this instanceof h)) return new h(uri); | |
if (b == void 0 || a == void 0 || f == void 0) throw Error("Invalid arguments."); | |
this.args = b; | |
this.list = a; | |
this.type = "sort"; | |
this.version = f; | |
this.field = b[0]; | |
this.order = | |
b[1] | |
} | |
function b(a, f, c) { | |
if (!(this instanceof b)) return new b(uri); | |
if (f == void 0 || a == void 0 || c == void 0) throw Error("Invalid arguments."); | |
this.args = f; | |
this.list = a; | |
this.type = "filter"; | |
this.version = c; | |
this.operator = f[0]; | |
this.field = f[1]; | |
this.matcher = f[2] | |
} | |
function a(b, f, c) { | |
if (!(this instanceof a)) return new a(uri); | |
if (f == void 0 || b == void 0 || c == void 0) throw Error("Invalid arguments."); | |
this.args = f; | |
this.list = b; | |
this.type = "range"; | |
this.version = c; | |
this.offset = f[0]; | |
this.length = f[1] | |
} | |
function f(a, b, c) { | |
if (!(this instanceof f)) return new f(uri); | |
if (b == void 0 || a == void 0 || c == void 0) throw Error("Invalid arguments."); | |
this.args = b; | |
this.list = a; | |
this.type = "shuffle"; | |
this.version = c; | |
this.seed = b[0] | |
} | |
Spotify.ItemList.Descriptor = {}; | |
Spotify.ItemList.Descriptor.from = function (a) { | |
return !a ? null : typeof descriptor == "string" ? this.fromString(a) : this.fromObject(a) | |
}; | |
Spotify.ItemList.Descriptor.fromString = function (a) { | |
try { | |
var b = this.fromObject(JSON.parse(a)); | |
return b instanceof d ? b : null | |
} catch (f) { | |
return null | |
} | |
}; | |
Spotify.ItemList.Descriptor.fromObject = | |
function (k) { | |
if (k instanceof d) return k; | |
try { | |
switch (k.type) { | |
case "list": | |
return new g(k.uri); | |
case "concatenate": | |
for (var o = [], p = 0, q = k.lists.length; p < q; p++) { | |
var n = this.fromObject(k.lists[p]); | |
if (!n) return null; | |
o.push(n) | |
} | |
return new c(o); | |
case "sort": | |
return new h(this.fromObject(k.list), k.args, k.version); | |
case "filter": | |
return new b(this.fromObject(k.list), k.args, k.version); | |
case "range": | |
return new a(this.fromObject(k.list), k.args, k.version); | |
case "shuffle": | |
return new f(this.fromObject(k.list), k.args, k.version); | |
default: | |
return null | |
} | |
} catch (s) { | |
return null | |
} | |
}; | |
Spotify.ItemList.Descriptor.occludeFields = function (a, b) { | |
return a == "operator" || a == "field" || a == "matcher" || a == "offset" || a == "length" || a == "seed" || a == "order" ? void 0 : b | |
}; | |
Spotify.ItemList.Descriptor.Base = d; | |
var k = Spotify.ItemList.Descriptor.occludeFields; | |
d.prototype.serialize = function () { | |
return JSON.stringify(this, k) | |
}; | |
g.prototype = new d; | |
Spotify.ItemList.Descriptor.List = g; | |
c.prototype = new d; | |
Spotify.ItemList.Descriptor.Concatenated = c; | |
h.prototype = new d; | |
Spotify.ItemList.Descriptor.Sorted = | |
h; | |
b.prototype = new d; | |
Spotify.ItemList.Descriptor.Filtered = b; | |
a.prototype = new d; | |
Spotify.ItemList.Descriptor.Ranged = a; | |
f.prototype = new d; | |
Spotify.ItemList.Descriptor.Shuffled = f | |
})(); | |
(function () { | |
function d(a, f) { | |
b.call(this, a); | |
this._index = -1; | |
this._loadLimit = f || 10; | |
this._infinite = !1; | |
this._callQueue = []; | |
this._init() | |
} | |
var g = Spotify.Promise, | |
c = Spotify.Shell.Range, | |
h = Spotify.ItemList, | |
b = h.Layered, | |
a = h.LoadedState, | |
f = h.Snapshot; | |
Spotify.inherit(d, b); | |
Spotify.ItemList.Iterable = d; | |
d.prototype._init = function () { | |
this._loadLength().then(this._unqueueCalls.bind(this)) | |
}; | |
d.prototype._queueCall = function () { | |
var a = new g, | |
b = this._queueCall.caller; | |
this._callQueue.push({ | |
fn: b, | |
args: b.arguments, | |
promise: a | |
}); | |
return a | |
}; | |
d.prototype._unqueueCalls = function () { | |
for (var a = this._callQueue, b = 0, f = a.length; b < f; b++) { | |
var c = a[b]; | |
c.fn.apply(this, c.args).pipe(c.promise) | |
} | |
}; | |
d.prototype._load = function (a) { | |
return this._base.snapshotRange(a).then(function (a) { | |
return { | |
range: new c(a.getOffset(), a.getLength()), | |
items: a.toArray() | |
} | |
}) | |
}; | |
d.prototype._loadLength = function () { | |
var b = this; | |
return this._base.getLength().then(function (f) { | |
b._length = f; | |
b._loadedState = a.PARTIAL; | |
return { | |
length: f | |
} | |
}) | |
}; | |
d.prototype.makeInfinite = function () { | |
this._infinite = !0 | |
}; | |
d.prototype.makeFinite = | |
function () { | |
this._infinite = !1 | |
}; | |
d.prototype.startAt = function (b) { | |
if (this._loadedState == a.UNLOADED) return this._queueCall(); | |
var f = new g; | |
this._index = b == -1 || b > this._length ? this._length : b < 0 ? -1 : b - 1; | |
f.fulfill(!0); | |
return f | |
}; | |
d.prototype.rewind = function () { | |
this._index = -1; | |
return this | |
}; | |
d.prototype.getIndex = function () { | |
var a = this._index; | |
return a < 0 ? h.LIST_START : a >= this._length ? h.LIST_END : a | |
}; | |
d.prototype.preload = function (b) { | |
if (this._loadedState == a.UNLOADED) return this._queueCall(); | |
var f = this._loadLimit, | |
b = new c((b == void 0 ? | |
0 : b) - f, (f || 1) * 2); | |
b.begin < 0 && (b = b.subtract(new c(0, 0)), b = b[1].add(new c(b[1].last, b[0].length))); | |
return this._fill(b).then(function () { | |
return !0 | |
}, function () { | |
return !1 | |
}) | |
}; | |
d.prototype.hasNext = function () { | |
if (this._loadedState == a.UNLOADED) return this._queueCall(); | |
var b = this._index, | |
f = new g; | |
return this._infinite ? (f.fulfill(!0), f) : b + 1 >= this.length ? (f.fulfill(!1), f) : this.snapshot(b + 1, 1).then(function (a) { | |
return a.get(0) !== h.NULL_VALUE | |
}, function () { | |
return !1 | |
}) | |
}; | |
d.prototype.hasPrevious = function () { | |
if (this._loadedState == | |
a.UNLOADED) return this._queueCall(); | |
var b = this._index, | |
f = new g; | |
return this._infinite ? (f.fulfill(!0), f) : b - 1 < 0 ? (f.fulfill(!1), f) : this.snapshot(b - 1, 1).then(function (a) { | |
return a.get(0) !== h.NULL_VALUE | |
}, function () { | |
return !1 | |
}) | |
}; | |
d.prototype.next = function () { | |
if (this._loadedState == a.UNLOADED) return this._queueCall(); | |
var b = this._index; | |
if (this._infinite && b + 1 == this._length) this._index = b = 0; | |
else if (b + 1 > this._length - 1) return this._index = b = this._length, b = new g, b.fulfill(h.LIST_END), b; | |
else this._index = b += 1; | |
return this.snapshot(b, | |
1).then(function (a) { | |
a = a.get(0); | |
return a == h.NULL_VALUE ? h.LIST_END : a | |
}, function () { | |
return h.LIST_END | |
}) | |
}; | |
d.prototype.previous = function () { | |
if (this._loadedState == a.UNLOADED) return this._queueCall(); | |
var b = this._index; | |
if (this._infinite && b - 1 == -1) this._index = b = this._length - 1; | |
else if (b - 1 < 0) return this._index = b = -1, b = new g, b.fulfill(h.LIST_START), b; | |
else this._index = b -= 1; | |
return this.snapshot(b, 1).then(function (a) { | |
a = a.get(0); | |
return a == h.NULL_VALUE ? h.LIST_START : a | |
}, function () { | |
return h.LIST_START | |
}) | |
}; | |
d.prototype.pop = | |
function () { | |
var b = this; | |
if (this._loadedState == a.UNLOADED) return this._queueCall(); | |
var f = new g; | |
this.snapshot(0, 1).then(function (a) { | |
var c = b._base.createMutator(), | |
d = a.get(0); | |
d == h.NULL_VALUE || c.canRemove(0, 1) != h.MutationResult.ALLOWED ? f.fulfill(h.NULL_VALUE) : (c.remove(0, 1), c.apply().then(function (a) { | |
a == h.MutationResult.SUCCESS ? f.fulfill(d) : f.fulfill(h.NULL_VALUE) | |
}, function () { | |
f.fulfill(h.NULL_VALUE) | |
})) | |
}, function () { | |
f.fulfill(h.NULL_VALUE) | |
}); | |
return f | |
}; | |
d.prototype.onMutate = function (a) { | |
a.length && this._applyMutations(a) | |
}; | |
d.prototype._applyMutations = function (a) { | |
this.notify("onBeforeMutate", new f(this._version, this._createVersionedAccessor(), new c(0, this._length), this._length)); | |
if (this._index != -1) | |
for (var b = 0, d = a.length; b < d; b++) { | |
var h = a[b]; | |
switch (h.type) { | |
case "insert": | |
this._applyInsertMutation(h); | |
break; | |
case "remove": | |
this._applyRemoveMutation(h); | |
break; | |
case "move": | |
this._applyMoveMutation(h) | |
} | |
} | |
this._version++; | |
this.notify("onMutate", a); | |
return a | |
}; | |
d.prototype._applyInsertMutation = function (a) { | |
var b = a.begin, | |
f = a.items.length; | |
if (!f) return a; | |
this._length += f; | |
b <= this._index + 1 && (this._index += f + 1); | |
return a | |
}; | |
d.prototype._applyRemoveMutation = function (a) { | |
var b = a.begin, | |
f = a.length; | |
if (!f) return a; | |
var d = new c(b, f); | |
this._length -= f; | |
b == this._index ? this._index-- : d.has(this._index) ? this._index = b - 1 : b < this._index && (this._index -= f); | |
return a | |
}; | |
d.prototype._applyMoveMutation = function (a) { | |
var b = a.begin, | |
f = a.end, | |
d = a.length; | |
if (!d) return a; | |
var h = new c(b, d); | |
h.has(this._index + 1) ? this._index = h.end + (this._index - h.begin) : b > f ? this._index += d : this._index -= | |
d; | |
return a | |
} | |
})(); | |
(function () { | |
function d(a, f) { | |
this._property = a; | |
this._baseSnapshot = f; | |
this._range = new b(f.getOffset(), f.getLength()); | |
this._version = f.getVersion(); | |
this._listLength = f.getListLength() | |
} | |
function g(a, b) { | |
if (!(this instanceof g)) return new g(a, b); | |
if (!b) throw new TypeError("PropertyItemList: Argument property must not be undefined."); | |
h.call(this, a); | |
this._property = b | |
} | |
var c = Spotify.ItemList, | |
h = c.Layered, | |
b = Spotify.Shell.Range; | |
Spotify.inherit(d, c.Snapshot); | |
Spotify.ItemList.PropertySnapshot = d; | |
d.prototype.get = function (a) { | |
var b = | |
this._property, | |
a = this._baseSnapshot.get(a); | |
a != c.NULL_VALUE && (a = b in a ? a[b] : c.NULL_VALUE); | |
return a | |
}; | |
Spotify.inherit(g, h); | |
Spotify.ItemList.Property = g; | |
g.prototype.onBeforeMutate = function (a) { | |
this.notify("onBeforeMutate", new d(this._property, a)) | |
}; | |
g.prototype.onMutate = function (a) { | |
a.length && this._applyMutations(a) | |
}; | |
g.prototype._applyMutations = function (a) { | |
for (var b = [], k = 0, d = a.length; k < d; k++) { | |
var h = a[k]; | |
switch (h.type) { | |
case "insert": | |
for (var g = this._property, q = h.items, n = q.length, s = Array(n); n--;) s[n] = g in q[n] ? | |
q[n][g] : c.NULL_VALUE; | |
this._length += n; | |
b.push({ | |
type: "insert", | |
begin: h.begin, | |
items: s | |
}); | |
break; | |
case "remove": | |
this._length -= h.length; | |
b.push(h); | |
break; | |
case "move": | |
b.push(h) | |
} | |
} | |
this._version++; | |
this.notify("onMutate", b); | |
return b | |
}; | |
g.prototype.snapshot = function (a, b) { | |
var c = this._property; | |
return this._base.snapshot(a, b).then(function (a) { | |
return new d(c, a) | |
}) | |
} | |
})(); | |
(function () { | |
function d(c) { | |
if (!(this instanceof d)) return new d(c); | |
this.uri = c.toString() | |
} | |
var g = Spotify.Utils; | |
Spotify.Shell.Entities = {}; | |
Spotify.Shell.Entities.Base = d; | |
Spotify.Shell.Entities.createImages = function (c, d) { | |
for (var d = d || "", b = null, a = [], f = 0, k = c.length; f < k; f++) { | |
var m = c[f]; | |
if (m.file_id) { | |
var o = d + g.str2hex(m.file_id); | |
a.push([m.width < m.height ? m.width : m.height, o]); | |
!b && m.size.toLowerCase() == "default" && (b = o) | |
} | |
}!b && a.length && (b = a[0][1]); | |
a.sort(function (a, b) { | |
return a[0] - b[0] | |
}); | |
return { | |
image: b, | |
images: a | |
} | |
}; | |
Spotify.Shell.Entities.createSearchImages = function (c, d) { | |
for (var d = d || "", b = null, a = [], f = { | |
small: 120, | |
large: 640, | |
"default": 300 | |
}, k = 0, m = c.length; k < m; k++) { | |
var g = c[k]; | |
if (g.file_id) { | |
var p = d + g.file_id; | |
a.push([f[g.size.toLowerCase()], p]); | |
!b && g.size.toLowerCase() == "default" && (b = p) | |
} | |
}!b && a.length && (b = a[0][1]); | |
a.sort(function (a, b) { | |
return a[0] - b[0] | |
}); | |
return { | |
image: b, | |
images: a | |
} | |
} | |
})(); | |
(function () { | |
function d(b, a) { | |
if (!(this instanceof d)) return new d(b, a); | |
this.uri = b.toString(); | |
a && this._fill(a) | |
} | |
var g = Spotify.Link, | |
c = Spotify.Promise, | |
h = Spotify.Shell.Entities; | |
Spotify.Shell.Entities.Album = d; | |
d.prototype._fill = function (b) { | |
var a, f; | |
this.artistName = ""; | |
this.artists = []; | |
this.availability = b.availability; | |
this.copyrights = []; | |
this.date = b.date || {}; | |
this.discs = []; | |
this.image = null; | |
this.images = []; | |
this.label = b.label; | |
this.name = b.name; | |
this.playable = b.playable; | |
this.popularity = b.popularity; | |
this.type = (b.type || | |
"").toLowerCase(); | |
var c = b.artist, | |
d = this.artists = [], | |
o = []; | |
this.artistName = ""; | |
if (c && c.length) { | |
for (a = 0, f = c.length; a < f; a++) { | |
var p = c[a]; | |
d.push({ | |
uri: g.artistLink(p.id).toString(), | |
name: p.name | |
}); | |
o.push(p.name) | |
} | |
this.artistName = o.join(";") | |
} | |
if (a = b.cover_group && b.cover_group.image) a = h.createImages(a, b.resourceUrl), this.image = a.image, this.images = a.images; | |
c = this.discs; | |
if (d = b.disc) { | |
o = g.fromString(this.uri); | |
for (a = 0, f = d.length; a < f; a++) { | |
p = d[a]; | |
o.disc = p.number; | |
for (var q = [], n = 0, s = p.track.length; n < s; n++) q.push(g.trackLink(p.track[n].id).toString()); | |
c.push({ | |
album: this.uri, | |
number: p.number, | |
tracks: q, | |
uri: o.toString() | |
}) | |
} | |
} | |
if (b = b.copyright) { | |
c = this.copyrights; | |
for (a = 0, f = b.length; a < f; a++) { | |
var t = b[a]; | |
c[a] = t.text.replace(/^(\([A-Z]+\))?(.*)$/, function (a, b, f) { | |
return b ? a : "(" + t.type + ") " + f | |
}) | |
} | |
} | |
}; | |
d.create = function (b, a) { | |
var f = new c; | |
try { | |
f.fulfill(new d(b, a)) | |
} catch (k) { | |
f.fail(k) | |
} | |
return f | |
}; | |
d.createComparator = function () { | |
return null | |
}; | |
d.createPredicate = function () { | |
return null | |
} | |
})(); | |
(function () { | |
function d(b, a) { | |
if (!(this instanceof d)) return new d(b, a); | |
this.uri = b.toString(); | |
a && this._fill(a) | |
} | |
var g = Spotify.Link, | |
c = Spotify.Promise, | |
h = Spotify.Shell.Entities; | |
Spotify.Shell.Entities.Artist = d; | |
d.prototype._fill = function (b) { | |
var a, f, c, d; | |
this.name = b.name; | |
this.popularity = b.popularity; | |
this.image = null; | |
this.images = []; | |
this.genres = []; | |
this.biography = ""; | |
this.portraits = []; | |
this.years = null; | |
if (b.genre) this.genres = b.genre.slice(); | |
if (c = b.portrait_group && b.portrait_group.image) c = h.createImages(c, b.resourceUrl), | |
this.image = c.image, this.images = c.images; | |
if ((c = b.biography) && c.length) | |
for (d = c.length; d--;) { | |
a = c[d]; | |
if (a.text) this.biography = a.text; | |
if (a.portrait_group) { | |
var g = a.portrait_group; | |
for (a = 0, f = g.length; a < f; a++) { | |
var p = g[a] && g[a].image; | |
p && (p = h.createImages(p, b.resourceUrl), p.image && this.portraits.push(p.image)) | |
} | |
} | |
} | |
if ((a = b.activity_period) && a.length) { | |
f = []; | |
for (c = 0, d = a.length; c < d; c++) p = a[c], g = p.start_year || p.decade, p = p.end_year || p.decade + 9, isNaN(p) && (p = (new Date).getFullYear()), f.push({ | |
start: g, | |
end: p | |
}); | |
if (f.length) this.years = { | |
from: f[0].start, | |
to: f[f.length - 1].end | |
} | |
} | |
this.getAlbumGroups = this.getAlbumGroups.bind(this, b); | |
this.getAppearsOnGroups = this.getAppearsOnGroups.bind(this, b); | |
this.getSingleGroups = this.getSingleGroups.bind(this, b); | |
this.getRelatedArtists = this.getRelatedArtists.bind(this, b); | |
this.getTopTracks = this.getTopTracks.bind(this, b) | |
}; | |
d.prototype.getAlbumGroups = function (b) { | |
var a = [], | |
f = b.album_group; | |
if (f && f.length) | |
for (var c = 0, d = f.length; c < d; c++) { | |
for (var h = f[c], b = [], p = 0, q = h.length; p < q; p++) b.push(g.albumLink(h[p].id).toURI()); | |
a.push(b) | |
} | |
return a | |
}; | |
d.prototype.getAppearsOnGroups = function (b) { | |
var a = [], | |
f = b.appears_on_group; | |
if (f && f.length) | |
for (var c = 0, d = f.length; c < d; c++) { | |
for (var h = f[c], b = [], p = 0, q = h.length; p < q; p++) b.push(g.albumLink(h[p].id).toURI()); | |
a.push(b) | |
} | |
return a | |
}; | |
d.prototype.getSingleGroups = function (b) { | |
var a = [], | |
f = b.single_group; | |
if (f && f.length) | |
for (var c = 0, d = f.length; c < d; c++) { | |
for (var h = f[c], b = [], p = 0, q = h.length; p < q; p++) b.push(g.albumLink(h[p].id).toURI()); | |
a.push(b) | |
} | |
return a | |
}; | |
d.prototype.getRelatedArtists = function (b) { | |
var a = []; | |
if ((b = b.related) && b.length) | |
for (var f = 0, c = b.length; f < c; f++) a.push(g.artistLink(b[f].id).toURI()); | |
return a | |
}; | |
d.prototype.getTopTracks = function (b) { | |
var a = []; | |
if ((b = b.top_track) && b.length) | |
for (i = 0, l = b.length; i < l; i++) a.push(g.trackLink(b[i].id).toURI()); | |
return a | |
}; | |
d.create = function (b, a) { | |
var f = new c; | |
f.fulfill(new d(b, a)); | |
return f | |
}; | |
d.createComparator = function () {}; | |
d.createPredicate = function () {} | |
})(); | |
(function () { | |
function d(a, b) { | |
if (!(this instanceof d)) return new d(a, b); | |
this.uri = a.toString(); | |
b && this._fill(b) | |
} | |
function g(a, b) { | |
if (!(this instanceof g)) return new g(a, b); | |
this.uri = a.toString(); | |
b && this._fill(b) | |
} | |
var c = Spotify.Link, | |
h = Spotify.Promise, | |
b = Spotify.ItemList, | |
a = b.Comparators, | |
f = b.Predicates, | |
k = Spotify.Shell.Entities; | |
Spotify.Shell.Entities.Playlist = d; | |
d.prototype._fill = function (a) { | |
this.name = a.name; | |
this.owner_name = a.owner; | |
this.owner = { | |
uri: c.profileLink(a.owner).toString() | |
}; | |
this.collaborative = !! a.collaborative; | |
this.description = a.description || ""; | |
if (a.picture) { | |
var b = a.picture; | |
try { | |
b = decodeURIComponent(b) | |
} catch (f) {} | |
a = k.createImages([{ | |
width: 300, | |
height: 300, | |
file_id: b | |
}], a.resourceUrl); | |
this.image = a.image; | |
this.images = a.images | |
} | |
}; | |
d.create = function (a, b) { | |
var f = new h; | |
try { | |
f.fulfill(new d(a, b)) | |
} catch (c) { | |
f.fail(c) | |
} | |
return f | |
}; | |
d.prototype.createComparator = function () { | |
return null | |
}; | |
d.prototype.createPredicate = function () { | |
return null | |
}; | |
Spotify.Shell.Entities.PlaylistRow = g; | |
g.prototype._fill = function (a) { | |
this.creator = (this.creatorName = | |
a.added_by) ? c.profileLink(a.added_by) : null; | |
this.addTime = a.timestamp; | |
this.track = a.track | |
}; | |
g.prototype.setTrack = function (a) { | |
this.track = a | |
}; | |
g.create = function (a, b) { | |
var f = new h; | |
try { | |
f.fulfill(new g(a, b)) | |
} catch (c) { | |
f.fail(c) | |
} | |
return f | |
}; | |
g.createComparator = function (b, f) { | |
switch (b) { | |
case "uri": | |
case "creator": | |
return f == "desc" ? a.forStringPropertyReversed(b) : a.forStringProperty(b); | |
case "addTime": | |
return f == "desc" ? a.forNumberPropertyReversed(b) : a.forNumberProperty(b); | |
default: | |
var c = k.Track.createComparator(b, f); | |
if (c) return function (a, | |
b) { | |
return c(a && a.track, b && b.track) | |
} | |
} | |
return null | |
}; | |
g.createPredicate = function (a, b, c) { | |
switch (a) { | |
case "uri": | |
case "creator": | |
case "addTime": | |
return f.forPropertyOperator(a, b, c); | |
default: | |
var d = k.Track.createPredicate(a, b, c); | |
if (d) return function (a) { | |
return d(a && a.track) | |
} | |
} | |
return null | |
} | |
})(); | |
(function () { | |
function d(a, b) { | |
if (!(this instanceof d)) return new d(a, b); | |
this.uri = a.toString(); | |
b && this._fill(b) | |
} | |
function g(a, b) { | |
if (!(this instanceof g)) return new g(a, b); | |
this.uri = a.toString(); | |
b && this._fill(b) | |
} | |
function c(a, b) { | |
if (!(this instanceof c)) return new c(a, b); | |
this.uri = a.toString(); | |
b && this._fill(b) | |
} | |
function h(a, b) { | |
if (!(this instanceof h)) return new h(a, b); | |
this.uri = a.toString(); | |
b && this._fill(b) | |
} | |
var b = Spotify.Link, | |
a = Spotify.Shell.Entities; | |
Spotify.Shell.Entities.SearchAlbum = d; | |
d.prototype._fill = function (f) { | |
var c, | |
d; | |
this.artistName = ""; | |
this.artists = []; | |
this.availability = f.availability; | |
this.image = void 0; | |
this.images = []; | |
this.name = f.name; | |
this.playable = f.playable; | |
this.popularity = f.popularity; | |
this.type = (f.type || "").toLowerCase(); | |
var h = f.artists, | |
g = this.artists, | |
q = []; | |
this.artistName = ""; | |
if (h && h.length) { | |
for (c = 0, d = h.length; c < d; c++) { | |
var n = h[c]; | |
g.push({ | |
uri: b.artistLink(n.id).toString(), | |
name: n.name | |
}); | |
q.push(n.name) | |
} | |
this.artistName = q.join(";") | |
} | |
if (c = f.cover) f = a.createSearchImages(c, f.resourceUrl), this.image = f.image, this.images = | |
f.images | |
}; | |
Spotify.Shell.Entities.SearchArtist = g; | |
g.prototype._fill = function (b) { | |
this.availability = b.availability; | |
this.image = void 0; | |
this.images = []; | |
this.name = b.name; | |
this.playable = b.playable; | |
this.popularity = b.popularity; | |
var c = b.portrait; | |
if (c) b = a.createSearchImages(c, b.resourceUrl), this.image = b.image, this.images = b.images | |
}; | |
Spotify.Shell.Entities.SearchPlaylist = c; | |
c.prototype._fill = function (a) { | |
this.image = void 0; | |
this.images = []; | |
this.name = a.name; | |
this.owner_name = a.owner; | |
this.owner = { | |
uri: b.profileLink(a.owner).toString() | |
}; | |
var c = a.image; | |
if (c) { | |
var d = this.images, | |
c = c.split(":").splice(2, c.length - 1).join(""), | |
c = this.image = a.resourceUrls.normal + c; | |
d.push([300, c]); | |
if (c = a["image-large"]) c = c.split(":").splice(2, c.length - 1).join(""), d.push([640, a.resourceUrl.large + c]); | |
if (c = a["image-small"]) c = c.split(":").splice(2, c.length - 1).join(""), d.push([120, a.resourceUrl.small + c]) | |
} | |
}; | |
Spotify.Shell.Entities.SearchTrack = h; | |
h.prototype._fill = function (f) { | |
this._pid = this.playableId = f.playableId; | |
this.availability = f.availability; | |
this.duration = f.length; | |
this.name = f.name; | |
this.playable = f.playable; | |
this.playableURI = b.trackLink(this._pid); | |
this.popularity = f.popularity; | |
var c = f.album, | |
d = this.album = {}; | |
if (c && (this.albumUri = d.uri = b.albumLink(c.id).toString(), this.albumName = d.name = c.name, c = c.cover)) c = a.createSearchImages(c, f.resourceUrl), d.image = c.image, d.images = c.images; | |
f = f.artist || f.artists; | |
d = this.artists = []; | |
c = []; | |
this.artistName = ""; | |
if (f && f.length) { | |
for (var h = 0, g = f.length; h < g; h++) { | |
var q = f[h]; | |
d.push({ | |
uri: b.artistLink(q.id).toString(), | |
name: q.name | |
}); | |
c.push(q.name) | |
} | |
this.artistName = | |
c.join(";") | |
} | |
} | |
})(); | |
(function () { | |
function d(a, b) { | |
if (!(this instanceof d)) return new d(a, b); | |
this.uri = a.toString(); | |
b && this._fill(b) | |
} | |
var g = Spotify.Link, | |
c = Spotify.Promise, | |
h = Spotify.ItemList, | |
b = h.Comparators, | |
a = h.Predicates, | |
f = Spotify.Shell.Entities; | |
Spotify.Shell.Entities.Track = d; | |
d.prototype._fill = function (a) { | |
this._pid = this.playableId = a.playableId; | |
this.playableURI = g.trackLink(this._pid); | |
this.name = a.name; | |
this.disc = a.disc_number == void 0 ? a.disc_number : parseInt(a.disc_number, 10); | |
this.duration = a.duration; | |
this.number = a.number == void 0 ? | |
a.number : parseInt(a.number, 10); | |
this.popularity = a.popularity; | |
this.availability = a.availability; | |
this.playable = a.playable; | |
this.image = a.image; | |
this.images = a.images; | |
this.starred = a.starred; | |
this.explicit = !! a.explicit; | |
this.advertisement = !! a.ad; | |
this.seen = !0; | |
var b = a.album, | |
c = this.album = {}; | |
if (b && (this.albumUri = c.uri = g.albumLink(b.id).toString(), this.albumName = c.name = b.name, b = b.cover_group && b.cover_group.image)) b = f.createImages(b, a.resourceUrl), this.image = b.image, this.images = b.images; | |
a = a.artist || a.artists; | |
b = this.artists = []; | |
c = []; | |
this.artistName = ""; | |
if (a && a.length) { | |
for (var d = 0, h = a.length; d < h; d++) { | |
var n = a[d]; | |
b.push({ | |
uri: g.artistLink(n.id).toString(), | |
name: n.name | |
}); | |
c.push(n.name) | |
} | |
this.artistName = c.join(";") | |
} | |
}; | |
d.create = function (a, b) { | |
var f = new c; | |
try { | |
f.fulfill(new d(a, b)) | |
} catch (h) { | |
f.fail(h) | |
} | |
return f | |
}; | |
d.createComparator = function (a, f) { | |
switch (a) { | |
case "uri": | |
case "name": | |
return f != "desc" ? b.forStringProperty(a) : b.forStringPropertyReversed(a); | |
case "disc": | |
case "duration": | |
case "number": | |
case "popularity": | |
case "seen": | |
case "starred": | |
return f != | |
"desc" ? b.forNumberProperty(a) : b.forNumberPropertyReversed(a); | |
case "artists.name": | |
return f != "desc" ? b.forStringProperty("artistName") : b.forStringPropertyReversed("artistName"); | |
case "album.name": | |
return f != "desc" ? b.forStringProperty("albumName") : b.forStringPropertyReversed("albumName") | |
} | |
return null | |
}; | |
d.createPredicate = function (b, f, c) { | |
switch (b) { | |
case "uri": | |
case "name": | |
case "disc": | |
case "duration": | |
case "number": | |
case "popularity": | |
case "seen": | |
case "starred": | |
return a.forPropertyOperator(b, f, c); | |
case "artists.name": | |
return a.forPropertyOperator("artistName", | |
f, c); | |
case "album.name": | |
return a.forPropertyOperator("albumName", f, c) | |
} | |
return null | |
} | |
})(); | |
(function () { | |
function d(a, c) { | |
if (!(this instanceof d)) return new d(a, c); | |
b.call(this, c); | |
this._uri = a.toString(); | |
this._loadLimit = 500 | |
} | |
function g(b, c) { | |
if (!(this instanceof g)) return new g(b, c); | |
a.call(this, c); | |
this._uri = b.toString() | |
} | |
var c = Spotify.Shell.Entities, | |
h = Spotify.ItemList, | |
b = h.Array, | |
a = h.Concatenated; | |
Spotify.inherit(d, b); | |
Spotify.ItemList.DiscTrack = d; | |
Spotify.inherit(g, a); | |
Spotify.ItemList.AlbumTrack = g; | |
g.prototype.createComparator = function (a, b) { | |
return c.Track.createComparator(a, b) | |
}; | |
g.prototype.createPredicate = | |
function (a, b, d) { | |
return c.Track.createPredicate(a, b, d) | |
} | |
})(); | |
(function () { | |
function d(b, c) { | |
if (!(this instanceof d)) return new d(b, c); | |
a.call(this); | |
this._uri = b.toString(); | |
this._loadLimit = 200; | |
this._itemLoader = c | |
} | |
var g = Spotify.Promise, | |
c = Spotify.Shell, | |
h = c.Range, | |
b = c.Entities, | |
a = Spotify.ItemList.Base; | |
Spotify.inherit(d, a); | |
Spotify.ItemList.PlaylistRow = d; | |
d.prototype._load = function (a) { | |
var b = this, | |
c = new g; | |
this._itemLoader(this._uri, a).then(function (d) { | |
c.fulfill({ | |
range: a, | |
items: b._createRows(d) | |
}) | |
}); | |
return c | |
}; | |
d.prototype._loadLength = function () { | |
var a = this, | |
b = new g; | |
this._itemLoader(this._uri, | |
new h(0, this._loadLimit)).then(function (c) { | |
var d = a._length = c.length; | |
a._insertLoadedData({ | |
range: new h(0, Math.min(d, a._loadLimit)), | |
items: a._createRows(c) | |
}); | |
b.fulfill({ | |
length: d | |
}) | |
}, function () { | |
var c = a._length = 0; | |
b.fulfill({ | |
length: c | |
}) | |
}); | |
return b | |
}; | |
d.prototype._createRows = function (a) { | |
for (var a = a.contents, c = [], d = 0, h = a.length; d < h; d++) { | |
var g = a[d]; | |
c.push(new b.PlaylistRow(g.uri, g.attributes)) | |
} | |
return c | |
}; | |
d.prototype.createComparator = function (a, c) { | |
return b.PlaylistRow.createComparator(a, c) | |
}; | |
d.prototype.createPredicate = | |
function (a, c, d) { | |
return b.PlaylistRow.createPredicate(a, c, d) | |
} | |
})(); | |
(function () { | |
function d(a, b) { | |
q.call(this); | |
this._uri = a.toString(); | |
this._loadLimit = 50; | |
this._itemLoader = b; | |
this._timestamp = (new Date).getTime() | |
} | |
function g(a, b) { | |
if (!(this instanceof g)) return new g(a, b); | |
d.call(this, a, b) | |
} | |
function c(a, b) { | |
if (!(this instanceof c)) return new c(a, b); | |
d.call(this, a, b) | |
} | |
function h(a, b) { | |
if (!(this instanceof h)) return new h(a, b); | |
d.call(this, a, b) | |
} | |
function b(a, f) { | |
if (!(this instanceof b)) return new b(a, f); | |
d.call(this, a, f) | |
} | |
var a = Spotify.Link, | |
f = Spotify.Promise, | |
k = Spotify.Shell, | |
m = k.Entities, | |
o = k.Range, | |
p = Spotify.ItemList, | |
q = p.Base; | |
Spotify.Shell.SearchTypes = { | |
ALBUMS: "albums", | |
ARTISTS: "artists", | |
PLAYLISTS: "playlists", | |
TRACKS: "tracks" | |
}; | |
Spotify.inherit(d, q); | |
Spotify.ItemList.Search = d; | |
d.create = function (a, b, f) { | |
switch (a) { | |
case "albums": | |
return new p.SearchAlbums(b, f); | |
case "artists": | |
return new p.SearchArtists(b, f); | |
case "playlists": | |
return new p.SearchPlaylists(b, f); | |
case "tracks": | |
return new p.SearchTracks(b, f); | |
default: | |
return null | |
} | |
}; | |
d.prototype._load = function (a) { | |
var b = this, | |
c = new f; | |
this._itemLoader(a).then(function (f) { | |
c.fulfill({ | |
range: a, | |
items: b._createRows(f.items) | |
}) | |
}, function (a) { | |
c.fail(a) | |
}); | |
return c | |
}; | |
d.prototype._loadLength = function () { | |
var a = this, | |
b = new f; | |
this._itemLoader(new o(0, this._loadLimit)).then(function (f) { | |
var c = a._length = Math.min(f.length, 1E4); | |
a._insertLoadedData({ | |
range: new o(0, Math.min(c, a._loadLimit)), | |
items: a._createRows(f.items) | |
}); | |
b.fulfill({ | |
length: c | |
}) | |
}, function () { | |
var f = a._length = 0; | |
b.fulfill({ | |
length: f | |
}) | |
}); | |
return b | |
}; | |
d.prototype._createRows = function (a) { | |
return a | |
}; | |
d.prototype.isOlderThan = function (a) { | |
return (new Date).getTime() - | |
this._timestamp >= a | |
}; | |
Spotify.inherit(g, d); | |
Spotify.ItemList.SearchAlbums = g; | |
g.prototype._createRows = function (a) { | |
for (var b = 0, f = a.length; b < f; b++) { | |
var c = a[b]; | |
a[b] = new m.SearchAlbum(new Spotify.Link.albumLink(c.id), c) | |
} | |
return a | |
}; | |
Spotify.inherit(c, d); | |
Spotify.ItemList.SearchArtists = c; | |
c.prototype._createRows = function (a) { | |
for (var b = 0, f = a.length; b < f; b++) { | |
var c = a[b]; | |
a[b] = new m.SearchArtist(new Spotify.Link.artistLink(c.id), c) | |
} | |
return a | |
}; | |
Spotify.inherit(h, d); | |
Spotify.ItemList.SearchPlaylists = h; | |
h.prototype._createRows = | |
function (b) { | |
for (var f = 0, c = b.length; f < c; f++) { | |
var k = b[f], | |
d = a.fromString(k.uri); | |
k.owner = d.username; | |
b[f] = new m.SearchPlaylist(d, k) | |
} | |
return b | |
}; | |
Spotify.inherit(b, d); | |
Spotify.ItemList.SearchTracks = b; | |
b.prototype._createRows = function (a) { | |
for (var b = 0, f = a.length; b < f; b++) { | |
var c = a[b]; | |
a[b] = new m.SearchTrack(new Spotify.Link.trackLink(c.id), c) | |
} | |
return a | |
} | |
})(); | |
(function () { | |
function d(a, b) { | |
if (!(this instanceof d)) return new d(a, b); | |
if (!b || !Array.isArray(b)) throw new TypeError("ToplistItemList: Argument `array` must be an array."); | |
for (var b = b.slice(0), c = b.length; c--;) b[c] = b[c].toString(); | |
f.call(this, b); | |
this._uri = a.toString() | |
} | |
function g(a, b) { | |
if (!(this instanceof g)) return new g(a, b); | |
d.call(this, a, b) | |
} | |
function c(a, b) { | |
if (!(this instanceof c)) return new c(a, b); | |
d.call(this, a, b) | |
} | |
function h(a, b) { | |
if (!(this instanceof h)) return new h(a, b); | |
d.call(this, a, b) | |
} | |
function b(a, | |
f) { | |
if (!(this instanceof b)) return new b(a, f); | |
d.call(this, a, f) | |
} | |
var a = Spotify.ItemList, | |
f = a.Array; | |
Spotify.Shell.ToplistTypes = { | |
ALBUM: "album", | |
ARTIST: "artist", | |
PLAYLIST: "playlist", | |
TRACK: "track" | |
}; | |
Spotify.inherit(d, f); | |
Spotify.ItemList.Toplist = d; | |
d.create = function (b, f, c) { | |
switch (b) { | |
case "artist": | |
return new a.ToplistArtist(f, c); | |
case "album": | |
return new a.ToplistAlbum(f, c); | |
case "playlist": | |
return new a.ToplistPlaylist(f, c); | |
default: | |
return new a.ToplistTrack(f, c) | |
} | |
}; | |
Spotify.inherit(g, d); | |
Spotify.ItemList.ToplistAlbum = | |
g; | |
Spotify.inherit(c, d); | |
Spotify.ItemList.ToplistArtist = c; | |
Spotify.inherit(h, d); | |
Spotify.ItemList.ToplistPlaylist = h; | |
Spotify.inherit(b, d); | |
Spotify.ItemList.ToplistTrack = b | |
})(); | |
(function () { | |
function d(a, b) { | |
if (!(this instanceof d)) return new d(a, b); | |
if (!b) throw new TypeError("ContextItemList: Constructor argument `owner` cannot be undefined."); | |
h.call(this, a, 10); | |
this._owner = b; | |
this._shuffled = !1; | |
this._shuffledList = null | |
} | |
var g = Spotify.Promise, | |
c = Spotify.ItemList, | |
h = c.Iterable, | |
b = c.LoadedState; | |
Spotify.inherit(d, h); | |
Spotify.ItemList.Context = d; | |
d.prototype.shuffle = function (a) { | |
if (this._loadedState == b.UNLOADED) return this._queueCall(); | |
var f = new g; | |
f.fulfill(!0); | |
if (this._shuffled) return f; | |
this._shuffled = !0; | |
for (var k = this._length, d = Array(k); k--;) d[k] = k; | |
for (var k = this.getIndex(), k = k == 0 || k == c.LIST_START || k == c.LIST_END ? null : d.splice(k, 1).pop(), h = d.length; h;) { | |
var p = Math.floor(Math.random() * h--), | |
q = d[h]; | |
d[h] = d[p]; | |
d[p] = q | |
} | |
if (k != null) d.unshift(k), this._index = a ? 0 : -1; | |
this._shuffledList = d; | |
return f | |
}; | |
d.prototype.unshuffle = function () { | |
if (this._loadedState == b.UNLOADED) return this._queueCall(); | |
var a = new g; | |
a.fulfill(!0); | |
if (!this._shuffled) return a; | |
this._shuffled = !1; | |
if (this._shuffledList) { | |
var f = this.getIndex(); | |
if (f != 0 || f != c.LIST_START || f != c.LIST_END) this._index = this._shuffledList[f]; | |
return a | |
} | |
}; | |
d.prototype.snapshot = function (a, b) { | |
this._shuffled && this._shuffledList && this._shuffledList.length && (a = this._shuffledList[a]); | |
return this._super("snapshot", a, b) | |
}; | |
d.prototype.getOwner = function () { | |
return this._owner | |
} | |
})(); | |
(function () { | |
function d(a, f) { | |
b.call(this, a); | |
if (!f) throw new TypeError("Argument requestSender is null."); | |
this._requestSender = f; | |
this._decoratedMap = {}; | |
this._init() | |
} | |
var g = Spotify.Promise, | |
c = Spotify.Shell.Range, | |
h = Spotify.ItemList, | |
b = h.Layered, | |
a = h.LoadedState, | |
f = h.Snapshot; | |
Spotify.inherit(d, b); | |
Spotify.ItemList.Decorator = d; | |
d.prototype._init = function () { | |
this._base.getLength().then(function (b) { | |
this._length = b; | |
this._loadedState = a.PARTIAL; | |
this._unqueueSnapshots() | |
}.bind(this)).catchError(function () {}) | |
}; | |
d.prototype._buildList = | |
function (a) { | |
var b = this._list, | |
f = new c(a.getOffset(), a.getLength()), | |
a = a.toArray(); | |
b.insertFrom(f.begin, a); | |
return this._decorateItems(a, f) | |
}; | |
d.prototype._decorateItems = function (a, b) { | |
var f = this, | |
c = new g, | |
d = this._decoratedMap; | |
this._requestSender(a).then(function (h) { | |
for (var g = 0, t = a.length; g < t; g++) { | |
var u = a[g]; | |
d[u] = h[u] | |
} | |
f._updateRanges(b); | |
f._updateState(); | |
c.fulfill(a) | |
}); | |
return c | |
}; | |
d.prototype.snapshot = function (b, d) { | |
var h = this, | |
p = new g, | |
q = new c(b, d, Math.max(this._length - b, 0)); | |
switch (this._loadedState) { | |
case a.COMPLETE: | |
this._base.snapshot(b, | |
d).then(function (a) { | |
a = new f(h._version, h._createVersionedAccessor(a.toArray()), new c(a.getOffset(), a.getLength(), a.getListLength()), a.getListLength()); | |
p.fulfill(a) | |
}, p.fail.bind(p)); | |
break; | |
case a.PARTIAL: | |
q.findContainer(this._loadedRanges) ? this._base.snapshot(b, d).then(function (a) { | |
a = new f(h._version, h._createVersionedAccessor(a.toArray()), new c(a.getOffset(), a.getLength(), a.getListLength()), a.getListLength()); | |
p.fulfill(a) | |
}, p.fail.bind(p)) : this._base.snapshot(b, d).then(function (a) { | |
return h._buildList(a) | |
}).then(function () { | |
return h.snapshot(b, | |
d).pipe(p) | |
}).catchError(function (a) { | |
p.fail(a) | |
}); | |
break; | |
case a.UNLOADED: | |
this._queueSnapshot(b, d, p) | |
} | |
return p | |
}; | |
d.prototype._createVersionedAccessor = function (a) { | |
var b = this, | |
f = this._decoratedMap; | |
return function (c, d, h) { | |
if (b._version != c) throw Error("Cannot access item with an expired snapshot."); | |
return f[a[h]].metadata | |
} | |
}; | |
d.prototype.onMutate = function (a) { | |
this.notify("onBeforeMutate", new f(this._version, this._createVersionedAccessor(this._list), new c(snapshot.getOffset(), snapshot.getLength(), snapshot.getListLength()), | |
snapshot.getListLength())); | |
for (var b = [], d = 0, h = a.length; d < h; d++) { | |
var q = a[d]; | |
switch (q.type) { | |
case "insert": | |
b.push(this._applyInsertMutation(q)); | |
break; | |
case "remove": | |
b.push(this._applyRemoveMutation(q)); | |
break; | |
case "move": | |
b.push(this._applyMoveMutation(q)) | |
} | |
} | |
b.length && g.join(b).then(function (a) { | |
this._version++; | |
this.notify("onMutate", a) | |
}.bind(this)) | |
}; | |
d.prototype._applyInsertMutation = function (a) { | |
var b = a.begin, | |
a = a.items; | |
this._list.spliceWith(b, 0, a); | |
this._length += a.length; | |
return this._decorateItems(a, new c(b, | |
a.length)).then(function (a) { | |
return { | |
type: "insert", | |
begin: b, | |
items: a | |
} | |
}) | |
}; | |
d.prototype._applyRemoveMutation = function (a) { | |
var b = new g, | |
f = a.length; | |
this._list.splice(a.begin, f); | |
this._length -= f; | |
b.fulfill(a); | |
return b | |
}; | |
d.prototype._applyMoveMutation = function () { | |
var a = new g, | |
b = mutation.end, | |
f = this._list, | |
c = f.splice(mutation.begin, mutation.length); | |
f.spliceWith(b, 0, c); | |
a.fulfill(mutation); | |
return a | |
} | |
})(); | |
(function () { | |
function d(c, d) { | |
g.call(this, c, d) | |
} | |
var g = Spotify.ItemList.Decorator; | |
Spotify.inherit(d, g); | |
Spotify.ItemList.MetadataDecorator = d; | |
d.prototype._decorateItems = function (c, d) { | |
return this._requestSender(c).then(this._processMetadata.bind(this, c, d), function () {}) | |
}; | |
d.prototype._processMetadata = function (c, d, b) { | |
for (var a = this._decoratedMap, f = c.length, k = Array(f); f--;) { | |
var m = c[f], | |
g = a[m]; | |
g ? g.count++ : g = a[m] = { | |
count: 1, | |
metadata: b[m] | |
}; | |
k[f] = g.metadata | |
} | |
this._updateRanges(d); | |
this._updateState(); | |
return k | |
}; | |
d.prototype._createVersionedAccessor = | |
function (c) { | |
var d = this, | |
b = this._decoratedMap; | |
return function (a, f, k) { | |
if (d._version != a) throw Error("Cannot access item with an expired snapshot."); | |
return b[c[k]].metadata | |
} | |
} | |
})(); | |
(function () { | |
function d(c, d) { | |
g.call(this, c, d); | |
this._rows = [] | |
} | |
var g = Spotify.ItemList.Decorator; | |
Spotify.inherit(d, g); | |
Spotify.ItemList.PlaylistTrackDecorator = d; | |
d.prototype._decorateItems = function (c, d) { | |
for (var b = c.length, a = Array(b); b--;) a[b] = c[b].uri; | |
return this._requestSender(a).then(this._processMetadata.bind(this, c, d), function () {}) | |
}; | |
d.prototype._processMetadata = function (c, d, b) { | |
for (var a = this._rows, f = c.length, k = Array(f); f--;) { | |
var m = c[f]; | |
m.setTrack(b[m.uri]); | |
k[f] = m | |
} | |
a.insertFrom(d.begin, k); | |
this._updateRanges(d); | |
this._updateState(); | |
return k | |
}; | |
d.prototype._createVersionedAccessor = function () { | |
var c = this, | |
d = this._rows; | |
return function (b, a) { | |
if (c._version != b) throw Error("Cannot access item with an expired snapshot."); | |
return d[a] | |
} | |
} | |
})(); | |
(function () { | |
function d(a) { | |
if (!(this instanceof d)) return new d(a); | |
this._audioManager = a; | |
this._stack = []; | |
this._players = {} | |
} | |
function g(c, d) { | |
if (!(this instanceof g)) return new g(player); | |
if (!c) throw new TypeError("ContextPlayer: Argument `id` cannot be undefined."); | |
if (!d) throw new TypeError("ContextPlayer: Argument `audioManager` cannot be undefined."); | |
f.call(this); | |
this._id = c; | |
this._uid = 0; | |
this._audioManager = d; | |
this._player = d.addPlayer(c + ":A"); | |
this._alternatePlayer = d.addPlayer(c + ":B"); | |
this._interceptContextList = | |
new a(new b([]), "intercept"); | |
this._queueContextList = new a(new b([]), "queue"); | |
this._previousPlayCall = this._currentTrack = this._currentContextOptions = this._currentContextList = null; | |
this._shuffled = this._fakePlayState = !1; | |
this._nextMovement = "next"; | |
this._crossfading = this._crossfade = this._stopped = !1; | |
this._crossfadeAmount = 0; | |
this._crossfadeBuffer = 1E3; | |
this._initEvents(this._player); | |
this._initEvents(this._alternatePlayer) | |
} | |
var c = Spotify.Promise, | |
h = Spotify.ItemList, | |
b = Spotify.ItemList.Array, | |
a = h.Context, | |
f = Spotify.Shell.EventEmitter; | |
Spotify.Shell.ContextOperationResult = { | |
CONTEXT_END: "contextEnd", | |
EMPTY: "empty", | |
FORBIDDEN: "forbidden", | |
INVALID: "invalid", | |
NO_CONTEXT: "nonContext", | |
SUCCESS: "success" | |
}; | |
var k = Spotify.Shell.ContextOperationResult; | |
Spotify.Shell.ContextPlayerGroup = d; | |
d.prototype.create = function (a) { | |
var b = this._players; | |
if (b[a]) throw new TypeError('A player with the id "' + a + '" already exists.'); | |
var f = new g(a, this._audioManager); | |
f.addEvents({ | |
trackLoaded: this._onTrackLoaded.bind(this), | |
play: this._onPlayerPlay.bind(this), | |
contextEnd: this._onContextStop.bind(this), | |
stop: this._onContextStop.bind(this) | |
}); | |
return b[a] = f | |
}; | |
d.prototype.get = function (a) { | |
return this._players[a] || null | |
}; | |
d.prototype._onTrackLoaded = function (a) { | |
var b = a.player, | |
a = this._stack; | |
if (!a.length) return this; | |
var f = a[0]; | |
if (f.player == b) return this; | |
f.state = f.player.getState(); | |
this._audioManager.crossfade(f.player.getPlayerId(), b.getPlayerId(), 800, function () { | |
f.player.pause(); | |
b.setPlayerVolume(1) | |
}) | |
}; | |
d.prototype._onPlayerPlay = function (a) { | |
var a = a.player, | |
b = this._stack; | |
b.length && b[0].player == a || b.unshift({ | |
player: a, | |
state: {} | |
}) | |
}; | |
d.prototype._onContextStop = function () { | |
var a = this._stack, | |
b = a.shift(); | |
if (a.length) { | |
var f = a[0]; | |
f.state.playing ? (f.player.resume(), this._audioManager.crossfade(b.player.getPlayerId(), f.player.getPlayerId(), 800, function () { | |
f.player.setPlayerVolume(1) | |
})) : f.player.setPlayerVolume(1) | |
} | |
}; | |
Spotify.inherit(g, f); | |
Spotify.Shell.ContextPlayer = g; | |
g.prototype._initEvents = function (a) { | |
a.onPlay = this._handlePlay.bind(this); | |
a.onPause = this._handlePause.bind(this); | |
a.onTrackEnded = this._handleEnded.bind(this); | |
a.onInvalidTrackUri = | |
a.onPlaybackFailed = this._handleInvalid.bind(this); | |
a.bind("BEFORE_END", this._handleBeforeEnded.bind(this)) | |
}; | |
g.prototype._handlePlay = function (a) { | |
this.fireEvent("play", { | |
player: this, | |
track: this._currentTrack, | |
position: typeof a.params == "number" ? a.params : 0, | |
context: this._currentContextList, | |
options: this._currentContextOptions | |
}) | |
}; | |
g.prototype._handlePause = function (a) { | |
this.fireEvent("pause", { | |
player: this, | |
track: this._currentTrack, | |
position: typeof a.params == "number" ? a.params : 0, | |
context: this._currentContextList, | |
options: this._currentContextOptions | |
}) | |
}; | |
g.prototype._handleEnded = function () { | |
this.fireEvent("playEnd", { | |
player: this, | |
track: this._currentTrack, | |
context: this._currentContextList, | |
options: this._currentContextOptions | |
}); | |
if (!this._crossfade) { | |
var a = this._nextMovement; | |
a == "next" ? this.next("trackdone") : a == "previous" && this.previous("trackdone") | |
} | |
}; | |
g.prototype._handleBeforeEnded = function () { | |
this.fireEvent("beforePlayEnd", { | |
player: this, | |
track: this._currentTrack, | |
context: this._currentContextList, | |
options: this._currentContextOptions | |
}); | |
if (this._crossfade) { | |
var a = | |
this._nextMovement; | |
a == "next" ? this.next("trackdone") : a == "previous" && this.previous("trackdone") | |
} | |
}; | |
g.prototype._handleInvalid = function (a) { | |
a = a.params; | |
if (a.domain == 12) switch (a.code) { | |
case 8: | |
this.fireEvent("requestCap", { | |
player: this | |
}); | |
break; | |
case 12: | |
this.fireEvent("playCap", { | |
player: this | |
}); | |
break; | |
case 11: | |
this.fireEvent("trackCap", { | |
player: this | |
}), this.next("trackdone") | |
} else this.next("trackdone") | |
}; | |
g.prototype.getPlayerId = function () { | |
return this._player.id | |
}; | |
g.prototype.getInterceptList = function () { | |
return this._interceptContextList | |
}; | |
g.prototype.getQueueList = function () { | |
return this._queueContextList | |
}; | |
g.prototype.getState = function () { | |
var a = this._player.getPlayerState(), | |
b = this._currentContextList, | |
f = this._currentTrack; | |
b.getRootBaseList().getDescriptor(); | |
return { | |
__uid: this._uid, | |
__rules: null, | |
__owner: b ? b.getOwner() : null, | |
__index: b ? b.getIndex() : null, | |
playing: this._fakePlayState ? !0 : !a.isPaused && !a.isStopped, | |
index: b ? b.getIndex() : null, | |
track: f, | |
context: b, | |
position: a.position, | |
duration: a.duration, | |
repeat: this._repeat, | |
shuffle: this._shuffled | |
} | |
}; | |
g.prototype.setCrossfade = | |
function (a) { | |
var b = new c; | |
if (typeof a != "number") return b.fail(k.INVALID), b; | |
a < 1E3 ? (this._crossfade = !1, this._crossfadeAmount = 0, this._crossfadeBuffer = 1E3) : (this._crossfade = !0, this._crossfadeAmount = a, this._crossfadeBuffer = a + 3E3); | |
b.fulfill(k.SUCCESS); | |
return b | |
}; | |
g.prototype.isCrossfading = function () { | |
return this._crossfade ? !1 : !! this._crossfading | |
}; | |
g.prototype.setVolume = function (a) { | |
var b = new c; | |
if (typeof a != "number") return b.fail(k.INVALID), b; | |
this.audioManager.setMasterVolume(a); | |
this.fireEvent("volumeChange", { | |
player: this | |
}); | |
b.fulfill(k.SUCCESS); | |
return b | |
}; | |
g.prototype.setPlayerVolume = function (a) { | |
var b = new c; | |
if (typeof a != "number") return b.fail(k.INVALID), b; | |
this._player.setVolume(a); | |
this.fireEvent("internalVolumeChange", { | |
player: this | |
}); | |
b.fulfill(k.SUCCESS); | |
return b | |
}; | |
g.prototype.setShuffle = function (a) { | |
this._shuffled = a; | |
var b = this._currentContextList; | |
b && (a ? b.shuffle(this.getState().playing) : b.unshuffle()); | |
a = new c; | |
a.fulfill(k.SUCCESS); | |
return a | |
}; | |
g.prototype.seek = function (a) { | |
var b = new c; | |
typeof a != "number" ? b.fail(k.INVALID) : this._currentContextList ? | |
(this._player.seek(a), b.fulfill(k.SUCCESS)) : b.fail(k.NO_CONTEXT); | |
return b | |
}; | |
g.prototype.togglePlay = function () { | |
var a = new c; | |
this._currentContextList ? (this._player.playpause(), a.fulfill(k.SUCCESS)) : a.fail(k.NO_CONTEXT); | |
return a | |
}; | |
g.prototype.resume = function () { | |
var a = new c; | |
this._currentContextList ? (this._player.resume(), a.fulfill(k.SUCCESS)) : a.fail(k.NO_CONTEXT); | |
return a | |
}; | |
g.prototype.pause = function () { | |
var a = new c; | |
this._currentContextList ? (this._player.pause(), a.fulfill(k.SUCCESS)) : a.fail(k.NO_CONTEXT); | |
return a | |
}; | |
g.prototype.stop = function () { | |
this._stopped = !0; | |
this._player.stop(); | |
this.fireEvent("stop", { | |
player: this | |
}); | |
return this | |
}; | |
g.prototype.clear = function () { | |
this.stop(); | |
this._currentContextOptions = this._currentContextList = this._currentTrack = null; | |
return this | |
}; | |
g.prototype.play = function (b, f) { | |
b instanceof a || (b = new a(b, f.owner)); | |
this._stopped = !1; | |
return b.getLength().then(function (a) { | |
return a == 0 ? (a = new c, a.fail(k.EMPTY), a) : (this.fireEventSync("beforeContextChange", { | |
player: this, | |
newContext: b, | |
newOptions: f, | |
oldContext: this._currentContextList, | |
oldOptions: this._currentContextOptions | |
}), b.startAt(f.index == -1 ? 0 : f.index), this._shuffled ? b.shuffle() : b.unshuffle(), this._repeat ? b.makeInfinite() : b.makeFinite(), this._currentContextList = b, this._currentContextOptions = f, this.fireEvent("contextChange", { | |
player: this, | |
context: b, | |
options: f | |
}), this.next(f.reason)) | |
}.bind(this)) | |
}; | |
g.prototype.next = function (a) { | |
var b = new c, | |
f = this; | |
if (!this._currentContextList) return b.fail(k.NO_CONTEXT), b; | |
return !a ? (b.fail(k.INVALID), b) : this._interceptContextList.pop().then(function (a) { | |
return a != | |
h.NULL_VALUE ? (f._nextMovement = "next", a) : f._queueContextList.pop() | |
}).then(function (a) { | |
return a != h.NULL_VALUE ? a : f._currentContextList.next() | |
}).then(function (b) { | |
if (b == h.LIST_END) return this.fireEvent("contextEnd", { | |
player: this, | |
context: this._currentContextList, | |
options: this._currentContextOptions | |
}), this.stop(), k.CONTEXT_END; | |
else { | |
this.fireEvent("beforeNextTrack", { | |
player: this, | |
newTrack: b, | |
oldTrack: this._currentTrack, | |
reason: a | |
}); | |
var f = this._playTrack(b); | |
this.fireEvent("nextTrack", { | |
player: this, | |
track: b, | |
reason: a | |
}); | |
return f | |
} | |
}.bind(this)) | |
}; | |
g.prototype.previous = function (a) { | |
var b = new c, | |
f = this; | |
if (!this._currentContextList) return b.fail(k.NO_CONTEXT), b; | |
return !a ? (b.fail(k.INVALID), b) : this._interceptContextList.pop().then(function (a) { | |
return a != h.NULL_VALUE ? (f._nextMovement = "previous", a) : (f._nextMovement = "next", f._currentContextList.previous()) | |
}).then(function (b) { | |
if (b == h.LIST_START) return this.fireEvent("contextEnd", { | |
player: this, | |
context: this._currentContextList, | |
options: this._currentContextOptions | |
}), this.stop(), k.CONTEXT_END; | |
else { | |
this.fireEvent("beforePreviousTrack", { | |
player: this, | |
newTrack: b, | |
oldTrack: this._currentTrack, | |
reason: a | |
}); | |
var f = this._playTrack(b); | |
this.fireEvent("previousTrack", { | |
player: this, | |
track: b, | |
reason: a | |
}); | |
return f | |
} | |
}.bind(this)) | |
}; | |
g.prototype._playTrack = function (a) { | |
if (this._stopped) return k.SUCCESS; | |
this.fireEvent("beforePlay", { | |
player: this, | |
context: this._currentContextList, | |
options: this._currentContextOptions, | |
track: a | |
}); | |
this._previousPlayCall ? (clearTimeout(this._previousPlayCall), this._previousPlayCall = setTimeout(this._loadTrackForPlayback.bind(this, | |
a), 1E3)) : (this._previousPlayCall = 1, this._previousPlayCall = setTimeout(this._loadTrackForPlayback.bind(this, a), 10)); | |
return k.SUCCESS | |
}; | |
g.prototype._loadTrackForPlayback = function (a) { | |
if (!this._stopped) { | |
var b = this._player, | |
f = this._alternatePlayer, | |
c = this._currentContextOptions; | |
this._uid++; | |
this._currentTrack = a; | |
var a = a.playableURI, | |
d = !c.pause; | |
c.pause = !1; | |
var k = c.offset || 0, | |
h = -1; | |
!isNaN(c.duration) && c.duration > 0 && (h = k + c.duration); | |
c = null; | |
b.getPlayerState().isPlaying && this._crossfade ? (c = f, f.onLoad = this._alternateLoaded.bind(this, | |
b, f, d)) : (c = b, b.onLoad = this._playerLoaded.bind(this, b, f, d)); | |
c.load(a.toString(), k, d, h, this._crossfadeBuffer); | |
this._previousPlayCall = null | |
} | |
}; | |
g.prototype._playerLoaded = function (a, b, f) { | |
this.fireEventSync("trackLoaded", { | |
player: this, | |
play: f, | |
mainPlayer: a, | |
alternatePlayer: b | |
}) | |
}; | |
g.prototype._alternateLoaded = function (a, b, f) { | |
this.fireEventSync("trackLoaded", { | |
player: this, | |
play: f, | |
mainPlayer: b, | |
alternatePlayer: a | |
}); | |
if (!this._stopped) this._crossfading = !0, this.fireEventSync("crossfadeStart", { | |
player: this, | |
mainPlayer: a, | |
alternatePlayer: b | |
}), | |
this._audioManager.crossfade(a.id, b.id, this._crossfadeAmount, function () { | |
this._crossfading = !1; | |
this.fireEventSync("crossfadeEnd", { | |
player: this, | |
mainPlayer: a, | |
alternatePlayer: b | |
}); | |
if (!this._stopped) a.pause(), b.setVolume(1), this._alternatePlayer = a, this._player = b | |
}.bind(this)) | |
} | |
})(); | |
(function () { | |
function d() { | |
this._handlers = {} | |
} | |
function g(a) { | |
function b() {} | |
if (typeof a != "object") return a; | |
b.prototype = a; | |
return new b | |
} | |
function c(a, b, f, d) { | |
if (!(this instanceof c)) return new c(a, b, f, d); | |
if (!a) throw new TypeError("DispatcherRequest: Argument `method` missing."); | |
if (!b) throw new TypeError("DispatcherRequest: Argument `path` missing."); | |
this.method = a; | |
this.path = b; | |
this.headers = f ? g(f) : {}; | |
this.body = d ? g(d) : {} | |
} | |
function h(a, b, c) { | |
if (!(this instanceof h)) return new h(a, header, c); | |
this.status = f.OK; | |
this.statusText = | |
k[200]; | |
this.headers = {}; | |
this.body = {}; | |
a != void 0 && this.setStatus(a); | |
b != void 0 && this.setHeaders(b); | |
c != void 0 && this.setBody(c) | |
} | |
function b() { | |
if (!(this instanceof b)) return new b; | |
this._ready = !1; | |
this._requestQueue = []; | |
this._handlers = new d; | |
this._requestSenders = {} | |
} | |
var a = Spotify.Promise; | |
Spotify.Shell.ResponseStatus = { | |
OK: 200, | |
CREATED: 201, | |
ACCEPTED: 202, | |
BAD_REQUEST: 400, | |
UNAUTHORIZED: 401, | |
FORBIDDEN: 403, | |
NOT_FOUND: 404, | |
METHOD_NOT_ALLOWED: 405, | |
TIMED_OUT: 408, | |
CONFLICT: 409, | |
GONE: 410, | |
INTERNAL_SERVER_ERROR: 500, | |
NOT_IMPLEMENTED: 501, | |
BAD_GATEWAY: 502, | |
SERVICE_UNAVAILABLE: 503 | |
}; | |
var f = Spotify.Shell.ResponseStatus; | |
Spotify.Shell.ResponseStatusText = { | |
200: "Ok", | |
201: "Created", | |
202: "Accepted", | |
400: "Bad Request", | |
401: "Unauthorized", | |
403: "Forbidden", | |
404: "Not Found", | |
405: "Method Not Allowed", | |
408: "Timed Out", | |
409: "Conflict", | |
410: "Gone", | |
500: "Internal Server Error", | |
501: "Not Implemented", | |
502: "Bad Gateway", | |
503: "Service Unavailable" | |
}; | |
var k = Spotify.Shell.ResponseStatusText; | |
Spotify.Shell.RequestMethod = { | |
CREATE: "CREATE", | |
FLUSH: "FLUSH", | |
GET: "GET", | |
REMOVE: "REMOVE", | |
UPDATE: "UPDATE" | |
}; | |
var m = Spotify.Shell.RequestMethod; | |
Spotify.Shell.MethodRequestMap = d; | |
d.prototype.get = function (a, b) { | |
var f = this._handlers, | |
a = a.toString().toUpperCase(), | |
f = f[a]; | |
return !f ? null : f[b] || null | |
}; | |
d.prototype.set = function (a, b, f) { | |
var c = this._handlers, | |
a = a.toString().toUpperCase(); | |
(c[a] || (c[a] = {}))[b] = f; | |
return this | |
}; | |
d.prototype.remove = function (a, b, f) { | |
var c = this._handlers, | |
a = a.toString().toUpperCase(), | |
a = c[a]; | |
if (!a) return null; | |
c = a[b]; | |
if (!c) return this; | |
c == f && (a[b] = null); | |
return this | |
}; | |
Spotify.Shell.DispatcherRequest = | |
c; | |
Spotify.Shell.DispatcherResponse = h; | |
h.prototype.setStatus = function (a) { | |
this.status = a; | |
this.statusText = k[a]; | |
return this | |
}; | |
h.prototype.setHeader = function (a, b) { | |
this.headers[a] = b; | |
return this | |
}; | |
h.prototype.setHeaders = function (a) { | |
for (var b in a) this.headers[b] = a[b]; | |
return this | |
}; | |
h.prototype.setBodyField = function (a, b) { | |
this.body[a] = b; | |
return this | |
}; | |
h.prototype.setBodyFields = function (a) { | |
var b = this.body, | |
f; | |
for (f in a) a.hasOwnProperty(f) && (b[f] = a[f]); | |
return this | |
}; | |
h.prototype.setBody = function (a) { | |
if (!a || typeof a != "object" || | |
Array.isArray(a)) throw Error("DispatcherResponse.setBody: `body` must be an object."); | |
this.body = a; | |
return this | |
}; | |
Spotify.Shell.Dispatcher = b; | |
b.prototype.setReady = function () { | |
this._ready = !0; | |
this._unqueue(); | |
return this | |
}; | |
b.prototype._queue = function (a, b) { | |
this._requestQueue.push({ | |
args: a, | |
promise: b | |
}); | |
return b | |
}; | |
b.prototype._unqueue = function () { | |
for (var a = this._requestQueue.splice(0), b = 0, f = a.length; b < f; b++) { | |
var c = a[b]; | |
this.request.apply(this, c.args).pipe(c.promise) | |
} | |
return this | |
}; | |
b.prototype.register = function (a, b, | |
f) { | |
this._handlers.set(a, b, f); | |
return this | |
}; | |
b.prototype.createRequestSender = function (a, b) { | |
var f = this, | |
c = this._requestSenders, | |
d = a + " " + b; | |
return c[d] || (c[d] = function (c, d) { | |
return f.request(a, b, c, d) | |
}) | |
}; | |
b.prototype.request = function (b, d, k, m) { | |
var g = new a; | |
if (!this._ready) return this._queue(arguments, g); | |
var b = (b || "").toString().toUpperCase(), | |
d = d || "/", | |
t = this._handlers.get(b, d); | |
if (t) { | |
var u = new c(b, d, k, m); | |
try { | |
var w = t.call(null, u, this); | |
w.pipe ? w.pipe(g) : g.fulfill(w) | |
} catch (v) { | |
g.fail(v) | |
} | |
} else g.fail(new h(f.NOT_IMPLEMENTED)); | |
return g | |
}; | |
b.prototype.create = function (a, b, f) { | |
return this.request(m.CREATE, a, b, f) | |
}; | |
b.prototype.get = function (a, b, f) { | |
return this.request(m.GET, a, b, f) | |
}; | |
b.prototype.flush = function (a, b, f) { | |
return this.request(m.FLUSH, a, b, f) | |
}; | |
b.prototype.remove = function (a, b, f) { | |
return this.request(m.REMOVE, a, b, f) | |
}; | |
b.prototype.update = function (a, b, f) { | |
return this.request(m.UPDATE, a, b, f) | |
} | |
})(); | |
(function () { | |
function d() { | |
if (!(this instanceof d)) return new d; | |
this._mediator = new f; | |
this._reactors = [] | |
} | |
function g(a) { | |
function b(a) { | |
this._ready = !1; | |
this._requestQueue = []; | |
this._mediator = a; | |
a = f.call(this); | |
return a === void 0 ? this : a | |
} | |
if (!(this instanceof g)) return new g(a); | |
this._registry = []; | |
var a = a || {}, f = a._construct || function () {}; | |
b.prototype = this; | |
b.prototype.constructor = g; | |
var c = /([A-Z]+)\s+(.+)/, | |
d; | |
for (d in a) | |
if (a.hasOwnProperty(d)) { | |
var h = a[d], | |
s = d.match(c); | |
s && typeof h == "function" ? this._createHandler(s[1], s[2], | |
h) : this[d] = h | |
} | |
return b | |
} | |
var c = Array.prototype.slice, | |
h = Spotify.Promise, | |
b = Spotify.Shell, | |
a = b.DispatcherResponse, | |
f = b.EventEmitter; | |
Spotify.Shell.ReactorSet = d; | |
d.prototype.create = function (a) { | |
a = new g(a); | |
this._reactors.push(a); | |
return a | |
}; | |
d.prototype.remove = function (a) { | |
var b = this._reactors, | |
f = b.indexOf(a); | |
b.indexOf(a) != -1 && b.splice(f, 1); | |
return this | |
}; | |
d.prototype.add = function (a) { | |
if (typeof a != "function" || !(a.prototype instanceof g)) throw new TypeError("Argument `reactor` must be a reactor."); | |
var b = this._reactors; | |
b.indexOf(a) == -1 && b.push(a); | |
return this | |
}; | |
d.prototype.attach = function (a) { | |
for (var b = this._reactors, f = 0, c = b.length; f < c; f++)(new b[f](this._mediator)).attach(a); | |
return this | |
}; | |
Spotify.Shell.DefaultReactors = new d; | |
Spotify.Shell.Reactor = g; | |
g.prototype._createHandler = function (a, b, f) { | |
var c = f.name; | |
if (!c || c == "anonymous") { | |
c = a.toLowerCase(); | |
pathSections = b.split("/"); | |
c = [c]; | |
if (pathSections.length == 2 && !pathSections[0] && !pathSections[1]) c.push("Root"); | |
else | |
for (var d = function (a) { | |
return a.toUpperCase() | |
}, h = 0, g = pathSections.length; h < | |
g; h++) { | |
var t = pathSections[h]; | |
t && c.push(t.replace(/^[a-z]/, d)) | |
} | |
c = c.join("") | |
} | |
this[c] = f; | |
this._registry.push({ | |
method: a, | |
path: b, | |
handler: c | |
}) | |
}; | |
g.prototype._createQueueable = function (a) { | |
var b = this, | |
f = this[a], | |
a = f ? function () { | |
return !b._ready ? b._queue() : f.apply(b, arguments) | |
} : function () { | |
var a = b._createPromise(); | |
a.fail(new TypeError("Method not found.")); | |
return a | |
}; | |
a._origin = f; | |
return a | |
}; | |
g.prototype._subscribe = function (a, b) { | |
this._mediator.addEvent(a, b.bind(this)); | |
return this | |
}; | |
g.prototype._subscribeAll = function (a) { | |
for (var b in a) a.hasOwnProperty(b) && | |
this._mediator.addEvent(b, a[b].bind(this)); | |
return this | |
}; | |
g.prototype._unsubscribe = function (a, b) { | |
typeof a == "object" ? this._mediator.removeEvents(a) : this._mediator.removeEvents(a, b); | |
return this | |
}; | |
g.prototype._broadcast = function (a, b) { | |
b = c.call(arguments, 1); | |
this._mediator.fireEvent(a, b); | |
return this | |
}; | |
g.prototype._broadcastFlush = function () { | |
this._broadcast("resources.flush") | |
}; | |
g.prototype._waitForServices = function (a) { | |
var b = 0, | |
f = [], | |
c; | |
for (c in a) f.push(this[c] = a[c]), b++; | |
a = function () { | |
!--b && this._onServicesReady && | |
this._onServicesReady() | |
}.bind(this); | |
for (c = b; c--;) f[c].onReady(a, this); | |
return this | |
}; | |
g.prototype._onServicesReady = function () { | |
this._ready = !0; | |
this._unqueue() | |
}; | |
g.prototype._createResponse = function (b, f, c) { | |
return new a(b, f, c) | |
}; | |
g.prototype._createPromise = function () { | |
return new h | |
}; | |
g.prototype._wrapDecoratorRequest = function (a) { | |
return function (b) { | |
return a({ | |
flush: !0 | |
}, { | |
uris: b | |
}).then(function (a) { | |
return a.body.result | |
}) | |
} | |
}; | |
g.prototype._setReady = function () { | |
this._ready = !0; | |
this._unqueue() | |
}; | |
g.prototype._queue = function () { | |
var a = | |
this._createPromise(), | |
b = this._queue.caller; | |
this._requestQueue.push({ | |
fn: b, | |
args: b.arguments, | |
promise: a | |
}); | |
return a | |
}; | |
g.prototype._unqueue = function () { | |
for (var a = this._requestQueue, b = 0, f = a.length; b < f; b++) { | |
var c = a[b]; | |
c.fn.apply(this, c.args).pipe(c.promise) | |
} | |
this._requestQueue = []; | |
return this | |
}; | |
g.prototype.attach = function (a) { | |
if (!a || typeof a.register != "function") throw new TypeError("Reactor.attach: Argument `dispatcher` must be a Dispatcher object."); | |
for (var b = this._registry, f = [], c = 0, d = b.length; c < d; c++) { | |
var h = | |
b[c], | |
g = h.method, | |
t = h.path, | |
h = this._createQueueable(h.handler); | |
a.register(g, t, h); | |
f.push({ | |
method: g, | |
path: t, | |
handler: h | |
}) | |
} | |
return f | |
} | |
})(); | |
(function () { | |
function d(a, f) { | |
if (f && f.substring(0, 4) == "NTX_") { | |
var d = g(f), | |
k = parseInt(h(c(b("spotify:test:" + a))).substring(0, 8), 16), | |
k = Math.floor(1E4 * k * Math.pow(2, -32)); | |
return Math.floor(d[k] / 10) | |
} else return d = "spotify:test:", f && (d += f + ":"), d += a, digest = parseInt(h(c(b(d))).substring(0, 8), 16), Math.floor(1E3 * digest * Math.pow(2, -32)) | |
} | |
function g(a) { | |
var f = 0, | |
d = q[a]; | |
if (d) return d; | |
f = 0; | |
d = Array(1E4); | |
for (i = 0; i < d.length; i++) d[i] = i; | |
var k = h(c(b(a))), | |
f = parseInt(k.substring(0, 8), 16); | |
(function (a) { | |
for (var b = a.length - 1; b >= | |
1; b--) { | |
f = 16807 * f % 2147483647; | |
var c = f % (b + 1), | |
d = a[b]; | |
a[b] = a[c]; | |
a[c] = d | |
} | |
})(d); | |
return q[a] = d | |
} | |
function c(b) { | |
var c = Array(b.length >> 2), | |
d, h; | |
for (d = 0, h = c.length; d < h; d++) c[d] = 0; | |
for (d = 0, h = b.length * 8; d < h; d += 8) c[d >> 5] |= (b.charCodeAt(d / 8) & 255) << d % 32; | |
b = b.length * 8; | |
c[b >> 5] |= 128 << b % 32; | |
c[(b + 64 >>> 9 << 4) + 14] = b; | |
b = 1732584193; | |
d = -271733879; | |
h = -1732584194; | |
for (var g = 271733878, n = 0; n < c.length; n += 16) { | |
var p = b, | |
q = d, | |
G = h, | |
B = g, | |
b = f(b, d, h, g, c[n + 0], 7, -680876936), | |
g = f(g, b, d, h, c[n + 1], 12, -389564586); | |
h = f(h, g, b, d, c[n + 2], 17, 606105819); | |
d = f(d, h, g, b, c[n + | |
3], 22, -1044525330); | |
b = f(b, d, h, g, c[n + 4], 7, -176418897); | |
g = f(g, b, d, h, c[n + 5], 12, 1200080426); | |
h = f(h, g, b, d, c[n + 6], 17, -1473231341); | |
d = f(d, h, g, b, c[n + 7], 22, -45705983); | |
b = f(b, d, h, g, c[n + 8], 7, 1770035416); | |
g = f(g, b, d, h, c[n + 9], 12, -1958414417); | |
h = f(h, g, b, d, c[n + 10], 17, -42063); | |
d = f(d, h, g, b, c[n + 11], 22, -1990404162); | |
b = f(b, d, h, g, c[n + 12], 7, 1804603682); | |
g = f(g, b, d, h, c[n + 13], 12, -40341101); | |
h = f(h, g, b, d, c[n + 14], 17, -1502002290); | |
d = f(d, h, g, b, c[n + 15], 22, 1236535329); | |
b = k(b, d, h, g, c[n + 1], 5, -165796510); | |
g = k(g, b, d, h, c[n + 6], 9, -1069501632); | |
h = k(h, | |
g, b, d, c[n + 11], 14, 643717713); | |
d = k(d, h, g, b, c[n + 0], 20, -373897302); | |
b = k(b, d, h, g, c[n + 5], 5, -701558691); | |
g = k(g, b, d, h, c[n + 10], 9, 38016083); | |
h = k(h, g, b, d, c[n + 15], 14, -660478335); | |
d = k(d, h, g, b, c[n + 4], 20, -405537848); | |
b = k(b, d, h, g, c[n + 9], 5, 568446438); | |
g = k(g, b, d, h, c[n + 14], 9, -1019803690); | |
h = k(h, g, b, d, c[n + 3], 14, -187363961); | |
d = k(d, h, g, b, c[n + 8], 20, 1163531501); | |
b = k(b, d, h, g, c[n + 13], 5, -1444681467); | |
g = k(g, b, d, h, c[n + 2], 9, -51403784); | |
h = k(h, g, b, d, c[n + 7], 14, 1735328473); | |
d = k(d, h, g, b, c[n + 12], 20, -1926607734); | |
b = a(d ^ h ^ g, b, d, c[n + 5], 4, -378558); | |
g = | |
a(b ^ d ^ h, g, b, c[n + 8], 11, -2022574463); | |
h = a(g ^ b ^ d, h, g, c[n + 11], 16, 1839030562); | |
d = a(h ^ g ^ b, d, h, c[n + 14], 23, -35309556); | |
b = a(d ^ h ^ g, b, d, c[n + 1], 4, -1530992060); | |
g = a(b ^ d ^ h, g, b, c[n + 4], 11, 1272893353); | |
h = a(g ^ b ^ d, h, g, c[n + 7], 16, -155497632); | |
d = a(h ^ g ^ b, d, h, c[n + 10], 23, -1094730640); | |
b = a(d ^ h ^ g, b, d, c[n + 13], 4, 681279174); | |
g = a(b ^ d ^ h, g, b, c[n + 0], 11, -358537222); | |
h = a(g ^ b ^ d, h, g, c[n + 3], 16, -722521979); | |
d = a(h ^ g ^ b, d, h, c[n + 6], 23, 76029189); | |
b = a(d ^ h ^ g, b, d, c[n + 9], 4, -640364487); | |
g = a(b ^ d ^ h, g, b, c[n + 12], 11, -421815835); | |
h = a(g ^ b ^ d, h, g, c[n + 15], 16, 530742520); | |
d = a(h ^ g ^ b, d, h, c[n + 2], 23, -995338651); | |
b = m(b, d, h, g, c[n + 0], 6, -198630844); | |
g = m(g, b, d, h, c[n + 7], 10, 1126891415); | |
h = m(h, g, b, d, c[n + 14], 15, -1416354905); | |
d = m(d, h, g, b, c[n + 5], 21, -57434055); | |
b = m(b, d, h, g, c[n + 12], 6, 1700485571); | |
g = m(g, b, d, h, c[n + 3], 10, -1894986606); | |
h = m(h, g, b, d, c[n + 10], 15, -1051523); | |
d = m(d, h, g, b, c[n + 1], 21, -2054922799); | |
b = m(b, d, h, g, c[n + 8], 6, 1873313359); | |
g = m(g, b, d, h, c[n + 15], 10, -30611744); | |
h = m(h, g, b, d, c[n + 6], 15, -1560198380); | |
d = m(d, h, g, b, c[n + 13], 21, 1309151649); | |
b = m(b, d, h, g, c[n + 4], 6, -145523070); | |
g = m(g, b, d, h, c[n + 11], 10, -1120210379); | |
h = m(h, g, b, d, c[n + 2], 15, 718787259); | |
d = m(d, h, g, b, c[n + 9], 21, -343485551); | |
b = o(b, p); | |
d = o(d, q); | |
h = o(h, G); | |
g = o(g, B) | |
} | |
c = [b, d, h, g]; | |
b = ""; | |
for (d = 0; d < c.length * 32; d += 8) b += String.fromCharCode(c[d >> 5] >>> d % 32 & 255); | |
return b | |
} | |
function h(a) { | |
for (var b = n ? "0123456789ABCDEF" : "0123456789abcdef", f = "", c, d = 0; d < a.length; d++) c = a.charCodeAt(d), f += b.charAt(c >>> 4 & 15) + b.charAt(c & 15); | |
return f | |
} | |
function b(a) { | |
for (var b = "", f = -1, c, d; ++f < a.length;) c = a.charCodeAt(f), d = f + 1 < a.length ? a.charCodeAt(f + 1) : 0, 55296 <= c && c <= 56319 && 56320 <= d && d <= | |
57343 && (c = 65536 + ((c & 1023) << 10) + (d & 1023), f++), c <= 127 ? b += String.fromCharCode(c) : c <= 2047 ? b += String.fromCharCode(192 | c >>> 6 & 31, 128 | c & 63) : c <= 65535 ? b += String.fromCharCode(224 | c >>> 12 & 15, 128 | c >>> 6 & 63, 128 | c & 63) : c <= 2097151 && (b += String.fromCharCode(240 | c >>> 18 & 7, 128 | c >>> 12 & 63, 128 | c >>> 6 & 63, 128 | c & 63)); | |
return b | |
} | |
function a(a, b, f, c, d, k) { | |
a = o(o(b, a), o(c, k)); | |
return o(a << d | a >>> 32 - d, f) | |
} | |
function f(b, f, c, d, k, h, g) { | |
return a(f & c | ~f & d, b, f, k, h, g) | |
} | |
function k(b, f, c, d, k, h, g) { | |
return a(f & d | c & ~d, b, f, k, h, g) | |
} | |
function m(b, f, c, d, k, h, g) { | |
return a(c ^ | |
(f | ~d), b, f, k, h, g) | |
} | |
function o(a, b) { | |
var f = (a & 65535) + (b & 65535); | |
return (a >> 16) + (b >> 16) + (f >> 16) << 16 | f & 65535 | |
} | |
var p = Spotify.Shell.ResponseStatus; | |
Spotify.Shell.DefaultReactors.create({ | |
_construct: function () { | |
this._setReady() | |
}, | |
"GET /user/groupid": function (a) { | |
var b = a.body, | |
a = this._createPromise(), | |
f = this._createResponse(); | |
!b.username || !b.salt || typeof b.salt != "string" ? (f.setStatus(p.BAD_REQUEST), a.fail(f)) : (b = d(b.username, b.salt), f.setBodyField("id", b), a.fulfill(f)); | |
return a | |
} | |
}); | |
Spotify.getGroupId = d; | |
Spotify.getDefaultGroupId = | |
function (a) { | |
return d(a, "") | |
}; | |
var q = {}, n = 0 | |
})(); | |
(function () { | |
var d = Spotify.SimpleCache, | |
g = Spotify.ItemList, | |
c = g.Descriptor, | |
h = Spotify.Shell.ResponseStatus; | |
Spotify.Shell.DefaultReactors.create({ | |
_construct: function () { | |
this._baseLists = {}; | |
this._cache = new d(100); | |
this._setReady() | |
}, | |
_retrieveList: function (b) { | |
var a = null, | |
f = null, | |
c = this._cache, | |
d = b.serialize(), | |
h = c.get(d); | |
if (h) return h; | |
try { | |
switch (b.type) { | |
case "list": | |
return this._baseLists[b.uri] || null; | |
case "concatenate": | |
for (var h = [], p = 0, q = b.lists.length; p < q; p++) { | |
f = this._retrieveList(b.lists[p]); | |
if (!f) return null; | |
h.push(f) | |
} | |
a = new g.Concatenated(h); | |
a.setDescriptor(b); | |
c.put(d, a); | |
break; | |
case "sort": | |
f = this._retrieveList(b.list); | |
if (!f) return null; | |
p = f.createComparator(b.field, b.order); | |
if (!p) return null; | |
a = new g.Sorted(f, p); | |
a.setDescriptor(b); | |
c.put(d, a); | |
break; | |
case "filter": | |
f = this._retrieveList(b.list); | |
if (!f) return null; | |
var n = f.createPredicate(b.field, b.operator, b.matcher); | |
if (!n) return null; | |
a = new g.Filtered(f, n); | |
a.setDescriptor(b); | |
c.put(d, a); | |
break; | |
case "range": | |
f = this._retrieveList(b.list); | |
if (!f) return null; | |
a = new g.Ranged(f, | |
b.offset, b.length); | |
a.setDescriptor(b); | |
c.put(d, a) | |
} | |
return a | |
} catch (s) { | |
return a | |
} | |
}, | |
"GET /list": function (b) { | |
var a = this._createPromise(), | |
f = this._createResponse(); | |
(b = b.body.descriptor) && !(b instanceof c.Base) && (b = c.from(b)); | |
f.setBodyField("descriptor", b); | |
if (!b) return f.setStatus(h.BAD_REQUEST), a.fail(f), a; | |
(b = this._retrieveList(b)) ? (f.setStatus(h.OK).setBodyField("list", b), a.fulfill(f)) : (f.setStatus(h.NOT_FOUND), a.fail(f)); | |
return a | |
}, | |
"UPDATE /list": function (b) { | |
var a = this._baseLists, | |
f = this._createPromise(), | |
c = this._createResponse(), | |
d = b.body.descriptor, | |
b = b.body.list; | |
b.setDescriptor(d); | |
switch (d.type) { | |
case "list": | |
a[d.uri] = b, c.setStatus(h.OK).setBodyField("descriptor", d), f.fulfill(c) | |
} | |
return f | |
} | |
}) | |
})(); | |
(function () { | |
var d = Spotify.SimpleCache, | |
g = Spotify.LinkHelper, | |
c = Spotify.Promise, | |
h = Spotify.Shell.RequestQueue, | |
b = Spotify.Shell.Entities, | |
a = Spotify.ItemList, | |
f = a.Descriptor, | |
k = Spotify.Shell.ResponseStatus; | |
Spotify.Shell.DefaultReactors.create({ | |
_construct: function () { | |
this._metadataService = this._cdnUrls = null; | |
this._albumCache = new d(1E3); | |
this._artistCache = new d(1E3); | |
this._trackCache = new d(1E3); | |
this._albumQueue = new h; | |
this._artistQueue = new h; | |
this._trackQueue = new h; | |
this._processAlbum = this._createProcessor(b.Album, | |
this._albumCache); | |
this._processArtist = this._createProcessor(b.Artist, this._artistCache); | |
this._processTrack = this._createProcessor(b.Track, this._trackCache); | |
this._handleAlbumError = this._createErrorHandler(this._albumCache); | |
this._handleArtistError = this._createErrorHandler(this._artistCache); | |
this._handleTrackError = this._createErrorHandler(this._trackCache); | |
this._subscribeAll({ | |
"resources.core": this._onCore, | |
"resources.flush": this._onFlush, | |
"resources.image": this._onImageResources | |
}) | |
}, | |
_onCore: function (a) { | |
this._waitForServices({ | |
_metadataService: a.metadata | |
}) | |
}, | |
_onFlush: function () { | |
this._queryMetadataService(this._albumQueue, this._processAlbum, this._handleAlbumError); | |
this._queryMetadataService(this._artistQueue, this._processArtist, this._handleArtistError); | |
this._queryMetadataService(this._trackQueue, this._processTrack, this._handleTrackError) | |
}, | |
_onImageResources: function (a) { | |
this._cdnUrls = a; | |
this._ready && this._unqueue() | |
}, | |
_onServicesReady: function () { | |
this._ready = !0; | |
this._cdnUrls && this._unqueue() | |
}, | |
_queryMetadataService: function (a, b, f) { | |
var c = a.takeIds(); | |
c.length && | |
this._metadataService.lookup(c, b.bind(this, c, a), f.bind(this, c, a)) | |
}, | |
_createProcessor: function (a, b) { | |
return function (f, c, d) { | |
Array.isArray(f) || (f = [f]); | |
for (var k = 0, h = f.length; k < h; k++) this._processServiceItem(a, c, f[k], d[k]).then(b.put.bind(b, f[k])) | |
} | |
}, | |
_processServiceItem: function (a, b, f, d) { | |
var h = this._createResponse(), | |
b = b.takeValues(f), | |
g = c.group(b), | |
b = this._cdnUrls.unbranded; | |
h.setBodyField("uri", f); | |
if (d) { | |
if (!d.resourceUrl) d.resourceUrl = b; | |
a.create(f, d).then(function (a) { | |
g.fulfill(h.setBodyField("result", a)) | |
}, | |
function () { | |
g.fail(h.setStatus(k.BAD_GATEWAY)) | |
}) | |
} else g.fail(h.setStatus(k.NOT_FOUND)); | |
return g | |
}, | |
_createErrorHandler: function (a) { | |
return function (b, f, d) { | |
Array.isArray(b) || (b = [b]); | |
for (var k = 0, h = b.length; k < h; k++) { | |
var g = b[k], | |
u = this._createResponse().setBodyField("uri", g), | |
w = f.takeValues(g), | |
w = c.group(w); | |
w.then(a.put.bind(a, g)); | |
w.fail(u.setStatus(d.code)) | |
} | |
} | |
}, | |
_multiplexMetadataRequest: function (a, b, f) { | |
for (var c = a.headers, a = a.body, d = this._createPromise(), h = a.uris, g = h.length, u = {}, w = this._createResponse(), a = function (a) { | |
var b = | |
a.body; | |
u[b.uri] = a.status == k.OK ? b.result : null; | |
--g || d.fulfill(w.setBodyFields({ | |
uris: h, | |
result: u | |
})) | |
}, v = 0, A = h.length; v < A; v++) b.get(f, {}, { | |
uri: h[v] | |
}).then(a, a); | |
c.flush && this._broadcastFlush(); | |
return d | |
}, | |
_getArtistSublist: function (a, b, f, c) { | |
var d = a.body, | |
a = this._createPromise(), | |
d = g.from(d.uri); | |
if (!d || d.type != "artist") return b = this._createResponse(), b.setHeader(k.BAD_REQUEST), a.fail(b), a; | |
f = d.toURI() + ":" + f; | |
c = this._handleListFetch.bind(this, d, c.bind(this, f, b), b); | |
return b.get("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: f | |
} | |
}).then(c, c) | |
}, | |
_handleListFetch: function (a, b, f, c) { | |
var d = this._createResponse(); | |
if (c.status == k.OK) return a = c.body.list, d.setStatus(k.OK).setBodyField("list", a), d; | |
else if (c.status == k.NOT_FOUND) return c = f.get("/artist", { | |
flush: !0 | |
}, { | |
uri: a | |
}).then(function (a) { | |
a = b(a); | |
d.setBodyField("list", a); | |
return d | |
}), c.then(this._storeList.bind(this, a, f)), c; | |
else throw c; | |
}, | |
_storeList: function (a, b, f) { | |
b.update("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: a | |
}, | |
list: f.body.list | |
}) | |
}, | |
_processAlbum: function () {}, | |
_processArtist: function () {}, | |
_processTrack: function () {}, | |
_createAlbumDecorator: function (b, d, k) { | |
var h = this, | |
b = this._createPromise(), | |
g = this._createPromise(); | |
b.then(function (b) { | |
var k = b.body && b.body.result, | |
m = []; | |
if (k) { | |
for (var p = k.discs, v = [], A = 0, x = p.length; A < x; A++) { | |
var F = p[A], | |
G = h._wrapDecoratorRequest(d.createRequestSender("GET", "/tracks")), | |
B = new a.DiscTrack(F.uri, F.tracks), | |
B = new a.MetadataDecorator(B, G); | |
v.push(B); | |
m.push(d.update("/list", {}, { | |
descriptor: new f.List(F.uri), | |
list: B | |
})) | |
} | |
p = new a.AlbumTrack(k.uri, v); | |
m.push(d.update("/list", {}, { | |
descriptor: new f.List(k.uri), | |
list: p | |
})) | |
} | |
b = g.fulfill.bind(g, b); | |
c.join(m).then(b, b); | |
return g | |
}, function (a) { | |
g.fail(a); | |
return g | |
}).pipe(k); | |
return b | |
}, | |
_createArtistDecorator: function () { | |
var a = this._createPromise(); | |
a.then(function (a) { | |
return a | |
}); | |
return a | |
}, | |
_createTrackDecorator: function () { | |
var a = this._createPromise(); | |
a.then(function (a) { | |
return a | |
}); | |
return a | |
}, | |
_createAlbumGroupList: function (b, f, c) { | |
return new a.Array(c.body.result.getAlbumGroups()) | |
}, | |
_createAppearsOnGroupList: function (b, f, c) { | |
return new a.Array(c.body.result.getAppearsOnGroups()) | |
}, | |
_createSingleGroupList: function (b, f, c) { | |
return new a.Array(c.body.result.getSingleGroups()) | |
}, | |
_createRelatedList: function (b, f, c) { | |
b = new a.Array(c.body.result.getRelatedArtists()); | |
f = this._wrapDecoratorRequest(f.createRequestSender("GET", "/artists")); | |
return new a.MetadataDecorator(b, f) | |
}, | |
_createToptracksList: function (b, f, c) { | |
b = new a.Array(c.body.result.getTopTracks()); | |
f = this._wrapDecoratorRequest(f.createRequestSender("GET", "/tracks")); | |
return new a.MetadataDecorator(b, f) | |
}, | |
"GET /track": function (a) { | |
var b = | |
a.headers, | |
f = a.body, | |
a = this._createPromise(), | |
f = g.from(f.uri); | |
if (!f || f.type != "track") return b = this._createResponse(), b.setHeader(k.BAD_REQUEST), a.fail(b), a; | |
var c = this._trackCache.get(f); | |
c ? c.status != k.OK ? a.fail(c) : a.fulfill(c) : (c = this._createTrackDecorator(), c.pipe(a), this._trackQueue.push(f, c), b.flush && this._broadcastFlush()); | |
return a | |
}, | |
"GET /tracks": function (a, b) { | |
return this._multiplexMetadataRequest(a, b, "/track") | |
}, | |
"GET /album": function (a, b) { | |
var f = a.headers, | |
c = a.body, | |
d = this._createPromise(), | |
c = g.from(c.uri); | |
if (!c || c.type != "album") return f = this._createResponse(), f.setHeader(k.BAD_REQUEST), d.fail(f), d; | |
var h = this._albumCache.get(c); | |
h ? h.status != k.OK ? d.fail(h) : d.fulfill(h) : (h = this._createAlbumDecorator(a, b, d), this._albumQueue.push(c, h), f.flush && this._broadcastFlush()); | |
return d | |
}, | |
"GET /albums": function (a, b) { | |
return this._multiplexMetadataRequest(a, b, "/album") | |
}, | |
"GET /album/tracks": function (a, b) { | |
var f = this._createPromise(), | |
c = g.from(a.body.uri), | |
d = this._createResponse(); | |
if (!c || c.type != "album") return d.setHeader(k.BAD_REQUEST), | |
f.fail(d), f; | |
var h = b.createRequestSender("GET", "/list").bind(null, {}, { | |
descriptor: { | |
type: "list", | |
uri: c.toString() | |
} | |
}), | |
t = b.createRequestSender("GET", "/album").bind(null, { | |
flush: !0 | |
}, { | |
uri: c.toString() | |
}), | |
u = function (a) { | |
return d.setBodyField("list", a.body.list) | |
}; | |
return h().then(u, function () { | |
return t().then(function () { | |
return h() | |
}).then(u).catchError(function (a) { | |
throw a; | |
}) | |
}) | |
}, | |
"GET /artist": function (a) { | |
var b = a.headers, | |
f = a.body, | |
a = this._createPromise(), | |
f = g.from(f.uri); | |
if (!f || f.type != "artist") return b = this._createResponse(), | |
b.setHeader(k.BAD_REQUEST), a.fail(b), a; | |
var c = this._artistCache.get(f); | |
c ? c.status != k.OK ? a.fail(c) : a.fulfill(c) : (c = this._createArtistDecorator(), c.pipe(a), this._artistQueue.push(f, c), b.flush && this._broadcastFlush()); | |
return a | |
}, | |
"GET /artists": function (a, b) { | |
return this._multiplexMetadataRequest(a, b, "/artist") | |
}, | |
"GET /artist/albums": function (a, b) { | |
return this._getArtistSublist(a, b, "albums", this._createAlbumGroupList) | |
}, | |
"GET /artist/appearances": function (a, b) { | |
return this._getArtistSublist(a, b, "appearances", | |
this._createAppearsOnGroupList) | |
}, | |
"GET /artist/singles": function (a, b) { | |
return this._getArtistSublist(a, b, "singles", this._createSingleGroupList) | |
}, | |
"GET /artist/related": function (a, b) { | |
return this._getArtistSublist(a, b, "related", this._createRelatedList) | |
}, | |
"GET /artist/toptracks": function (a, b) { | |
return this._getArtistSublist(a, b, "top:tracks", this._createToptracksList) | |
} | |
}) | |
})(); | |
(function () { | |
var d = Spotify.SimpleCache, | |
g = Spotify.Promise, | |
c = Spotify.ItemList, | |
h = c.Descriptor, | |
b = Spotify.Shell.Entities, | |
a = Spotify.Shell.ResponseStatus; | |
Spotify.Shell.DefaultReactors.create({ | |
_construct: function () { | |
this._cdnUrls = null; | |
this._metadataCache = new d(1E3); | |
this._popcountService = this._metadataService = null; | |
this._subscribeAll({ | |
"resources.core": this._onCore, | |
"resources.image": this._onImageResources | |
}) | |
}, | |
_onCore: function (a) { | |
_core = a; | |
this._waitForServices({ | |
_playlistService: a.playlist, | |
_popcountService: a.popcount | |
}) | |
}, | |
_onImageResources: function (a) { | |
this._cdnUrls = a; | |
this._ready && this._unqueue() | |
}, | |
_queryPlaylistMetadataService: function (a) { | |
var b = this, | |
c = this._createPromise(); | |
this._playlistService.metadata(a, function (d) { | |
b._processPlaylistMetadata(a, d).pipe(c) | |
}, function (d) { | |
b._handleMetadataError(a, d).pipe(c) | |
}); | |
return c | |
}, | |
_processPlaylistMetadata: function (f, c) { | |
var d = this._createPromise(), | |
h = this._cdnUrls.unbranded, | |
g = this._createResponse(); | |
g.setBodyField("uri", f); | |
this._metadataCache.put(f, g); | |
if (!c.resourceUrl) c.resourceUrl = | |
h; | |
b.Playlist.create(f, c).then(function (a) { | |
d.fulfill(g.setBodyField("result", a)) | |
}, function () { | |
d.fail(g.setStatus(a.BAD_GATEWAY)) | |
}); | |
return d | |
}, | |
_handleMetadataError: function (a, b) { | |
var c = this._createPromise(), | |
d = this._createResponse(); | |
d.setStatus(b.code).setBodyField("uri", a); | |
b.code == 404 && this._metadataCache.put(a, d); | |
c.fail(d); | |
return c | |
}, | |
_createPlaylistTrackLoader: function () { | |
var a = this._playlistService; | |
return function (b, c) { | |
var d = new g; | |
a.list({ | |
uri: b, | |
offset: c.begin, | |
length: c.length | |
}, d.fulfill.bind(d), d.fail.bind(d)); | |
return d | |
} | |
}, | |
_createPlaylistDecorator: function (a) { | |
var b = this, | |
d = this._createPromise(), | |
g = d.then(function (d) { | |
var g = d.body && d.body.uri; | |
if (g) { | |
var m = b._wrapDecoratorRequest(a.createRequestSender("GET", "/tracks")), | |
o = new c.PlaylistRow(g, b._createPlaylistTrackLoader()), | |
o = new c.PlaylistTrackDecorator(o, m); | |
return a.update("/list", {}, { | |
descriptor: new h.List(g), | |
list: o | |
}).then(function () { | |
return d | |
}) | |
} | |
return d | |
}, function (a) { | |
throw a; | |
}); | |
return { | |
promise: d, | |
decorated: g | |
} | |
}, | |
"GET /playlist": function (b, c) { | |
var d = b.body, | |
h = this._createPromise(), | |
d = d.uri, | |
g = this._metadataCache.get(d); | |
g ? g.status != a.OK ? h.fail(g) : h.fulfill(g) : (g = this._createPlaylistDecorator(c), g.decorated.pipe(h), this._queryPlaylistMetadataService(d).pipe(g.promise)); | |
return h | |
}, | |
"GET /playlists": function (b, c) { | |
for (var d = b.headers, h = b.body, g = this._createPromise(), q = h.uris, n = q.length, s = {}, t = this._createResponse(), h = function (b) { | |
var f = b.body; | |
s[f.uri] = b.status == a.OK ? f.result : null; | |
--n || g.fulfill(t.setBodyFields({ | |
uris: q, | |
result: s | |
})) | |
}, u = 0, w = q.length; u < w; u++) c.get("/playlist", {}, { | |
uri: q[u] | |
}).then(h, | |
h); | |
d.flush && this._broadcastFlush(); | |
return g | |
} | |
}) | |
})(); | |
(function () { | |
Spotify.Shell.DefaultReactors.create({ | |
_construct: function () { | |
this._playerGroup = this._listManager = this._CDNUrls = this._core = null; | |
this._coreRequestPromise = this._createPromise(); | |
this._sourceRequestPromise = this._createPromise(); | |
this._listManagerRequestPromise = this._createPromise(); | |
this._playerGroupPromise = this._createPromise(); | |
this._setReady() | |
}, | |
"FLUSH /resources": function () { | |
var d = this._createPromise(); | |
d.fulfill(!0); | |
this._broadcastFlush(); | |
return d | |
}, | |
"CREATE /resources/core": function (d) { | |
var g = | |
this._createPromise(); | |
if (!this._core) this._core = d.body.core, this._broadcast("resources.core", this._core), this._coreRequestPromise.fulfill(this._core), g.fulfill(!0); | |
return g | |
}, | |
"GET /resources/core": function () { | |
var d = this._createPromise(); | |
this._core ? d.fulfill(this._core) : this._coreRequestPromise.pipe(d); | |
return d | |
}, | |
"CREATE /resources/image": function (d) { | |
var d = d.body, | |
g = this._createPromise(); | |
d.sources ? (this._CDNUrls = d.sources, this._broadcast("resources.image", this._CDNUrls), this._sourceRequestPromise.fulfill(this._CDNUrls), | |
g.fulfill(!0)) : g.fulfill(!1); | |
return g | |
}, | |
"GET /resources/image": function () { | |
var d = this._createPromise(); | |
this._CDNUrls ? d.fulfill(this._CDNUrls) : this._sourceRequestPromise.pipe(d); | |
return d | |
}, | |
"CREATE /resources/listmanager": function (d) { | |
var d = d.body, | |
g = this._createPromise(); | |
d.listManager ? (this._listManager = d.listManager, this._broadcast("resources.listmanager", this._listManager), this._listManagerRequestPromise.fulfill(this._listManager), g.fulfill(!0)) : g.fulfill(!1); | |
return g | |
}, | |
"GET /resources/listmanager": function () { | |
var d = | |
this._createPromise(); | |
this._listManager ? d.fulfill(this._listManager) : this._listManagerRequestPromise.pipe(d); | |
return d | |
}, | |
"CREATE /resources/playergroup": function (d) { | |
var d = d.body, | |
g = this._createPromise(); | |
d.playerGroup ? (this._playerGroup = d.playerGroup, this._broadcast("resources.playergroup", this._playerGroup), this._playerGroupPromise.fulfill(this._playerGroup), g.fulfill(!0)) : g.fulfill(!1); | |
return g | |
}, | |
"GET /resources/playergroup": function () { | |
var d = this._createPromise(); | |
this._playerGroup ? d.fulfill(this._playerGroup) : | |
this._playerGroupPromise.pipe(d); | |
return d | |
} | |
}) | |
})(); | |
(function () { | |
var d = Spotify.ItemList, | |
g = Spotify.Shell.SearchTypes; | |
Spotify.Shell.DefaultReactors.create({ | |
_construct: function () { | |
this._fuzzyMatches = {}; | |
this._searchTTL = 36E5; | |
this._searchService = this._cdnUrls = null; | |
this._subscribeAll({ | |
"resources.core": this._onCore, | |
"resources.flush": this._onFlush, | |
"resources.image": this._onImageResources | |
}) | |
}, | |
_onCore: function (c) { | |
this._waitForServices({ | |
_searchService: c.search | |
}) | |
}, | |
_onFlush: function () {}, | |
_onImageResources: function (c) { | |
this._cdnUrls = c; | |
this._ready && this._unqueue() | |
}, | |
_onServicesReady: function () { | |
this._ready = !0; | |
this._cdnUrls && this._unqueue() | |
}, | |
_createSearchItemsLoader: function (c, d) { | |
var b = this, | |
a = this._fuzzyMatches, | |
f = this._searchService, | |
k = null, | |
m = this._cdnUrls; | |
switch (d) { | |
case g.ALBUMS: | |
k = f.ALBUMS; | |
break; | |
case g.ARTISTS: | |
k = f.ARTISTS; | |
break; | |
case g.PLAYLISTS: | |
k = f.PLAYLISTS; | |
break; | |
default: | |
k = f.TRACKS | |
} | |
return function (g) { | |
var p = b._createPromise(); | |
f.search(c, { | |
type: k, | |
offset: g.begin, | |
length: g.length | |
}, function (b) { | |
if (b.didYouMean) a[c] = b.didYouMean; | |
for (var f = b[d].slice(0), k = 0, g = f.length; k < g; k++) | |
if (f[k]) f[k].resourceUrl = m.unbranded, | |
f[k].resourceUrls = m; | |
p.fulfill({ | |
length: b.total[d], | |
items: f | |
}) | |
}, function (a) { | |
p.fail(a) | |
}); | |
return p | |
} | |
}, | |
_handleListFetch: function (c, d, b, a) { | |
var f = null, | |
k = this._createResponse(); | |
if (a.status == 200) return f = a.body.list, f.getRootBaseList().isOlderThan(this._searchTTL) ? this._createSearchList(c, d, b, k) : k.setBodyField("list", f); | |
else if (a.status == 404) return this._createSearchList(c, d, b, k); | |
else throw a; | |
}, | |
_createSearchList: function (c, h, b, a) { | |
var f = c.toString() + ":" + b, | |
k = this._createSearchItemsLoader(c.query, b), | |
g = d.Search.create(b, | |
c, k), | |
g = new d.Property(g, "uri"), | |
c = this._wrapDecoratorRequest(h.createRequestSender("GET", "/" + b)), | |
g = new d.MetadataDecorator(g, c); | |
return h.update("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: f | |
}, | |
list: g | |
}).then(function () { | |
return a.setBodyField("list", g) | |
}) | |
}, | |
"GET /search/tracks": function (c, d) { | |
var b = c.body.uri, | |
a = b.toString() + ":tracks", | |
b = this._handleListFetch.bind(this, b, d, "tracks"); | |
return d.get("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: a | |
} | |
}).then(b, b) | |
}, | |
"GET /search/artists": function (c, d) { | |
var b = c.body.uri, | |
a = b.toString() + | |
":artists", | |
b = this._handleListFetch.bind(this, b, d, "artists"); | |
return d.get("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: a | |
} | |
}).then(b, b) | |
}, | |
"GET /search/albums": function (c, d) { | |
var b = c.body.uri, | |
a = b.toString() + ":albums", | |
b = this._handleListFetch.bind(this, b, d, "albums"); | |
return d.get("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: a | |
} | |
}).then(b, b) | |
}, | |
"GET /search/playlists": function (c, d) { | |
var b = c.body.uri, | |
a = b.toString() + ":playlists", | |
b = this._handleListFetch.bind(this, b, d, "playlists"); | |
return d.get("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: a | |
} | |
}).then(b, b) | |
}, | |
"GET /search/fuzzymatch": function (c) { | |
var d = this._createPromise(), | |
b = this._searchService, | |
a = this._fuzzyMatches, | |
f = c.body.query, | |
k = this._createResponse(); | |
f in a ? (k.setBodyField("match", a[f]), d.fulfill(k)) : b.search(f, { | |
type: b.TRACKS, | |
offset: 0, | |
total: 20 | |
}, function (b) { | |
b = b.didYouMean || null; | |
a[f] = b; | |
k.setBodyField("match", b); | |
d.fulfill(k) | |
}, function () { | |
a[f] = null; | |
k.setBodyField("match", null); | |
d.fulfill(k) | |
}); | |
return d | |
} | |
}) | |
})(); | |
(function () { | |
var d = Spotify.Link, | |
g = Spotify.ItemList, | |
c = Spotify.Shell.ResponseStatus; | |
Spotify.Shell.DefaultReactors.create({ | |
_construct: function () { | |
this._toplistService = null; | |
this._subscribe("resources.core", this._onCore) | |
}, | |
_onCore: function (c) { | |
this._waitForServices({ | |
_toplistService: c.toplist | |
}) | |
}, | |
_handleServiceError: function (c) { | |
var b = this._createPromise(), | |
a = this._createResponse(); | |
a.setStatus(c.code); | |
b.fail(a); | |
return b | |
}, | |
_queryToplistForUser: function (c, b) { | |
var a = this, | |
f = this._createPromise(); | |
this._toplistService.lookupForUser(c, | |
b, function (a, b) { | |
f.fulfill({ | |
type: b, | |
array: a | |
}) | |
}, function (b) { | |
a._handleServiceError(b).pipe(f) | |
}); | |
return f | |
}, | |
_queryToplistForRegion: function (c, b) { | |
var a = this, | |
f = this._createPromise(); | |
this._toplistService.lookupForRegion(c, b, function (a, b) { | |
f.fulfill({ | |
type: b, | |
array: a | |
}) | |
}, function (b) { | |
a._handleServiceError(b).pipe(f) | |
}); | |
return f | |
}, | |
_createToplist: function (c, b, a) { | |
var f = a.type, | |
d = g.Toplist.create(f, c, a.array), | |
a = this._wrapDecoratorRequest(b.createRequestSender("GET", "/" + f + "s")), | |
d = new g.MetadataDecorator(d, a); | |
return b.update("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: c.toString() | |
}, | |
list: d | |
}).then(function () { | |
return d | |
}) | |
}, | |
_handleUserToplistQuery: function (d, b, a, f) { | |
var k = null, | |
g = this._createResponse(); | |
if (f.status == c.OK) return k = f.body.list, g.setBodyField("list", k); | |
else if (f.status == c.NOT_FOUND) return this._queryToplistForUser(d.username, a).then(this._createToplist.bind(this, d, b), function (a) { | |
throw a; | |
}).then(function (a) { | |
return g.setBodyField("list", a) | |
}); | |
else throw f; | |
}, | |
_handleRegionToplistQuery: function (d, b, a, f) { | |
var k = null, | |
g = this._createResponse(); | |
if (f.status == c.OK) return k = f.body.list, g.setBodyField("list", k); | |
else if (f.status == c.NOT_FOUND) return this._queryToplistForRegion(d.country || null, a).then(this._createToplist.bind(this, d, b), function (a) { | |
throw a; | |
}).then(function (a) { | |
return g.setBodyField("list", a) | |
}); | |
else throw f; | |
}, | |
"GET /toplist": function (h, b) { | |
var a = this._createResponse(), | |
f = this._createPromise(), | |
k = h.body, | |
g = k.uri || null; | |
if (typeof g == "string") try { | |
g = d.fromString(g) | |
} catch (o) {} | |
if (!g) return a.setStatus(c.BAD_REQUEST), f.fail(a), f; | |
k.uri = g; | |
k = null; | |
switch (g.type) { | |
case "toplist": | |
k = "/toplist/region"; | |
break; | |
case "user-toplist": | |
k = "/toplist/user" | |
} | |
return !k ? (a.setStatus(c.BAD_REQUEST), f.fail(a), f) : b.get(k, h.headers, h.body) | |
}, | |
"GET /toplist/user": function (h, b) { | |
var a = this._toplistService, | |
f = this._createResponse(), | |
k = this._createPromise(), | |
g = h.body.uri || null; | |
if (typeof g == "string") try { | |
g = d.fromString(g) | |
} catch (o) {} | |
if (!g) return f.setStatus(c.BAD_REQUEST), k.fail(f), k; | |
f = null; | |
switch (g.toplist) { | |
case "albums": | |
f = a.ALBUM; | |
break; | |
case "artists": | |
f = a.ARTIST; | |
break; | |
case "playlists": | |
f = | |
a.PLAYLIST; | |
break; | |
default: | |
f = a.TRACK | |
} | |
a = this._handleUserToplistQuery.bind(this, g, b, f); | |
return b.get("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: g.toURI() | |
} | |
}).then(a, a) | |
}, | |
"GET /toplist/region": function (h, b) { | |
var a = this._toplistService, | |
f = this._createResponse(), | |
k = this._createPromise(), | |
g = h.body.uri || null; | |
if (typeof g == "string") try { | |
g = d.fromString(g) | |
} catch (o) {} | |
if (!g) return f.setStatus(c.BAD_REQUEST), k.fail(f), k; | |
f = null; | |
switch (g.toplist) { | |
case "albums": | |
f = a.ALBUM; | |
break; | |
case "artists": | |
f = a.ARTIST; | |
break; | |
case "playlists": | |
f = | |
a.PLAYLIST; | |
break; | |
default: | |
f = a.TRACK | |
} | |
a = this._handleRegionToplistQuery.bind(this, g, b, f); | |
return b.get("/list", {}, { | |
descriptor: { | |
type: "list", | |
uri: g.toURI() | |
} | |
}).then(a, a) | |
} | |
}) | |
})(); | |
(function () { | |
Spotify.Bridge = new Spotify.Shell.EventEmitter; | |
Spotify.Bridge.SourceURLs = { | |
unbranded: "https://d3rt1990lpmkn.cloudfront.net/unbranded/", | |
tiny: "https://d3rt1990lpmkn.cloudfront.net/60/", | |
normal: "https://d3rt1990lpmkn.cloudfront.net/300/", | |
small: "https://d3rt1990lpmkn.cloudfront.net/120/", | |
large: "https://d3rt1990lpmkn.cloudfront.net/640/", | |
avatar: "https://d3rt1990lpmkn.cloudfront.net/artist_image/" | |
} | |
})(); | |
(function () { | |
function d(b) { | |
this._storage = c[b] || (c[b] = {}); | |
this._watchers = h[b] || (h[b] = {}) | |
} | |
var g = !1, | |
c = {}, h = {}; | |
d.prototype.wait = function (b, a) { | |
var f = this._watchers[b] || (this._watchers[b] = []); | |
f.indexOf(a) == -1 && f.push(a); | |
return this | |
}; | |
d.prototype.store = function (b, a) { | |
var f = this._storage, | |
c = this._watchers[b], | |
d = f[b]; | |
f[b] = a; | |
if (c && c.length) | |
for (var f = 0, h = c.length; f < h; f++) c[f](a, d); | |
return this | |
}; | |
d.prototype.retrieve = function (b) { | |
var a = this._storage; | |
return b in a ? a[b] : null | |
}; | |
Spotify.getStorage = function (b) { | |
if (g) throw Error("Cannot fetch from locked storage."); | |
return new d(b) | |
}; | |
Spotify.lockStorage = function () { | |
g = !0 | |
} | |
})(); | |
(function () { | |
function d(a) { | |
Error.apply(this, arguments); | |
this.message = a | |
} | |
function g(a) { | |
d.call(this, a) | |
} | |
function c(a) { | |
d.call(this, a) | |
} | |
function h(a) { | |
d.call(this, a) | |
} | |
function b(a) { | |
d.call(this, a) | |
} | |
function a(a) { | |
d.call(this, a) | |
} | |
function f(a) { | |
d.call(this, a) | |
} | |
function k(a) { | |
d.call(this, a) | |
} | |
function m(a) { | |
d.call(this, a) | |
} | |
function o(a) { | |
d.call(this, a) | |
} | |
function p(a) { | |
d.call(this, a) | |
} | |
function q(a) { | |
d.call(this, a) | |
} | |
function n(a) { | |
d.call(this, a) | |
} | |
function s(a) { | |
d.call(this, a) | |
} | |
function t(a) { | |
d.call(this, a) | |
} | |
function u(a) { | |
d.call(this, | |
a) | |
} | |
var w = Spotify.Shell.ResponseStatus; | |
Spotify.Bridge.translateShellError = function (a) { | |
if (a instanceof Error) b = new d.Transient("Operation errored while performing request."); | |
else { | |
var b = a; | |
switch (a.status) { | |
case w.NOT_FOUND: | |
b = new d.NotFound("Resource not found."); | |
break; | |
case w.BAD_REQUEST: | |
b = new d.InvalidRequest("Request failed because of invalid arguments.") | |
} | |
} | |
throw b; | |
}; | |
Spotify.inherit(d, Error); | |
d.prototype.name = "BridgeError"; | |
d.prototype.type = "bridge-error"; | |
Spotify.Bridge.Error = d; | |
d.Aborted = g; | |
d.Forbidden = | |
c; | |
d.Hermes = h; | |
d.InvalidRequest = b; | |
d.InvalidURI = a; | |
d.NotConnected = f; | |
d.NotFound = k; | |
d.NotImplemented = m; | |
d.OutOfDate = o; | |
d.PlayCapped = p; | |
d.RateLimited = q; | |
d.Timeout = n; | |
d.Transient = s; | |
d.Unknown = t; | |
d.Unplayable = u; | |
Spotify.inherit(g, d); | |
g.prototype.name = "BridgeAbortedError"; | |
g.prototype.type = "aborted"; | |
Spotify.inherit(c, d); | |
c.prototype.name = "BridgeForbiddenError"; | |
c.prototype.type = "forbidden"; | |
Spotify.inherit(h, d); | |
h.prototype.name = "BridgeHermesError"; | |
h.prototype.type = "hermes"; | |
Spotify.inherit(b, d); | |
b.prototype.name = "BridgeInvalidRequestError"; | |
b.prototype.type = "invalid-request"; | |
Spotify.inherit(a, d); | |
a.prototype.name = "BridgeInvalidURIError"; | |
a.prototype.type = "invalid-uri"; | |
Spotify.inherit(f, d); | |
f.prototype.name = "BridgeNotConnectedError"; | |
f.prototype.type = "not-connected"; | |
Spotify.inherit(k, d); | |
k.prototype.name = "BridgeNotFoundError"; | |
k.prototype.type = "not-found"; | |
Spotify.inherit(m, d); | |
m.prototype.name = "BridgeNotImplementedError"; | |
m.prototype.type = "not-implemented"; | |
Spotify.inherit(o, d); | |
o.prototype.name = "BridgeOutOfDateError"; | |
o.prototype.type = "out-of-date"; | |
Spotify.inherit(p, d); | |
p.prototype.name = "BridgePlayCappedError"; | |
p.prototype.type = "play-capped"; | |
Spotify.inherit(q, d); | |
q.prototype.name = "BridgeRateLimitedError"; | |
q.prototype.type = "rate-limited"; | |
Spotify.inherit(n, d); | |
n.prototype.name = "BridgeTimeoutError"; | |
n.prototype.type = "timeout"; | |
Spotify.inherit(s, d); | |
s.prototype.name = "BridgeTransientError"; | |
s.prototype.type = "transient"; | |
Spotify.inherit(t, d); | |
t.prototype.name = "BridgeUnknownError"; | |
t.prototype.type = "unknown"; | |
Spotify.inherit(u, d); | |
u.prototype.name = "BridgeUnplayableError"; | |
u.prototype.type = "unplayable" | |
})(); | |
(function () { | |
function d(b, a) { | |
for (var f in a) a.hasOwnProperty(f) && (b[f] = a[f]); | |
return b | |
} | |
function g(b, a, f) { | |
if (!(this instanceof g)) return new g(b, a, f); | |
this.timestamp = (new Date).getTime(); | |
this._id = b; | |
this._origin = a; | |
this._source = f; | |
this._payload = null; | |
this._success = !0; | |
this._sent = this._persisted = this._hasPartial = !1 | |
} | |
function c(b, a) { | |
if (!(this instanceof c)) return new c(b, a); | |
this._done = b; | |
this._error = a; | |
this._payload = null; | |
this._success = !0; | |
this._sent = this._persisted = this._hasPartial = !1 | |
} | |
var h = Spotify.Bridge.Error; | |
Spotify.Bridge.Reply = g; | |
g.prototype.persist = function () { | |
this._persisted = !0; | |
return this | |
}; | |
g.prototype.addPartial = function (b) { | |
if (!(this._sent || typeof b != "object")) this._hasPartial ? this._payload = d(this._payload, b) : (this._payload = d({}, b), this._hasPartial = !0) | |
}; | |
g.prototype.send = function (b) { | |
if (this._sent) return null; | |
this._sent = !0; | |
this._hasPartial && (b = d(this._payload, b)); | |
if (this._source) { | |
var a = { | |
id: this._id, | |
success: this._success, | |
payload: b | |
}; | |
if (b.type) { | |
if (b.data) b.event = b.type; | |
if (b.receiver) b.target = b.receiver | |
} | |
this._source !== | |
window && this._source.postMessage(JSON.stringify(a), this._origin); | |
this._payload = this._source = this._origin = null | |
} | |
}; | |
g.prototype.fail = function (b, a, f) { | |
if (this._sent) return null; | |
if (b instanceof h) f = b.code, a = b.message, b = b.type; | |
b = typeof b == "string" ? { | |
error: b, | |
message: a, | |
code: f | |
} : b; | |
this._success = !1; | |
return this.send(b) | |
}; | |
g.prototype.timeout = function () { | |
return this._sent || this._persisted ? !1 : this.fail(new h.Timeout("Request timed-out.")) | |
}; | |
Spotify.inherit(c, g); | |
Spotify.Bridge.Reply.Internal = c; | |
c.prototype.send = function (b) { | |
if (this._sent) return null; | |
this._sent = !0; | |
this._hasPartial && (b = d(this._payload, b)); | |
this._success && this._done ? this._done(b) : !this._success && this._error && this._error(b) | |
} | |
})(); | |
(function () { | |
function d() { | |
this._requests = {}; | |
this._hostMap = {} | |
} | |
function g(c, d, b) { | |
this._id = c; | |
this._request = d; | |
this._params = b || []; | |
this._status = "pending"; | |
this._timestamp = (new Date).getTime(); | |
this._roundtrip = 0 | |
} | |
Spotify.Bridge.RequestLogger = d; | |
d.prototype.enter = function (c, d, b, a) { | |
var f = this._requests, | |
f = f[c] || (f[c] = { | |
total: 0, | |
success: 0, | |
failure: 0, | |
pending: 0, | |
requests: {} | |
}); | |
f.total++; | |
f.pending++; | |
f.requests[d] = new g(d, b, a); | |
this._hostMap[d] = c | |
}; | |
d.prototype.succeed = function (c, d) { | |
var b = this._hostMap[c]; | |
if (!b) return this; | |
b = this._requests[b]; | |
b.success++; | |
b.pending--; | |
b.requests[c].finish(d); | |
return this | |
}; | |
d.prototype.fail = function (c, d) { | |
var b = this._hostMap[c]; | |
if (!b) return this; | |
b = this._requests[b]; | |
b.failure++; | |
b.pending--; | |
b.requests[c].finish(d); | |
return this | |
}; | |
d.prototype.get = function (c) { | |
return this._requests[c] || null | |
}; | |
d.prototype.formatted = function (c) { | |
var d = this.get(c); | |
if (!d) return "No logs for item."; | |
var b = []; | |
b.push([c, "- total:", d.total, "- success:", d.success, "- failed:", d.failure, "- pending:", d.pending].join(" ")); | |
var c = | |
d.requests, | |
a; | |
for (a in c) b.push(c[a].toString()); | |
return b.join("\n") | |
}; | |
g.prototype.finish = function (c) { | |
this._status = c; | |
this._roundtrip = (new Date).getTime() - this._timestamp; | |
return this | |
}; | |
g.prototype.toString = function () { | |
for (var c = this._params.slice(0, 5), d = Math.max(this._params.length - 5, 0), b = c.length; b--;) c[b] = JSON.stringify(c[b]); | |
return [" |", [" |- ", this._request, ": ", this._status].join(""), [" | [", this._status == "pending" ? "P" : this._roundtrip + "ms", "] params: [", c.join(", "), d !== 0 ? ", plus " + d + " more.." : "", | |
"]" | |
].join("")].join("\n") | |
}; | |
g.prototype.toJSON = g.prototype.toString | |
})(); | |
(function () { | |
function d(a, b, f) { | |
return function () { | |
if (!this._ready) return this.queue(f); | |
a[f].fn = b; | |
return b.apply(this, arguments) | |
} | |
} | |
function g(a) { | |
for (var b in a) | |
if (a.hasOwnProperty(b)) { | |
var f = b, | |
c = a[b]; | |
switch (!0) { | |
case f == "flushRequests": | |
p.push(c.bind(this)); | |
break; | |
case !!(matches = f.match(/^(\*|@)(\1)?([^*@]+)$/)): | |
var k = matches[1] == "*", | |
h = matches[2] ? o : m, | |
f = matches[3]; | |
if (f in h) throw Error('Redefinition of message handler "' + f + '".'); | |
if (typeof c == "string") { | |
if (c = h[c]) h[f] = c; | |
else throw Error('Aliasing of undefined message handler "' + | |
f + '".'); | |
break | |
} | |
h[f] = { | |
bound: this, | |
fn: d(h, c, f), | |
passApp: k | |
}; | |
break; | |
default: | |
this[f] = c | |
} | |
} | |
this._queue = []; | |
this.create && this.create(); | |
if (this.init) Spotify.Bridge.onReady(this.init.bind(this)); | |
return this | |
} | |
var c = Spotify.Promise, | |
h = Spotify.defer, | |
b = Spotify.Bridge, | |
a = b.Error, | |
f = b.Reply, | |
k = b.SourceURLs; | |
Spotify.getStorage("app.message.ns"); | |
var m = {}, o = {}, p = [], | |
q = {}, n = {}, s = null; | |
Spotify.Bridge.Responder = g; | |
g.getHandler = function (a) { | |
return m[a] | |
}; | |
g.respondsTo = function (a) { | |
return a in m | |
}; | |
g.setPublisher = function (a) { | |
s = a; | |
return this | |
}; | |
g.block = function (a) { | |
n[a] = !0; | |
return this | |
}; | |
g.blockAll = function (a) { | |
for (var b = a.length; b--;) n[a[b]] = !0; | |
return this | |
}; | |
g.unblock = function (a) { | |
n[a] = null; | |
return this | |
}; | |
g.unblockAll = function () { | |
n = {}; | |
return this | |
}; | |
g.hasBlocked = function (a) { | |
return !!n[a] | |
}; | |
g.handleBlocked = function (a, b, f) { | |
s && s.notify("LIMITED_FEATURE_CALL", { | |
origin: a.source, | |
feature: f, | |
callback: function () {} | |
}); | |
return b.fail("restricted", "Cannot perform action in this session.") | |
}; | |
g.prototype.traceOut = function () { | |
return function () {} | |
}; | |
g.prototype.traceError = | |
function () { | |
return function () {} | |
}; | |
g.flush = function () { | |
for (var a = p.length; a--;) p[a]() | |
}; | |
g.prototype.use = function (a) { | |
var b = 0, | |
f = [], | |
c; | |
for (c in a) this[c] = a[c], f.push(a[c]), b++; | |
a = function () { | |
--b || this.start() | |
}.bind(this); | |
for (c = b; c--;) f[c].onReady(a, this); | |
return this | |
}; | |
g.prototype._createPromise = function () { | |
return new c | |
}; | |
g.prototype.queue = function (a) { | |
var b = this.queue.caller; | |
this._queue.push({ | |
name: a, | |
fn: b, | |
args: b.arguments | |
}) | |
}; | |
g.prototype.unqueue = function () { | |
for (var a = this._queue, b = 0, f = a.length; b < f; b++) { | |
var c = a[b]; | |
n[c.name] ? g.handleBlocked.apply(this, c.args.concat(c.name)) : c.fn.apply(this, c.args) | |
} | |
this._queue = []; | |
return this | |
}; | |
g.prototype.store = function (a, b, f) { | |
(q[b] || (q[b] = new Spotify.SimpleCache(1E3))).put(a, f); | |
return this | |
}; | |
g.prototype.retrieve = function (a, b) { | |
return q[b] ? q[b].get(a) || null : null | |
}; | |
g.prototype.trigger = function (a, b, c, d) { | |
a = m[a] || o[a]; | |
if (!a) return typeof d !== "undefined" ? d({ | |
error: "not-implemented" | |
}) : null; | |
Array.isArray(b) && (b = { | |
args: b | |
}); | |
c = new f.Internal(c, d); | |
(b = a.fn.call(a.bound || {}, b, c)) && b.then && b.then(c.send.bind(c), | |
c.fail.bind(c)); | |
h(function () { | |
g.flush() | |
}) | |
}; | |
g.prototype._request = function (f, c, d) { | |
var k = this._createPromise(), | |
f = m[f] || o[f]; | |
if (!f || !f.passApp) return k.fail(new a.NotImplemented("Message not implemented.")), k; | |
(c = f.fn.call(f.bound || {}, d, c)) && c.then ? c.catchError(b.translateShellError).pipe(k) : k.fulfill(c); | |
return k | |
}; | |
g.prototype.createImageSizes = function (a, b) { | |
var f = [ | |
[60, k.tiny + a], | |
[120, k.small + a], | |
[300, k.normal + a], | |
[640, k.large + a] | |
]; | |
b && (f.shift(), f.pop()); | |
return f | |
}; | |
g.prototype.createUserImageSizes = function (a, | |
b) { | |
var f = []; | |
a && f.push([50, a]); | |
b && f.push([180, b]); | |
for (var c = 0, d = f.length; c < d; c++) { | |
var k = f[c][1].match(/^spotify:image:(.+)/); | |
k && (f[c][1] = Spotify.Bridge.SourceURLs.avatar + k[1]) | |
} | |
return f | |
}; | |
g.prototype.createSnapshot = function (a, b, f, c) { | |
var d = a[1] || 0, | |
a = a[2] || -1, | |
a = a == -1 ? b.length : a; | |
return { | |
range: { | |
offset: d, | |
length: a | |
}, | |
length: f || b.length, | |
array: b.slice(d, d + a), | |
metadata: (c || []).slice(d, d + a) | |
} | |
}; | |
g.prototype.createDimensions = function (a, b, f) { | |
a = a || 0; | |
f = f || 500; | |
b = b == -1 ? f : Math.min(b, f); | |
return { | |
start: a, | |
end: a + b - 1, | |
length: b | |
} | |
} | |
})(); | |
(function () { | |
function d() { | |
this._keys = []; | |
this._values = [] | |
} | |
Spotify.Bridge.WeakMap = d; | |
d.prototype.get = function (d) { | |
d = this._keys.indexOf(d); | |
return d == -1 ? null : this._values[d] | |
}; | |
d.prototype.getKey = function (d) { | |
d = this._values.indexOf(d); | |
return d == -1 ? null : this._keys[d] | |
}; | |
d.prototype.set = function (d, c) { | |
var h = this._keys, | |
b = this._values, | |
a = h.indexOf(d); | |
if (a != -1) return b[a] = c, this; | |
h.push(d); | |
b.push(c); | |
return this | |
}; | |
d.prototype.remove = function (d) { | |
var c = this._keys, | |
h = this._values, | |
d = c.indexOf(d); | |
if (d == -1) return this; | |
c.splice(d, | |
1); | |
h.splice(d, 1); | |
return this | |
}; | |
d.prototype.clear = function () { | |
this._keys.splice(0, this._keys.length); | |
this._values.splice(0, this._values.length); | |
return this | |
} | |
})(); | |
(function () { | |
function d(a, b, c) { | |
for (var d = 0, h = b, b = c.length + b; h < b; d++, h++) a[h] = c[d] | |
} | |
function g(a) { | |
for (var b = a.length; b;) { | |
var c = Math.floor(Math.random() * b--), | |
d = a[b]; | |
a[b] = a[c]; | |
a[c] = d | |
} | |
return a | |
} | |
function c(a, f) { | |
this._id = a; | |
this._rule = b.defaults; | |
this._currentIndex = 0; | |
this._shuffled = this._repeated = !1; | |
this._shuffledList = null; | |
this._metadata = []; | |
var c = this._list = this._origin = []; | |
if (!f) return this; | |
for (var d = 0, h = f.length; d < h; d++) d in f && f[d] && c.push(f[d]) | |
} | |
var h = Spotify.getStorage("app.context.ns"); | |
h.store("quickShuffle", | |
g); | |
var b = { | |
defaults: { | |
skipCount: -1, | |
volume: !0, | |
seek: !0, | |
indexing: !0, | |
previous: !0, | |
next: !0, | |
shuffle: !0, | |
repeat: !0 | |
}, | |
intercept: { | |
skipcount: -1, | |
volume: !1, | |
seek: !1, | |
indexing: !0, | |
previous: !1, | |
next: !1, | |
shuffle: !1, | |
repeat: !1 | |
}, | |
radio: { | |
skipCount: -1, | |
volume: !0, | |
seek: !0, | |
indexing: !0, | |
previous: !1, | |
next: !0, | |
shuffle: !1, | |
repeat: !1 | |
}, | |
dmca: { | |
skipCount: 6, | |
volume: !0, | |
seek: !0, | |
indexing: !0, | |
previous: !1, | |
next: !0, | |
shuffle: !1, | |
repeat: !1 | |
}, | |
stream: { | |
skipcount: -1, | |
volume: !0, | |
seek: !1, | |
indexing: !0, | |
previous: !1, | |
next: !1, | |
shuffle: !1, | |
repeat: !1 | |
} | |
}; | |
h.store("Context", c); | |
c.prototype.getId = | |
function () { | |
return this._anonymous ? null : this._id | |
}; | |
c.prototype.setAnonymous = function (a) { | |
this._anonymous = !! a; | |
return this | |
}; | |
c.prototype.setRule = function (a) { | |
return (a = b[a]) ? (this._rule = a, !0) : !1 | |
}; | |
c.prototype.getRule = function () { | |
return this._rule | |
}; | |
c.prototype.setRepeat = function (a) { | |
return !this._rule.repeat ? !1 : this._repeated = a | |
}; | |
c.prototype.isRepeated = function () { | |
return this._repeated | |
}; | |
c.prototype.setShuffle = function (a) { | |
if (!this._rule.shuffle) return !1; | |
(this._shuffled = a) ? this._shuffle() : this._unshuffle(); | |
return a | |
}; | |
c.prototype.isShuffled = function () { | |
return this._shuffled | |
}; | |
c.prototype.setExpiry = function (a) { | |
if (!a || a < 0) return this; | |
this._time = (new Date).getTime(); | |
this._ttl = a; | |
return this | |
}; | |
c.prototype.isExpired = function () { | |
var a = this._ttl; | |
return !a ? !1 : (new Date).getTime() - this._time >= a | |
}; | |
c.prototype.mapToURI = function (a, b) { | |
return b || a | |
}; | |
c.prototype.mapToId = function (a, b) { | |
return b || a | |
}; | |
c.prototype._shufflePartial = function (a) { | |
var b = this._shuffledList; | |
if (!b) return this; | |
for (var c = this._origin.length - a, d = Array(c); c--;) d[c] = a + | |
c; | |
g(d).unshift(a, 0); | |
b.splice.apply(b, d); | |
return this | |
}; | |
c.prototype._shuffle = function (a) { | |
if (a != void 0) return this._shufflePartial(a); | |
for (var b = this._origin.length, a = Array(b); b--;) a[b] = b; | |
b = a.splice(this._currentIndex, 1).pop(); | |
g(a).unshift(b); | |
this._list = this._shuffledList = a; | |
this._currentIndex = 0; | |
return this | |
}; | |
c.prototype._unshuffle = function () { | |
if (!this._shuffledList) return this; | |
this._list = this._origin; | |
this._currentIndex = this._shuffledList[this._currentIndex]; | |
return this | |
}; | |
c.prototype.get = function (a) { | |
var b = | |
this._origin; | |
if (a < 0 || a > b.length) return null; | |
this._shuffled && (a = this._shuffledList[a]); | |
b = b[a]; | |
a = this._metadata[a]; | |
return !b || !a ? null : { | |
item: b, | |
metadata: a | |
} | |
}; | |
c.prototype.getList = function () { | |
return this._origin | |
}; | |
c.prototype.getLength = function () { | |
return this._origin.length | |
}; | |
c.prototype.setFullLength = function (a) { | |
if (typeof a != "number" && (a = parseInt(a, 10), isNaN(a))) throw new TypeError("Cannot set possible length to a non-number"); | |
this._actualLen = a; | |
return this | |
}; | |
c.prototype.getFullLength = function () { | |
return this._actualLen != | |
void 0 ? Math.max(this._actualLen, this.getLength()) : this.getLength() | |
}; | |
c.prototype.append = function (a) { | |
if (!a) return this; | |
if (this._resolved) Spotify.Bridge.trigger("track_multi_metadata", [a], function (b) { | |
var f = this._origin.push(a) - 1; | |
this._metadata.push(b[a]); | |
this._shuffled && this._shuffle(f) | |
}.bind(this)); | |
else { | |
var b = this._origin.push(a) - 1; | |
this._shuffled && this._shuffle(b) | |
} | |
return this | |
}; | |
c.prototype.prependMany = function (a) { | |
a = Array.isArray(a) ? a : [a]; | |
this._resolved ? Spotify.Bridge.trigger("track_multi_metadata", a, | |
function (b) { | |
this._origin.unshift.apply(this._origin, a); | |
for (var c = [], d = 0, h = a.length; d < h; d++) c[d] = b[a[d]]; | |
this._metadata.unshift.apply(this._metadata, c); | |
this._shuffled && this._shuffle(0) | |
}.bind(this)) : (this._origin.unshift.apply(this._origin, a), this._shuffled && this._shuffle(0)); | |
return this | |
}; | |
c.prototype.appendWithMeta = function (a, b) { | |
if (!a || !b) return this; | |
var c = this._origin.push(a) - 1; | |
this._metadata[c] = b; | |
this._shuffled && this._shuffle(c); | |
return this | |
}; | |
c.prototype.concat = function (a) { | |
if (!a || !a.length) return this; | |
if (this._resolved) Spotify.Bridge.trigger("track_multi_metadata", a, function (b) { | |
for (var f = 0, c = a.length; f < c; f++) this._origin.push(a[f]), this._metadata.push(b[a[f]]); | |
this._shuffled && this._shuffle(this._origin.length - a.length - 1) | |
}.bind(this)); | |
else { | |
for (var b = 0, c = a.length; b < c; b++) this._origin.push(a[b]); | |
this._shuffled && this._shuffle(this._origin.length - a.length - 1) | |
} | |
return this | |
}; | |
c.prototype.splice = function (a, b) { | |
if (typeof a == "undefined" || !b || !b.length) return this; | |
if (this._resolved) Spotify.Bridge.trigger("track_multi_metadata", | |
b, function (c) { | |
for (var k = [], h = [], g = 0, m = b.length; g < m; g++) g in b && b[g] && (k.push(b[g]), h.push(c[b[g]])); | |
d(this._origin, a, b); | |
d(this._metadata, a, h); | |
this._shuffled && this._shuffle(a) | |
}.bind(this)); | |
else { | |
for (var c = [], h = 0, g = b.length; h < g; h++) h in b && b[h] && c.push(b[h]); | |
d(this._origin, a, c); | |
this._shuffled && this._shuffle(a) | |
} | |
}; | |
c.prototype.trim = function (a, b) { | |
var c = this._origin; | |
if (c[a] != b) return !1; | |
a += 1; | |
var d = c.length; | |
c.splice(a, d); | |
this._resolved && this._metadata.splice(a, d); | |
this._shuffled && this._shuffle(); | |
return !0 | |
}; | |
c.prototype.insert = | |
function (a, b, c) { | |
if (!c) return !1; | |
typeof c == "string" && (c = [c]); | |
var d = this._origin; | |
if (d[a] != b) return !1; | |
this._resolved ? Spotify.Bridge.trigger("track_multi_metadata", c, function (h) { | |
d.splice.apply(d, [a, 1, b].concat(c)); | |
for (var g = [], q = 0, n = c.length; q < n; q++) g.push(h[c[q]]); | |
this._metadata.splice.apply(this._metadata, [a + 1, 0].concat(g)) | |
}.bind(this)) : d.splice.apply(d, [a, 1, b].concat(c)); | |
return !0 | |
}; | |
c.prototype.remove = function (a, b) { | |
if (!b) return !1; | |
var c = this._origin; | |
if (c[a] != b) return !1; | |
c.splice(a, 1); | |
this._resolved && this._metadata.splice(a, | |
1); | |
this._shuffled && this._shuffle(); | |
return !0 | |
}; | |
c.prototype.clear = function () { | |
var a = this._origin, | |
b = this._metadata; | |
a.splice(0, a.length); | |
b.splice(0, b.length); | |
return this | |
}; | |
c.prototype.hasRange = function (a, b) { | |
var c = this._origin; | |
if (a < 0) return !1; | |
if (b >= c.length) return !1; | |
for (var c = c.slice(a, b), d = c.length; d--;) | |
if (!(d in c)) return !1; | |
return !0 | |
}; | |
c.prototype.slice = function (a, b) { | |
return this._origin.slice(a, b) | |
}; | |
c.prototype.indexOf = function (a) { | |
return this._list.indexOf(a) | |
}; | |
c.prototype.getIndex = function () { | |
return this._rule.indexing ? | |
this._currentIndex : 0 | |
}; | |
c.prototype.getPlayingIndex = function () { | |
return this._shuffled ? this._shuffledList[this._currentIndex] : this._currentIndex | |
}; | |
c.prototype.startFrom = function (a) { | |
var b = a.track; | |
if (this._shuffled) { | |
a = this._shuffledList; | |
if (b == -1) { | |
do b = Math.floor(Math.random() * a.length); while (b >= a.length) | |
} | |
for (var c = a.length; c--;) | |
if (a[c] === b) { | |
b = a[0]; | |
a[0] = a[c]; | |
a[c] = b; | |
this._currentIndex = 0; | |
break | |
} | |
} else this._currentIndex = b == -1 ? 0 : b; | |
return this | |
}; | |
c.prototype.current = function () { | |
var a = this._shuffled ? this._list[this._currentIndex] : | |
this._currentIndex; | |
return { | |
item: this._origin[a], | |
metadata: this._metadata[a] | |
} | |
}; | |
c.prototype.shift = function () { | |
var a = this._shuffled ? this._list[this._currentIndex] : this._currentIndex; | |
if (!this._origin[a]) return null; | |
var b = { | |
item: this._origin[a], | |
metadata: this._metadata[a] | |
}; | |
this._origin.splice(a, 1); | |
this._metadata.splice(a, 1); | |
this._shuffled && this._list.splice(this._currentIndex, 1); | |
return b | |
}; | |
c.prototype.hasNext = function () { | |
return this._repeated || this._currentIndex + 1 < this._origin.length | |
}; | |
c.prototype.next = function () { | |
if (!this._rule.next) return !1; | |
var a = ++this._currentIndex, | |
b = this._origin; | |
if (this._repeated) { | |
if (a >= b.length) a = this._currentIndex = 0; | |
this._shuffled && (a = this._shuffledList[a]); | |
return { | |
item: b[a], | |
metadata: this._metadata[a] | |
} | |
} else if (a < b.length) return this._shuffled && (a = this._shuffledList[a]), { | |
item: b[a], | |
metadata: this._metadata[a] | |
}; | |
this._currentIndex--; | |
return null | |
}; | |
c.prototype.hasPrevious = function () { | |
return this._repeated || this._currentIndex - 1 >= 0 | |
}; | |
c.prototype.previous = function () { | |
if (!this._rule.previous) return !1; | |
var a = --this._currentIndex, | |
b = this._origin; | |
if (this._repeated) { | |
if (a < 0) a = this._currentIndex = b.length - 1; | |
this._shuffled && (a = this._shuffledList[a]); | |
return { | |
item: b[a], | |
metadata: this._metadata[a] | |
} | |
} else if (a >= 0) return this._shuffled && (a = this._shuffledList[a]), { | |
item: b[a], | |
metadata: this._metadata[a] | |
}; | |
this._currentIndex++; | |
return null | |
}; | |
c.prototype._loader = null; | |
c.prototype.setLoader = function (a) { | |
if (typeof a != "function") return this; | |
this._loader = a; | |
return this | |
}; | |
c.prototype._requestContents = function (a, b) { | |
return !this._loader || this._origin.length == | |
this.getFullLength() ? b.call(this) : this._loader.call(this, this, a.track, b.bind(this)) | |
}; | |
c.prototype._resolved = !1; | |
c.prototype._resolvePartial = function (a, b, c, d, h) { | |
for (var g = this._metadata, q = a.length; q--;) g[a[q].idx] = h[a[q]]; | |
this._resolved = !0; | |
if (!b) return this; | |
c(this); | |
this._requestMeta(b, null, null, d) | |
}; | |
c.prototype._requestMeta = function (a, b, c, d) { | |
Spotify.Bridge.trigger("track_multi_metadata", a, this._resolvePartial.bind(this, a, b, c, d), d.bind(null)) | |
}; | |
c.prototype._resolve = function (a, b, c) { | |
b = b || function () {}; | |
c = c || | |
function () {}; | |
if (this._resolved) return b(this); | |
var a = a == -1 ? 0 : a || 0, | |
d = this._origin, | |
h = this._shuffledList, | |
g = Math.max(a - 7, 0), | |
q, n, s, t = []; | |
if (this._shuffled) { | |
for (q = 0, n = h.length; q < n; q++) s = new String(d[h[q]]), s.idx = h[q], h[q] == a ? (h.unshift(h.splice(q, 1).pop()), t.unshift(s)) : t.push(s); | |
g = this._currentIndex = 0 | |
} else | |
for (q = 0, n = d.length; q < n; q++) s = new String(d[q]), s.idx = q, t.push(s); | |
this._requestMeta(t.splice(g, 15), t, b, c) | |
}; | |
c.prototype.resolve = function (a, b, c) { | |
this._requestContents(a, this._resolve.bind(this, a.track, b, c)) | |
} | |
})(); | |
(function () { | |
function d(a) { | |
this._id = a; | |
this._repeated = this._shuffled = !1; | |
this._currentContext = 0; | |
this._contexts = []; | |
this._shuffledContexts = []; | |
this._noReset = new g; | |
this._ttl = (new Date).getTime(); | |
this.setRule("defaults") | |
} | |
var g = Spotify.Bridge.WeakMap, | |
c = Spotify.getStorage("app.context.ns"), | |
h = c.retrieve("quickShuffle"), | |
b = c.retrieve("Context"); | |
c.store("ContextGroup", d); | |
d.prototype.mapToId = b.prototype.mapToId; | |
d.prototype.mapToURI = b.prototype.mapToURI; | |
d.prototype.setExpiry = b.prototype.setExpiry; | |
d.prototype.isExpired = | |
b.prototype.isExpired; | |
d.prototype.setRule = b.prototype.setRule; | |
d.prototype.getContext = function (a) { | |
a = a != void 0 ? a : this._currentContext; | |
return this._shuffled ? this._contexts[this._shuffledContexts[a]] : this._contexts[a] | |
}; | |
d.prototype.getContextIds = function () { | |
var a = [], | |
b = this._contexts, | |
c = b.length; | |
if (!c) return a; | |
for (; c--;) a[c] = b[c].getId(); | |
return a | |
}; | |
d.prototype.getRule = function () { | |
return this.getContext().getRule() | |
}; | |
d.prototype.setShuffle = function (a) { | |
if (!this._rule.shuffle) return !1; | |
(this._shuffled = a) ? this._shuffle() : | |
this._unshuffle(); | |
return a | |
}; | |
d.prototype.isShuffled = function () { | |
return this._shuffled | |
}; | |
d.prototype.setRepeat = function (a) { | |
return !this._rule.repeat ? !1 : this._repeated = a | |
}; | |
d.prototype.isRepeated = function () { | |
return this._repeated | |
}; | |
d.prototype.startFrom = function (a) { | |
var b = a.context; | |
if (this._shuffled) { | |
var c = this._shuffledContexts; | |
if (b == -1) { | |
do b = Math.floor(Math.random() * c.length); while (b >= c.length) | |
} | |
for (var d = c.length; d--;) | |
if (c[d] === b) { | |
b = c[0]; | |
c[0] = c[d]; | |
c[d] = b; | |
this._currentContext = 0; | |
break | |
} | |
} else this._currentContext = | |
b == -1 ? 0 : b; | |
(c = this.getContext()) && c.startFrom(a); | |
return this | |
}; | |
d.prototype._shufflePartial = function (a) { | |
var b = this._shuffledContexts; | |
if (!b) return this; | |
for (var c = this._contexts, d = c.length - a, g = Array(d); d--;) { | |
var p = c[a + d]; | |
p && p.setShuffle(!0); | |
g[d] = a + d | |
} | |
h(g).unshift(a, 0); | |
b.splice.apply(b, g) | |
}; | |
d.prototype._shuffle = function (a) { | |
if (a != void 0) return this._shufflePartial(a); | |
for (var b = this._contexts.slice(0), a = this._shuffledContexts = [], c = 0, d = b.length; c < d; c++) b[c].setShuffle(!0), a.push(c); | |
b = a.splice(this._currentContext, | |
1).pop(); | |
h(a).unshift(b); | |
this._currentContext = 0; | |
this._noReset.clear(); | |
this._noReset.set(this.getContext(), !0); | |
return this | |
}; | |
d.prototype._unshuffle = function () { | |
this._currentContext = this._shuffledContexts[this._currentContext]; | |
for (var a = this._contexts.slice(0), b = 0, c = a.length; b < c; b++) a[b].setShuffle(!1); | |
this._noReset.clear(); | |
return this | |
}; | |
d.prototype.append = function (a) { | |
this._contexts.push(a.unwrap()); | |
this._resolved && a.resolve({ | |
track: 0, | |
context: 0 | |
}); | |
this._shuffled && this._shuffle(this.length - 1); | |
return this | |
}; | |
d.prototype.concat = function (a) { | |
if (!a || !a.length) return this; | |
for (var b = 0, c = a.length; b < c; b++) this._contexts.push(a[b].unwrap()), this._resolved && a[b].resolve({ | |
track: 0, | |
context: 0 | |
}); | |
this._shuffled && this._shuffle(this._contexts.length - a.length) | |
}; | |
d.prototype.splice = function (a, b) { | |
if (typeof a == "undefined" || !b || !b.length) return this; | |
for (var c = [a, b.length], d = 0, h = b.length; d < h; d++) d in b && b[d] && (c.push(b[d].unwrap()), this._resolved && b[d].resolve({ | |
track: 0, | |
context: 0 | |
})); | |
this._contexts.splice.apply(this._origin, c); | |
this._shuffled && this._shuffle(a) | |
}; | |
d.prototype.insert = function (a, b, c) { | |
if (!c) return !1; | |
var d = this._contexts, | |
b = b.unwrap(), | |
c = c.unwrap(); | |
if (d[a] != b) return !1; | |
d.splice(a, 1, b, c); | |
this._resolved && c.resolve({ | |
track: 0, | |
context: 0 | |
}); | |
return !0 | |
}; | |
d.prototype.remove = function (a, b) { | |
if (!b) return !1; | |
var c = this._contexts, | |
b = b.unwrap(); | |
if (c[a] != b) return !1; | |
c.splice(a, 1); | |
this._shuffled && this._shuffle(); | |
return !0 | |
}; | |
d.prototype.clear = function () { | |
var a = this._contexts; | |
a.splice(0, a.length); | |
return this | |
}; | |
d.prototype.slice = function (a, b) { | |
return this._contexts.slice(a, | |
b) | |
}; | |
d.prototype.get = function (a) { | |
for (var b = this._contexts, c = 0, d = b.length; c < d; c++) { | |
var h = b[c], | |
g = h.getLength(); | |
if (g < a) a -= g; | |
else return h.get(a) | |
} | |
return null | |
}; | |
d.prototype.current = function () { | |
return this.getContext().current() | |
}; | |
d.prototype.getIndex = function (a) { | |
var b = this.getContext().getIndex(); | |
if (!a) return b; | |
for (var a = this._currentContext, c = this._contexts, d = 0; d != a; d++) b += c[d]._origin.length; | |
return b | |
}; | |
d.prototype.getPlayingIndex = function () { | |
return this.getContext().getPlayingIndex() | |
}; | |
d.prototype.getContextIndex = | |
function () { | |
return this._shuffled ? this._shuffledContexts[this._currentContext] : this._currentContext | |
}; | |
d.prototype.getLength = function (a) { | |
if (!a) return this.getContext().getLength(); | |
for (var a = 0, b = this._contexts.length; b--;) a += this._contexts[b]._origin.length; | |
return a | |
}; | |
d.prototype.getFullLength = function () { | |
return this.getContext().getFullLength() | |
}; | |
d.prototype.getContextsLength = function () { | |
return this._contexts.length | |
}; | |
d.prototype.previous = function () { | |
if (!this._rule.previous) return !1; | |
var a = this._contexts, | |
b = | |
a.length, | |
c = null, | |
d; | |
if (this._shuffled) | |
for (var h = this._noReset; b--;) { | |
d = --this._currentContext; | |
if (d < 0) d = this._currentContext = a.length - 1; | |
d = a[this._shuffledContexts[d]]; | |
if (!d) return null; | |
if (this._repeated && d._currentIndex == 0) d._currentIndex = d.getLength(); | |
h.get(d) || (d._currentIndex++, h.set(d, !0)); | |
if (c = this.getContext().previous()) break | |
} else | |
for (; b--;) { | |
if (c = this.getContext().previous()) break; | |
d = --this._currentContext; | |
if (d < 0) { | |
if (!this._repeated) { | |
this._currentContext++; | |
break | |
} | |
d = this._currentContext = a.length - | |
1 | |
} | |
d = a[d]; | |
if (!d) return null; | |
d._currentIndex = d.getLength() | |
} | |
return c | |
}; | |
d.prototype.next = function () { | |
if (!this._rule.next) return !1; | |
var a = this._contexts, | |
b = a.length, | |
c = null, | |
d; | |
if (this._shuffled) | |
for (var h = this._noReset; b--;) { | |
d = ++this._currentContext; | |
if (d >= a.length) d = this._currentContext = 0; | |
next = a[this._shuffledContexts[d]]; | |
if (!next) return null; | |
if (this._repeated && next._currentIndex == next.getLength() - 1) next._currentIndex = -1; | |
h.get(next) || (next._currentIndex--, h.set(next, !0)); | |
if (c = this.getContext().next()) break | |
} else | |
for (; b--;) { | |
if (c = | |
this.getContext().next()) break; | |
d = ++this._currentContext; | |
if (d >= a.length) { | |
if (!this._repeated) { | |
this._currentContext--; | |
break | |
} | |
d = this._currentContext = 0 | |
} | |
next = a[d]; | |
if (!next) return null; | |
next._currentIndex = -1 | |
} | |
return c | |
}; | |
d.prototype.getId = function () { | |
return this.getContext().getId() | |
}; | |
d.prototype.resolve = function (a, b, c) { | |
this.startFrom(a); | |
var d = this._contexts; | |
if (this._resolved) return b(); | |
this.getContext().resolve(a, function () { | |
this._resolved = !0; | |
b(); | |
for (var c = d.length; c--;) d[c].resolve(a) | |
}.bind(this), c) | |
} | |
})(); | |
(function () { | |
function d(a) { | |
this._context = a; | |
this._owner = "" | |
} | |
function g() { | |
this.cache = new b(1E3) | |
} | |
function c(a, b, c) { | |
a = new a(b.toString()); | |
this.cache.put(b, a); | |
return (new d(a)).setExpiry(c) | |
} | |
function h(a, b, c, f) { | |
var h = this.cache.get(b.toString()); | |
if (h) | |
if (h.isExpired()) this.cache.remove(h); | |
else return (new d(h)).setExpiry(f); | |
return c ? a == k ? this.create(b, f) : this.createGroup(b, f) : null | |
} | |
var b = Spotify.SimpleCache, | |
a = Spotify.getStorage("app.ns"), | |
f = Spotify.getStorage("app.context.ns"), | |
k = f.retrieve("Context"), | |
m = f.retrieve("ContextGroup"); | |
d.prototype.getOwner = function () { | |
return this._owner | |
}; | |
d.prototype.unwrap = function () { | |
return this._context | |
}; | |
d.prototype.setOwner = function (a) { | |
if (a) this._owner = a; | |
return this | |
}; | |
d.prototype.isContext = function () { | |
return this._context instanceof k | |
}; | |
d.prototype.isContextGroup = function () { | |
return this._context instanceof m | |
}; | |
for (var o in k.prototype)(function (a) { | |
d.prototype[a] = function () { | |
var b = this._context, | |
c = b[a]; | |
if (!c) throw Error('Context object has no method "' + a + '"'); | |
c = c.apply(b, arguments); | |
return c == b ? this : c | |
} | |
})(o); | |
a.store("ContextManager", g); | |
g.prototype.create = function (a, b) { | |
return c.call(this, k, a, b) | |
}; | |
g.prototype.createGroup = function (a, b) { | |
return c.call(this, m, a, b) | |
}; | |
g.prototype.get = function (a, b, c) { | |
return h.call(this, k, a, b, c) | |
}; | |
g.prototype.getGroup = function (a, b, c) { | |
return h.call(this, m, a, b, c) | |
}; | |
g.prototype.remove = function (a) { | |
return this.cache.remove(a.toString()) | |
} | |
})(); | |
(function () { | |
function d(a, b, c, d) { | |
var f; | |
h.call(this); | |
this._available = this._uid = 0; | |
this._previous = {}; | |
this._incoming = {}; | |
f = this.audioManager = a.audioManager, a = f; | |
this.player = b; | |
this.logging = a.getTrackerForPlayerWithId(b.id); | |
this.alternate = c; | |
this._fade = !! d; | |
this._intercept = !1; | |
this._interceptions = this._intercepted = null; | |
this._queue = []; | |
this._history = []; | |
this.setup() | |
} | |
var g = Spotify.Link, | |
c = Spotify.defer, | |
h = Spotify.Shell.EventEmitter, | |
b = Spotify.getStorage("app.ns"), | |
a = [].slice; | |
d.prototype = new h; | |
d.prototype.constructor = | |
d; | |
b.store("ContextPlayer", d); | |
d.prototype.setup = function () { | |
var a = this.player; | |
a.bind("BEFORE_END", this.onBeforeEnded, this); | |
a.onPlay = this.onPlay.bind(this); | |
a.onPause = this.onPause.bind(this); | |
a.onTrackEnded = this.onEnded.bind(this); | |
a.onInvalidTrackUri = a.onPlaybackFailed = this.onInvalid.bind(this) | |
}; | |
d.prototype.onPlay = function () { | |
if (!this._hardStopped) { | |
this._available++; | |
this._keepPlay && this.player.resume(); | |
delete this._keepPlay; | |
this.fireEvent("play"); | |
var a = this.player.trackUri, | |
b = this._incoming[a]; | |
delete this._incoming[a]; | |
b && c(b.bind(this)) | |
} | |
}; | |
d.prototype.onPause = function () { | |
this.fireEvent("pause") | |
}; | |
d.prototype.onBeforeEnded = function () { | |
var a = this; | |
if (this._fade && !this._currentContext.hasNext()) a._crossfading = !0, this._fadeback != null && this._fadeback && a.alternate.resume(), this.audioManager.crossfade(this.player.id, this.alternate.id, 800, function () { | |
a.player.pause(); | |
a._fadeback = null; | |
a._crossfading = !1 | |
}) | |
}; | |
d.prototype.onEnded = function () { | |
delete this._keepPlay; | |
this.fireEvent("ended"); | |
this._playIntercepted() || this.next(!0) | |
}; | |
d.prototype.onInvalid = | |
function (a) { | |
delete this._keepPlay; | |
var b = a.params.data, | |
d = this._incoming[b]; | |
delete this._incoming[b]; | |
d && c(d.bind(this, "unplayable")); | |
b = this.next.bind(this, !0, function (a) { | |
if (!(a !== "no-context" || a !== "forbidden" || a !== "no-tracks")) a = this._previous, this._currentContext = a.context, this._currentTrack = a.track, this._currentGroup = a.group | |
}.bind(this)); | |
a.params.domain == 12 && (a.params.code == 8 || a.params.code == 12) || b() | |
}; | |
d.prototype._shuffled = !1; | |
d.prototype.setShuffle = function (a) { | |
this._shuffled = a = !! a; | |
var b = this._currentContext; | |
b && b.setShuffle(a); | |
return !0 | |
}; | |
d.prototype._repeated = !1; | |
d.prototype.setRepeat = function (a) { | |
this._repeated = a = !! a; | |
var b = this._currentContext; | |
b && b.setRepeat(a); | |
return !0 | |
}; | |
d.prototype.setVolume = function (a) { | |
if (typeof a != "number") return !1; | |
this.audioManager.setMasterVolume(a); | |
return !0 | |
}; | |
d.prototype.getState = function (a) { | |
var b = this.player.getPlayerState(), | |
c = this._currentContext, | |
b = { | |
__uid: this._uid, | |
__index: c ? c.getIndex(!0) : null, | |
__length: c ? c.getLength(!0) : null, | |
__rules: c ? c.getRule() : {}, | |
__owner: c ? c.getOwner() : null, | |
playing: this._keepPlay ? !0 : !b.isPaused && !b.isStopped, | |
context: c ? { | |
uri: c.getId() | |
} : null, | |
index: !c ? null : c.getPlayingIndex(), | |
track: this._currentTrack || { |
View raw
(Sorry about that, but we can’t show files that are this big right now.)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment