Created
January 14, 2011 17:07
-
-
Save adammw/779895 to your computer and use it in GitHub Desktop.
Grooveshark HTML5 Audio Injector
This file contains hidden or 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
| /* | |
| * Grooveshark HTML5 Audio Injector for Flash-less browsers | |
| * <https://gist.github.com/gists/779895> | |
| * Version 0.0.8 | |
| * | |
| * To use, simply copy and paste this code into the Developer Console | |
| * for the open Grooveshark page and hit enter. Only tested with Google Chrome. | |
| * | |
| * Porting to Javascript Copyright (C) 2011 Adam Malcontenti-Wilson <adman.com@gmail.com> | |
| * All other elements Copyright (C) Escape Media Group ("Grooveshark") | |
| * | |
| * This code is based on Grooveshark ActionScript-based JSQueue and | |
| * portions of Grooveshark's app.js script to allow requests to use | |
| * native XMLHttpRequest. | |
| * | |
| * Known Bugs: | |
| * + All HTTPS urls will be attempted over HTTP due to XHR cross-origin restrictions | |
| * + On the end of a song, songs may be skipped twice | |
| * - Clearing the queue not supported | |
| * - Repeat and crossfade not supported | |
| */ | |
| (function () { | |
| function a(k, m, n, q, s, A, B, E) { | |
| this.methodName = k; | |
| this.parameters = _.orEqual(m, {}); | |
| this.useHTTPS = _.orEqual(B, false); | |
| this.useSWF = _.orEqual(E, false); | |
| this.callback = _.orEqual(n, null); | |
| this.errback = _.orEqual(q, null); | |
| this.overrideEndpoint = _.orEqual(A, null); | |
| this.overrideHeaders = {}; | |
| this.options = _.orEqual(s, {}); | |
| this.type = "normal"; | |
| this.failedAuth = false | |
| } | |
| function b(k, m, n, q, s) { | |
| this.method = _.orEqual(k, ""); | |
| this.parameters = _.orEqual(m, {}); | |
| this.httpMethod = _.orEqual(n, "POST"); | |
| this.callback = _.orEqual(q, null); | |
| this.errback = _.orEqual(s, null); | |
| this.type = "facebook" | |
| } | |
| function c(k, m, n, q) { | |
| this.method = k; | |
| this.parameters = _.orEqual(m, {}); | |
| this.callback = _.orEqual(n, null); | |
| this.errback = _.orEqual(q, null); | |
| this.type = "lastfm" | |
| } | |
| function d(k, m) { | |
| var n = true, | |
| q = new Date; | |
| m = _.orEqual(m, 0); | |
| if (m >= 3) { | |
| console.error("service.sendRequest. numRetries maxed out. ", k); | |
| } else { | |
| if (m > 0) n = false; | |
| GS.service = GS.service || GS.Controllers.ServiceController.instance(); | |
| /*if (k.type == "facebook" || k.type == "lastfm") { | |
| if ($.isFunction(GS.service.swfProxy)) { | |
| n = o(); | |
| GS.service.outgoingSWFCalls[n] = | |
| k; | |
| console.log("swfproxy:", k, {}, n); | |
| GS.service.swfProxy(k, {}, n) | |
| } else { | |
| GS.service.callsPendingSWF.push(k); | |
| } | |
| } else */if (GS.service.tokenExpires > q.valueOf() || k.methodName == "getCommunicationToken" || k.methodName == "initiateSession" || k.methodName == "getServiceStatus") { | |
| if (GS.service.downForMaintenance && k.methodName != "getServiceStatus") { | |
| $.isFunction(k.errback) && k.errback({ | |
| message: $.localize.getString("SERVICE_DOWN_MAINTENANCE"), | |
| code: GS.service.faultCodes.MAINTENANCE | |
| }); | |
| } else { | |
| q = "more.php"; | |
| if (GS.service.runMode === "dev") { | |
| q = "proxy.php"; | |
| } | |
| // Damn Cross-Domain Ajax restrictions screw us here | |
| var proto = 'http:'; //(k.useHTTPS) ? 'https:' : 'http:'; | |
| var s = proto+"//" + GS.service.hostname + "/" + q + "?" + k.methodName; | |
| if (k.type == "facebook" || k.type == "lastfm") { | |
| if (!k.overrideHeaders) { k.overrideHeaders = []; } | |
| k.overrideHeaders['client'] = 'jsqueue'; | |
| } | |
| //console.log('url:',a.useHTTPS,proto,s); | |
| var A = { | |
| header: x(k.overrideHeaders), | |
| method: k.methodName, | |
| parameters: k.parameters | |
| }; | |
| if (GS.service.currentToken) { | |
| GS.service.lastRandomizer = h(); | |
| q = hex_sha1(k.methodName + ":" + GS.service.currentToken + ":quitStealinMahShit:" + GS.service.lastRandomizer); | |
| A.header.token = GS.service.lastRandomizer + q | |
| } | |
| $.ajax($.extend(k.options, { | |
| contentType: "application/json", | |
| dataType: "json", | |
| type: "POST", | |
| data: JSON.stringify(A), | |
| cache: n, | |
| url: s, | |
| success: function (B, E) { | |
| console.log("ajax success: " + s + ", status: " + E + ", request: ", A, B); | |
| if (B) f(B, k); | |
| else { | |
| m++; | |
| console.error("service.success NO DATA. retry request again", k); | |
| setTimeout(function () { | |
| d(k, m) | |
| }, 100 + m * 100) | |
| } | |
| }, | |
| error: function (B, E, G) { | |
| console.error("ajax error: status: " + E + ", error: " + G, B, k); | |
| B = {}; | |
| switch (E) { | |
| case "parsererror": | |
| B.code = | |
| GS.service.faultCodes.PARSE_ERROR; | |
| B.message = $.localize.getString("SERVICE_PARSE_JSON"); | |
| break; | |
| case "timeout": | |
| B.code = GS.service.faultCodes.HTTP_TIMEOUT; | |
| B.message = $.localize.getString("SERVICE_REQUEST_TIMEOUT"); | |
| m++; | |
| console.error("service.sendRequest.error.timeout. retry request again", k); | |
| setTimeout(function () { | |
| d(k, m); | |
| }, 100 + m * 100); | |
| return; | |
| case "error": | |
| case "notmodified": | |
| default: | |
| B.code = GS.service.faultCodes.HTTP_ERROR; | |
| B.message = $.localize.getString("SERVICE_HTTP_ERROR"); | |
| break; | |
| } | |
| $.isFunction(k.errback) && k.errback(B) | |
| } | |
| })); | |
| } | |
| } else { | |
| GS.service.callsPendingToken.push(k); | |
| GS.service.tokenPending || p() | |
| } | |
| } | |
| } | |
| function f(k, m) { | |
| if (k && k.header) { | |
| var n = k.header.session; | |
| if (n && n != GS.service.sessionID) { | |
| GS.service.sessionID = n; | |
| p() | |
| } | |
| n = k.header.secondsUntilDowntime; | |
| if (n < 0) setTimeout(v, 1E3); | |
| else if (n > 0) { | |
| n = Math.floor(n / 60); | |
| var q = (new Date).valueOf(); | |
| if (n <= 60) if (lastDowntimeNotification == 0 || n > 30 && q - lastDowntimeNotification > 36E5 || n <= 30 && n > 15 && q - lastDowntimeNotification > 18E5 || n <= 15 && n > 10 && q - lastDowntimeNotification > 9E5 || n <= 10 && n > 5 && q - lastDowntimeNotification > 6E5 || n <= 5 && q - lastDowntimeNotification > 3E5) { | |
| lastDowntimeNotification = q; | |
| n = new GS.Models.DataString($.localize.getString("NOTIFICATION_MAINTENANCE_WARNING"), { | |
| min: n | |
| }); | |
| $.publish("gs.notification", { | |
| type: "info", | |
| message: n | |
| }) | |
| } | |
| } | |
| } | |
| if (k && k.fault) g(k.fault, m); | |
| else $.isFunction(m.callback) && m.callback(k.result) | |
| } | |
| function g(k, m) { | |
| console.error("HANDLE FAULT CODE", k.code); | |
| if (k.code == GS.service.faultCodes.INVALID_TOKEN) { | |
| GS.service.callsPendingToken.push(m); | |
| GS.service.tokenPending || p() | |
| } else { | |
| if (k.code == GS.service.faultCodes.MAINTENANCE) setTimeout(v, 1E3); | |
| else if (k.code == GS.service.faultCodes.INVALID_CLIENT) { | |
| console.log("INVALID CLIENT"); | |
| GS.lightbox.open("invalidClient") | |
| } else if (k.code == GS.service.faultCodes.MUST_BE_LOGGED_IN) if (!m.failedAuth) { | |
| m.failedAuth = true; | |
| GS.service.callsPendingAuth.push(m); | |
| if (!GS.service.reauthPending) { | |
| GS.service.reauthPending = true; | |
| GS.service.reauthPending = true; | |
| GS.auth.reauthenticate(F, H) | |
| } | |
| return | |
| } | |
| $.isFunction(m.errback) && m.errback(k) | |
| } | |
| } | |
| function h() { | |
| for (var k = "", m = 0; m < 6; m++) k += Math.floor(Math.random() * 16).toString(16); | |
| return k != GS.service.lastRandomizer ? k : h() | |
| } | |
| function o() { | |
| var k = String(Math.floor(Math.random() * 1E4)); | |
| return !GS.service.outgoingSWFCalls[k] ? k : o() | |
| } | |
| function p() { | |
| GS.service.currentToken = null; | |
| GS.service.tokenExpires = 0; | |
| GS.service.tokenPending = true; | |
| if (GS.service.sessionID) { | |
| var k = hex_md5(GS.service.sessionID); | |
| req = new a("getCommunicationToken", { | |
| secretKey: k | |
| }, t, w, null, null, true) | |
| } else req = new a("initiateSession", {}); | |
| d(req) | |
| } | |
| function t(k) { | |
| var m = new Date; | |
| GS.service.currentToken = k; | |
| GS.service.tokenPending = false; | |
| for (GS.service.tokenExpires = 15E5 + m.valueOf(); GS.service.callsPendingToken.length;) { | |
| req = | |
| GS.service.callsPendingToken.shift(); | |
| d(req) | |
| } | |
| } | |
| function w() { | |
| for (GS.service.tokenPending = false; GS.service.callsPendingToken.length;) { | |
| req = GS.service.callsPendingToken.shift(); | |
| $.isFunction(req.errback) && req.errback({ | |
| fault: { | |
| message: $.localize.getString("SERVICE_CREATE_TOKEN_FAIL"), | |
| code: GS.service.faultCodes.BAD_TOKEN | |
| } | |
| }) | |
| } | |
| } | |
| function z(k) { | |
| GS.service = _.orEqual(GS.service, GS.Controllers.ServiceController.instance()); | |
| for (GS.service.country = k ? k : { | |
| CC1: 0, | |
| ID: 223, | |
| CC4: 1073741824, | |
| CC3: 0, | |
| CC2: 0 | |
| }; GS.service.callsPendingCountry.length;) { | |
| req = | |
| GS.service.callsPendingCountry.shift(); | |
| req.parameters.country = GS.service.country; | |
| d(req) | |
| } | |
| } | |
| function r() { | |
| for (GS.service.country = { | |
| CC1: 0, | |
| ID: 223, | |
| CC4: 1073741824, | |
| CC3: 0, | |
| CC2: 0 | |
| }; GS.service.callsPendingCountry.length;) { | |
| req = GS.service.callsPendingCountry.shift(); | |
| req.parameters.country = GS.service.country; | |
| d(req) | |
| } | |
| } | |
| function F() { | |
| GS.service.reauthPending = false; | |
| for (var k; k = GS.service.callsPendingAuth.shift();) d(k) | |
| } | |
| function H() { | |
| GS.service.reauthPending = false; | |
| for (var k; k = GS.service.callsPendingAuth.shift();) $.isFunction(k.errback) && k.errback({ | |
| code: GS.service.faultCodes.MUST_BE_LOGGED_IN, | |
| message: $.localize.getString("SERVICE_LOGIN_REQUIRED") | |
| }) | |
| } | |
| function x(k) { | |
| k = _.orEqual(k, {}); | |
| var m = { | |
| client: GS.service.client, | |
| clientRevision: GS.service.clientRevision, | |
| privacy: GS.service.privacy, | |
| country: GS.service.country, | |
| uuid: GS.service.uuID | |
| }; | |
| if (GS.service.sessionID) m.session = GS.service.sessionID; | |
| return $.extend(m, k) | |
| } | |
| function u() { | |
| return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (k) { | |
| var m = Math.random() * 16 | 0; | |
| return (k == "x" ? m : m & 3 | 8).toString(16) | |
| }).toUpperCase() | |
| } | |
| function v() { | |
| if (!GS.service.downForMaintenance) { | |
| GS.service.downForMaintenance = true; | |
| GS.lightbox.open("maintenance"); | |
| y() | |
| } | |
| } | |
| function y() { | |
| req = new a("getServiceStatus", {}, D, C); | |
| d(req) | |
| } | |
| function D(k) { | |
| console.log("maintenanceCallback", k); | |
| if (k.status == 1) { | |
| GS.service.downForMaintenance = false; | |
| GS.lightbox.close() | |
| } else setTimeout(y, 2E4) | |
| } | |
| function C(k) { | |
| console.log("maintenanceCallback", k); | |
| setTimeout(y, 2E4) | |
| } | |
| function jsQueue(params) { | |
| function getTimer() { | |
| return new Date().valueOf(); | |
| } | |
| var helpers = { | |
| getterFunction: function(property,context) { | |
| return function() { | |
| if (!context) { context = this; } | |
| return context['_'+property]; | |
| } | |
| }, | |
| setterFunction: function(property,context,isStatic) { | |
| return function(newValue) { | |
| if (!context) { context = this; } | |
| var oldValue = context['_'+property]; | |
| if (oldValue !== newValue) { | |
| context['_'+property] = newValue; | |
| if (isStatic && context.staticEventDispatcher) { | |
| context.staticEventDispatcher.dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, property, oldValue, newValue)); | |
| } else if (!isStatic) { | |
| context.dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, property, oldValue, newValue)); | |
| } | |
| } | |
| } | |
| }, | |
| }; | |
| var ObjectUtil = { | |
| copy: function(origObj) { | |
| var newObj = (origObj instanceof Array) ? [] : {}; | |
| for (i in origObj) { | |
| newObj[i] = (origObj[i] && typeof origObj[i] == "object") ? ObjectUtil.copy(origObj[i]) : origObj[i]; | |
| } | |
| return newObj; | |
| } | |
| }; | |
| var StringUtils = { | |
| ucfirst: function (_arg1) { | |
| return _arg1.substr(0, 1).toUpperCase() + _arg1.substr(1); | |
| }, | |
| ucwords: function (_arg1) { | |
| var _local2 = _arg1.split(" "); | |
| for (i=0;i<_local2.length;i++) { | |
| _local2[i] = StringUtils.ucfirst(_local2[i]); | |
| }; | |
| return (_local2.join(" ")); | |
| }, | |
| condenseTitle: function (_arg1) { | |
| var _local2 = /[^A-Za-z0-9]+/g; | |
| var _local3 = /\sand\s|\sbut\s|\sor\s|\sthe\s/g; | |
| _arg1 = _arg1.toLowerCase(); | |
| _arg1 = _arg1.replace(_local2, " "); | |
| _arg1 = " " + _arg1 + " "; | |
| _arg1 = _arg1.replace(_local3, " "); | |
| _arg1 = _arg1.replace(/\s/g, ""); | |
| return (_arg1); | |
| } | |
| } | |
| var FlashEvent = jQuery.Class.extend({ | |
| init: function(type, bubbles, cancelable) { | |
| // Constructor | |
| this.type = type; | |
| this.bubbles = bubbles || false; | |
| this.cancelable = cancelable || false; | |
| }, | |
| /*preventDefault: function() { | |
| if (!this.cancelable) { return; } | |
| },*/ | |
| }); | |
| var PropertyChangeEvent = FlashEvent.extend({ | |
| init: function(type, bubbles, cancelable, kind, property, oldValue, newValue, source) { | |
| this._super(type, bubbles, cancelable); | |
| this.kind = kind; | |
| this.property = property; | |
| this.oldValue = oldValue; | |
| this.newValue = newValue; | |
| this.source = source; | |
| } | |
| }); | |
| PropertyChangeEvent.createUpdateEvent = function(source, property, oldValue, newValue){ | |
| var event = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE); | |
| event.kind = PropertyChangeEventKind.UPDATE; | |
| event.oldValue = oldValue; | |
| event.newValue = newValue; | |
| event.source = source; | |
| event.property = property; | |
| return event; | |
| }; | |
| var TimerEvent = FlashEvent.extend({ | |
| init: function(type, bubbles, cancelable) { | |
| this._super(type, bubbles, cancelable); | |
| } | |
| }); | |
| var CollectionEvent = FlashEvent.extend({ | |
| init: function(type, bubbles, cancelable, kind, location, oldLocation, items) { | |
| this._super(type, bubbles, cancelable); | |
| this.kind = kind; | |
| this.location = location; | |
| this.oldLocation = oldLocation; | |
| this.items = ((items) ? items : []); | |
| } | |
| }); | |
| var SongEvent = FlashEvent.extend({ | |
| init: function(type, song, bubbles, cancelable){ | |
| this._super(type, bubbles, cancelable); | |
| this.song = song; | |
| }, | |
| clone: function() { | |
| return (new SongEvent(this.type, this.song, this.bubbles, this.cancelable)); | |
| } | |
| }); | |
| var PlayableSongEvent = FlashEvent.extend({ | |
| init: function(type, code, preErrorStatus, bubbles, cancelable){ | |
| this._super(type, bubbles, cancelable); | |
| this.code = code || 0; | |
| this.preErrorStatus = preErrorStatus || -1; | |
| if (type == this.ERROR){ | |
| console.error("SongEvent { " + type + ": finalCode:" + String(code) + " resultCode:" + String(preErrorStatus) + " }"); | |
| } | |
| } | |
| }); | |
| var QueueChangeEvent = FlashEvent.extend({ | |
| fullQueue: null, | |
| init: function(type, details) { | |
| this.type = type; | |
| this.details = ((details) ? details : {}); | |
| } | |
| }); | |
| var GSSoundEvent = FlashEvent.extend({ | |
| init: function GSSoundEvent(type, bubbles, cancelable){ | |
| this._super(type, bubbles, cancelable); | |
| }, | |
| clone: function() { | |
| return (new GSSoundEvent(this.type, this.bubbles, this.cancelable)); | |
| } | |
| }); | |
| // FlashEvent Constants | |
| FlashEvent.ACTIVATE = "activate"; | |
| FlashEvent.ADDED = "added"; | |
| FlashEvent.ADDED_TO_STAGE = "addedToStage"; | |
| FlashEvent.CANCEL = "cancel"; | |
| FlashEvent.CHANGE = "change"; | |
| FlashEvent.CLEAR = "clear"; | |
| FlashEvent.CLOSE = "close"; | |
| FlashEvent.COMPLETE = "complete"; | |
| FlashEvent.CONNECT = "connect"; | |
| FlashEvent.COPY = "copy"; | |
| FlashEvent.CUT = "cut"; | |
| FlashEvent.DEACTIVATE = "deactivate"; | |
| FlashEvent.ENTER_FRAME = "enterFrame"; | |
| FlashEvent.EXIT_FRAME = "exitFrame"; | |
| FlashEvent.FRAME_CONSTRUCTED = "frameConstructed"; | |
| FlashEvent.FULLSCREEN = "fullScreen"; | |
| FlashEvent.ID3 = "id3"; | |
| FlashEvent.INIT = "init"; | |
| FlashEvent.MOUSE_LEAVE = "mouseLeave"; | |
| FlashEvent.OPEN = "open"; | |
| FlashEvent.PASTE = "paste"; | |
| FlashEvent.REMOVED = "removed"; | |
| FlashEvent.REMOVED_FROM_STAGE = "removedFromStage"; | |
| FlashEvent.RENDER = "render"; | |
| FlashEvent.RESIZE = "resize"; | |
| FlashEvent.SCROLL = "scroll"; | |
| FlashEvent.SELECT = "select"; | |
| FlashEvent.SELECT_ALL = "selectAll"; | |
| FlashEvent.SOUND_COMPLETE = "soundComplete"; | |
| FlashEvent.TAB_CHILDREN_CHANGE = "tabChildrenChange"; | |
| FlashEvent.TAB_ENABLED_CHANGE = "tabEnabledChange"; | |
| FlashEvent.TAB_INDEX_CHANGE = "tabIndexChange"; | |
| FlashEvent.UNLOAD = "unload"; | |
| // PropertyChangeEvent Constants | |
| PropertyChangeEvent.PROPERTY_CHANGE = "propertyChange" | |
| PropertyChangeEventKind = {UPDATE: "update", DELETE: "delete"}; | |
| // TimerEvent Constants | |
| TimerEvent.TIMER = "timer"; | |
| TimerEvent.TIMER_COMPLETE = "timerComplete"; | |
| // CollectionEvent Constants | |
| CollectionEvent.COLLECTION_CHANGE = "collectionChange"; | |
| // SongEvent Constants | |
| SongEvent.SONG_DIRTY = "songDirty"; | |
| // PlayableSongEvent Constants | |
| PlayableSongEvent.COMPLETE = "complete"; | |
| PlayableSongEvent.FAILED_TOO_MANY_STREAMKEY_FAILS = 3; | |
| PlayableSongEvent.SONG_VOTE_FAILED = "songVoteFailed"; | |
| PlayableSongEvent.COMPLETE_SOUND_COMPLETE = 7; | |
| PlayableSongEvent.FAILED_IO_ERROR = 1; | |
| PlayableSongEvent.FAILED_TOO_MANY_BAD_FRAMES = 5; | |
| PlayableSongEvent.PLAYBACK_BEGUN = "playbackBegun"; | |
| PlayableSongEvent.SONG_FLAGGED = "songFlagged"; | |
| PlayableSongEvent.FAILED_UNKNOWN_SERVER_ERROR = 6; | |
| PlayableSongEvent.ERROR = "error"; | |
| PlayableSongEvent.FAILED_STREAMKEY_OTHER = 4; | |
| PlayableSongEvent.SONG_VOTED = "songVoted"; | |
| PlayableSongEvent.FAILED_STREAMKEY_LIMIT = 2; | |
| PlayableSongEvent.WARNING_FREQUENT_BUFFERING = 10; | |
| PlayableSongEvent.COMPLETE_VBR_COMPLETE = 8; | |
| PlayableSongEvent.COMPLETE_FORCE_FROWN_SKIP = 9; | |
| // QueueChangeEvent Constants | |
| QueueChangeEvent.QUEUE_RESET = "queueReset"; | |
| QueueChangeEvent.CONTENT_CHANGE = "contentChange"; | |
| QueueChangeEvent.PROPERTY_CHANGE = "propertyChange"; | |
| // GSSoundEvent Constants | |
| GSSoundEvent.BUFFER_FULL = "bufferFull"; | |
| GSSoundEvent.IO_ERROR = "ioError"; | |
| GSSoundEvent.DOWNLOAD_COMPLETE = "downloadComplete"; | |
| GSSoundEvent.BUFFER_EMPTY = "bufferEmpty"; | |
| GSSoundEvent.PLAYBACK_BEGUN = "playbackBegun"; | |
| GSSoundEvent.PLAYBACK_COMPLETE = "playbackComplete"; | |
| var CollectionEventKind = { | |
| ADD:"add", | |
| REMOVE:"remove", | |
| UPDATE:"update", | |
| MOVE:"move", | |
| EXPAND:"expand", | |
| REPLACE:"replace", | |
| REFRESH:"refresh", | |
| RESET:"reset", | |
| }; | |
| var FlashProxy = jQuery.Class.extend({ | |
| }); | |
| var ItemResponder = jQuery.Class.extend({ | |
| init: function(resultHandler, faultHandler, token){ | |
| this._resultHandler = resultHandler; | |
| this._faultHandler = faultHandler; | |
| this._token = token || null; | |
| }, | |
| result: function(caller) { | |
| me = this; | |
| return function(_arg1) { if (me._resultHandler) { me._resultHandler.call(caller, _arg1, me._token); } }; | |
| }, | |
| fault: function(caller) { | |
| me = this; | |
| return function(_arg1) { if (me._faultHandler) { me._faultHandler.call(caller, _arg1, me._token); } }; | |
| } | |
| }); | |
| var AutoplayStatus = jQuery.Class.extend({ | |
| userSeeds: [], | |
| smiles: [], | |
| frowns: [], | |
| taggedArtistIDs: [], | |
| flaggedSongIDs: [], | |
| init: function(queue) { | |
| this.parent = queue; | |
| this._minSeeds = AutoplayStatus.minSeeds; | |
| this._numPlayedArtists = AutoplayStatus.numPlayedArtists; | |
| this._numPlayedSongs = AutoplayStatus.numPlayedSongs; | |
| this._numBadTitles = AutoplayStatus.numBadTitles; | |
| this._secondarySeedWeightMultiplier = AutoplayStatus.secondarySeedWeightMultiplier; | |
| this._seedWeightRange = AutoplayStatus.seedWeightRange; | |
| this._weightModifierRange = AutoplayStatus.weightModifierRange; | |
| this._minDuration = AutoplayStatus.minDuration; | |
| this._maxDuration = AutoplayStatus.maxDuration; | |
| for (i in queue.source) { | |
| if (queue.source[i].source == "user"){ | |
| this.userSeeds.push(_local2); | |
| }; | |
| //needs checking not sure if correct autoplayVote | |
| if (queue.gs_queue._autoplayVote == QueueSong.AUTOPLAY_VOTE_UP){ | |
| this.smiles.push(queue.source[i]); | |
| } else if (queue.gs_queue._autoplayVote == QueueSong.AUTOPLAY_VOTE_DOWN){ | |
| this.frowns.push(queue.source[i]); | |
| }; | |
| }; | |
| // Define getters/setters | |
| this.__defineGetter__("badTitles",this["get badTitles"]); | |
| this.__defineGetter__("statusForRPC",this["get statusForRPC"]); | |
| }, | |
| "get badTitles": function() { | |
| var _local1 = []; | |
| var _local2 = (this.parent.length - 1); | |
| while (_local2 >= 0) { | |
| if (_local1.length < AutoplayStatus.numBadTitles){ | |
| _local3 = this.parent.getItemAt(_local2); | |
| _local4 = StringUtils.condenseTitle(_local3.song.songName); | |
| if (_local4){ | |
| _local1.push(_local4); | |
| }; | |
| } else { | |
| break; | |
| }; | |
| _local2--; | |
| }; | |
| return (_local1); | |
| }, | |
| "get statusForRPC": function() { | |
| var _local1 = {}; | |
| var _local2 = []; | |
| var _local12 = 0; | |
| for (i in this.frowns) { | |
| if (this.frowns[i] instanceof QueueSong){ | |
| _local2.push(this.frowns[i].song.artistID); | |
| } else if (parseInt(this.frowns[i])){ | |
| _local2.push(parseInt(this.frowns[i])); | |
| }; | |
| }; | |
| _local4 = this.userSeeds.concat(); | |
| for (i in this.smiles) { | |
| if (_local4.indexOf(this.smiles[i]) == -1){ | |
| _local4.push(this.smiles[i]); | |
| }; | |
| }; | |
| _local4 = _local4.concat(this.taggedArtistIDs); | |
| _local6 = []; | |
| for (i in _local4) { | |
| if (_local4[i] instanceof QueueSong){ | |
| _local12 = _local4[i].song.artistID; | |
| } else if (parseInt(_local4[i]) != 0){ | |
| _local12 = parseInt(_local4[i]); | |
| }; | |
| _local11 = _local2.indexOf(_local12); | |
| if (_local11 == -1){ | |
| _local13 = {}; | |
| _local13.artistID = _local12; | |
| _local13.type = "p"; | |
| _local6.push(_local13); | |
| } else { | |
| _local2.splice(_local11, 1); | |
| }; | |
| }; | |
| _local7 = []; | |
| _local8 = []; | |
| _local9 = (this.parent.length - 1); | |
| while (_local9 >= 0) { | |
| _local14 = this.parent.getItemAt(_local9); | |
| _local15 = _local14.song.songID; | |
| _local12 = _local14.song.artistID; | |
| if (_local6.length < this._minSeeds && _local14.thirtySecReported && _local4.indexOf(_local14) == -1 && _local14.source != "sponsored"){ | |
| _local11 = _local2.indexOf(_local12); | |
| if (_local11 == -1){ | |
| _local13 = {}; | |
| _local13.artistID = _local12; | |
| _local13.type = "s"; | |
| _local6.push(_local13); | |
| } else { | |
| _local2.splice(_local11, 1); | |
| }; | |
| }; | |
| if ((((_local7.length < this._numPlayedArtists)) && ((_local7.indexOf(_local12) == -1)))){ | |
| _local7.push(_local12); | |
| }; | |
| if ((((_local8.length < this._numPlayedSongs)) && ((_local8.indexOf(_local15) == -1)))){ | |
| _local8.push(_local15); | |
| }; | |
| if ((((((_local6.length >= this._minSeeds)) && ((_local7.length == this._numPlayedArtists)))) && ((_local8.length == this._numPlayedSongs)))){ | |
| break; | |
| }; | |
| _local9--; | |
| }; | |
| var _local10 = {}; | |
| for (i in _local6) { | |
| if (!_local10[_local6[i].artistID]){ | |
| _local10[_local6[i].artistID] = _local6[i].type; | |
| }; | |
| }; | |
| _local1.seedArtists = _local10; | |
| _local1.frowns = _local2; | |
| _local1.recentArtists = _local7; | |
| _local1.songIDsAlreadySeen = _local8.concat(this.flaggedSongIDs); | |
| _local1.secondaryArtistWeightModifier = this._secondarySeedWeightMultiplier; | |
| _local1.seedArtistWeightRange = this._seedWeightRange; | |
| _local1.weightModifierRange = this._weightModifierRange; | |
| _local1.minDuration = this._minDuration; | |
| _local1.maxDuration = this._maxDuration; | |
| return (_local1); | |
| }, | |
| addTagArtistSeeds: function(_arg1) { | |
| this.taggedArtistIDs = _arg1; | |
| this._seedWeightRange = [110, 130]; | |
| this._secondarySeedWeightMultiplier = 0.75; | |
| this._numPlayedArtists = 15; | |
| }, | |
| songsAddedToQueue: function(_arg1) { | |
| for (i in _arg1) { | |
| if (_arg1[i].source == "user"){ | |
| this.userSeeds.push(_arg1[i]); | |
| }; | |
| }; | |
| } | |
| }); | |
| // AutoplayStatus Statics | |
| AutoplayStatus.numPlayedSongs = 50; | |
| AutoplayStatus.minDuration = 60; | |
| AutoplayStatus.weightModifierRange = [-9, 9]; | |
| AutoplayStatus.minSeeds = 10; | |
| AutoplayStatus.numPlayedArtists = 5; | |
| AutoplayStatus.maxDuration = 1500; | |
| AutoplayStatus.numBadTitles = 25; | |
| AutoplayStatus.seedWeightRange = [70, 100]; | |
| AutoplayStatus.secondarySeedWeightMultiplier = 0.9; | |
| var EventDispatcher = jQuery.Class.extend({ | |
| listeners: {}, | |
| init: function() { | |
| this.listeners = {}; | |
| }, | |
| addEventListener: function(event, listener, context) { | |
| if (this.listeners.hasOwnProperty(event)) { | |
| this.listeners[event].push([listener,context]); | |
| } else { | |
| this.listeners[event] = [[listener,context]]; | |
| } | |
| //console.log('addedEventListener',event,listener,this,context); | |
| }, | |
| hasEventListener: function() { | |
| }, | |
| removeEventListener: function(event, listener) { | |
| if (this.listeners.hasOwnProperty(event)) { | |
| for (i in this.listeners[event]) { | |
| if (this.listeners[event][i][0] == listener) { | |
| this.listeners[event].splice(i,1); | |
| //console.log('removeEventListener',event,listener,this); | |
| return true; | |
| } | |
| } | |
| } else { | |
| //console.log('no listener found for',event,listener,this); | |
| return false; | |
| } | |
| }, | |
| dispatchEvent: function(event) { | |
| if (event.type && this.listeners.hasOwnProperty(event.type)) { | |
| event.currentTarget = this; | |
| //console.log('dispatchEvent',event,this); | |
| for (i in this.listeners[event.type]) { | |
| if (typeof this.listeners[event.type][i][0] == 'function') { | |
| this.listeners[event.type][i][0].call(this.listeners[event.type][i][1],event); | |
| } | |
| } | |
| } else { | |
| console.log("not a FlashEvent or no listeners for",event,this); | |
| } | |
| }, | |
| }); | |
| var Timer = EventDispatcher.extend({ | |
| init: function(delay, repeatCount) { | |
| this.delay = delay; | |
| this.repeatCount = repeatCount || 0; | |
| this.currentCount = 0; | |
| this.running = false; | |
| }, | |
| start: function() { | |
| console.log('timer started for',this.delay,'ms',this); | |
| this.running = true; | |
| this.timeout = setTimeout(function(me){ | |
| return function() { me.timerUp.call(me);} | |
| }(this), this.delay); | |
| }, | |
| stop: function() { | |
| this.running=false; | |
| clearTimeout(this.timeout); | |
| console.log('timer stopped',this); | |
| }, | |
| reset: function() { | |
| this.stop(); | |
| this.currentCount = 0; | |
| this.start(); | |
| }, | |
| timerUp: function() { | |
| //console.log('timer tick',this); | |
| this.currentCount++; | |
| this.dispatchEvent(new TimerEvent(TimerEvent.TIMER)); | |
| if (this.timeout) { | |
| clearTimeout(this.timeout); | |
| } | |
| if (this.running && (this.repeatCount == 0 || this.currentCount < this.repeatCount)) { | |
| this.timeout = setTimeout(function(me){ | |
| return function() { me.timerUp.call(me);} | |
| }(this), this.delay); | |
| } | |
| } | |
| }); | |
| var Tag = EventDispatcher.extend({ | |
| init: function(tagID, tagName) { | |
| // Define getter/setters | |
| this.__defineGetter__('tagID',helpers.getterFunction('tagID')); | |
| this.__defineSetter__('tagID',helpers.setterFunction('tagID')); | |
| this.__defineGetter__('tagName',helpers.getterFunction('tagName')); | |
| this.__defineSetter__('tagName',helpers.setterFunction('tagName')); | |
| this.tagID = tagID; | |
| this.tagName = tagName; | |
| } | |
| }); | |
| // Tag statics | |
| Tag.TAG_STATIONS = [new Tag(13, "ALTERNATIVE"), new Tag(75, "AMBIENT"), new Tag(96, "BLUEGRASS"), new Tag(230, "BLUES"), new Tag(750, "CLASSICAL"), new Tag(3529, "CLASSIC_ROCK"), new Tag(80, "COUNTRY"), new Tag(67, "ELECTRONICA"), new Tag(191, "EXPERIMENTAL"), new Tag(122, "FOLK"), new Tag(29, "HIP_HOP"), new Tag(136, "INDIE"), new Tag(43, "JAZZ"), new Tag(528, "LATIN"), new Tag(17, "METAL"), new Tag(102, "OLDIES"), new Tag(56, "POP"), new Tag(111, "PUNK"), new Tag(3, "RAP"), new Tag(160, "REGGAE"), new Tag(4, "RNB"), new Tag(12, "ROCK"), new Tag(69, "TRANCE")]; | |
| Tag.buildLookup = function() { | |
| var _local1 = {}; | |
| for (i in Tag.TAG_STATIONS) { | |
| _local1[Tag.TAG_STATIONS[i].tagID] = Tag.TAG_STATIONS[i]; | |
| }; | |
| return (_local1); | |
| }; | |
| Tag.__defineGetter__('tagIDLookup',function(){ | |
| if (!Tag._tagIDLookup){ | |
| Tag._tagIDLookup = Tag.buildLookup(); | |
| }; | |
| return (Tag._tagIDLookup); | |
| }); | |
| /* | |
| var JSONService = EventDispatcher.extend({ | |
| init: function(url) { | |
| this.httpService = new HTTPService(); | |
| this._headers = {}; | |
| this._super(); | |
| this.httpService.method = "POST"; | |
| this.httpService.contentType = "application/json"; | |
| this.httpService.resultFormat = "text"; | |
| this.url = url || ""; | |
| } | |
| });*/ | |
| var GSSound9 = EventDispatcher.extend({ | |
| //_volume: 1, | |
| _isStopped: true, | |
| _isMuted: false, | |
| _isPaused: false, | |
| muteVolume: 1, | |
| pausedPosition: 0, | |
| isBuffering: true, | |
| init: function(url,bufferSize,checkPolicyFile){ | |
| this._url = url; | |
| this.sourceSound = new Audio(requestUrl); | |
| this.sourceSound.preload = 'auto'; | |
| this.sourceSound.autobuffer = 'true'; | |
| this.sourceSound.volume = 1; | |
| // Attach event listeners | |
| this.sourceSound.addEventListener('progress',function(me){return function(e){me._onProgress.call(me,e);}}(this)); | |
| this.sourceSound.addEventListener('ended',function(me){return function(e){me._onSoundComplete.call(me,e);}}(this)); | |
| this.sourceSound.addEventListener('loadeddata',function(me){return function(e){me._onLoadedData.call(me,e);}}(this)); | |
| // Define getters/setters | |
| this.__defineGetter__("bytesLoaded",this["get bytesLoaded"]); | |
| this.__defineGetter__("bytesTotal",this["get bytesTotal"]); | |
| this.__defineGetter__("duration",this["get duration"]); | |
| this.__defineGetter__("position",this["get position"]); | |
| this.__defineGetter__("isPaused",this["get isPaused"]); | |
| this.__defineGetter__("isMuted",this["get isMuted"]); | |
| this.__defineGetter__("isStopped",this["get isStopped"]); | |
| this.__defineGetter__("volume",this["get volume"]); | |
| this.__defineSetter__("position",this["set position"]); | |
| this.__defineSetter__("isMuted",this["set isMuted"]); | |
| this.__defineSetter__("volume",this["set volume"]); | |
| }, | |
| "get bytesLoaded": function() { | |
| if (this.sourceSound.readyState != this.sourceSound.HAVE_NOTHING && this.sourceSound.buffered.length == 1 && this.sourceSound.buffered.end(0)) { | |
| return this.sourceSound.buffered.end(0) * 1000; | |
| } | |
| return 0; | |
| }, | |
| "get bytesTotal": function() { | |
| //fudge it | |
| return this.sourceSound.duration * 1000; | |
| }, | |
| "get duration": function() { | |
| return this.sourceSound.duration * 1000; | |
| }, | |
| "get isPaused": function() { | |
| return (!this._isStopped) ? this.sourceSound.paused : false; | |
| }, | |
| "get isMuted": function() { | |
| return (this.sourceSound.volume == 0 && this._isMuted); | |
| }, | |
| "get isStopped": function() { | |
| return this._isStopped; | |
| }, | |
| "get position": function() { | |
| return this.sourceSound.currentTime * 1000; | |
| }, | |
| "get volume": function() { | |
| return (this._isMuted) ? this.muteVolume : this.sourceSound.volume; | |
| }, | |
| "set position": function(pos) { | |
| if (this.sourceSound.readyState != this.sourceSound.HAVE_NOTHING && this.sourceSound.currentTime != (pos/1000)) { | |
| this.sourceSound.currentTime = (pos/1000); | |
| } | |
| }, | |
| "set isMuted": function(muted) { | |
| if (!muted && this._isMuted && this.muteVolume) { | |
| if (this.sourceSound.readyState != this.sourceSound.HAVE_NOTHING) { | |
| this.sourceSound.volume = this.muteVolume; | |
| } | |
| this._isMuted = false; | |
| } else if( muted && !this._isMuted) { | |
| console.log('muting oldVolume',this.sourceSound.volume); | |
| this.muteVolume = this.sourceSound.volume; | |
| this._isMuted = true; | |
| if (this.sourceSound.readyState != this.sourceSound.HAVE_NOTHING) { | |
| this.sourceSound.volume = 0; | |
| } | |
| } | |
| }, | |
| "set volume": function(volume) { | |
| if (this.sourceSound.readyState != this.sourceSound.HAVE_NOTHING) { | |
| this.sourceSound.volume = volume; | |
| } | |
| }, | |
| play: function(){ | |
| this.sourceSound.play(); | |
| this._isStopped = false; | |
| }, | |
| pause: function() { | |
| this.sourceSound.pause(); | |
| this.pausedPostion = this.position; | |
| }, | |
| stop: function() { | |
| this.sourceSound.pause(); | |
| this.position = 0; | |
| this._isStopped = true; | |
| }, | |
| _onSoundComplete: function(e) { | |
| this.dispatchEvent(new GSSoundEvent(GSSoundEvent.PLAYBACK_COMPLETE)); | |
| }, | |
| _onProgress: function(e) { | |
| //console.log('progress',e,e.target.buffered,e.target.buffered.end(0),e.target.duration); | |
| /*if (e.target.readyState != e.target.HAVE_NOTHING && e.target.buffered.length == 1 && e.target.buffered.end(0) && e.target.duration && e.target.buffered.end(0) == e.target.duration) { | |
| console.warn('finished buffering'); | |
| }*/ | |
| }, | |
| _onLoadedData: function(e) { | |
| this.isBuffering = false; | |
| } | |
| }); | |
| var Service = EventDispatcher.extend({ | |
| init: function(hostname, defaultScript, revision, session, allowHTTPS) { | |
| this.hostname = hostname; | |
| this.defaultScript = defaultScript; | |
| this.revision = revision; | |
| this.session = session || ""; | |
| this.allowHTTPS = (allowHTTPS == undefined) ? true : allowHTTPS; | |
| this.pendingCalls = []; | |
| this.headers = {}; | |
| this._super(); | |
| //this.service = new JSONService(); | |
| //this.service.addEventListener(HeaderEvent.HEADER, onHeader); | |
| //this.service.addEventListener(ResultEvent.RESULT, onResult); | |
| //this.service.addEventListener(FaultEvent.FAULT, onFault); | |
| this.addHeader("clientRevision", revision); | |
| this.addHeader("client", "jsqueue"); | |
| this.addHeader("privacy", 0); | |
| // Define getter | |
| this.__defineGetter__("country",this["get country"]); | |
| }, | |
| "get country": function() { | |
| return GS.service.country; | |
| }, | |
| addHeader: function(key, obj) { | |
| //console.log(((("[Service] addHeader " + key) + ":"), obj)); | |
| //this.service.addHeader(key, obj); | |
| this.headers[key] = obj; | |
| if (key == "session") { | |
| this.invalidateToken(); | |
| } | |
| }, | |
| invalidateToken: function() { | |
| this.currentToken = ""; | |
| this.tokenExpires = 0; | |
| }, | |
| send: function(caller,isSecure,methodName,params,responder,overrideScript,extraHeaders) { | |
| caller = caller || this; | |
| if (extraHeaders) { | |
| for(key in this.headers) { | |
| if (extraHeaders.hasOwnProperty(key)) { continue; } | |
| extraHeaders[key] = this.headers[key]; | |
| } | |
| } else { extraHeaders = this.headers; } | |
| console.log('service send',isSecure,methodName,params,responder,overrideScript,extraHeaders,caller,this); | |
| if (responder) { | |
| d.call(caller,{ | |
| isSecure:isSecure, | |
| methodName:methodName, | |
| parameters:params, | |
| overrideScript:overrideScript, | |
| overrideHeaders:extraHeaders, | |
| errback: responder.fault(caller), | |
| callback: responder.result(caller) | |
| },0); | |
| } else { | |
| d.call(caller,{ | |
| isSecure:isSecure, | |
| methodName:methodName, | |
| parameters:params, | |
| overrideScript:overrideScript, | |
| overrideHeaders:extraHeaders | |
| },0); | |
| } | |
| } | |
| }); | |
| var BaseSong = EventDispatcher.extend({ | |
| init: function() { | |
| this.DEFAULT_ART_PATH = "http://beta.grooveshark.com/static/amazonart/"; | |
| this.artFilename = ""; | |
| this.token = ""; | |
| this.estimateDuration = 0; | |
| this.albumID = null; | |
| this.trackNum = 0; | |
| this.albumName = ""; | |
| this.songID = null; | |
| this.artistName = ""; | |
| this.flags = 0; | |
| this.artistID = null; | |
| this.songName = ""; | |
| } | |
| }); | |
| var PlayableSong = EventDispatcher.extend({ | |
| _position: 0, | |
| _soundVolume: 1, | |
| _duration: 0, | |
| _thirtySecReported:false, | |
| _fileLoaded:false, | |
| _playStatus:0, | |
| _lastStreamKey:"", | |
| _secondsListened: 0, | |
| _bytesLoaded:0, | |
| _bytesTotal: 0, | |
| pausedPosition: 0, | |
| consecutiveBadFrames: 0, | |
| downloadReported: false, | |
| isBuffering: false, | |
| bufferCount: 0, | |
| fadeAmountDown: 600, | |
| fadeAmountUp:1500, | |
| playbackReported: false, | |
| completeReported: false, | |
| playOnStreamKey: false, | |
| fadeInOut: false, | |
| noBufferCount: 0, | |
| lastPosition:0, | |
| cancelPendingPlayback: false, | |
| isBuffering: false, | |
| init: function(song, service) { | |
| this.song = song; | |
| if (song.estimateDuration && parseInt(song.estimateDuration)){ | |
| this.duration = song.estimateDuration; | |
| }; | |
| song.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.songPropChange, this); | |
| this.service = service; | |
| this.streamWatcher = new Timer(500); //should be 500ms | |
| this.streamWatcher.addEventListener(TimerEvent.TIMER, this.onStreamPoll, this); | |
| // Define getters and setters | |
| this.__defineGetter__("duration",this["get duration"]); | |
| this.__defineGetter__("fileLoaded",helpers.getterFunction('fileLoaded')); | |
| this.__defineGetter__("playStatus",helpers.getterFunction('playStatus')); | |
| this.__defineGetter__("position",helpers.getterFunction('position')); | |
| this.__defineGetter__("isMuted",this["get isMuted"]); | |
| this.__defineGetter__("sound",helpers.getterFunction('sound')); | |
| this.__defineGetter__("_sound",helpers.getterFunction('_sound')); | |
| this.__defineGetter__("soundVolume",this["get soundVolume"]); | |
| this.__defineSetter__("fileLoaded",helpers.setterFunction('fileLoaded')); | |
| this.__defineSetter__("playStatus",helpers.setterFunction('playStatus')); | |
| this.__defineSetter__("position",helpers.setterFunction('position')); | |
| this.__defineSetter__("isMuted",this["set isMuted"]); | |
| this.__defineSetter__("sound",helpers.setterFunction('sound')); | |
| this.__defineSetter__("_sound",this["set _sound"]); | |
| this.__defineSetter__("soundVolume",this["set soundVolume"]); | |
| }, | |
| "set _sound": function(newSound) { | |
| if (newSound != this.__sound) { | |
| if (this.__sound){ | |
| this.__sound.stop(); | |
| this.__sound.removeEventListener(GSSoundEvent.DOWNLOAD_COMPLETE, this.onDownloadComplete); | |
| this.__sound.removeEventListener(GSSoundEvent.PLAYBACK_COMPLETE, this.onSoundComplete); | |
| this.__sound.removeEventListener(GSSoundEvent.IO_ERROR, this.onIOError); | |
| } | |
| this.__sound = newSound; | |
| if (this.__sound){ | |
| this.__sound.addEventListener(GSSoundEvent.DOWNLOAD_COMPLETE, this.onDownloadComplete, this); | |
| this.__sound.addEventListener(GSSoundEvent.PLAYBACK_COMPLETE, this.onSoundComplete, this); | |
| this.__sound.addEventListener(GSSoundEvent.IO_ERROR, this.onIOError, this); | |
| this.__sound.volume = this._soundVolume; | |
| this.__sound.filters = this._filters; | |
| } | |
| } | |
| }, | |
| "get soundVolume": function() { | |
| return (this.sound) ? this.sound.volume : 1; | |
| }, | |
| "set soundVolume": function(volume) { | |
| if (this.sound) { | |
| this.sound.volume = volume; | |
| } | |
| }, | |
| "get duration": function() { | |
| return (this.sound) ? this.sound.duration : 0; | |
| }, | |
| "get isMuted": function() { | |
| return (this.sound) ? this.sound.isMuted : false; | |
| }, | |
| "set isMuted": function(isMuted) { | |
| if (this.sound) { | |
| this.sound.isMuted = isMuted; | |
| } | |
| }, | |
| seekTo: function(_arg1) { | |
| if (_arg1 < 0){ | |
| _arg1 = 0; | |
| }; | |
| this.playSoundFrom(_arg1, true); | |
| }, | |
| play: function() { | |
| switch (this.playStatus) { | |
| case PlayableSong.PLAY_STATUS_INITIALIZING: | |
| this.playOnStreamKey = true; | |
| return; | |
| case PlayableSong.PLAY_STATUS_BUFFERING: | |
| case PlayableSong.PLAY_STATUS_PLAYING: | |
| if (this.position < 5){ | |
| return; | |
| } | |
| break; | |
| }; | |
| if (this.__sound && !this.thirtySecReported){ | |
| this.playSoundFrom(0); | |
| } else { | |
| this.playOnStreamKey = true; | |
| this.fetchNewStreamKey(); | |
| }; | |
| }, | |
| pause: function() { | |
| if (this.__sound){ | |
| if (this.fadeInOut){ | |
| this.fadeOut(); | |
| } else { | |
| this._sound.pause(); | |
| }; | |
| this.playStatus = PlayableSong.PLAY_STATUS_PAUSED; | |
| } else { | |
| this.playOnStreamKey = false; | |
| }; | |
| }, | |
| resume: function() { | |
| if (this.__sound && this.playStatus == PlayableSong.PLAY_STATUS_PAUSED){ | |
| this.playSoundFrom(this._sound.position); | |
| }; | |
| }, | |
| stop: function() { | |
| this.streamWatcher.stop(); | |
| if (this.sound){ | |
| this.sound.stop(); | |
| }; | |
| this.sound = null; | |
| this.cancelPendingPlayback = true; | |
| switch (this.playStatus){ | |
| case PlayableSong.PLAY_STATUS_COMPLETED: | |
| case PlayableSong.PLAY_STATUS_FAILED: | |
| break; | |
| default: | |
| this.playStatus = PlayableSong.PLAY_STATUS_NONE; | |
| } | |
| }, | |
| flag: function(_arg1) { | |
| var _local2 = new FlagSong(this.service, this); | |
| _local2.flagReason = _arg1; | |
| _local2.execute(); | |
| }, | |
| fetchNewStreamKey: function() { | |
| this.sound = null; | |
| this.playStatus = PlayableSong.PLAY_STATUS_INITIALIZING; | |
| this.lastStreamKey = ""; | |
| this.lastServerID = 0; | |
| this.secondsListened = 0; | |
| this.downloadReported = false; | |
| this.playbackReported = false; | |
| this.thirtySecReported = false; | |
| this.completeReported = false; | |
| this.position = 0; | |
| this.bytesLoaded = 0; | |
| this.bytesTotal = 0; | |
| this.consecutiveBadFrames = 0; | |
| this.bufferCount = 0; | |
| this.noBufferCount = 0; | |
| this.cancelPendingPlayback = false; | |
| if (this.consecutiveFailedStreamKeys > 4){ | |
| this.playStatus = PlayableSong.PLAY_STATUS_NONE; | |
| this.consecutiveFailedStreamKeys = 0; | |
| this.dispatchEvent(new PlayableSongEvent(PlayableSongEvent.ERROR, PlayableSongEvent.FAILED_TOO_MANY_STREAMKEY_FAILS)); | |
| } else { | |
| this.service.send(this, false, "getStreamKeyFromSongIDEx", { | |
| songID:this.song.songID, | |
| prefetch:!(this.playOnStreamKey), | |
| country:this.service.country, | |
| mobile:this.useMobile | |
| }, new ItemResponder(this.getStreamKeyResult, this.getStreamKeyFault, {prefetch:!(this.playOnStreamKey)})); | |
| }; | |
| }, | |
| getStreamKeyResult: function(result, token) { | |
| if (result && !this.cancelPendingPlayback) { | |
| console.log('getStreamKeyResult',result); | |
| if ((!result.streamKey || result.streamKey == "false") && Boolean(token.prefetch)) { | |
| if (this.playOnStreamKey) { | |
| this.playStatus = PlayableSong.PLAY_STATUS_NONE; | |
| this.play(); | |
| } | |
| return; | |
| } | |
| if (!result.streamKey || result.streamKey == "false" || result.streamKey == "null" || !result.ip || result.ip == "null" || !result.streamServerID) { | |
| this.consecutiveFailedStreamKeys++; | |
| this.onSongFailure(PlayableSongEvent.FAILED_STREAMKEY_OTHER); | |
| console.error("[PlayableSong] Error fetching streamKey: Result came back null."); | |
| return; | |
| } | |
| if (this.useStagingScript){ | |
| result.ip = ("staging." + result.ip); | |
| } | |
| url = "http://" + result.ip + "/stream.php"; | |
| this.lastStreamKey = result.streamKey; | |
| this.lastServerID = result.streamServerID; | |
| this.loadSoundObject(url, {streamKey: result.streamKey}, this.playOnStreamKey); | |
| if (this.song.hasOwnProperty("token") && result.FileToken && result.FileToken != "null"){ | |
| this.song["token"] = result.FileToken; | |
| } | |
| if (result.uSecs){ | |
| this.song.estimateDuration = (result.uSecs / 1000); | |
| } | |
| } else if (!result) { | |
| this.consecutiveFailedStreamKeys++; | |
| this.onSongFailure(PlayableSongEvent.FAILED_STREAMKEY_OTHER); | |
| console.error("[PlayableSong] Error fetching streamKey: Empty result set"); | |
| } | |
| }, | |
| loadSoundObject: function(url, urlVariables, autoPlay) { | |
| // Turn POST into GET | |
| requestUrl = url + '?'; | |
| for (key in urlVariables) { | |
| requestUrl += '&' + key + '=' + urlVariables[key]; | |
| } | |
| this.sound = new GSSound9(requestUrl); | |
| console.log('loadSoundObject',this.sound,autoPlay); | |
| this.playStatus = PlayableSong.PLAY_STATUS_LOADING; | |
| this.isBuffering = false; | |
| this.fileLoaded = false; | |
| if (autoPlay) { | |
| this.playSoundFrom(0); | |
| } | |
| if (!this.downloadReported){ | |
| _local7 = new MarkSongDownloaded(this.service, this); | |
| _local7.execute(); | |
| this.downloadReported = true; | |
| } | |
| }, | |
| playSoundFrom: function(time, arg2) { | |
| console.log('playSoundFrom',time,arg2,this._sound); | |
| if (this._sound) { | |
| if (time < 0){ | |
| time = 0; | |
| } | |
| this._sound.position = time; | |
| this.position = this.lastPosition = this.pausedPosition = this._sound.position; | |
| if (!arg2 && ((this._sound.isPaused || this._sound.isStopped) )){ //|| (this._fadeTimerDown && this._fadeTimerDown.running))){ | |
| //if (this.fadeInOut){ | |
| // this._sound.play(); | |
| // this.fadeIn(); | |
| //} else { | |
| console.log('playing'); | |
| this._sound.play(); | |
| //} | |
| } | |
| if (!this._sound.isPaused && !this._sound.isStopped && this._sound.position != this._sound.duration){ | |
| if (!this.streamWatcher.running){ | |
| this.streamWatcher.reset(); | |
| this.streamWatcher.start(); | |
| } | |
| this.playStatus = PlayableSong.PLAY_STATUS_PLAYING; | |
| } | |
| } | |
| }, | |
| onSoundComplete: function(event) { | |
| console.log("[PlayableSong] onSoundComplete: ",event); | |
| this.streamWatcher.stop(); | |
| this.playStatus = PlayableSong.PLAY_STATUS_COMPLETED; | |
| PlayableSong.currentBufferSize = (PlayableSong.currentBufferSize - 1000); | |
| if (PlayableSong.currentBufferSize < PlayableSong.MIN_BUFFER_SIZE){ | |
| PlayableSong.currentBufferSize = PlayableSong.MIN_BUFFER_SIZE; | |
| } | |
| this.dispatchEvent(new PlayableSongEvent(PlayableSongEvent.COMPLETE, (event) ? PlayableSongEvent.COMPLETE_SOUND_COMPLETE : PlayableSongEvent.COMPLETE_VBR_COMPLETE)); | |
| if (!this.completeReported){ | |
| _local3 = new MarkSongComplete(this.service, this); | |
| _local3.execute(); | |
| this.completeReported = true; | |
| } | |
| }, | |
| onSongFailure: function(_arg1) { | |
| this.streamWatcher.stop(); | |
| if (this.sound){ | |
| this.sound.stop(); | |
| }; | |
| this.sound = null; | |
| var _local2 = this.playStatus; | |
| this.playStatus = PlayableSong.PLAY_STATUS_FAILED; | |
| this.dispatchEvent(new PlayableSongEvent(PlayableSongEvent.ERROR, _arg1, _local2)); | |
| }, | |
| onStreamPoll: function() { | |
| if (this.sound) { | |
| if (this.isBuffering != this.sound.isBuffering) { | |
| if (this.sound.isBuffering){ | |
| if (this.playStatus != PlayableSong.PLAY_STATUS_INITIALIZING && this.playStatus != PlayableSong.PLAY_STATUS_LOADING && this.position > 0){ | |
| PlayableSong.currentBufferSize = (PlayableSong.currentBufferSize + 3000); | |
| this.bufferCount++; | |
| this.noBufferCount = 0; | |
| if (PlayableSong.currentBufferSize > PlayableSong.MAX_BUFFER_SIZE){ | |
| PlayableSong.currentBufferSize = PlayableSong.MAX_BUFFER_SIZE; | |
| if (this.bufferCount > 5){ | |
| this.dispatchEvent(new PlayableSongEvent(PlayableSongEvent.ERROR, PlayableSongEvent.WARNING_FREQUENT_BUFFERING)); | |
| }; | |
| }; | |
| }; | |
| if (this.playStatus != PlayableSong.PLAY_STATUS_LOADING){ | |
| this.playStatus = PlayableSong.PLAY_STATUS_BUFFERING; | |
| }; | |
| } | |
| this.isBuffering = this.sound.isBuffering; | |
| } | |
| if (!this.sound.isBuffering && !this.sound.isPaused && !this.sound.isStopped && (!this._fadeTimerDown || !this._fadeTimerDown.running)){ | |
| this.playStatus = PlayableSong.PLAY_STATUS_PLAYING; | |
| }; | |
| this.bytesLoaded = this.sound.bytesLoaded; | |
| this.bytesTotal = this.sound.bytesTotal; | |
| _local2 = this.sound.duration; | |
| //console.log('onStreamPoll sound:',this.sound,'isBuffering:',this.isBuffering,'duration:',this.sound.duration,'position:',this.sound.position); | |
| if (this.playStatus != PlayableSong.PLAY_STATUS_PAUSED){ | |
| this.position = this.sound.position; | |
| }; | |
| if (this.playStatus == PlayableSong.PLAY_STATUS_PLAYING && this.position > this.lastPosition && (this.position + PlayableSong.currentBufferSize * 1.5) < this.sound.duration){ | |
| this.noBufferCount++; | |
| if ((this.noBufferCount % 70) == 0){ | |
| PlayableSong.currentBufferSize = (PlayableSong.currentBufferSize - 4000); | |
| if (PlayableSong.currentBufferSize < PlayableSong.MIN_BUFFER_SIZE){ | |
| PlayableSong.currentBufferSize = PlayableSong.MIN_BUFFER_SIZE; | |
| }; | |
| }; | |
| }; | |
| if ((!this.playbackReported && this.playStatus == PlayableSong.PLAY_STATUS_PLAYING)){ | |
| this.dispatchEvent(new PlayableSongEvent(PlayableSongEvent.PLAYBACK_BEGUN)); | |
| _local3 = new MarkSongPlayed(this.service, this); | |
| _local3.execute(); | |
| this.playbackReported = true; | |
| }; | |
| if (this.duration == 0 && !this.fileLoaded){ | |
| this.duration = _local2; | |
| }; | |
| if (((((((!((this.position == 0))) && ((this.position == this.lastPosition)))) && ((this.playStatus == PlayableSong.PLAY_STATUS_PLAYING)))) && (this.fileLoaded))){ | |
| if ((_local2 - this.position) > 5000){ | |
| if (this.consecutiveBadFrames > 4){ | |
| this.onSongFailure(PlayableSongEvent.FAILED_TOO_MANY_BAD_FRAMES); | |
| } else { | |
| this.consecutiveBadFrames++; | |
| switch (this.consecutiveBadFrames){ | |
| case 0: | |
| default: | |
| _local4 = 10; | |
| break; | |
| case 1: | |
| _local4 = 100; | |
| break; | |
| case 2: | |
| _local4 = 250; | |
| break; | |
| case 3: | |
| _local4 = 500; | |
| break; | |
| case 4: | |
| _local4 = 1000; | |
| }; | |
| console.log((("[PlayableSong] Bad frame? Skipping " + _local4) + "ms")); | |
| this.lastPosition = (this.position + _local4); | |
| this.playSoundFrom(lastPosition); | |
| }; | |
| } else { | |
| console.log("[PlayableSong] VBR Fake Stop"); | |
| this.onSoundComplete(); | |
| }; | |
| } else { | |
| this.consecutiveBadFrames = 0; | |
| this.lastPosition = this.position; | |
| if (this.playStatus == PlayableSong.PLAY_STATUS_PLAYING){ | |
| this.secondsListened = (this.secondsListened + 0.5); | |
| if ((((this.secondsListened > 30)) && (!(this.thirtySecReported)))){ | |
| _local3 = new MarkSongOver30Seconds(this.service, this); | |
| _local3.execute(); | |
| this.thirtySecReported = true; | |
| }; | |
| }; | |
| }; | |
| } | |
| }, | |
| }); | |
| // PlayableSong Constants | |
| PlayableSong.PLAY_STATUS_COMPLETED=7; | |
| PlayableSong.PASSTHROUGH_PROP= ["songName", "songID", "artistName", "artistID", "albumName", "albumID", "trackNum", "popularity", "isArtistVerified", "isAlbumVerified", "isFavorite"]; | |
| PlayableSong.PLAY_STATUS_PAUSED=4; | |
| PlayableSong.MIN_BUFFER_SIZE= 3000; | |
| PlayableSong.PLAY_STATUS_NONE= 0; | |
| PlayableSong.PLAY_STATUS_FAILED= 6; | |
| PlayableSong.MAX_BUFFER_SIZE= 20000; | |
| PlayableSong.PLAY_STATUS_BUFFERING= 5; | |
| PlayableSong.PLAY_STATUS_INITIALIZING= 1; | |
| PlayableSong.PLAY_STATUS_PLAYING= 3; | |
| PlayableSong.PLAY_STATUS_LOADING= 2; | |
| // PlayableSong Statics | |
| PlayableSong._useStagingScript = false; | |
| PlayableSong._useMobile = false; | |
| PlayableSong._currentBufferSize = 3000; | |
| PlayableSong._staticBindingEventDispatcher = new EventDispatcher(); | |
| PlayableSong._consecutiveFailedStreamKeys = 0; | |
| PlayableSong.__defineGetter__("useStagingScript",helpers.getterFunction('useStagingScript', PlayableSong)); | |
| PlayableSong.__defineGetter__("useMobile",helpers.getterFunction('useMobile', PlayableSong)); | |
| PlayableSong.__defineGetter__("currentBufferSize",helpers.getterFunction('currentBufferSize', PlayableSong)); | |
| PlayableSong.__defineGetter__("staticEventDispatcher",helpers.getterFunction('staticEventDispatcher', PlayableSong)); | |
| PlayableSong.__defineGetter__("consecutiveFailedStreamKeys",helpers.getterFunction('consecutiveFailedStreamKeys', PlayableSong)); | |
| PlayableSong.__defineSetter__("useStagingScript",helpers.setterFunction('useStagingScript', PlayableSong, true)); | |
| PlayableSong.__defineSetter__("useMobile",helpers.setterFunction('useMobile', PlayableSong, true)); | |
| PlayableSong.__defineSetter__("currentBufferSize",helpers.setterFunction('currentBufferSize', PlayableSong, true)); | |
| PlayableSong.__defineSetter__("consecutiveFailedStreamKeys",helpers.setterFunction('consecutiveFailedStreamKeys', PlayableSong, true)); | |
| var QueueSong = PlayableSong.extend({ | |
| _queueSongID: 0, | |
| _autoplayVote: 0, | |
| _source: "user", | |
| _eligibleForAutoplayRemoval: false, | |
| addedToRecent: false, | |
| init: function(song, queue, service) { | |
| this._super(song, service); | |
| this.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onPropChange, this); | |
| this.song.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onSongPropChange, this); | |
| this.parent = queue; | |
| this.parent.addEventListener(CollectionEvent.COLLECTION_CHANGE, this.onQueueCollectionChange, this); | |
| //gs_queue::recalcEligibleForAutoplayRemoval(); | |
| }, | |
| play: function() { | |
| this.addedToRecent = false; | |
| if (this.autoplayVote == QueueSong.AUTOPLAY_VOTE_DOWN && this.parent && this.parent.autoplayEnabled) { | |
| this.playStatus = PlayableSong.PLAY_STATUS_COMPLETED; | |
| this.dispatchEvent(new PlayableSongEvent(PlayableSongEvent.COMPLETE, PlayableSongEvent.COMPLETE_FORCE_FROWN_SKIP)); | |
| return; | |
| } | |
| this._super(); | |
| }, | |
| onQueueCollectionChange: function() { | |
| console.log('onQueueCollectionChange'); | |
| //gs_queue::recalcEligibleForAutoplayRemoval(); | |
| } | |
| }); | |
| // QueueSong Constants | |
| QueueSong.AUTOPLAY_VOTE_NONE = 0; | |
| QueueSong.AUTOPLAY_VOTE_UP = 1; | |
| QueueSong.AUTOPLAY_VOTE_DOWN = -1; | |
| var QueueCommand = EventDispatcher.extend({ | |
| init: function(service, queue) { | |
| this.service = service; | |
| this.queue = queue; | |
| this._super(); | |
| }, | |
| execute: function() { | |
| throw("NotImplemented"); | |
| } | |
| }); | |
| var SongCommand = EventDispatcher.extend({ | |
| init: function(service, song) { | |
| this.service = service; | |
| this.song = song; | |
| this._super(); | |
| }, | |
| execute: function() { | |
| throw("NotImplemented"); | |
| }, | |
| reexecute: function() { | |
| this.execute(); | |
| }, | |
| serviceFault: function (_arg1, _arg2) { | |
| this.onFail(_arg1.message); | |
| }, | |
| serviceSuccess: function (_arg1, arg2) { | |
| this.dispatchEvent(new FlashEvent(FlashEvent.COMPLETE)); | |
| }, | |
| }); | |
| var MarkSongDownloaded = SongCommand.extend({ | |
| execute: function() { | |
| if (!this.song || !this.song.lastStreamKey){ | |
| this.onFail("Either no song, or song is missing streamKey."); | |
| return; | |
| } | |
| var args = {}; | |
| args.streamKey = this.song.lastStreamKey; | |
| args.streamServerID = this.song.lastServerID; | |
| args.songID = this.song.song.songID; | |
| this.service.send(this, false, "markSongDownloadedEx", args, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| }, | |
| onFail: function(message) { | |
| console.log("[MarkSongDownloaded] Failed: " + message + " Giving up."); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| } | |
| }); | |
| var MarkSongPlayed = SongCommand.extend({ | |
| execute: function() { | |
| if (!this.song || !this.song.lastStreamKey){ | |
| this.onFail("Either no song, or song is missing streamKey."); | |
| return; | |
| } | |
| var args = {}; | |
| args.streamKey = this.song.lastStreamKey; | |
| args.streamServerID = this.song.lastServerID; | |
| args.songID = this.song.song.songID; | |
| var _local2 = this.song; | |
| if (_local2.hasOwnProperty("queueSongID")){ | |
| args.songQueueSongID = _local2.queueSongID; | |
| } else { | |
| args.songQueueSongID = 0; | |
| }; | |
| if (((_local2.hasOwnProperty("parent")) && (_local2.parent.hasOwnProperty("queueID")))){ | |
| args.songQueueID = _local2.parent.queueID; | |
| } else { | |
| args.songQueueID = 0; | |
| }; | |
| this.service.send(this, false, "markSongQueueSongPlayed", args, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| }, | |
| onFail: function(message) { | |
| console.log("[MarkSongPlayed] Failed: " + message + " Giving up."); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| } | |
| }); | |
| var MarkSongOver30Seconds = SongCommand.extend({ | |
| execute: function() { | |
| if (!this.song || !this.song.lastStreamKey){ | |
| this.onFail("Either no song, or song is missing streamKey."); | |
| return; | |
| } | |
| var args = {}; | |
| args.streamKey = this.song.lastStreamKey; | |
| args.streamServerID = this.song.lastServerID; | |
| args.songID = this.song.song.songID; | |
| var _local2 = this.song; | |
| if (_local2.hasOwnProperty("queueSongID")){ | |
| args.songQueueSongID = _local2.queueSongID; | |
| } else { | |
| args.songQueueSongID = 0; | |
| }; | |
| if (((_local2.hasOwnProperty("parent")) && (_local2.parent.hasOwnProperty("queueID")))){ | |
| args.songQueueID = _local2.parent.queueID; | |
| } else { | |
| args.songQueueID = 0; | |
| }; | |
| this.service.send(this, false, "markStreamKeyOver30Seconds", args, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| }, | |
| onFail: function(message) { | |
| console.log("[MarkSongOver30Seconds] Failed: " + message + " Giving up."); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| } | |
| }); | |
| var MarkSongSkipped = SongCommand.extend({ | |
| execute: function() { | |
| if (!this.song.parent || !this.song.parent.queueID || !this.song.parent.autoplayEnabled){ | |
| this.onFail("Queue not initialized, or autoplay is off.", false); | |
| return; | |
| } | |
| if (this.song || !this.song.queueSongID){ | |
| this.onFail("Either no song, or song is missing queueSongID.", false); | |
| return; | |
| } | |
| var _local1 = {}; | |
| _local1.songQueueSongID = this.song.queueSongID; | |
| _local1.songQueueID = this.song.parent.queueID; | |
| this.service.send(this, false, "markSongSkipped", _local1, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| }, | |
| onFail: function(message) { | |
| console.log("[MarkSongSkipped] Failed: " + message + " Giving up."); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| } | |
| }); | |
| var MarkSongComplete = SongCommand.extend({ | |
| execute: function() { | |
| if (!this.song || !this.song.lastStreamKey){ | |
| this.onFail("Either no song, or song is missing streamKey."); | |
| return; | |
| } | |
| var args = {}; | |
| args.streamKey = this.song.lastStreamKey; | |
| args.streamServerID = this.song.lastServerID; | |
| args.songID = this.song.song.songID; | |
| args.song = {}; | |
| args.song.songID = this.song.song.songID; | |
| args.song.songName = this.song.song.songName; | |
| args.song.artistID = this.song.song.artistID; | |
| args.song.artistName = this.song.song.artistName; | |
| args.song.albumID = this.song.song.albumID; | |
| args.song.albumName = this.song.song.albumName; | |
| args.song.token = ((this.song.song.hasOwnProperty("token")) ? this.song.song["token"] : ""); | |
| args.song.artFilename = this.song.song.artFilename; | |
| this.service.send(this, false, "markSongComplete", args, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| }, | |
| onFail: function(message) { | |
| console.log("[MarkSongComplete] Failed: " + message + " Giving up."); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| } | |
| }); | |
| var FlagSong = SongCommand.extend({ | |
| execute: function() { | |
| if (!this.song || !this.song.lastStreamKey){ | |
| this.onFail("Either no song, or song is missing streamKey.", false); | |
| return; | |
| }; | |
| var args = {}; | |
| args.streamKey = this.song.lastStreamKey; | |
| args.streamServerID = this.song.lastServerID; | |
| args.songID = this.song.song.songID; | |
| args.reason = this.flagReason; | |
| this.attempts++; | |
| this.service.send(this, false, "flagSong", args, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| }, | |
| onFail: function(message, _arg2) { | |
| if (((_arg2) && ((this.attempts < 3)))){ | |
| console.log("[FlagSong] Failed: " + message + " Will re-attempt."); | |
| _local3 = (100 + Math.floor((Math.random() * 400))); | |
| _local4 = new Timer(_local3, 1); | |
| _local4.addEventListener(TimerEvent.TIMER_COMPLETE, this.reexecute, this); | |
| _local4.start(); | |
| } else { | |
| console.log("[FlagSong] Failed: " + message + " Giving up."); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| }; | |
| } | |
| }); | |
| var InitiateQueue = QueueCommand.extend({ | |
| init: function (service, queue) { | |
| this.attempts = 0; | |
| this._super(service, queue); | |
| }, | |
| execute: function() { | |
| console.warn("initiateQueue execute",this.attempts); | |
| this.attempts++; | |
| this.service.send(this, false, "initiateQueue", null, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| }, | |
| serviceSuccess: function(result,arg2) { | |
| console.log('serviceSuccess','initiateQueue',result,arg2,this); | |
| if (result) { | |
| this.queue.queueID = result; | |
| this.dispatchEvent(new FlashEvent(FlashEvent.COMPLETE)); | |
| } else { | |
| console.error("No id returned."); | |
| } | |
| }, | |
| serviceFault: function(arg1,arg2) { | |
| console.log('serviceFault','initiateQueue',arg1,arg2); | |
| } | |
| }); | |
| var GetArtistsForTagAutoplay = QueueCommand.extend({ | |
| init: function(service, queue, tag, userInitiated) { | |
| this._super(service, queue); | |
| this.tag = tag; | |
| this.userInitiated = userInitiated; | |
| }, | |
| execute: function() { | |
| if (!this.tag || !this.tag.tagID){ | |
| this.onFail("No tagID provided.", false); | |
| return; | |
| }; | |
| this.attempts++; | |
| this.service.send(this, false, "getArtistsForTagRadio", {tagID:this.tag.tagID}, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| }, | |
| reexecute: function(event) { | |
| this.execute(); | |
| }, | |
| serviceSuccess: function(result) { | |
| if (result && result.length){ | |
| _local4 = []; | |
| for (i in result) { | |
| _local6 = parseInt(result[i].ArtistID); | |
| if (_local6){ | |
| _local4.push(_local6); | |
| } | |
| } | |
| if (!this.queue.gs_queue.autoplayStatus){ | |
| this.queue.gs_queue.autoplayStatus = new AutoplayStatus(this.queue); | |
| } | |
| this.queue.gs_queue.autoplayStatus.addTagArtistSeeds(_local4); | |
| this.queue.currentAutoplayTag = this.tag; | |
| if (this.queue.autoplayEnabled){ | |
| this.queue.resetPendingAutoplaySuggestion(true); | |
| } else { | |
| this.queue.setAutoplayEnabled(true, this.userInitiated); | |
| } | |
| this.dispatchEvent(new FlashEvent(FlashEvent.COMPLETE)); | |
| } else { | |
| this.onFail("No artists returned."); | |
| } | |
| }, | |
| serviceFault: function(fault) { | |
| this.onFail(fault.message); | |
| }, | |
| onFail: function(message, _arg2) { | |
| if (_arg2 == undefined) { _arg2 = true; } | |
| if (_arg2 && this.attempts < 3){ | |
| console.log("[GetArtistsForTagAutoplay] Failed: " + message + " Will re-attempt."); | |
| _local3 = (100 + Math.floor((Math.random() * 400))); | |
| _local4 = new Timer(_local3, 1); | |
| _local4.addEventListener(TimerEvent.TIMER_COMPLETE, this.reexecute, this); | |
| _local4.start(); | |
| } else { | |
| console.log("[GetArtistsForTagAutoplay] Failed: " + message + " Giving up."); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| } | |
| } | |
| }); | |
| var VerifyAutoplay = QueueCommand.extend({ | |
| init: function(service, queue, playOnSuccess) { | |
| this._super(service, queue); | |
| this.userInitiated = queue.gs_queue.autoplayUserInitiated; | |
| if (!queue.gs_queue.autoplayStatus){ | |
| queue.gs_queue.autoplayStatus = new AutoplayStatus(queue); | |
| }; | |
| this.status = queue.gs_queue.autoplayStatus.statusForRPC; | |
| this.playOnSuccess = playOnSuccess; | |
| }, | |
| reexecute: function(event) { | |
| this.execute(); | |
| }, | |
| execute: function() { | |
| if (!this.queue || !this.queue.queueID){ | |
| this.onFail(QueueEvent.QUEUE_NOT_READY, false); | |
| return; | |
| }; | |
| if (this.status.seedArtists.length == 0){ | |
| this.onFail(QueueEvent.NO_SEEDS, false); | |
| return; | |
| }; | |
| if (this.queue.gs_queue.consecutiveFailedAutoplayRequests >= 3 && (this.getTimer() - this.queue.gs_queue.lastFailedAutoplayRequest) < 5000){ | |
| this.onFail(QueueEvent.TOO_MANY_FAILURES, false); | |
| return; | |
| }; | |
| var _local1 = ObjectUtil.copy(this.status); | |
| _local1.songQueueID = this.queue.queueID; | |
| _local1.country = this.service.country; | |
| this.attempts++; | |
| this.service.send(this, false, "autoplayGetSong", _local1, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| }, | |
| makeSongFromRaw: function(song) { | |
| var _local2 = new BaseSong(); | |
| _local2.songID = song.SongID; | |
| _local2.songName = song.SongName; | |
| _local2.artistID = song.ArtistID; | |
| _local2.artistName = song.ArtistName; | |
| _local2.albumID = song.AlbumID; | |
| _local2.albumName = song.AlbumName; | |
| _local2.estimateDuration = (parseInt(song.EstimateDuration) * 1000); | |
| if (song.CoverArtUrl){ | |
| var _local3 = []; | |
| _local3 = String(song.CoverArtUrl).split("/"); | |
| if (_local3.length){ | |
| _local2.artFilename = String(_local3[(_local3.length - 1)]).substring(1); | |
| }; | |
| }; | |
| return (_local2); | |
| }, | |
| onFail: function(type, retry) { | |
| if (retry && this.attempts < 3){ | |
| console.error("[VerifyAutoplay] Failed: " + type + " Will re-attempt."); | |
| _local3 = (100 + Math.floor((Math.random() * 400))); | |
| _local4 = new Timer(_local3, 1); | |
| _local4.addEventListener(TimerEvent.TIMER_COMPLETE, this.reexecute, this); | |
| _local4.start(); | |
| } else { | |
| console.error("[VerifyAutoplay] Failed: " + type + " Giving up."); | |
| switch (type){ | |
| case QueueEvent.TOO_MANY_FAILURES: | |
| this.queue.dispatchEvent(new QueueEvent(QueueEvent.AUTOPLAY_FAILED, type, true)); | |
| this.queue.setAutoplayEnabled(false, false); | |
| break; | |
| case "tokenFailure": | |
| case "maintenanceMode": | |
| this.queue.gs_queue.consecutiveFailedAutoplayRequests++; | |
| this.queue.gs_queue.lastFailedAutoplayRequest = getTimer(); | |
| break; | |
| default: | |
| this.queue.gs_queue.consecutiveFailedAutoplayRequests++; | |
| this.queue.gs_queue.lastFailedAutoplayRequest = getTimer(); | |
| this.queue.dispatchEvent(new QueueEvent(QueueEvent.AUTOPLAY_FAILED, type, this.userInitiated)); | |
| }; | |
| this.queue.gs_queue._autoplayEnabled = false; | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| } | |
| }, | |
| serviceSuccess: function(result, _arg2) { | |
| this.queue.gs_queue.consecutiveFailedAutoplayRequests = 0; | |
| if (!result){ | |
| this.onFail(QueueEvent.UNKNOWN_ERROR); | |
| return; | |
| }; | |
| var baseSong = this.makeSongFromRaw(result); | |
| var queueSong = new QueueSong(baseSong, this.queue, this.service); | |
| queueSong.source = result.source; | |
| queueSong.sponsoredAutoplayID = parseInt(result.SponsoredAutoplayID); | |
| var _local6 = StringUtils.condenseTitle(queueSong.song.songName); | |
| if (this.queue.gs_queue.autoplayStatus && this.queue.gs_queue.autoplayStatus.badTitles.indexOf(_local6) != -1 && this.attempts < 3){ | |
| this.status.songIDsAlreadySeen.push(queueSong.song.songID); | |
| this.onFail("Title Match"); | |
| return; | |
| }; | |
| var _local7 = false; | |
| if (this.playOnSuccess && this.queue.activeSong){ | |
| switch (this.queue.activeSong.playStatus){ | |
| case PlayableSong.PLAY_STATUS_NONE: | |
| case PlayableSong.PLAY_STATUS_FAILED: | |
| case PlayableSong.PLAY_STATUS_COMPLETED: | |
| _local7 = true; | |
| break; | |
| }; | |
| }; | |
| if (!this.userInitiated){ | |
| _local7 = false; | |
| }; | |
| if (_local7 && this.queue.activeSong && this.queue.activeSong.playStatus == PlayableSong.PLAY_STATUS_NONE){ | |
| this.queue.addItemsAt([queueSong], this.queue.length, false); | |
| this.queue.playSong(queue.activeSong); | |
| } else { | |
| this.queue.addItemsAt([queueSong], -1, _local7); | |
| }; | |
| this.dispatchEvent(new FlashEvent(FlashEvent.COMPLETE)); | |
| }, | |
| serviceFault: function(fault) { | |
| switch (fault.code){ | |
| case 0x0800: | |
| _local4 = QueueEvent.NO_RECOMMENDATIONS; | |
| break; | |
| case 0x0200: | |
| _local4 = QueueEvent.RATE_LIMIT_EXCEEDED; | |
| break; | |
| case -256: | |
| _local4 = "tokenFailure"; | |
| break; | |
| case 10: | |
| _local4 = "maintenanceMode"; | |
| break; | |
| default: | |
| _local4 = QueueEvent.UNKNOWN_ERROR; | |
| }; | |
| this.onFail(_local4, (_local4 == QueueEvent.UNKNOWN_ERROR)); | |
| } | |
| }); | |
| var TurnOffAutoplay = QueueCommand.extend({ | |
| init: function(service, queue) { | |
| this._super(service,queue); | |
| this.userInitiated = queue.gs_queue.autoplayUserInitiated; | |
| }, | |
| execute: function() { | |
| this.queue.gs_queue.autoplayStatus = null; | |
| this.queue.currentAutoplayTag = null; | |
| if (this.userInitiated){ | |
| this.queue.autoAutoplayDisabled = true; | |
| }; | |
| var _local1 = []; | |
| for (i in this.queue.source) { | |
| if (this.queue.source[i].eligibleForAutoplayRemoval){ | |
| _local1.push(this.queue.source[i]); | |
| }; | |
| }; | |
| if (_local1.length){ | |
| this.queue.removeItems(_local1, false); | |
| }; | |
| this.dispatchEvent(new FlashEvent(FlashEvent.COMPLETE)); | |
| } | |
| }); | |
| var RemoveSongsFromQueue = QueueCommand.extend({ | |
| init: function(service, queue, songs, userRemoved) { | |
| this.removeWithoutReport = []; | |
| this._super(service, queue); | |
| this.songs = songs; | |
| this.userRemoved = userRemoved; | |
| }, | |
| buildParams: function() { | |
| var songQueueSongIDs = []; | |
| for (i in this.songs) { | |
| if (this.songs[i].queueSongId) { | |
| if (this.songs[i].autoplayVote == QueueSong.AUTOPLAY_VOTE_DOWN){ | |
| this.removeWithoutReport.push(this.songs[i]); | |
| } else { | |
| songQueueSongIDs.push(this.songs[i].queueSongID); | |
| }; | |
| } | |
| } | |
| this.params = { | |
| songQueueSongIDs: songQueueSongIDs, | |
| songQueueID: this.queue.queueID, | |
| userRemoved: this.userRemoved | |
| }; | |
| }, | |
| execute: function() { | |
| if (!this.queue.queueID){ | |
| this.queue.gs_queue.completeRemoveSongs(this.songs); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| return; | |
| }; | |
| if (!this.params){ | |
| this.buildParams(); | |
| }; | |
| if (!this.params.songQueueSongIDs.length){ | |
| if (this.removeWithoutReport.length){ | |
| this.queue.gs_queue.completeRemoveSongs(this.removeWithoutReport); | |
| }; | |
| this.dispatchEvent(new FlashEvent(FlashEvent.COMPLETE)); | |
| return; | |
| }; | |
| this.service.send(this, false, "removeSongsFromQueue", this.params, new ItemResponder(this.serviceSuccess, this.serviceFault)); | |
| this.queue.gs_queue.completeRemoveSongs(songs); | |
| } | |
| }); | |
| var AddSongsToQueue = QueueCommand.extend({ | |
| init: function (service, queue, items, index, playOnAdd, autoplayOnAdd) { | |
| this._super(service, queue); | |
| this.ignoreInitFail = false; | |
| this.relativeSong = null; | |
| //this.processTimer = new Timer(); | |
| this.idsToFetch = []; | |
| this.queueSongs = null; | |
| this.items = items; | |
| this.index = index; | |
| this.playOnAdd = playOnAdd; | |
| this.autoplayOnAdd = autoplayOnAdd; | |
| this.queue.gs_queue.pendingAdds++; | |
| }, | |
| buildQueueSongsArray: function() { | |
| this.queueSongs = new Array(this.items.length); | |
| badSongs = []; | |
| for (i=0;i<this.items.length;i++) { | |
| item = this.items[i]; | |
| if (item instanceof QueueSong) { | |
| if (item.queueSongID != 0){ | |
| this.queueSongs[i] = new QueueSong(item.song, this.queue, this.service); | |
| } else { | |
| this.queueSongs[i] = item; | |
| } | |
| } else if (item instanceof BaseSong) { | |
| this.queueSongs[i] = new QueueSong(item, this.queue, this.service); | |
| } else if (parseInt(item)) { | |
| song = this.idToSong(parseInt(item)); | |
| if (song) { | |
| this.queueSongs[i] = new QueueSong(song, this.queue, this.service); | |
| } else { | |
| this.idsToFetch.push(parseInt(item)); | |
| } | |
| } else { | |
| badSongs.push(i); | |
| } | |
| } | |
| if (badSongs.length) { | |
| for (i=0;i<badSongs.length;i++) { | |
| this.queueSongs.splice(badSongs[i] + i, 1); | |
| } | |
| } | |
| if (this.idsToFetch.length){ | |
| this.fetchMissingIDs(); | |
| } else { | |
| this.execute(); | |
| } | |
| }, | |
| fetchMissingIDs: function() { | |
| this.service.send(this, false, "getQueueSongListFromSongIDs", {songIDs:this.idsToFetch}, new ItemResponder(this.onSongCreateComplete, this.onSongCreateFailed)); | |
| }, | |
| onSongCreateComplete: function(result, something) { | |
| console.log('onSongCreateComplete',result,something); | |
| songs = {} | |
| for (i in result) { | |
| song = new BaseSong(); | |
| song.songID = parseInt(result[i].SongID); | |
| song.songName = String(result[i].Name); | |
| song.artistID = parseInt(result[i].ArtistID); | |
| song.artistName = String(result[i].ArtistName); | |
| song.albumID = parseInt(result[i].AlbumID); | |
| song.albumName = String(result[i].AlbumName); | |
| if (result[i].CoverArtFilename){ | |
| song.artFilename = String(result[i].CoverArtFilename); | |
| } | |
| if (parseInt(result[i].EstimateDuration)){ | |
| song.estimateDuration = (parseInt(result[i].EstimateDuration) * 1000); | |
| } | |
| songs[song.songID] = song; | |
| } | |
| _local6 = 0; | |
| _local7 = []; | |
| for (i=0;i<this.queueSongs.length;i++) { | |
| if (!this.queueSongs[i]){ | |
| song = songs[this.idsToFetch[_local6]]; | |
| if (song) { | |
| this.queueSongs[i] = new QueueSong(song, this.queue, this.service); | |
| } else { | |
| _local7.push(i); | |
| } | |
| _local6++; | |
| } | |
| } | |
| if (_local7.length){ | |
| for (i=0;i<local7.length;i++) { | |
| this.queueSongs.splice(_local7[i] + i, 1); | |
| } | |
| } | |
| this.execute(); | |
| }, | |
| onSongCreateFailed: function(result, something) { | |
| console.log('onSongCreateFailed',result,something); | |
| this.queue.dispatchEvent(new QueueEvent(QueueEvent.ERROR_ADDING_SONGS, QueueEvent.FAILED_TO_CREATE_SONGS, true, {songs:this.items})); | |
| this.queue.gs_queue.pendingAdds--; | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| }, | |
| idToSong: function() { return null; }, | |
| buildParams: function(songs) { | |
| _local2 = []; | |
| for (i in songs) { | |
| songs[i].queueSongID = this.queue.gs_queue.songCount; | |
| this.queue.gs_queue.songCount++; | |
| _local5 = {}; | |
| _local5.songID = songs[i].song.songID; | |
| _local5.artistID = songs[i].song.artistID; | |
| _local5.songQueueSongID = songs[i].queueSongID; | |
| _local5.source = songs[i].source || "user"; | |
| _local2.push(_local5); | |
| }; | |
| _local4 = {}; | |
| _local4.songIDsArtistIDs = _local2; | |
| _local4.songQueueID = this.queue.queueID; | |
| return _local4; | |
| }, | |
| processSongs: function() { | |
| console.log("[AddSongsToQueue] processSongs: songs left " + this.queueSongs.length); | |
| if (!this.queueSongs.length){ | |
| this.processTimer.stop(); | |
| this.processTimer.removeEventListener(TimerEvent.TIMER, this.processSongs); | |
| this.queue.gs_queue.pendingAdds--; | |
| this.dispatchEvent(new FlashEvent(FlashEvent.COMPLETE)); | |
| return; | |
| } | |
| songsChunk = this.queueSongs.splice(0, this.queue.gs_queue.chunkSize); | |
| params = this.buildParams(songsChunk); | |
| this.service.send(this, false, "addSongsToQueue", params); | |
| if (this.relativeSong){ | |
| index = this.queue.gs_queue.INDEX_RELATIVE; | |
| this.playOnAdd = false; | |
| this.autoplayOnAdd = false; | |
| } | |
| console.log("Sent " + songsChunk.length + " items, queue chunk size is: " + this.queue.gs_queue.chunkSize); | |
| this.queue.gs_queue.completeAddSongsAt(songsChunk, this.index, this.playOnAdd, this.autoplayOnAdd, this.relativeSong); | |
| this.relativeSong = songsChunk[(songsChunk.length - 1)]; | |
| }, | |
| execute: function() { | |
| console.warn("addSongsToQueue execute"); | |
| if (!this.items || !this.items.length) { | |
| console.error("tried to add empty array to queue"); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| return; | |
| } | |
| if (!this.queue.queueID && !this.ignoreInitFail) { | |
| _local1 = new InitiateQueue(service, queue); | |
| _local1.addEventListener(FlashEvent.COMPLETE, this.reexecute, this); | |
| _local1.addEventListener("failed", this.onInitQueueFail, this); | |
| _local1.execute(); | |
| return; | |
| } | |
| if (!this.queueSongs){ | |
| this.buildQueueSongsArray(); | |
| return; | |
| } | |
| if (!this.queueSongs.length){ | |
| console.error("tried to add empty array to queue"); | |
| this.dispatchEvent(new FlashEvent("failed")); | |
| return; | |
| }; | |
| console.log("[AddSongsToQueue] execute: " + this.queueSongs.length + " songs total"); | |
| this.processTimer = new Timer(50); | |
| this.processTimer.addEventListener(TimerEvent.TIMER, this.processSongs, this); | |
| this.processTimer.start(); | |
| }, | |
| onInitQueueFail: function(event) { | |
| this.ignoreInitFail = true; | |
| this.execute(); | |
| }, | |
| reexecute: function(event) { | |
| this.execute(); | |
| } | |
| }); | |
| var JSAddSongsToQueue = AddSongsToQueue.extend({ | |
| init: function(service, queue, items, index, playOnAdd, autoplayOnAdd){ | |
| this._super(service, queue, items, index, playOnAdd, autoplayOnAdd); | |
| } | |
| }); | |
| var CommandQueue = jQuery.Class.extend({ | |
| init: function () { | |
| this.queue = []; | |
| this.currentCommand = null; | |
| this.Event = {}; | |
| }, | |
| queueCommand: function (command) { | |
| if (!this.currentCommand){ | |
| console.log('commandQueue',command,'execing'); | |
| this.currentCommand = command; | |
| this.currentCommand.addEventListener(FlashEvent.COMPLETE, this.onCommandComplete, this); | |
| this.currentCommand.addEventListener("failed", this.onCommandComplete, this); | |
| this.currentCommand.execute(); | |
| } else { | |
| console.log('commandQueue',command,'queued as',this.currentCommand,'is running'); | |
| this.queue.push(command); | |
| }; | |
| }, | |
| onCommandComplete: function (event) { | |
| _local2 = event.currentTarget; | |
| console.log('onCommandComplete',this); | |
| _local2.removeEventListener(FlashEvent.COMPLETE, this.onCommandComplete); | |
| _local2.removeEventListener("failed", this.onCommandComplete); | |
| if (_local2 != this.currentCommand) { | |
| if (this.currentCommand.hasEventListener(FlashEvent.COMPLETE)){ | |
| this.currentCommand.removeEventListener(FlashEvent.COMPLETE, this.onCommandComplete); | |
| } | |
| if (this.currentCommand.hasEventListener("failed")){ | |
| this.currentCommand.removeEventListener("failed", this.onCommandComplete); | |
| } | |
| _local3 = this.queue.indexOf(_local2);this.dispatchEvent(new FlashEvent(FlashEvent.COMPLETE)); | |
| if (_local3 != -1){ | |
| this.queue.splice(_local3, 1); | |
| } | |
| } | |
| if (this.queue.length) { | |
| this.currentCommand = this.queue.shift(); | |
| this.currentCommand.addEventListener(FlashEvent.COMPLETE, this.onCommandComplete, this); | |
| this.currentCommand.addEventListener("failed", this.onCommandComplete, this); | |
| this.currentCommand.execute(); | |
| } else { | |
| this.currentCommand = null; | |
| } | |
| } | |
| }); | |
| var QueueEvent = jQuery.Class.extend({ | |
| init: function(arg1, detail, notifiyUser, extra, arg5, arg6) { | |
| this.UNKNOWN_STOPPING = "unknownStopping"; | |
| this.PLAYBACK_ERROR = "playbackError"; | |
| this.FAILED_TO_CREATE_ARTIST_SONGS = "failedToCreateArtistSongs"; | |
| this.NO_SEEDS = "noSeeds"; | |
| this.UNKNOWN_HAS_NEXT = "unknownHasNext"; | |
| this.SONG_FLAGGED = "songFlagged"; | |
| this.UNKNOWN_ERROR = "unknownError"; | |
| this.FAILED_TO_CREATE_SONGS = "failedToCreateSongs"; | |
| this.AUTOPLAY_FAILED = "autoplayFailed"; | |
| this.QUEUE_NOT_READY = "queueNotReady"; | |
| this.FAILED_TO_CREATE_ALBUM_SONGS = "failedToCreateAlbumSongs"; | |
| this.AUTOPLAY_VOTE_ERROR = "autoplayVoteError"; | |
| this.TOO_MANY_SONGS = "tooManySongs"; | |
| this.RATE_LIMIT_EXCEEDED = "rateLimitExceeded"; | |
| this.ERROR_ADDING_SONGS = "errorAddingSongs"; | |
| this.NO_RECOMMENDATIONS = "noRecommendations"; | |
| this.TOO_MANY_FAILURES = "tooManyFailures"; | |
| //this._super(arg1, arg5, arg6); | |
| this.detail = detail; | |
| this.notifiyUser = notifiyUser; | |
| this.extra = extra; | |
| } | |
| }); | |
| var ListCollectionView = FlashProxy.extend({ | |
| init: function(list) { | |
| this.VERSION = "3.5.0.12683"; | |
| this._list = null; | |
| this._filterFunction = null; | |
| this._sort = null; | |
| this.autoUpdateCounter = null; | |
| this.localIndex = []; | |
| this.dispatchResetEvent = true; | |
| this.pendingUpdates = []; | |
| this.resourceManager = null; | |
| this.eventDispatcher = null; | |
| this.revision = null; | |
| //resourceManager = ResourceManager.getInstance(); | |
| //this._super(); | |
| //eventDispatcher = new EventDispatcher(this); | |
| this.list = list; | |
| } | |
| }); | |
| var gs_queue = null; | |
| var ListCollectionView = EventDispatcher.extend({}); | |
| var Queue = ListCollectionView.extend({ | |
| chunkSize:100, | |
| source:[], | |
| playedSongs:[], | |
| pendingSongs:[], | |
| queueSongLookupBySongID:{}, | |
| queueSongLookupByQueueSongID: {}, | |
| pendingAdds:0, | |
| maxChunks: 10, | |
| songCount: 1, | |
| INDEX_NEXT:-2, | |
| REPEAT_ONE: 2, | |
| INDEX_LAST:-3, | |
| CROSSFADE_STEPS:6, | |
| INDEX_DEFAULT: -1, | |
| INDEX_RELATIVE: -4, | |
| REPEAT_NONE: 0, | |
| REPEAT_ALL: 1, | |
| __autoplayEnabled: false, | |
| _crossfadeAmount: 5000, | |
| _crossfadeEnabled: false, | |
| _crossfadeInOutEnabled: false, | |
| _hasNextSong: false, | |
| _repeatMode: 0, | |
| __shuffleEnabled: false, | |
| _crossfadeSong: null, | |
| init: function(service, autoAutoplayDisabled, _arg3) { | |
| // Define getters and setters | |
| this.__defineGetter__("activeSong",this["get activeSong"]); | |
| this.__defineGetter__("_activeSong",this["get _activeSong"]); | |
| this.__defineSetter__("_activeSong",this["set _activeSong"]); | |
| this.__defineGetter__("__activeSong",helpers.getterFunction('__activeSong')); | |
| this.__defineSetter__("__activeSong",this["set __activeSong"]); | |
| this.__defineGetter__("adjustedActiveSongIndex",this["get adjustedActiveSongIndex"]); | |
| this.__defineGetter__("_autoplayEnabled",this["get _autoplayEnabled"]); | |
| this.__defineSetter__("_autoplayEnabled",this["set _autoplayEnabled"]); | |
| this.__defineGetter__("autoplayEnabled",helpers.getterFunction('autoplayEnabled')); | |
| this.__defineSetter__("autoplayEnabled",helpers.setterFunction('autoplayEnabled')); | |
| this.__defineGetter__("crossfadeAmount",helpers.getterFunction('crossfadeAmount')); | |
| this.__defineSetter__("crossfadeAmount",helpers.setterFunction('crossfadeAmount')); | |
| this.__defineGetter__("crossfadeEnabled",helpers.getterFunction('crossfadeEnabled')); | |
| this.__defineSetter__("crossfadeEnabled",helpers.setterFunction('crossfadeEnabled')); | |
| this.__defineGetter__("crossfadeSong",helpers.getterFunction('crossfadeSong')); | |
| this.__defineSetter__("crossfadeSong",helpers.setterFunction('crossfadeSong')); | |
| this.__defineGetter__("crossfadeInOutEnabled",helpers.getterFunction('crossfadeInOutEnabled')); | |
| this.__defineSetter__("crossfadeInOutEnabled",helpers.setterFunction('crossfadeInOutEnabled')); | |
| this.__defineGetter__("hasNextSong",helpers.getterFunction('hasNextSong')); | |
| this.__defineSetter__("hasNextSong",helpers.setterFunction('hasNextSong')); | |
| this.__defineGetter__("length",this["get length"]); | |
| this.__defineGetter__("repeatMode",helpers.getterFunction('repeatMode')); | |
| this.__defineSetter__("repeatMode",helpers.setterFunction('repeatMode')); | |
| this.__defineGetter__("_shuffleEnabled",this["get _shuffleEnabled"]); | |
| this.__defineSetter__("_shuffleEnabled",this["set _shuffleEnabled"]); | |
| this.__defineGetter__("shuffleEnabled",helpers.getterFunction('shuffleEnabled')); | |
| this.__defineSetter__("shuffleEnabled",helpers.setterFunction('shuffleEnabled')); | |
| if (_arg3 == undefined) { _arg3 = true; } | |
| if (!gs_queue) { gs_queue = this; } | |
| this.gs_queue = gs_queue; | |
| this.commandQueue = new CommandQueue(); | |
| this.prefetchedSongs = []; | |
| this.service = service; | |
| this.autoAutoplayDisabled = (autoAutoplayDisabled) ? autoAutoplayDisabled : false; | |
| if (_arg3){ | |
| initiateQueue = new InitiateQueue(service, this); | |
| this.commandQueue.queueCommand(initiateQueue); | |
| }; | |
| this.crossfadeSongStopTimer = new Timer(((1 / this.CROSSFADE_STEPS) * 1000), ((this.CROSSFADE_STEPS * this.crossfadeAmount) / 1000)); | |
| }, | |
| "get _autoplayEnabled": function() { | |
| return this.__autoplayEnabled; | |
| }, | |
| "set _autoplayEnabled": function(newValue) { | |
| var oldValue = this.gs_queue._autoplayEnabled; | |
| if (oldValue !== newValue){ | |
| this.gs_queue.__autoplayEnabled = newValue; | |
| this.dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, "gs_queue::_autoplayEnabled", oldValue, newValue)); | |
| }; | |
| }, | |
| "get activeSong": function() { | |
| return this.__activeSong; | |
| }, | |
| "get _activeSong": function() { | |
| return this.__activeSong; | |
| }, | |
| "set _activeSong": function(song) { | |
| console.log('set _activeSong',song,this.gs_queue._activeSong,this.gs_queue.__activeSong,Boolean(this.gs_queue._activeSong !== song)); | |
| var oldValue = this.gs_queue.__activeSong; | |
| if (this.gs_queue.__activeSong !== song) { | |
| this.gs_queue.__activeSong = song; | |
| this.dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, "gs_queue::_activeSong", oldValue, song)); | |
| } | |
| }, | |
| "set __activeSong": function(_arg1) { | |
| if (_arg1 != this.___activeSong){ | |
| _local2 = this.___activeSong; | |
| if (this.___activeSong && this.___activeSong !== this.crossfadeSong){ | |
| this.___activeSong.stop(); | |
| this.removeEventListeners(this.___activeSong); | |
| }; | |
| this.___activeSong = _arg1; | |
| if (this.___activeSong){ | |
| //___activeSong.setFadeOptions(this.crossfadeInOutEnabled); | |
| this.___activeSong.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onSongPropChange, this); | |
| this.___activeSong.addEventListener(PlayableSongEvent.COMPLETE, this.onSongComplete, this); | |
| this.___activeSong.addEventListener(PlayableSongEvent.ERROR, this.onSongError, this); | |
| this.___activeSong.addEventListener(PlayableSongEvent.PLAYBACK_BEGUN, this.onSongPlayback, this); | |
| } else { | |
| if (this._crossfadeSong && this._crossfadeSong.playStatus == PlayableSong.PLAY_STATUS_PLAYING && !this.crossfadeSongStopTimer.running) { | |
| this.startCrossfade(); | |
| }; | |
| }; | |
| while (this.prefetchedSongs.length) { | |
| _local3 = this.prefetchedSongs.shift(); | |
| if (_local3 !== this.___activeSong && _local3 !== this.crossfadeSong){ | |
| _local3.stop(); | |
| } | |
| } | |
| this.recalcHasNextPrev(); | |
| this.dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, "activeSong", _local2, _arg1)); | |
| }; | |
| }, | |
| "get adjustedActiveSongIndex": function() { | |
| if (!this.gs_queue._activeSong){ | |
| return (-1); | |
| }; | |
| if (this._shuffleEnabled){ | |
| _local1 = this.gs_queue.playedSongs.indexOf(this.gs_queue._activeSong); | |
| return (((_local1)!=-1) ? _local1 : 0); | |
| }; | |
| return this.gs_queue.source.indexOf(this.gs_queue._activeSong); | |
| }, | |
| "get length": function() { | |
| return this.gs_queue.source.length; | |
| }, | |
| "get _shuffleEnabled": function() { | |
| return this.__shuffleEnabled; | |
| }, | |
| "set _shuffleEnabled": function(newValue) { | |
| if (newValue != this.__shuffleEnabled){ | |
| this.__shuffleEnabled = newValue; | |
| if (this.length || !newValue){ | |
| this.setupShuffle(newValue); | |
| } else { | |
| this.setupShuffle(false); | |
| }; | |
| }; | |
| }, | |
| removeEventListeners: function(song) { | |
| song.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onSongPropChange); | |
| song.removeEventListener(PlayableSongEvent.COMPLETE, this.onSongComplete); | |
| song.removeEventListener(PlayableSongEvent.ERROR, this.onSongError); | |
| song.removeEventListener(PlayableSongEvent.PLAYBACK_BEGUN, this.onSongPlayback); | |
| }, | |
| seekInCurrentSong: function(_arg1) { | |
| if (this.gs_queue._activeSong){ | |
| this.gs_queue._activeSong.seekTo(_arg1); | |
| }; | |
| }, | |
| completeAddSongsAt: function(_arg1, _arg2, _arg3, _arg4, _arg5) { | |
| console.log('completeAddSongsAt',_arg1,_arg2,_arg3,_arg4,_arg5); | |
| if (!_arg1.length){ | |
| return; | |
| } | |
| _local6 = Boolean(this._shuffleEnabled && this.length == 0); | |
| _local7 = Boolean(_arg1[0].source == "user"); | |
| if (_arg2 >= 0){ | |
| _local10 = "index"; | |
| } else if (_local7 && _arg2 == this.gs_queue.INDEX_RELATIVE && _arg5 && this.contains(_arg5)) { | |
| _local10 = "relative"; | |
| } else if ((_local7 && this.gs_queue._activeSong) && (_arg2 == Queue.INDEX_NEXT || (_arg2 == Queue.INDEX_DEFAULT && _arg3))) { | |
| _local10 = "next"; | |
| } else { | |
| _local10 = "last"; | |
| } | |
| switch (_local10){ | |
| case "index": | |
| _local11 = _arg2; | |
| break; | |
| case "relative": | |
| _local11 = (this.gs_queue.source.indexOf(_arg5) + 1); | |
| break; | |
| case "next": | |
| if (this.gs_queue._activeSong.playStatus == PlayableSong.PLAY_STATUS_NONE && !this.gs_queue._activeSong.lastStreamKey){ | |
| _local11 = this.gs_queue.source.indexOf(this.gs_queue._activeSong); | |
| } else { | |
| _local11 = (this.gs_queue.source.indexOf(this.gs_queue._activeSong) + 1); | |
| } | |
| break; | |
| case "last": | |
| default: | |
| if (_local7){ | |
| _local11 = this.lengthAdjustedForAutoplay; | |
| } else { | |
| _local11 = this.length; | |
| } | |
| } | |
| this.gs_queue.source = this.insertItemsAtIndex(this.gs_queue.source, _arg1, _local11); | |
| if (this._shuffleEnabled) { | |
| if (_local6){ | |
| this.setupShuffle(true); | |
| } else { | |
| _local12 = -1; | |
| if (_local10 == "relative") { | |
| _local12 = this.gs_queue.playedSongs.indexOf(_arg5); | |
| } else if (_local10 == "next"){ | |
| _local12 = this.adjustedActiveSongIndex; | |
| } | |
| if (_local12 == -1){ | |
| for (i in _arg1) { | |
| this.gs_queue.pendingSongs.push(_arg1[i]); | |
| } | |
| } else { | |
| this.gs_queue.playedSongs = this.insertItemsAtIndex(this.gs_queue.playedSongs, this.randomizeArray(_arg1), (_local12 + 1)); | |
| } | |
| } | |
| } | |
| var _local8 = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE); | |
| _local8.kind = CollectionEventKind.ADD; | |
| _local8.location = _local11; | |
| _local8.items = _arg1; | |
| this.dispatchEvent(_local8); | |
| for (i in _arg1) { | |
| _arg1[i].addEventListener(PlayableSongEvent.SONG_FLAGGED, this.onSongFlagged, this); | |
| _arg1[i].addEventListener(PlayableSongEvent.SONG_VOTE_FAILED, this.onSongVoteFailed, this); | |
| _local14 = this.gs_queue.queueSongLookupBySongID[_arg1[i].song.songID]; | |
| if (_local14){ | |
| _local14.push(_arg1[i]); | |
| } else { | |
| this.gs_queue.queueSongLookupBySongID[_arg1[i].song.songID] = [_arg1[i]]; | |
| } | |
| this.gs_queue.queueSongLookupByQueueSongID[_arg1[i].queueSongID] = _arg1[i]; | |
| _local15 = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE); | |
| _local15.property = _local11; | |
| _local15.newValue = _arg1[i]; | |
| this.dispatchEvent(_local15); | |
| _local11++; | |
| } | |
| if (_arg3){ | |
| if (this._shuffleEnabled && _arg1.length > 1){ | |
| _local16 = Math.floor((Math.random() * _arg1.length)); | |
| this.playSong(_arg1[_local16], false, this.crossfadeEnabled); | |
| } else { | |
| this.playSong(_arg1[0], false, this.crossfadeEnabled); | |
| } | |
| } else { | |
| if (!this.gs_queue._activeSong){ | |
| this.gs_queue._activeSong = _arg1[0]; | |
| } | |
| } | |
| this.recalcHasNextPrev(); | |
| if (this.gs_queue.autoplayStatus) { | |
| this.gs_queue.autoplayStatus.songsAddedToQueue(_arg1); | |
| } | |
| if (this.autoplayEnabled && _arg1[0].source == "user"){ | |
| _local17 = this.gs_queue.source[(this.gs_queue.source.length - 1)]; | |
| if (_local17 && _local17.eligibleForAutoplayRemoval){ | |
| this.generateRefreshPendingAutoplaySong(_local17); | |
| } | |
| } else if (!this.autoAutoplayDisabled || _arg4){ | |
| this.setAutoplayEnabled(true, _arg4); | |
| } | |
| }, | |
| moveItemsTo: function(songs, index) { | |
| songs = this.properlyOrderSongs(songs); | |
| for (i in songs) { | |
| var songIndex = gs_queue.source.indexOf(songs[i]); | |
| if (songIndex != -1 && songIndex != index) { | |
| var _local6 = gs_queue.source.slice(0, index).concat(songs[i]).concat(gs_queue.source.slice(index)); | |
| if (songIndex < index) { | |
| _local6.splice(_local6.indexOf(songs[i]), 1); | |
| } else { | |
| _local6.splice(_local6.lastIndexOf(songs[i]), 1); | |
| } | |
| gs_queue.source = _local6; | |
| _local7 = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE); | |
| _local7.kind = CollectionEventKind.MOVE; | |
| _local7.location = gs_queue.source.indexOf(song[i]); | |
| _local7.oldLocation = songIndex; | |
| this.dispatchEvent(_local7); | |
| } | |
| } | |
| this.recalcHasNextPrev(); | |
| }, | |
| removeItem: function(_arg1, _arg2) { | |
| this.removeItems([_arg1], _arg2); | |
| }, | |
| removeItems: function(songs, _arg2) { | |
| while (songs.length > 0) { | |
| chunk = songs.splice(0, 100); | |
| this.generateRemoveSongsFromQueue(chunk, _arg2); | |
| }; | |
| }, | |
| properlyOrderSongs: function(songs) { | |
| var orderedSongs = []; | |
| for (i in this.source) { | |
| if (songs.indexOf(this.source[i]) != -1){ | |
| orderedSongs.push(this.source[i]); | |
| } | |
| } | |
| return orderedSongs; | |
| }, | |
| recalcHasNextPrev: function() { | |
| if (!this.length){ | |
| this.hasNextSong = (this.hasPreviousSong = false); | |
| return; | |
| } | |
| var _local1 = this.adjustedActiveSongIndex; | |
| this.hasPreviousSong = (this.repeatMode == Queue.REPEAT_ALL || _local1 >= 1); | |
| this.hasNextSong = (this.repeatMode == Queue.REPEAT_ALL || (_local1 != -1 && (_local1 < (this.length - 1)))); | |
| this.determinePreviousSong(); | |
| this.determineNextSong(); | |
| this.checkForNeededAutoplay(); | |
| }, | |
| checkForNeededAutoplay: function() { | |
| if (!this.autoplayEnabled){ | |
| return; | |
| }; | |
| if (!this.hasNextSong){ | |
| this.generateGetAutoplaySong(); | |
| }; | |
| }, | |
| generateRemoveSongsFromQueue: function(_arg1, _arg2) { | |
| this.gs_queue.commandQueue.queueCommand(new RemoveSongsFromQueue(this.service, this, _arg1, _arg2)); | |
| }, | |
| generateGetAutoplaySong: function() { | |
| console.warn('generateGetAutoplaySong unimplemented!'); | |
| //var _local1 = new GetAutoplaySong(this.service, this); | |
| //this.gs_queue.commandQueue.queueCommand(_local1); | |
| }, | |
| generateRefreshPendingAutoplaySong: function() { | |
| console.warn('generateRefreshPendingAutoplaySong unimplemented!'); | |
| }, | |
| getItemIndex: function(item){ | |
| return gs_queue.source.indexOf(item); | |
| }, | |
| getItemAt: function(index) { | |
| if (index < 0 || index >= this.gs_queue.source.length){ | |
| console.error("[Queue] Index " + index + " is out of bounds."); | |
| }; | |
| return this.gs_queue.source[index]; | |
| }, | |
| insertItemsAtIndex: function(_arg1, _arg2, index) { | |
| var items = []; | |
| if (index == 0){ | |
| items = _arg2.concat(_arg1); | |
| } else if (index == _arg1.length){ | |
| items = _arg1.concat(_arg2); | |
| } else { | |
| items = _arg1.slice(0, index).concat(_arg2).concat(_arg1.slice(index)); | |
| }; | |
| return items; | |
| }, | |
| contains: function(obj) { | |
| return (this.gs_queue.source.indexOf(obj) != -1); | |
| }, | |
| enableCrossfade: function(crossfadeEnabled, crossfadeAmount, crossfadeInOutEnabled) { | |
| if (crossfadeEnabled != this.crossfadeEnabled){ | |
| this.crossfadeEnabled = crossfadeEnabled; | |
| } | |
| if (crossfadeAmount != this.crossfadeAmount){ | |
| this.crossfadeAmount = crossfadeAmount || 5000; | |
| } | |
| if (crossfadeInOutEnabled != this.crossfadeInOutEnabled){ | |
| this.crossfadeInOutEnabled = crossfadeInOutEnabled || false; | |
| } | |
| }, | |
| startTagAutoplay: function(tag, _arg2) { | |
| console.log('startTagAutoplay tagID:',tag.tagID,'tagName:',tag.tagName); | |
| this.stopTagAutoplay(); | |
| this.gs_queue.commandQueue.queueCommand(new GetArtistsForTagAutoplay(this.service, this, tag, _arg2)); | |
| }, | |
| stopTagAutoplay: function() { | |
| this.currentAutoplayTag = null; | |
| if (this.autoplayEnabled){ | |
| this.gs_queue.autoplayStatus.addTagArtistSeeds([]); | |
| }; | |
| }, | |
| setAutoplayEnabled: function(_arg1, _arg2, _arg3) { | |
| if (_arg2 == undefined) { _arg2 = false; } | |
| if (_arg3 == undefined) { _arg3 = true; } | |
| if (_arg1 != this.gs_queue._autoplayEnabled){ | |
| this.gs_queue.autoplayUserInitiated = _arg2; | |
| this.gs_queue.consecutiveFailedAutoplayRequests = 0; | |
| this.gs_queue.lastFailedAutoplayRequest = 0; | |
| if (_arg1){ | |
| this.repeatMode = Queue.REPEAT_NONE; | |
| this.shuffleEnabled = false; | |
| this.gs_queue._autoplayEnabled = true; | |
| this.generateVerifyAutoplay(_arg3); | |
| } else { | |
| this.gs_queue._autoplayEnabled = false; | |
| this.generateTurnOffAutoplay(); | |
| }; | |
| }; | |
| }, | |
| setupShuffle: function(_arg1) { | |
| var _local2; | |
| var _local3; | |
| if (_arg1){ | |
| this.gs_queue.playedSongs = []; | |
| this.gs_queue.pendingSongs = this.gs_queue.source.concat(); | |
| _local2 = this.gs_queue._activeSong; | |
| if (!_local2 || _local2.playStatus == PlayableSong.PLAY_STATUS_NONE || _local2.playStatus == PlayableSong.PLAY_STATUS_COMPLETED){ | |
| _local3 = Math.floor((Math.random() * (this.gs_queue.pendingSongs.length - 1))); | |
| _local2 = this.gs_queue.pendingSongs[_local3]; | |
| }; | |
| this.gs_queue.pendingSongs.splice(this.gs_queue.pendingSongs.indexOf(_local2), 1); | |
| this.gs_queue.playedSongs.unshift(_local2); | |
| this.gs_queue._activeSong = _local2; | |
| } else { | |
| this.gs_queue.playedSongs = []; | |
| this.gs_queue.pendingSongs = []; | |
| }; | |
| this.recalcHasNextPrev(); | |
| }, | |
| generateVerifyAutoplay: function(_arg1) { | |
| if (_arg1 == undefined) { _arg1 = true; } | |
| this.gs_queue.commandQueue.queueCommand(new VerifyAutoplay(this.service, this, _arg1)); | |
| }, | |
| generateTurnOffAutoplay: function() { | |
| this.gs_queue.commandQueue.queueCommand(new TurnOffAutoplay(this.service, this)); | |
| }, | |
| playSong: function(song, _arg2, _arg3) { | |
| if (song == undefined) { song=null; } | |
| if (_arg2 == undefined) { _arg2=false; } | |
| if (_arg3 == undefined) { _arg3=true; } | |
| crossfadeEnabled = (_arg3) ? this.crossfadeEnabled : false; | |
| if (song instanceof QueueSong) { | |
| if (this.contains(song)) { | |
| if (crossfadeEnabled && this.gs_queue._activeSong && song !== this.gs_queue._activeSong && this.gs_queue._activeSong.playStatus === PlayableSong.PLAY_STATUS_PLAYING){ | |
| this.crossfadeSong = this.gs_queue._activeSong; | |
| song.soundVolume = 0; | |
| } | |
| this.gs_queue._activeSong = song; | |
| this.activeSong.play(); | |
| _local4 = true; | |
| } else { | |
| this.addItemsAt([song.song], -1, true); | |
| } | |
| } else if (song instanceof BaseSong || parseInt(song)) { | |
| songID = (song instanceof BaseSong) ? song.songID : parseInt(song); | |
| queueSongs = this.gs_queue.queueSongLookupBySongID[songID]; | |
| if (queueSongs && queueSongs.length) { | |
| queueSong = queueSongs[0]; | |
| if (this.contains(queueSong)) { | |
| if (crossfadeEnabled && this.gs_queue._activeSong && queueSong !== this.gs_queue._activeSong && this.gs_queue._activeSong.playStatus === PlayableSong.PLAY_STATUS_PLAYING){ | |
| this.crossfadeSong = this.gs_queue._activeSong; | |
| queueSong.soundVolume = 0; | |
| } | |
| this.gs_queue._activeSong = queueSong; | |
| this.activeSong.play(); | |
| _local4 = true; | |
| } else { | |
| queueSongs.shift(); | |
| if (!queueSongs.length){ | |
| delete this.gs_queue.queueSongLookupBySongID[songID]; | |
| } | |
| this.addItemsAt([queueSong.song], -1, true); | |
| } | |
| } else { | |
| this.addItemsAt([songID], -1, true); | |
| } | |
| } else if (song == null){ | |
| if (this.gs_queue._activeSong){ | |
| this.gs_queue._activeSong.play(); | |
| _local4 = true; | |
| } else if (this.length){ | |
| this.gs_queue._activeSong = this.gs_queue.source[0]; | |
| this.gs_queue._activeSong.play(); | |
| _local4 = true; | |
| } | |
| } | |
| if (_local4 && this._shuffleEnabled){ | |
| _local10 = gs_queue.playedSongs.indexOf(this.gs_queue._activeSong); | |
| _local11 = gs_queue.pendingSongs.indexOf(this.gs_queue._activeSong); | |
| _local12 = (this.adjustedActiveSongIndex + 1); | |
| if (((!(_arg2)) && (!((_local10 == -1))))){ | |
| gs_queue.playedSongs.splice(_local10, 1); | |
| if (_local10 < _local12){ | |
| _local12--; | |
| } | |
| gs_queue.playedSongs.splice(_local12, 0, this.gs_queue._activeSong); | |
| } else if (_local11 != -1){ | |
| gs_queue.pendingSongs.splice(_local11, 1); | |
| gs_queue.playedSongs.splice(_local12, 0, this.gs_queue._activeSong); | |
| } | |
| } | |
| this.recalcHasNextPrev(); | |
| }, | |
| completeRemoveSongs: function(songs) { | |
| var _local3 = false; | |
| for (i=0;i<songs.length;i++) { | |
| if (!songs[i]){ | |
| break; | |
| }; | |
| songIndex = gs_queue.source.indexOf(songs[i]); | |
| if (songIndex != -1){ | |
| gs_queue.source.splice(songIndex, 1); | |
| }; | |
| playedSongIndex = gs_queue.playedSongs.indexOf(songs[i]); | |
| if (playedSongIndex != -1){ | |
| gs_queue.playedSongs.splice(playedSongIndex, 1); | |
| } else { | |
| pendingSongIndex = gs_queue.pendingSongs.indexOf(songs[i]); | |
| if (pendingSongIndex != -1){ | |
| gs_queue.pendingSongs.splice(pendingSongIndex, 1); | |
| }; | |
| }; | |
| if (songs[i] === gs_queue._activeSong){ | |
| _local2 = songIndex; | |
| switch (songs[i].playStatus){ | |
| case PlayableSong.PLAY_STATUS_INITIALIZING: | |
| case PlayableSong.PLAY_STATUS_LOADING: | |
| case PlayableSong.PLAY_STATUS_PLAYING: | |
| case PlayableSong.PLAY_STATUS_PAUSED: | |
| case PlayableSong.PLAY_STATUS_BUFFERING: | |
| _local3 = true; | |
| break; | |
| }; | |
| }; | |
| this.removeEventListeners(songs[i]); //TODO: check | |
| _local9 = gs_queue.queueSongLookupBySongID[songs[i].song.songID]; | |
| if (_local9){ | |
| _local8 = _local9.indexOf(_local5); | |
| if (_local8 != -1){ | |
| _local9.splice(_local8, 1); | |
| }; | |
| if (!_local9.length){ | |
| delete gs_queue.queueSongLookupBySongID[songs[i].song.songID]; | |
| }; | |
| }; | |
| delete gs_queue.queueSongLookupByQueueSongID[songs[i].queueSongID]; | |
| }; | |
| if (songs.length == 1 && this.source.length){ | |
| _local10 = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE); | |
| _local10.kind = CollectionEventKind.REMOVE; | |
| _local10.location = songIndex; | |
| _local10.items = [songs[songs.length-1]]; | |
| this.dispatchEvent(_local10); | |
| _local11 = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE); | |
| _local11.property = songIndex; | |
| _local11.oldValue = songs[songs.length-1]; | |
| this.dispatchEvent(_local11); | |
| } else { | |
| _local10 = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE); | |
| _local10.kind = CollectionEventKind.RESET; | |
| this.dispatchEvent(_local10); | |
| }; | |
| if (this.source.length && _local2.toString() != "NaN"){ | |
| _local12 = false; | |
| /*if ((this.crossfadeEnabled && (this.gs_queue::_activeSong.playStatus === PlayableSong.PLAY_STATUS_PLAYING))){ | |
| this.crossfadeSong = this.gs_queue::_activeSong; | |
| };*/ | |
| if (this._shuffleEnabled){ | |
| if (_local2 < gs_queue.playedSongs.length){ | |
| gs_queue._activeSong = gs_queue.playedSongs[_local2]; | |
| } else if (gs_queue.pendingSongs.length){ | |
| _local13 = Math.floor((Math.random() * (gs_queue.pendingSongs.length - 1))); | |
| gs_queue._activeSong = gs_queue.pendingSongs.splice(_local13, 1)[0]; | |
| gs_queue.playedSongs.push(gs_queue._activeSong); | |
| } else { | |
| gs_queue._activeSong = gs_queue.playedSongs[(gs_queue.playedSongs.length - 1)]; | |
| _local12 = true; | |
| }; | |
| } else if (_local2 < this.source.length){ | |
| gs_queue._activeSong = gs_queue.source[_local2]; | |
| } else { | |
| gs_queue._activeSong = gs_queue.source[(this.source.length - 1)]; | |
| _local12 = true; | |
| }; | |
| if (_local3 && (!_local12 || (gs_queue._activeSong.playStatus == PlayableSong.PLAY_STATUS_NONE && !gs_queue._activeSong.lastStreamKey))){ | |
| this.playSong(gs_queue._activeSong); | |
| } else if (_local12){ | |
| gs_queue._activeSong = null; | |
| }; | |
| }; | |
| if (!this.source.length){ | |
| gs_queue._activeSong = null; | |
| }; | |
| this.recalcHasNextPrev(); | |
| if (gs_queue.autoplayStatus){ | |
| gs_queue.autoplayStatus.songsRemovedFromQueue(songs); | |
| }; | |
| }, | |
| onSongPropChange: function(event) { | |
| var _local2 = event.currentTarget; | |
| if (event.property == "position" && _local2 !== this._crossfadeSong){ | |
| if (Queue.prefetchEnabled && PlayableSong.consecutiveFailedStreamKeys == 0 && this.repeatMode != Queue.REPEAT_ONE && _local2.fileLoaded && _local2.position && _local2.duration && (_local2.duration - _local2.position) < 20000){ | |
| _local3 = this.determineNextSong(); | |
| if (_local3 && _local3 !== this.activeSong){ | |
| _local3.load(); | |
| this.prefetchedSongs.push(_local3); | |
| if (this.crossfadeEnabled && (_local2.duration - _local2.position) < this.crossfadeAmount){ | |
| if (_local3.playStatus != PlayableSong.PLAY_STATUS_PLAYING){ | |
| this.playNextSong(); | |
| }; | |
| }; | |
| }; | |
| }; | |
| if (((((((((this._crossfadeSong) && ((((this._crossfadeSong.playStatus === PlayableSong.PLAY_STATUS_PLAYING)) || (((this.gs_queue._activeSong) && ((this.gs_queue._activeSong.soundVolume < 1)))))))) && ((_local2 === this.gs_queue._activeSong)))) && ((_local2.position > (this.crossfadeAmount + 1000))))) && (((_local2.duration - _local2.position) > this.crossfadeAmount)))){ | |
| this.crossfadeSongStop(); | |
| if (this.gs_queue._activeSong){ | |
| this.gs_queue._activeSong.soundVolume = 1; | |
| }; | |
| }; | |
| }; | |
| }, | |
| onSongComplete: function(event) { | |
| console.log('[Queue] onSongComplete',event); | |
| if (this.repeatMode == Queue.REPEAT_ONE){ | |
| this.playSong(event.currentTarget); | |
| } else if (event.currentTarget === this._crossfadeSong){ | |
| this.removeEventListeners(this._crossfadeSong); | |
| this._crossfadeSong = null; | |
| } else if (this.hasNextSong){ | |
| if (this.crossfadeEnabled && event.code == PlayableSongEvent.COMPLETE_FORCE_FROWN_SKIP && event.currentTarget.playStatus == PlayableSong.PLAY_STATUS_COMPLETED){ | |
| this.crossfadeSong = event.currentTarget; | |
| }; | |
| this.playNextSong(); | |
| } | |
| }, | |
| playPreviousSong: function(_arg1) { | |
| var _local2 = (((this.crossfadeAmount < 5)) ? 5 : this.crossfadeAmount); | |
| if (((((!(_arg1)) && (this.gs_queue._activeSong))) && ((this.gs_queue._activeSong.position > _local2)))){ | |
| this.playSong(this.gs_queue._activeSong, true, false); | |
| return; | |
| }; | |
| if (((this.crossfadeSongStopTimer) && (this.crossfadeSongStopTimer.running))){ | |
| this.stopCrossfade(); | |
| this.crossfadeSongStop(); | |
| this.gs_queue._activeSong.soundVolume = 1; | |
| }; | |
| var _local3 = this.determinePreviousSong(); | |
| if (_local3){ | |
| this.playSong(_local3, true); | |
| }; | |
| }, | |
| playNextSong: function() { | |
| if (this.gs_queue._activeSong && this.autoplayEnabled){ | |
| switch (this.gs_queue._activeSong.playStatus){ | |
| case PlayableSong.PLAY_STATUS_INITIALIZING: | |
| case PlayableSong.PLAY_STATUS_LOADING: | |
| case PlayableSong.PLAY_STATUS_BUFFERING: | |
| case PlayableSong.PLAY_STATUS_PLAYING: | |
| _local2 = new MarkSongSkipped(this.service, this.gs_queue._activeSong); | |
| this.gs_queue.commandQueue.queueCommand(_local2); | |
| }; | |
| } | |
| var _local1 = this.determineNextSong(); | |
| if (this.crossfadeSongStopTimer && this.crossfadeSongStopTimer.running){ | |
| this.stopCrossfade(); | |
| this.crossfadeSongStop(); | |
| this.gs_queue._activeSong.soundVolume = 1; | |
| }; | |
| if (_local1){ | |
| this.playSong(_local1, true); | |
| } else if (this.autoplayEnabled){ | |
| this.generateGetAutoplaySong(); | |
| }; | |
| }, | |
| determinePreviousSong: function() { | |
| var _local1 = null; | |
| var _local2 = this.adjustedActiveSongIndex; | |
| if (_local2 <= 0){ | |
| if (this.repeatMode == Queue.REPEAT_ALL){ | |
| if (this._shuffleEnabled){ | |
| if (this.gs_queue.pendingSongs.length){ | |
| _local3 = Math.floor((Math.random() * (this.gs_queue.pendingSongs.length - 1))); | |
| _local1 = this.gs_queue.pendingSongs.splice(_local3, 1)[0]; | |
| this.gs_queue.playedSongs.unshift(_local1); | |
| } else { | |
| _local1 = this.gs_queue.playedSongs[(this.gs_queue.playedSongs.length - 1)]; | |
| }; | |
| } else { | |
| _local1 = this.gs_queue.source[(this.length - 1)]; | |
| }; | |
| }; | |
| } else if (this._shuffleEnabled) { | |
| _local1 = this.gs_queue.playedSongs[(_local2 - 1)]; | |
| } else { | |
| _local1 = this.gs_queue.source[(_local2 - 1)]; | |
| }; | |
| this.previousSong = _local1; | |
| return (_local1); | |
| }, | |
| determineNextSong: function() { | |
| var _local1 = null; | |
| var _local2 = this.adjustedActiveSongIndex; | |
| if (_local2 >= (this.length - 1)){ | |
| if (this.repeatMode == Queue.REPEAT_ALL){ | |
| _local1 = (this._shuffleEnabled) ? this.gs_queue.playedSongs[0] : this.gs_queue.source[0]; | |
| } | |
| } else if (this._shuffleEnabled){ | |
| if (_local2 < (this.gs_queue.playedSongs.length - 1)){ | |
| _local1 = this.gs_queue.playedSongs[(_local2 + 1)]; | |
| } else { | |
| _local3 = Math.random(); | |
| _local4 = Math.floor((_local3 * this.gs_queue.pendingSongs.length)); | |
| _local1 = this.gs_queue.pendingSongs.splice(_local4, 1)[0]; | |
| this.gs_queue.playedSongs.push(_local1); | |
| } | |
| } else { | |
| _local1 = this.gs_queue.source[(_local2 + 1)]; | |
| } | |
| this.nextSong = _local1; | |
| return (_local1); | |
| }, | |
| pause: function() { | |
| if (this._crossfadeSong && this._crossfadeSong.playStatus === PlayableSong.PLAY_STATUS_PLAYING){ | |
| if ((this._crossfadeSong.duration - this._crossfadeSong.position) < this.crossfadeAmount){ | |
| this._crossfadeSong.soundVolume = 0; | |
| } else { | |
| this.crossfadeSongStop(); | |
| }; | |
| }; | |
| if (this.gs_queue._activeSong){ | |
| this.gs_queue._activeSong.pause(); | |
| this.gs_queue._activeSong.soundVolume = 1; | |
| }; | |
| }, | |
| resume: function() { | |
| if (this.gs_queue._activeSong){ | |
| this.gs_queue._activeSong.resume(); | |
| }; | |
| }, | |
| stop: function() { | |
| if (this.gs_queue._activeSong){ | |
| this.gs_queue._activeSong.stop(); | |
| }; | |
| if (this._crossfadeSong && this._crossfadeSong.playStatus === PlayableSong.PLAY_STATUS_PLAYING){ | |
| this.crossfadeSongStop(); | |
| }; | |
| } | |
| }); | |
| // Queue static functions | |
| Queue._prefetchEnabled = true; | |
| Queue._staticBindingEventDispatcher = new EventDispatcher(); | |
| Queue.__defineGetter__("prefetchEnabled", helpers.getterFunction('prefetchEnabled',Queue)); | |
| Queue.__defineGetter__("staticEventDispatcher", helpers.getterFunction('staticEventDispatcher',Queue)); | |
| Queue.__defineSetter__("prefetchEnabled", helpers.setterFunction('prefetchEnabled',Queue,true)); | |
| var QueueJS = Queue.extend({ | |
| init: function (service, songCache, autoAutoplayDisabled, arg4) { | |
| if (autoAutoplayDisabled == undefined) autoAutoplayDisabled = true; | |
| if (arg4 == undefined) arg4 = true; | |
| this._super(service, autoAutoplayDisabled, arg4); | |
| this.service = service; | |
| //console.log(this,this.gs_queue,Boolean(this == gs_queue)); | |
| this.gs_queue.songCache = songCache; | |
| this.gs_queue.chunkSize = 1000; | |
| this.gs_queue.maxChunks = 1; | |
| this.songs = []; | |
| //this.commandQueue = null; | |
| }, | |
| addItemsAt: function(songs, index, playOnAdd, autoplayOnAdd) { | |
| if (!index) index=-1; | |
| if (!playOnAdd) playOnAdd=false; | |
| if (!autoplayOnAdd) autoplayOnAdd=false; | |
| var chunk = songs.splice(0, (this.gs_queue.chunkSize * this.gs_queue.maxChunks)); | |
| this.generateAddSongsToQueue(chunk, index, playOnAdd, autoplayOnAdd); | |
| if (songs.length){ | |
| this.dispatchEvent(new QueueEvent(QueueEvent.ERROR_ADDING_SONGS, QueueEvent.TOO_MANY_SONGS, false, {songs:songs})); | |
| } | |
| }, | |
| generateAddSongsToQueue: function(songs, index, playOnAdd, autoplayOnAdd) { | |
| console.log('generateAddSongsToQueue',songs,index,playOnAdd, autoplayOnAdd); | |
| //console.log(this, this.gs_queue, gs_queue, this.commandQueue, gs_queue.commandQueue, Boolean(this == this.gs_queue)); | |
| var command = new JSAddSongsToQueue(this.service, this, songs, index, playOnAdd, autoplayOnAdd); | |
| this.gs_queue.commandQueue.queueCommand(command); | |
| }, | |
| completeAddSongsAt: function(_arg1, _arg2, _arg3, _arg4, _arg5) { | |
| this._super(_arg1, _arg2, _arg3, _arg4, _arg5 || null); | |
| for (i in _arg1) { | |
| _arg1[i].addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.dirtySong, this); | |
| } | |
| }, | |
| dirtySong: function(event) { | |
| if (event.currentTarget){ | |
| switch (event.property){ | |
| case "queueSongID": | |
| case "autoplayVote": | |
| case "source": | |
| case "sponsoredAutoplayID": | |
| case "songID": | |
| case "songName": | |
| case "artistID": | |
| case "artistName": | |
| case "albumID": | |
| case "albumName": | |
| case "estimateDuration": | |
| this.dispatchEvent(new SongEvent(SongEvent.SONG_DIRTY, event.currentTarget)); | |
| break; | |
| }; | |
| }; | |
| } | |
| }); | |
| var Model = EventDispatcher.extend({ | |
| _crossfadeAmount: 5000, | |
| _crossfadeEnabled: false, | |
| _isMuted: false, | |
| _persistShuffle: false, | |
| _playPauseFadeEnabled: false, | |
| _shuffleEnabled: false, | |
| _volume: 100, | |
| init: function(service){ | |
| // Define getters/setters | |
| this.__defineGetter__("currentQueue",helpers.getterFunction('currentQueue')); | |
| this.__defineSetter__("currentQueue",helpers.setterFunction('currentQueue')); | |
| this.__defineGetter__("crossfadeAmount",helpers.getterFunction('crossfadeAmount')); | |
| this.__defineSetter__("crossfadeAmount",helpers.setterFunction('crossfadeAmount')); | |
| this.__defineGetter__("crossfadeEnabled",helpers.getterFunction('crossfadeEnabled')); | |
| this.__defineSetter__("crossfadeEnabled",helpers.setterFunction('crossfadeEnabled')); | |
| this.__defineGetter__("isMuted",this["get isMuted"]); | |
| this.__defineSetter__("isMuted",this["set isMuted"]); | |
| this.__defineGetter__("persistShuffle",helpers.getterFunction('persistShuffle')); | |
| this.__defineSetter__("persistShuffle",helpers.setterFunction('persistShuffle')); | |
| this.__defineGetter__("playPauseFadeEnabled",helpers.getterFunction('playPauseFadeEnabled')); | |
| this.__defineSetter__("playPauseFadeEnabled",helpers.setterFunction('playPauseFadeEnabled')); | |
| this.__defineGetter__("shuffleEnabled",helpers.getterFunction('shuffleEnabled')); | |
| this.__defineSetter__("shuffleEnabled",helpers.setterFunction('shuffleEnabled')); | |
| this.__defineGetter__("volume",this["get volume"]); | |
| this.__defineSetter__("volume",this["set volume"]); | |
| this.songCache = {}; | |
| this.service = service; | |
| this.currentQueue = new QueueJS(this.service, this.songCache); | |
| this.previousQueue = new QueueJS(this.service, this.songCache); | |
| }, | |
| "get isMuted": function() { | |
| return (this.currentQueue.activeSong) ? this.currentQueue.activeSong.isMuted : false; | |
| }, | |
| "set isMuted": function(newValue) { | |
| if (this.currentQueue.activeSong) { | |
| this.currentQueue.activeSong.isMuted = newValue; | |
| } | |
| }, | |
| "get volume": function() { | |
| return (this.currentQueue.activeSong) ? (this.currentQueue.activeSong.soundVolume * 100) : 100; | |
| }, | |
| "set volume": function(newValue) { | |
| if (this.currentQueue.activeSong) { | |
| this.currentQueue.activeSong.soundVolume = (newValue / 100); | |
| } | |
| }, | |
| }); | |
| var Controller = jQuery.Class.extend({ | |
| needToken: false, | |
| propsDirty: false, | |
| init: function (model, swfname, playerController, serviceController){ | |
| // Define getters/setters | |
| this.__defineGetter__("activeSong",helpers.getterFunction('activeSong')); | |
| this.__defineSetter__("activeSong",this["set activeSong"]); | |
| this.__defineGetter__("currentQueue",helpers.getterFunction('currentQueue')); | |
| this.__defineSetter__("currentQueue",this["set currentQueue"]); | |
| this.__defineGetter__("model",helpers.getterFunction('model')); | |
| this.__defineSetter__("model",this["set model"]); | |
| /*this.activeSong = null; | |
| this.autoplayEnabled = false; | |
| this.currentAutoplayTagID = 0; | |
| this.hasRestoreQueue = false; | |
| this.nextSong = null; | |
| this.previousSong = null; | |
| this.queueID = null; | |
| this.repeatMode = 0; | |
| this.shuffleEnabled = true; | |
| this.songs = new Array();*/ | |
| this.songsDirty = []; | |
| this.queueDirty = []; | |
| this.PROXY_ALLOWED = ["initiateSession", "getCommunicationToken", "userForgotPassword", "getUserByInviteID", "getGoogleAuthToken", "getGoogleContacts", "getDetailsForBroadcast", "broadcastSong", "getUserFacebookDataEx", "saveUserFacebookDataEx", "updateUserFacebookData", "getUserGoogleData", "authenticateUser", "authenticateFacebookUser", "authenticateGoogleUser", "getStoredUsers", "deleteStoredUser", "loginStoredUser", "reportUserChange", "killAuthToken", "logoutUser", "changePassword", "registerUser", "registerFacebookUser", "registerGoogleUser", "getThemeFromDFP", "getSubscriptionDetails"]; | |
| this.allowedHTTPMethods = ["GET", "POST", "HEAD", "OPTIONS", "PUT", "TRACE", "DELETE"]; | |
| this.model = model; | |
| this.playerController = playerController; | |
| this.serviceController = serviceController; | |
| this.handleCallbacks(); | |
| this.ready = true; | |
| if (this.needToken) { | |
| this.fetchToken(); | |
| } | |
| }, | |
| doInit: function() { | |
| if (this.playerController) { | |
| try { | |
| eval(this.playerController + ".playerReady").call(eval(this.playerController),this.buildEverything()); | |
| } catch (e) { | |
| console.error(e); | |
| } | |
| } | |
| if (this.serviceController) { | |
| try { | |
| eval(this.serviceController + ".swfReady").call(eval(this.serviceController),"thingy"); | |
| } catch (e) { | |
| console.error(e); | |
| } | |
| } | |
| this.handleCallbacksTimer = new Timer(500); | |
| this.handleCallbacksTimer.addEventListener(TimerEvent.TIMER, this.handleCallbacks, this); | |
| this.handleCallbacksTimer.start(); | |
| }, | |
| handleCallbacks: function() { | |
| if (this.propsDirty){ | |
| this.propsDirty = !(this.reportPropertyChange()); | |
| } | |
| if (this.queueDirty.length){ | |
| this.queueDirty = this.reportQueueChange(); | |
| if (this.ready){ | |
| this.storeQueue(true); | |
| } | |
| } | |
| if (this.playStatusDirty){ | |
| this.playStatusDirty = !(this.reportPlaybackStatus()); | |
| } | |
| var songsDirty = this.songsDirty.concat(); | |
| for (i in songsDirty) { | |
| if (this.reportSongPropertyChange(songsDirty[i])){ | |
| songsDirty.splice(i, 1); | |
| } | |
| } | |
| }, | |
| "set activeSong": function(newSong) { | |
| if (newSong !== this._activeSong){ | |
| if (this._activeSong){ | |
| this._activeSong.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onSongPropChange); | |
| }; | |
| this._activeSong = newSong; | |
| if (this._activeSong){ | |
| this._activeSong.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onSongPropChange, this); | |
| }; | |
| this.playStatusDirty = true; | |
| }; | |
| }, | |
| "set currentQueue": function(newQueue) { | |
| if (newQueue !== this._currentQueue){ | |
| if (this._currentQueue){ | |
| this._currentQueue.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onQueuePropChange); | |
| this._currentQueue.removeEventListener(CollectionEvent.COLLECTION_CHANGE, this.onQueueCollectionChange); | |
| this._currentQueue.removeEventListener(QueueEvent.AUTOPLAY_FAILED, this.onQueueAutoplayFailed); | |
| this._currentQueue.removeEventListener(QueueEvent.ERROR_ADDING_SONGS, this.onQueueAddError); | |
| this._currentQueue.removeEventListener(QueueEvent.PLAYBACK_ERROR, this.onQueuePlaybackError); | |
| this._currentQueue.removeEventListener(QueueEvent.AUTOPLAY_VOTE_ERROR, this.onAutoplayVoteError); | |
| this._currentQueue.removeEventListener(SongEvent.SONG_DIRTY, this.onSongDirty); | |
| } | |
| this._currentQueue = newQueue; | |
| if (this._currentQueue){ | |
| this._currentQueue.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onQueuePropChange, this); | |
| this._currentQueue.addEventListener(CollectionEvent.COLLECTION_CHANGE, this.onQueueCollectionChange, this); | |
| this._currentQueue.addEventListener(QueueEvent.AUTOPLAY_FAILED, this.onQueueAutoplayFailed, this); | |
| this._currentQueue.addEventListener(QueueEvent.ERROR_ADDING_SONGS, this.onQueueAddError, this); | |
| this._currentQueue.addEventListener(QueueEvent.PLAYBACK_ERROR, this.onQueuePlaybackError, this); | |
| this._currentQueue.addEventListener(QueueEvent.AUTOPLAY_VOTE_ERROR, this.onAutoplayVoteError, this); | |
| this._currentQueue.addEventListener(SongEvent.SONG_DIRTY, this.onSongDirty, this); | |
| this.activeSong = this._currentQueue.activeSong; | |
| this._currentQueue.enableCrossfade(this.model.crossfadeEnabled, this.model.crossfadeAmount, this.model.playPauseFadeEnabled); | |
| if (this.model.persistShuffle){ | |
| this._currentQueue.shuffleEnabled = this.model.shuffleEnabled; | |
| } else { | |
| this.model.shuffleEnabled = this._currentQueue.shuffleEnabled; | |
| } | |
| } else { | |
| this.activeSong = null; | |
| } | |
| event = new QueueChangeEvent(QueueChangeEvent.QUEUE_RESET); | |
| this.queueDirty.push(event); | |
| this.propsDirty = true; | |
| } | |
| }, | |
| "set model": function(newModel) { | |
| if (newModel !== this._model){ | |
| if (this._model){ | |
| this._model.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onModelChange); | |
| } | |
| this._model = newModel; | |
| if (this._model){ | |
| this._model.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, this.onModelChange, this); | |
| this.service = this._model.service; | |
| this.currentQueue = this._model.currentQueue; | |
| } | |
| }; | |
| }, | |
| clearQueue: function() { | |
| this.model.previousQueue = this.model.currentQueue; | |
| this.model.currentQueue = new QueueJS(this.model.service, this.model.songCache); | |
| this.model.lastQueue = null; | |
| }, | |
| getVolume: function() { | |
| return this.model.volume; | |
| }, | |
| setVolume: function(volume) { | |
| if (isNaN(volume) || volume < 0){ | |
| volume = 0; | |
| } else if (volume > 100){ | |
| volume = 100; | |
| } | |
| this.model.isMuted = false; | |
| this.model.volume = volume; | |
| if (this.model.currentQueue.activeSong) { | |
| this.model.currentQueue.activeSong.soundVolume = (volume / 100); | |
| } | |
| }, | |
| getCrossfadeEnabled: function() { | |
| return this.model.crossfadeEnabled; | |
| }, | |
| setCrossfadeEnabled: function(crossfadeEnabled) { | |
| this.model.crossfadeEnabled = crossfadeEnabled; | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.crossfadeEnabled = crossfadeEnabled; | |
| } | |
| if (this.model.previousQueue){ | |
| this.model.previousQueue.crossfadeEnabled = crossfadeEnabled; | |
| } | |
| }, | |
| getCrossfadeAmount: function() { | |
| return this.model.crossfadeAmount; | |
| }, | |
| setCrossfadeAmount: function(crossfadeAmount) { | |
| this.model.crossfadeAmount = crossfadeAmount; | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.crossfadeAmount = crossfadeAmount; | |
| } | |
| if (this.model.previousQueue){ | |
| this.model.previousQueue.crossfadeAmount = crossfadeAmount; | |
| } | |
| }, | |
| getLowerQuality: function() { | |
| return PlayableSong.useMobile; | |
| }, | |
| setLowerQuality: function(useMobile) { | |
| PlayableSong.useMobile = useMobile; | |
| }, | |
| getPrefetchEnabled: function() { | |
| return Queue.prefetchEnabled; | |
| }, | |
| setPrefetchEnabled: function(prefetchEnabled) { | |
| Queue.prefetchEnabled = prefetchEnabled; | |
| }, | |
| getPlayPauseFade: function() { | |
| return this.model.playPauseFadeEnabled; | |
| }, | |
| setPlayPauseFade: function(playPauseFadeEnabled) { | |
| this.model.playPauseFadeEnabled = playPauseFadeEnabled; | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.crossfadeInOutEnabled = playPauseFadeEnabled; | |
| } | |
| if (this.model.previousQueue){ | |
| this.model.previousQueue.crossfadeInOutEnabled = playPauseFadeEnabled; | |
| } | |
| }, | |
| setPersistShuffle: function(persistShuffle) { | |
| console.log('setPerisistShuffle',persistShuffle); | |
| this.model.persistShuffle = persistShuffle; | |
| }, | |
| getShuffle: function() { | |
| return this.model.shuffleEnabled; | |
| }, | |
| setShuffle: function(shuffleEnabled) { | |
| this.model.shuffleEnabled = shuffleEnabled; | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.shuffleEnabled = shuffleEnabled; | |
| }; | |
| }, | |
| getIsMuted: function() { | |
| return this.model.isMuted; | |
| }, | |
| setIsMuted: function(isMuted) { | |
| this.model.isMuted = isMuted; | |
| }, | |
| getPlaybackStatus: function() { | |
| return this.buildPlaybackStatus(); | |
| }, | |
| setAutoplay: function(autoplay, tagId) { | |
| _local3 = false; | |
| if (this.model.currentQueue){ | |
| if (tagId){ | |
| if (autoplay){ | |
| _local3 = true; | |
| if (!Tag.tagIDLookup[tagId]){ | |
| Tag.tagIDLookup[tagId] = new Tag(tagId, ""); | |
| }; | |
| this.model.currentQueue.startTagAutoplay(Tag.tagIDLookup[tagId], true); | |
| } | |
| } else { | |
| this.model.currentQueue.stopTagAutoplay(); | |
| }; | |
| if (autoplay != this.model.currentQueue.autoplayEnabled && !_local3){ | |
| this.model.currentQueue.setAutoplayEnabled(autoplay, true); | |
| }; | |
| }; | |
| }, | |
| seekTo: function(_arg1) { | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.seekInCurrentSong(_arg1); | |
| }; | |
| }, | |
| playSong: function(songID) { | |
| if (this.model.currentQueue){ | |
| _local2 = null; | |
| if (songID){ | |
| _local2 = this.model.currentQueue.gs_queue.queueSongLookupByQueueSongID[songID]; | |
| }; | |
| this.model.currentQueue.playSong(_local2); | |
| }; | |
| }, | |
| pauseSong: function() { | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.pause(); | |
| }; | |
| }, | |
| resumeSong: function() { | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.resume(); | |
| }; | |
| }, | |
| previousSong: function(arg1) { | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.playPreviousSong(arg1); | |
| }; | |
| }, | |
| nextSong: function() { | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.playNextSong(); | |
| }; | |
| }, | |
| stopSong: function() { | |
| if (this.model.currentQueue){ | |
| this.model.currentQueue.stop(); | |
| }; | |
| }, | |
| removeSongs: function(songIds) { | |
| if (this.model.currentQueue){ | |
| var songs = []; | |
| for (i in songIds) { | |
| var queueSong = this.model.currentQueue.gs_queue.queueSongLookupByQueueSongID[songIds[i]]; | |
| if (queueSong){ | |
| songs.push(queueSong); | |
| } | |
| } | |
| this.model.currentQueue.removeItems(songs); | |
| }; | |
| }, | |
| moveSongsTo: function(songIds, index) { | |
| if (this.model.currentQueue){ | |
| var songs = []; | |
| for (i in songIds) { | |
| var queueSong = this.model.currentQueue.gs_queue.queueSongLookupByQueueSongID[songIds[i]]; | |
| if (queueSong){ | |
| songs.push(queueSong); | |
| } | |
| } | |
| this.model.currentQueue.moveItemsTo(songs, index); | |
| }; | |
| }, | |
| onModelChange: function(change) { | |
| if (change.property == "service"){ | |
| this.service = change.newValue; | |
| } | |
| if (change.property == "currentQueue"){ | |
| this.currentQueue = change.newValue; | |
| } | |
| }, | |
| onSongPropChange: function(event) { | |
| switch (event.property){ | |
| case "playStatus": | |
| case "bytesLoaded": | |
| case "bytesTotal": | |
| case "position": | |
| case "duration": | |
| this.playStatusDirty = true; | |
| break; | |
| }; | |
| }, | |
| onQueuePropChange: function(event) { | |
| switch (event.property){ | |
| case "activeSong": | |
| this.activeSong = event.newValue; | |
| case "queueID": | |
| case "nextSong": | |
| case "previousSong": | |
| case "autoplayEnabled": | |
| case "autoplayEnabled": | |
| case "shuffleEnabled": | |
| case "repeatMode": | |
| case "currentAutoplayTag": | |
| this.queueDirty.push(new QueueChangeEvent(QueueChangeEvent.PROPERTY_CHANGE, event.property)); | |
| break; | |
| case "crossfadeAmount": | |
| case "crossfadeEnabled": | |
| case "crossfadeInOutEnabled": | |
| this.propsDirty = true; | |
| break; | |
| }; | |
| }, | |
| onQueueCollectionChange: function(event) { | |
| console.log('onQueueCollectionChange',event); | |
| var _local2 = null; | |
| var _local3 = {}; | |
| switch (event.kind){ | |
| case CollectionEventKind.REFRESH: | |
| case CollectionEventKind.RESET: | |
| _local2 = new QueueChangeEvent(QueueChangeEvent.QUEUE_RESET); | |
| break; | |
| case CollectionEventKind.ADD: | |
| _local3.index = event.location; | |
| _local3.items = event.items; | |
| _local3.kind = "add"; | |
| _local2 = new QueueChangeEvent(QueueChangeEvent.CONTENT_CHANGE, _local3); | |
| break; | |
| case CollectionEventKind.REMOVE: | |
| _local3.index = event.location; | |
| _local3.items = event.items; | |
| _local3.kind = "remove"; | |
| _local2 = new QueueChangeEvent(QueueChangeEvent.CONTENT_CHANGE, _local3); | |
| break; | |
| case CollectionEventKind.MOVE: | |
| _local3.index = event.location; | |
| _local3.oldIndex = event.oldLocation; | |
| _local3.items = event.items; | |
| _local3.kind = "move"; | |
| _local2 = new QueueChangeEvent(QueueChangeEvent.CONTENT_CHANGE, _local3); | |
| break; | |
| case CollectionEventKind.REPLACE: | |
| _local3.index = event.location; | |
| _local3.items = event.items; | |
| _local3.kind = "replace"; | |
| _local2 = new QueueChangeEvent(QueueChangeEvent.CONTENT_CHANGE, _local3); | |
| break; | |
| }; | |
| if (_local2){ | |
| this.queueDirty.push(_local2); | |
| }; | |
| }, | |
| reportSongPropertyChange: function(song) { | |
| if (this.ready && this.songPropertyChangeCallback){ | |
| try { | |
| eval(songPropertyChangeCallback).call(eval(songPropertyChangeCallback),this.buildSong(song)); | |
| } catch(e) { | |
| console.error('reportSongPropertyChange',e); | |
| } | |
| return (true); | |
| } | |
| return (false); | |
| }, | |
| reportPropertyChange: function() { | |
| console.log('reportPropertyChange',this.ready,this.propertyChangeCallback); | |
| if (this.ready && this.propertyChangeCallback) { | |
| eval(this.propertyChangeCallback).call(eval(this.propertyChangeCallback),this.buildProperties()); | |
| return true; | |
| } | |
| return false; | |
| }, | |
| reportQueueChange: function() { | |
| var events = null; | |
| var failed = false; | |
| var e = null; | |
| console.log('reportQueueChange'); | |
| if (this.ready && this.queueChangeCallback){ | |
| events = this.cleanQueueChangeEvents(); | |
| console.log('reportQueueChange',events); | |
| while (events.length) { | |
| e = events.shift(); | |
| if (!e) { continue; } | |
| try { | |
| eval(this.queueChangeCallback).call(eval(this.queueChangeCallback),e); | |
| } catch(e) { | |
| failed = true; | |
| console.error('reportQueueChange',e); | |
| } | |
| } | |
| } | |
| return ((failed) ? [new QueueChangeEvent(QueueChangeEvent.QUEUE_RESET)] : []); | |
| }, | |
| reportPlaybackStatus: function() { | |
| if (this.ready && this.playbackStatusCallback){ | |
| try { | |
| eval(this.playbackStatusCallback).call(eval(this.playbackStatusCallback), this.buildPlaybackStatus()); | |
| } catch(e) { | |
| console.error('reportPlaybackStatus',e); | |
| }; | |
| return (true); | |
| }; | |
| return (false); | |
| }, | |
| cleanQueueChangeEvents: function() { | |
| if (!this.model.currentQueue){ | |
| return ([new QueueChangeEvent(QueueChangeEvent.QUEUE_RESET)]); | |
| } | |
| var _local1 = {}; | |
| var _local2 = false; | |
| var _local3 = []; | |
| var _local4 = this.buildQueue(this.model.currentQueue); | |
| var _local5 = []; | |
| for (i in this.queueDirty) { | |
| switch (this.queueDirty[i].type){ | |
| case QueueChangeEvent.QUEUE_RESET: | |
| this.queueDirty[i].details = _local4; | |
| this.queueDirty[i].fullQueue = _local4; | |
| return ([this.queueDirty[i]]); | |
| case QueueChangeEvent.CONTENT_CHANGE: | |
| for (j=0;j<this.queueDirty[i].details.items.length;j++) { | |
| this.queueDirty[i].details.items[j] = this.buildSong(this.queueDirty[i].details.items[j]); | |
| }; | |
| this.queueDirty[i].fullQueue = _local4; | |
| _local3.push(this.queueDirty[i]); | |
| break; | |
| case QueueChangeEvent.PROPERTY_CHANGE: | |
| _local2 = true; | |
| _local7 = String(this.queueDirty[i].details); | |
| _local8 = this.model.currentQueue[_local7]; | |
| if (_local8 instanceof QueueSong){ | |
| _local8 = this.buildSong(_local8); | |
| } else if (_local7 == "currentAutoplayTag"){buildProperties | |
| _local7 = "currentAutoplayTagID"; | |
| _local8 = ((this.model.currentQueue.currentAutoplayTag) ? this.model.currentQueue.currentAutoplayTag.tagID : 0); | |
| }; | |
| _local1[_local7] = _local8; | |
| break; | |
| } | |
| } | |
| if (_local2){ | |
| _local6 = new QueueChangeEvent(QueueChangeEvent.PROPERTY_CHANGE, _local1); | |
| _local6.fullQueue = _local4; | |
| _local5.push(_local6); | |
| }; | |
| cleanEvents = _local5.concat(_local3); | |
| console.log('cleanQueueChangeEvents',cleanEvents); | |
| return (cleanEvents); | |
| }, | |
| addSongsToQueueAt: function(songIDs, index, playOnAdd) { | |
| if (!this.model.currentQueue){ | |
| this.model.currentQueue = new QueueJS(this.model.service, this.model.songCache); | |
| } | |
| if (((!(songIDs)) || (!(songIDs.length)))){ | |
| console.error("addSongsToQueueAt called with no songs!"); | |
| return; | |
| } | |
| songs = []; | |
| for (i in songIDs) { | |
| if (songIDs[i]) { | |
| songID = parseInt(songIDs[i].SongID); | |
| if (songID) { | |
| songs.push(songID); | |
| songModel = this.model.songCache[songID]; | |
| if (!songModel) { | |
| song = new BaseSong(); | |
| song.songID = songID; | |
| song.songName = String(songIDs[i].SongName); | |
| song.artistID = parseInt(songIDs[i].ArtistID) || null; | |
| song.artistName = String(songIDs[i].ArtistName); | |
| song.albumID = parseInt(songIDs[i].AlbumID) || null; | |
| song.albumName = String(songIDs[i].AlbumName); | |
| song.flags = parseInt(songIDs[i].Flags) || null; | |
| if (songIDs[i].CoverArtFilename){ | |
| song.artFilename = String(songIDs[i].CoverArtFilename); | |
| }; | |
| if (parseInt(songIDs[i].EstimateDuration)){ | |
| song.estimateDuration = (parseInt(song.EstimateDuration) * 1000); | |
| }; | |
| this.model.songCache[song.songID] = song; | |
| } | |
| } | |
| } | |
| } | |
| this.model.currentQueue.addItemsAt(songs, index, playOnAdd); | |
| }, | |
| getCurrentQueue: function() { | |
| console.log('getCurrentQueue'); | |
| return this.buildQueue(this.model.currentQueue); | |
| }, | |
| getQueueIsRestorable: function(){ | |
| return (((((((!(this.model.currentQueue)) || ((this.model.currentQueue.songs.length == 0)))) && (this.model.previousQueue))) && ((this.model.previousQueue.songs.length > 0)))); | |
| }, | |
| getSongDetails: function(_arg1, _arg2) { | |
| var _local3 = []; | |
| var _local4 = (!_arg1 || this.model.currentQueue.queueID == _arg1) ? this.model.currentQueue : (this.model.previousQueue && this.model.previousQueue.queueID) ? this.model.previousQueue : null; | |
| if (_local4){ | |
| for (i in _arg2) { | |
| var _local6 = _local4.gs_queue.queueSongLookupByQueueSongID[_arg2[i]]; | |
| if (_local6){ | |
| _local3.push(this.buildSong(_local6)); | |
| }; | |
| }; | |
| }; | |
| return _local3; | |
| }, | |
| flagSong: function(_arg1, _arg2) { | |
| if (this.model.currentQueue){ | |
| var _local3 = this.model.currentQueue.gs_queue.queueSongLookupByQueueSongID[_arg1]; | |
| if (_local3){ | |
| _local3.flag(_arg2); | |
| }; | |
| }; | |
| }, | |
| buildProperties: function() { | |
| console.log('buildProperties',this,this.model); | |
| return { | |
| volume:this.model.volume, | |
| isMuted:this.model.isMuted, | |
| crossfadeAmount:((this.model.currentQueue) ? this.model.currentQueue.crossfadeAmount : 0), | |
| crossfadeEnabled:((this.model.currentQueue) ? this.model.currentQueue.crossfadeEnabled : false), | |
| playPauseFade:((this.model.currentQueue) ? this.model.currentQueue.crossfadeInOutEnabled : false) | |
| }; | |
| }, | |
| buildEverything: function() { | |
| everything = this.buildProperties(); | |
| everything.currentQueue = this.buildQueue(this.model.currentQueue); | |
| everything.previousQueue = this.buildQueue(this.model.previousQueue); | |
| }, | |
| buildQueue: function(queue) { | |
| if (!queue) return null; | |
| console.log('buildQueue',queue); | |
| songs = []; | |
| for (i in queue.source) { | |
| songs.push(this.buildSong(queue.source[i])); | |
| } | |
| result = { | |
| "songs": songs, | |
| "queueID": queue.queueID, | |
| "activeSong": ((queue.activeSong) ? this.buildSong(queue.activeSong) : null), | |
| "previousSong": ((queue.previousSong) ? this.buildSong(queue.previousSong) : null), | |
| "nextSong": ((queue.nextSong) ? this.buildSong(queue.nextSong) : null), | |
| "autoplayEnabled": queue.autoplayEnabled, | |
| "currentAutoplayTagID": ((queue.currentAutoplayTag) ? queue.currentAutoplayTag.tagID : 0), | |
| "shuffleEnabled": queue.shuffleEnabled, | |
| "repeatMode": queue.repeatMode | |
| }; | |
| if (result.activeSong){ | |
| result.activeSong.index = queue.getItemIndex(queue.activeSong); | |
| }; | |
| return result; | |
| }, | |
| buildSong: function(queueSong) { | |
| return { | |
| "parentQueueID":queueSong.parent.queueID, | |
| "queueSongID":queueSong.queueSongID, | |
| "autoplayVote":queueSong.rawAutoplayVote, | |
| "source":queueSong.source, | |
| "sponsoredAutoplayID":queueSong.sponsoredAutoplayID, | |
| "songID":queueSong.song.songID, | |
| "songName":queueSong.song.songName, | |
| "artistID":queueSong.song.artistID, | |
| "artistName":queueSong.song.artistName, | |
| "albumID":queueSong.song.albumID, | |
| "albumName":queueSong.song.albumName, | |
| "artFilename":queueSong.song.artFilename, | |
| "estimateDuration":queueSong.song.estimateDuration, | |
| "flags":queueSong.song.flags | |
| }; | |
| }, | |
| buildPlaybackStatus: function() { | |
| var _local1 = null; | |
| if (this.activeSong){ | |
| _local1 = { | |
| activeSong:this.buildSong(this.activeSong), | |
| bytesLoaded:this.activeSong.bytesLoaded, | |
| bytesTotal:this.activeSong.bytesTotal, | |
| position:this.activeSong.position, | |
| duration:this.activeSong.duration, | |
| status:this.activeSong.playStatus | |
| }; | |
| } | |
| if (_local1 && _local1.activeSong && this.currentQueue){ | |
| _local1.activeSong.index = this.currentQueue.getItemIndex(this.activeSong); | |
| }; | |
| return (_local1); | |
| }, | |
| storeQueue: function() { | |
| console.log('STOREQUEUE! (Unimplemented)'); | |
| }, | |
| setErrorCallback: function(errorCallback) { | |
| this.errorCallback = errorCallback; | |
| }, | |
| setPlaybackStatusCallback: function(playbackStatusCallback) { | |
| this.playbackStatusCallback = playbackStatusCallback; | |
| return (this.buildPlaybackStatus()); | |
| }, | |
| setPropertyChangeCallback: function(propertyChangeCallback) { | |
| this.propertyChangeCallback = propertyChangeCallback; | |
| return (this.buildProperties()); | |
| }, | |
| setQueueChangeCallback: function(queueChangeCallback) { | |
| this.queueChangeCallback = queueChangeCallback; | |
| return (this.buildQueue(this.model.currentQueue)); | |
| }, | |
| setSongPropertyChangeCallback: function(songPropertyChangeCallback) { | |
| this.songPropertyChangeCallback = songPropertyChangeCallback; | |
| }, | |
| }); | |
| this.VERSION = String(20101012.36); | |
| this.hostname = params.hostname || GS.service.hostname; | |
| this.session = params.session || GS.service.sessionID; | |
| this.revision = params.version || GS.service.clientRevision; | |
| this.defaultScript = params.defaultScript || GS.service.defaultEndpoint; | |
| this.service = new Service(this.hostname, this.defaultScript, this.revision, this.session, !params.disableHTTPS); | |
| this.model = new Model(this.service); | |
| this.controller = new Controller(this.model, params.name, params.playerController, params.serviceController); | |
| this.gs_queue = gs_queue; | |
| } | |
| jsQueue = new jsQueue({ | |
| hostname: GS.service.hostname, | |
| session: window.gsConfig.sessionID, | |
| name: "jsPlayerEmbed", | |
| playerController: "GS.Controllers.PlayerController.instance()", | |
| serviceController: "GS.Controllers.ServiceController.instance()", | |
| disableHTTPS: 0 | |
| }); | |
| GS.jsQueue = jsQueue; | |
| GS.player.player = jsQueue.controller; | |
| GS.Models.Queue = jsQueue.model; | |
| GS.service.swfProxy = function(request, header, key) { | |
| console.log('overriding swf request with ajax!',request,header,key); | |
| header['client'] = 'jsqueue'; | |
| d(request); | |
| }; | |
| /*GS.player.player = { | |
| "playSong": function(a){console.log('playSong',a);}, | |
| "getCurrentQueue": function(){return GS.player.player.queue.getCurrentQueue()}, | |
| "getQueueIsRestorable": function(){return GS.player.player.queue.getQueueIsRestorable()}, | |
| "addSongsToQueueAt": function(songIDs, index, playOnAdd){return GS.player.player.queue.addSongsToQueueAt(songIDs, index, playOnAdd)}, | |
| "queue": jsQueue.controller, | |
| };*/ | |
| p(); | |
| GS.player.player.doInit(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment