// Luna bus access. // // Talks to PalmServiceBridge directly rather than pulling in webOSTV.js: it is // the same object webOSTV.js wraps, it is injected into every webOS app, and // it means there is no third-party file to keep in sync. // // Opened in a desktop browser the bridge is absent, so everything falls back // to a small mock. That is what makes the UI developable without a TV. (function (global) { 'use strict'; var SERVICE = 'luna://org.webosbrew.audiocap.service/'; var HBCHANNEL = 'luna://org.webosbrew.hbchannel.service/'; var haveBridge = typeof global.PalmServiceBridge !== 'undefined'; // A call in flight. `cancel()` tears down a subscription. function Request(bridge) { this.bridge = bridge; this.cancelled = false; } Request.prototype.cancel = function () { this.cancelled = true; if (this.bridge && this.bridge.cancel) { this.bridge.cancel(); } }; // Low-level call. `onReply` fires once per reply, so subscriptions keep // calling it until cancelled. function call(uri, params, onReply, onError) { if (!haveBridge) { return global.LunaMock.call(uri, params, onReply, onError); } var bridge = new global.PalmServiceBridge(); var request = new Request(bridge); bridge.onservicecallback = function (raw) { if (request.cancelled) { return; } var reply; try { reply = JSON.parse(raw); } catch (e) { if (onError) { onError('Malformed reply from ' + uri); } return; } // Luna reports both its own failures and ours through returnValue. if (reply.returnValue === false) { if (onError) { onError(reply.errorText || reply.errorMessage || 'Call to ' + uri + ' failed'); } return; } if (onReply) { onReply(reply); } }; try { bridge.call(uri, JSON.stringify(params || {})); } catch (e) { if (onError) { onError(String(e)); } } return request; } var Luna = { available: haveBridge, // --- our service ------------------------------------------------------- start: function (patch, ok, fail) { return call(SERVICE + 'start', patch || {}, ok, fail); }, stop: function (ok, fail) { return call(SERVICE + 'stop', {}, ok, fail); }, subscribeStatus: function (ok, fail) { return call(SERVICE + 'getStatus', { subscribe: true }, ok, fail); }, getConfig: function (ok, fail) { return call(SERVICE + 'getConfig', {}, ok, fail); }, setConfig: function (patch, ok, fail) { return call(SERVICE + 'setConfig', { settings: patch }, ok, fail); }, resetConfig: function (ok, fail) { return call(SERVICE + 'resetConfig', {}, ok, fail); }, listBackends: function (ok, fail) { return call(SERVICE + 'listBackends', {}, ok, fail); }, listSinks: function (ok, fail) { return call(SERVICE + 'listSinks', {}, ok, fail); }, getDiagnostics: function (ok, fail) { return call(SERVICE + 'getDiagnostics', {}, ok, fail); }, // Ends the service process. Any later call starts a fresh one, which is // how the service picks up new bus permissions after being elevated. quit: function (ok, fail) { return call(SERVICE + 'quit', {}, ok, fail); }, // `clear` empties the ring buffer after reading it, so the reply is the // last thing anyone sees of those lines. getLogs: function (clear, ok, fail) { return call(SERVICE + 'getLogs', { clear: !!clear }, ok, fail); }, // --- Homebrew Channel -------------------------------------------------- // Used for the boot symlink. Needs the Homebrew Channel installed, which // it will be on any TV that can run this app. exec: function (command, ok, fail) { return call(HBCHANNEL + 'exec', { command: command }, ok, fail); }, // --- system ------------------------------------------------------------ getNetworkStatus: function (ok, fail) { return call('luna://com.palm.connectionmanager/getStatus', {}, ok, fail); }, }; global.Luna = Luna; })(window);