5 lines
11 KiB
JavaScript
5 lines
11 KiB
JavaScript
/*! Mopidy.js - built 2013-03-31
|
|
* http://www.mopidy.com/
|
|
* Copyright (c) 2013 Stein Magnus Jodal and contributors
|
|
* Licensed under the Apache License, Version 2.0 */
|
|
function Mopidy(e){return this instanceof Mopidy?(this._settings=this._configure(e||{}),this._console=this._getConsole(),this._backoffDelay=this._settings.backoffDelayMin,this._pendingRequests={},this._webSocket=null,bane.createEventEmitter(this),this._delegateEvents(),this._settings.autoConnect&&this.connect(),void 0):new Mopidy(e)}if(("function"==typeof define&&define.amd&&function(e){define(e)}||"object"==typeof module&&function(e){module.exports=e()}||function(e){this.bane=e()})(function(){"use strict";function e(e,t,n){var o,i=n.length;if(i>0)for(o=0;i>o;++o)n[o](e,t);else setTimeout(function(){throw t.message=e+" listener threw error: "+t.message,t},0)}function t(e){if("function"!=typeof e)throw new TypeError("Listener is not function");return e}function n(e){return e.supervisors||(e.supervisors=[]),e.supervisors}function o(e,t){return e.listeners||(e.listeners={}),t&&!e.listeners[t]&&(e.listeners[t]=[]),t?e.listeners[t]:e.listeners}function i(e){return e.errbacks||(e.errbacks=[]),e.errbacks}function r(r){function c(t,n,o){try{n.listener.apply(n.thisp||r,o)}catch(s){e(t,s,i(r))}}return r=r||{},r.on=function(e,i,r){return"function"==typeof e?n(this).push({listener:e,thisp:i}):(o(this,e).push({listener:t(i),thisp:r}),void 0)},r.off=function(e,t){var r,s,c,f;if(!e){r=n(this),r.splice(0,r.length),s=o(this);for(c in s)s.hasOwnProperty(c)&&(r=o(this,c),r.splice(0,r.length));return r=i(this),r.splice(0,r.length),void 0}if("function"==typeof e?(r=n(this),t=e):r=o(this,e),!t)return r.splice(0,r.length),void 0;for(c=0,f=r.length;f>c;++c)if(r[c].listener===t)return r.splice(c,1),void 0},r.once=function(e,t,n){var o=function(){r.off(e,o),t.apply(this,arguments)};r.on(e,o,n)},r.bind=function(e,t){var n,o,i;if(t)for(o=0,i=t.length;i>o;++o){if("function"!=typeof e[t[o]])throw Error("No such method "+t[o]);this.on(t[o],e[t[o]],e)}else for(n in e)"function"==typeof e[n]&&this.on(n,e[n],e);return e},r.emit=function(e){var t,i,r=n(this),f=s.call(arguments);for(t=0,i=r.length;i>t;++t)c(e,r[t],f);for(r=o(this,e).slice(),f=s.call(arguments,1),t=0,i=r.length;i>t;++t)c(e,r[t],f)},r.errback=function(e){this.errbacks||(this.errbacks=[]),this.errbacks.push(t(e))},r}var s=Array.prototype.slice;return{createEventEmitter:r}}),"undefined"!=typeof window&&(window.define=function(e){try{delete window.define}catch(t){window.define=void 0}window.when=e()},window.define.amd={}),function(e){"use strict";e(function(){function e(e,t,o,i){return n(e).then(t,o,i)}function t(e){this.then=e}function n(e){return r(function(t){t(e)})}function o(t){return e(t,f)}function i(){function e(e,r,s){t.resolve=t.resolver.resolve=function(t){return i?n(t):(i=!0,e(t),o)},t.reject=t.resolver.reject=function(e){return i?n(f(e)):(i=!0,r(e),o)},t.notify=t.resolver.notify=function(e){return s(e),e}}var t,o,i;return t={promise:R,resolve:R,reject:R,notify:R,resolver:{resolve:R,reject:R,notify:R}},t.promise=o=r(e),t}function r(e){function n(e,t,n){return r(function(o,i,r){p?p.push(function(s){s.then(e,t,n).then(o,i,r)}):k(function(){h.then(e,t,n).then(o,i,r)})})}function o(e){p&&(h=s(e),a(p,h),p=R)}function i(e){o(f(e))}function c(e){p&&a(p,u(e))}var h,p=[];try{e(o,i,c)}catch(l){i(l)}return new t(n)}function s(e){return e instanceof t?e:e!==Object(e)?c(e):r(function(t,n,o){k(function(){try{var i=e.then;"function"==typeof i?j(i,e,t,n,o):t(c(e))}catch(r){n(r)}})})}function c(e){var n=new t(function(t){try{return"function"==typeof t?s(t(e)):n}catch(o){return f(o)}});return n}function f(e){var n=new t(function(t,o){try{return"function"==typeof o?s(o(e)):n}catch(i){return f(i)}});return n}function u(e){var n=new t(function(t,o,i){try{return"function"==typeof i?u(i(e)):n}catch(r){return u(r)}});return n}function a(e,t){k(function(){for(var n,o=0;n=e[o++];)n(t)})}function h(e){return e&&"function"==typeof e.then}function p(t,n,o,i,s){return m(2,arguments),e(t,function(t){function c(o,i,r){function s(e){l(e)}function c(e){p(e)}var f,u,a,h,p,l,d,y;if(d=t.length>>>0,f=Math.max(0,Math.min(n,d)),a=[],u=d-f+1,h=[],f)for(l=function(e){h.push(e),--u||(p=l=v,i(h))},p=function(e){a.push(e),--f||(p=l=v,o(a))},y=0;d>y;++y)y in t&&e(t[y],c,s,r);else o(a)}return r(c).then(o,i,s)})}function l(e,t,n,o){function i(e){return t?t(e[0]):e[0]}return p(e,1,i,n,o)}function d(e,t,n,o){return m(1,arguments),b(e,M).then(t,n,o)}function y(){return b(arguments,M)}function b(t,n){return e(t,function(t){function o(o,i,r){var s,c,f,u,a;if(f=c=t.length>>>0,s=[],f)for(u=function(t,c){e(t,n).then(function(e){s[c]=e,--f||o(s)},i,r)},a=0;c>a;a++)a in t?u(t[a],a):--f;else o(s)}return r(o)})}function w(t,n){var o=j(E,arguments,1);return e(t,function(t){var i;return i=t.length,o[0]=function(t,o,r){return e(t,function(t){return e(o,function(e){return n(t,e,r,i)})})},S.apply(t,o)})}function k(e){1===W.push(e)&&g()}function g(){D(_)}function _(){for(var e,t=0;e=W[t++];)e();W=[]}function m(e,t){for(var n,o=t.length;o>e;)if(n=t[--o],null!=n&&"function"!=typeof n)throw Error("arg "+o+" must be a function")}function v(){}function M(e){return e}e.defer=i,e.resolve=n,e.reject=o,e.join=y,e.all=d,e.map=b,e.reduce=w,e.any=l,e.some=p,e.isPromise=h,t.prototype={otherwise:function(e){return this.then(R,e)},ensure:function(e){function t(){return n(e())}var o=this;return this.then(t,t).yield(o)},yield:function(e){return this.then(function(){return e})},spread:function(e){return this.then(function(t){return d(t,function(t){return e.apply(R,t)})})},always:function(e,t){return this.then(e,e,t)}};var S,E,j,D,W,O,q,C,x,R;return W=[],O=setTimeout,D="function"==typeof setImmediate?"undefined"==typeof window?setImmediate:setImmediate.bind(window):"object"==typeof process?process.nextTick:function(e){O(e,0)},q=Function.prototype,C=q.call,j=q.bind?C.bind(C):function(e,t){return e.apply(t,E.call(arguments,2))},x=[],E=x.slice,S=x.reduce||function(e){var t,n,o,i,r;if(r=0,t=Object(this),i=t.length>>>0,n=arguments,1>=n.length)for(;;){if(r in t){o=t[r++];break}if(++r>=i)throw new TypeError}else o=n[1];for(;i>r;++r)r in t&&(o=e(o,t[r],r,t));return o},e})}("function"==typeof define&&define.amd?define:function(e){module.exports=e()}),"object"==typeof module&&"function"==typeof require)var bane=require("bane"),websocket=require("faye-websocket"),when=require("when");Mopidy.WebSocket="object"==typeof module&&"function"==typeof require?websocket.Client:window.WebSocket,Mopidy.prototype._configure=function(e){var t="undefined"!=typeof document&&document.location.host||"localhost";return e.webSocketUrl=e.webSocketUrl||"ws://"+t+"/mopidy/ws/",e.autoConnect!==!1&&(e.autoConnect=!0),e.backoffDelayMin=e.backoffDelayMin||1e3,e.backoffDelayMax=e.backoffDelayMax||64e3,e},Mopidy.prototype._getConsole=function(){var e=e!==void 0&&e||{};return e.log=e.log||function(){},e.warn=e.warn||function(){},e.error=e.error||function(){},e},Mopidy.prototype._delegateEvents=function(){this.off("websocket:close"),this.off("websocket:error"),this.off("websocket:incomingMessage"),this.off("websocket:open"),this.off("state:offline"),this.on("websocket:close",this._cleanup),this.on("websocket:error",this._handleWebSocketError),this.on("websocket:incomingMessage",this._handleMessage),this.on("websocket:open",this._resetBackoffDelay),this.on("websocket:open",this._getApiSpec),this.on("state:offline",this._reconnect)},Mopidy.prototype.connect=function(){if(this._webSocket){if(this._webSocket.readyState===Mopidy.WebSocket.OPEN)return;this._webSocket.close()}this._webSocket=this._settings.webSocket||new Mopidy.WebSocket(this._settings.webSocketUrl),this._webSocket.onclose=function(e){this.emit("websocket:close",e)}.bind(this),this._webSocket.onerror=function(e){this.emit("websocket:error",e)}.bind(this),this._webSocket.onopen=function(){this.emit("websocket:open")}.bind(this),this._webSocket.onmessage=function(e){this.emit("websocket:incomingMessage",e)}.bind(this)},Mopidy.prototype._cleanup=function(e){Object.keys(this._pendingRequests).forEach(function(t){var n=this._pendingRequests[t];delete this._pendingRequests[t],n.reject({message:"WebSocket closed",closeEvent:e})}.bind(this)),this.emit("state:offline")},Mopidy.prototype._reconnect=function(){this.emit("reconnectionPending",{timeToAttempt:this._backoffDelay}),setTimeout(function(){this.emit("reconnecting"),this.connect()}.bind(this),this._backoffDelay),this._backoffDelay=2*this._backoffDelay,this._backoffDelay>this._settings.backoffDelayMax&&(this._backoffDelay=this._settings.backoffDelayMax)},Mopidy.prototype._resetBackoffDelay=function(){this._backoffDelay=this._settings.backoffDelayMin},Mopidy.prototype.close=function(){this.off("state:offline",this._reconnect),this._webSocket.close()},Mopidy.prototype._handleWebSocketError=function(e){this._console.warn("WebSocket error:",e.stack||e)},Mopidy.prototype._send=function(e){var t=when.defer();switch(this._webSocket.readyState){case Mopidy.WebSocket.CONNECTING:t.resolver.reject({message:"WebSocket is still connecting"});break;case Mopidy.WebSocket.CLOSING:t.resolver.reject({message:"WebSocket is closing"});break;case Mopidy.WebSocket.CLOSED:t.resolver.reject({message:"WebSocket is closed"});break;default:e.jsonrpc="2.0",e.id=this._nextRequestId(),this._pendingRequests[e.id]=t.resolver,this._webSocket.send(JSON.stringify(e)),this.emit("websocket:outgoingMessage",e)}return t.promise},Mopidy.prototype._nextRequestId=function(){var e=-1;return function(){return e+=1}}(),Mopidy.prototype._handleMessage=function(e){try{var t=JSON.parse(e.data);t.hasOwnProperty("id")?this._handleResponse(t):t.hasOwnProperty("event")?this._handleEvent(t):this._console.warn("Unknown message type received. Message was: "+e.data)}catch(n){if(!(n instanceof SyntaxError))throw n;this._console.warn("WebSocket message parsing failed. Message was: "+e.data)}},Mopidy.prototype._handleResponse=function(e){if(!this._pendingRequests.hasOwnProperty(e.id))return this._console.warn("Unexpected response received. Message was:",e),void 0;var t=this._pendingRequests[e.id];delete this._pendingRequests[e.id],e.hasOwnProperty("result")?t.resolve(e.result):e.hasOwnProperty("error")?(t.reject(e.error),this._console.warn("Server returned error:",e.error)):(t.reject({message:"Response without 'result' or 'error' received",data:{response:e}}),this._console.warn("Response without 'result' or 'error' received. Message was:",e))},Mopidy.prototype._handleEvent=function(e){var t=e.event,n=e;delete n.event,this.emit("event:"+this._snakeToCamel(t),n)},Mopidy.prototype._getApiSpec=function(){return this._send({method:"core.describe"}).then(this._createApi.bind(this),this._handleWebSocketError).then(null,this._handleWebSocketError)},Mopidy.prototype._createApi=function(e){var t=function(e){return function(){var t=Array.prototype.slice.call(arguments);return this._send({method:e,params:t})}.bind(this)}.bind(this),n=function(e){var t=e.split(".");return t.length>=1&&"core"===t[0]&&(t=t.slice(1)),t},o=function(e){var t=this;return e.forEach(function(e){e=this._snakeToCamel(e),t[e]=t[e]||{},t=t[e]}.bind(this)),t}.bind(this),i=function(i){var r=n(i),s=this._snakeToCamel(r.slice(-1)[0]),c=o(r.slice(0,-1));c[s]=t(i),c[s].description=e[i].description,c[s].params=e[i].params}.bind(this);Object.keys(e).forEach(i),this.emit("state:online")},Mopidy.prototype._snakeToCamel=function(e){return e.replace(/(_[a-z])/g,function(e){return e.toUpperCase().replace("_","")})},"object"==typeof exports&&(exports.Mopidy=Mopidy); |