Загрузка данных
Windows PowerShell 5.1
(C) Корпорация Майкрософт (Microsoft Corporation). Все права защищены.
PS C:\Users\str> $root = 'C:\Temp\pepper42-build\wgt-staging'
PS C:\Users\str> $js = Join-Path $root 'static\js'
PS C:\Users\str>
PS C:\Users\str> function Show-Range {
>> param([string]$File, [int]$From, [int]$Count)
>> $lines = Get-Content -LiteralPath $File
>> $start = [Math]::Max(0, $From - 1)
>> $end = [Math]::Min($lines.Length - 1, $start + $Count - 1)
>> for ($i = $start; $i -le $end; $i++) {
>> '{0,4}: {1}' -f ($i + 1), $lines[$i]
>> }
>> }
PS C:\Users\str>
PS C:\Users\str> Write-Host "`n===== INDEX.JS: НАЧАЛО ====="
===== INDEX.JS: НАЧАЛО =====
PS C:\Users\str> Show-Range (Join-Path $js 'index.js') 1 100
1: var hosts = {}; // hosts is an associative array of NvHTTP objects, keyed by server UID
2: var activePolls = {}; // hosts currently being polled. An associated array of polling IDs, keyed by server UID
3: var pairingCert;
4: var myUniqueid = '0123456789ABCDEF'; // Use the same UID as other Moonlight clients to allow them to quit each other's games
5: var api; // `api` should only be set if we're in a host-specific screen. on the initial screen it should always be null.
6: var isInGame = false; // flag indicating whether the game stream started
7:
8: // Called by the common.js module.
9: function attachListeners() {
10: changeUiModeForNaClLoad();
11: $('.resolutionMenu li').on('click', saveResolution);
12: $('.framerateMenu li').on('click', saveFramerate);
13: $('#bitrateSlider').on('input', updateBitrateField); // input occurs every notch you slide
14: //$('#bitrateSlider').on('change', saveBitrate); //FIXME: it seems not working
15: $("#remoteAudioEnabledSwitch").on('click', saveRemoteAudio);
16: $("#mouseLockEnabledSwitch").on('click', saveMouseLock);
17: $('#optimizeGamesSwitch').on('click', saveOptimize);
18: $('#addHostCell').on('click', addHost);
19: $('#backIcon').on('click', showHostsAndSettingsMode);
20: $('#quitCurrentApp').on('click', stopGameWithConfirmation);
21: $(window).resize(fullscreenNaclModule);
22: var registerMenu = function registerMenu(elementId, view) {
23: $("#".concat(elementId)).on('click', function () {
24: if (view.isActive()) Navigation.pop();else Navigation.push(view);
25: });
26: };
27: registerMenu('selectResolution', Views.SelectResolutionMenu);
28: registerMenu('selectFramerate', Views.SelectFramerateMenu);
29: registerMenu('bandwidthMenu', Views.SelectBitrateMenu);
30: Controller.startWatching();
31: window.addEventListener('gamepadbuttonpressed', function (e) {
32: var pressed = e.detail.pressed;
33: var key = e.detail.key;
34: if (!pressed) return;
35: var gamepadMapping = {
36: 0: function _() {
37: return Navigation.accept();
38: },
39: 1: function _() {
40: return Navigation.back();
41: },
42: 8: function _() {
43: return Navigation.selectBtn();
44: },
45: 9: function _() {
46: return Navigation.startBtn();
47: },
48: 12: function _() {
49: return Navigation.up();
50: },
51: 13: function _() {
52: return Navigation.down();
53: },
54: 14: function _() {
55: return Navigation.left();
56: },
57: 15: function _() {
58: return Navigation.right();
59: }
60: };
61: if (gamepadMapping[key]) {
62: gamepadMapping[key]();
63: }
64: });
65: }
66: function changeUiModeForNaClLoad() {
67: $('#main-navigation').children().hide();
68: $("#main-content").children().not("#listener, #naclSpinner").hide();
69: $('#naclSpinnerMessage').text('Loading Moonlight plugin...');
70: $('#naclSpinner').css('display', 'inline-block');
71: }
72: function startPollingHosts() {
73: for (var hostUID in hosts) {
74: beginBackgroundPollingOfHost(hosts[hostUID]);
75: }
76: }
77: function stopPollingHosts() {
78: for (var hostUID in hosts) {
79: stopBackgroundPollingOfHost(hosts[hostUID]);
80: }
81: }
82: function restoreUiAfterNaClLoad() {
83: $('#main-navigation').children().not("#quitCurrentApp").show();
84: $("#main-content").children().not("#listener, #naclSpinner, #game-grid").show();
85: $('#naclSpinner').hide();
86: $('#loadingSpinner').css('display', 'none');
87: Navigation.push(Views.Hosts);
88: showHostsAndSettingsMode();
89: findNvService(function (finder, opt_error) {
90: if (finder.byService_['_nvstream._tcp']) {
91: var ips = Object.keys(finder.byService_['_nvstream._tcp']);
92: for (var i in ips) {
93: var ip = ips[i];
94: if (finder.byService_['_nvstream._tcp'][ip]) {
95: var mDnsDiscoveredHost = new NvHTTP(ip, myUniqueid);
96: mDnsDiscoveredHost.pollServer(function (returneMdnsDiscoveredHost) {
97: // Just drop this if the host doesn't respond
98: if (!returneMdnsDiscoveredHost.online) {
99: return;
100: }
PS C:\Users\str>
PS C:\Users\str> Write-Host "`n===== COMMON.JS: СОЗДАНИЕ EMBED ====="
===== COMMON.JS: СОЗДАНИЕ EMBED =====
PS C:\Users\str> Show-Range (Join-Path $js 'common.js') 1 205
1: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2: // Use of this source code is governed by a BSD-style license that can be
3: // found in the LICENSE file.
4:
5: // Set to true when loading a "Release" NaCl module, false when loading a
6: // "Debug" NaCl module.
7: var isRelease = true;
8:
9: // Javascript module pattern:
10: // see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript#Namespaces
11: // In essence, we define an anonymous function which is immediately called and
12: // returns a new object. The new object contains only the exported definitions;
13: // all other definitions in the anonymous function are inaccessible to external
14: // code.
15: var common = function () {
16: function isHostToolchain(tool) {
17: return tool == 'win' || tool == 'linux' || tool == 'mac';
18: }
19:
20: /**
21: * Return the mime type for NaCl plugin.
22: *
23: * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
24: * @return {string} The mime-type for the kind of NaCl plugin matching
25: * the given toolchain.
26: */
27: function mimeTypeForTool(tool) {
28: console.log('%c[mimeTypeForTool, common.js]', 'color: gray;', 'tool: ' + tool);
29: // For NaCl modules use application/x-nacl.
30: var mimetype = 'application/x-nacl';
31: if (isHostToolchain(tool)) {
32: mimetype = 'application/x-ppapi-release';
33: } else if (tool == 'pnacl') {
34: mimetype = 'application/x-nacl'; //FIXME: replaced from 'application/x-pnacl' to work for tizen didn't bother to correctly do it.
35: }
36: console.log('%c[updateStatus, common.js]', 'color: gray;', 'mimetype: ' + mimetype);
37: return mimetype;
38: }
39:
40: /**
41: * Check if the browser supports NaCl plugins.
42: *
43: * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
44: * @return {bool} True if the browser supports the type of NaCl plugin
45: * produced by the given toolchain.
46: */
47: function browserSupportsNaCl(tool) {
48: // Assume host toolchains always work with the given browser.
49: // The below mime-type checking might not work with
50: // --register-pepper-plugins.
51: if (isHostToolchain(tool)) {
52: return true;
53: }
54: console.log('%c[browserSupportsNaCl, common.js]', 'color: gray;', 'is NOT host toolchain for tool: ' + tool);
55: var mimetype = mimeTypeForTool(tool);
56: console.log('%c[browserSupportsNaCl, common.js]', 'color: gray;', 'mimetypes: ' + mimetype);
57: return navigator.mimeTypes[mimetype] !== undefined;
58: }
59:
60: /**
61: * Create the Native Client <embed> element as a child of the DOM element
62: * named "listener".
63: *
64: * @param {string} name The name of the example.
65: * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
66: * @param {string} path Directory name where .nmf file can be found.
67: * @param {number} width The width to create the plugin.
68: * @param {number} height The height to create the plugin.
69: * @param {Object} attrs Dictionary of attributes to set on the module.
70: */
71: function createNaClModule(name, tool, path, width, height, attrs) {
72: console.log('Parameters:', name, tool, path, width, height, attrs);
73: var moduleEl = document.createElement('embed');
74: moduleEl.setAttribute('name', 'nacl_module');
75: moduleEl.setAttribute('id', 'nacl_module');
76: moduleEl.setAttribute('width', width);
77: moduleEl.setAttribute('height', height);
78: moduleEl.setAttribute('path', path);
79: moduleEl.setAttribute('src', path + '/' + name + '.nmf');
80:
81: // Add any optional arguments
82: if (attrs) {
83: for (var key in attrs) {
84: moduleEl.setAttribute(key, attrs[key]);
85: console.log('After setting ' + key + ':', moduleEl);
86: }
87: }
88: var mimetype = mimeTypeForTool(tool);
89: moduleEl.setAttribute('type', mimetype);
90: console.log('%c[createNaClModule, common.js]', 'color: gray;', "moduleEl: " + moduleEl.outerHTML);
91:
92: // The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
93: // and a 'message' event listener attached. This wrapping method is used
94: // instead of attaching the event listeners directly to the <EMBED> element
95: // to ensure that the listeners are active before the NaCl module 'load'
96: // event fires.
97: var listenerDiv = document.getElementById('listener');
98: listenerDiv.appendChild(moduleEl);
99:
100: // Request the offsetTop property to force a relayout. As of Apr 10, 2014
101: // this is needed if the module is being loaded on a Chrome App's
102: // background page (see crbug.com/350445).
103: moduleEl.offsetTop;
104:
105: // Host plugins don't send a moduleDidLoad message. We'll fake it here.
106: var isHost = isHostToolchain(tool);
107: if (isHost) {
108: window.setTimeout(function () {
109: moduleEl.readyState = 1;
110: moduleEl.dispatchEvent(new CustomEvent('loadstart'));
111: moduleEl.readyState = 4;
112: moduleEl.dispatchEvent(new CustomEvent('load'));
113: moduleEl.dispatchEvent(new CustomEvent('loadend'));
114: }, 100); // 100 ms
115: }
116: }
117:
118: /**
119: * Add the default "load" and "message" event listeners to the element with
120: * id "listener".
121: *
122: * The "load" event is sent when the module is successfully loaded. The
123: * "message" event is sent when the naclModule posts a message using
124: * PPB_Messaging.PostMessage() (in C) or pp::Instance().PostMessage() (in
125: * C++).
126: */
127: function attachDefaultListeners() {
128: var listenerDiv = document.getElementById('listener');
129: listenerDiv.addEventListener('load', moduleDidLoad, true);
130: listenerDiv.addEventListener('message', handleMessage, true);
131: listenerDiv.addEventListener('error', handleError, true);
132: listenerDiv.addEventListener('crash', handleCrash, true);
133: if (typeof window.attachListeners !== 'undefined') {
134: window.attachListeners();
135: }
136: }
137:
138: /**
139: * Called when the NaCl module fails to load.
140: *
141: * This event listener is registered in createNaClModule above.
142: */
143: function handleError(event) {
144: // We can't use common.naclModule yet because the module has not been
145: // loaded.
146: console.log('%c[handleError, common.js]', 'color: red;', event);
147: var moduleEl = document.getElementById('nacl_module');
148: updateStatus('ERROR [' + moduleEl.lastError + ']');
149: }
150:
151: /**
152: * Called when the Browser can not communicate with the Module
153: *
154: * This event listener is registered in attachDefaultListeners above.
155: */
156: function handleCrash(event) {
157: console.log('%c[handleCrash, common.js]', 'color: red;', event);
158: if (common.naclModule.exitStatus == -1) {
159: updateStatus('CRASHED');
160: } else {
161: updateStatus('EXITED [' + common.naclModule.exitStatus + ']');
162: }
163: if (typeof window.handleCrash !== 'undefined') {
164: window.handleCrash(common.naclModule.lastError);
165: }
166: }
167:
168: /**
169: * Called when the NaCl module is loaded.
170: *
171: * This event listener is registered in attachDefaultListeners above.
172: */
173: function moduleDidLoad() {
174: common.naclModule = document.getElementById('nacl_module');
175: updateStatus('RUNNING');
176: if (typeof window.moduleDidLoad !== 'undefined') {
177: window.moduleDidLoad();
178: }
179: }
180:
181: /**
182: * Hide the NaCl module's embed element.
183: *
184: * We don't want to hide by default; if we do, it is harder to determine that
185: * a plugin failed to load. Instead, call this function inside the example's
186: * "moduleDidLoad" function.
187: *
188: */
189: function hideModule() {
190: // Setting common.naclModule.style.display = "None" doesn't work; the
191: // module will no longer be able to receive postMessages.
192: common.naclModule.style.height = '0';
193: }
194:
195: /**
196: * Remove the NaCl module from the page.
197: */
198: function removeModule() {
199: console.log('%c[removeModule, common.js]', 'color: gray;', "removing module...");
200: common.naclModule.parentNode.removeChild(common.naclModule);
201: common.naclModule = null;
202: }
203:
204: /**
205: * Return true when |s| starts with the string |prefix|.
PS C:\Users\str>
PS C:\Users\str> Write-Host "`n===== COMMON.JS: ОБРАБОТЧИКИ И СОЗДАНИЕ МОДУЛЯ ====="
===== COMMON.JS: ОБРАБОТЧИКИ И СОЗДАНИЕ МОДУЛЯ =====
PS C:\Users\str> Show-Range (Join-Path $js 'common.js') 75 135
75: moduleEl.setAttribute('id', 'nacl_module');
76: moduleEl.setAttribute('width', width);
77: moduleEl.setAttribute('height', height);
78: moduleEl.setAttribute('path', path);
79: moduleEl.setAttribute('src', path + '/' + name + '.nmf');
80:
81: // Add any optional arguments
82: if (attrs) {
83: for (var key in attrs) {
84: moduleEl.setAttribute(key, attrs[key]);
85: console.log('After setting ' + key + ':', moduleEl);
86: }
87: }
88: var mimetype = mimeTypeForTool(tool);
89: moduleEl.setAttribute('type', mimetype);
90: console.log('%c[createNaClModule, common.js]', 'color: gray;', "moduleEl: " + moduleEl.outerHTML);
91:
92: // The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
93: // and a 'message' event listener attached. This wrapping method is used
94: // instead of attaching the event listeners directly to the <EMBED> element
95: // to ensure that the listeners are active before the NaCl module 'load'
96: // event fires.
97: var listenerDiv = document.getElementById('listener');
98: listenerDiv.appendChild(moduleEl);
99:
100: // Request the offsetTop property to force a relayout. As of Apr 10, 2014
101: // this is needed if the module is being loaded on a Chrome App's
102: // background page (see crbug.com/350445).
103: moduleEl.offsetTop;
104:
105: // Host plugins don't send a moduleDidLoad message. We'll fake it here.
106: var isHost = isHostToolchain(tool);
107: if (isHost) {
108: window.setTimeout(function () {
109: moduleEl.readyState = 1;
110: moduleEl.dispatchEvent(new CustomEvent('loadstart'));
111: moduleEl.readyState = 4;
112: moduleEl.dispatchEvent(new CustomEvent('load'));
113: moduleEl.dispatchEvent(new CustomEvent('loadend'));
114: }, 100); // 100 ms
115: }
116: }
117:
118: /**
119: * Add the default "load" and "message" event listeners to the element with
120: * id "listener".
121: *
122: * The "load" event is sent when the module is successfully loaded. The
123: * "message" event is sent when the naclModule posts a message using
124: * PPB_Messaging.PostMessage() (in C) or pp::Instance().PostMessage() (in
125: * C++).
126: */
127: function attachDefaultListeners() {
128: var listenerDiv = document.getElementById('listener');
129: listenerDiv.addEventListener('load', moduleDidLoad, true);
130: listenerDiv.addEventListener('message', handleMessage, true);
131: listenerDiv.addEventListener('error', handleError, true);
132: listenerDiv.addEventListener('crash', handleCrash, true);
133: if (typeof window.attachListeners !== 'undefined') {
134: window.attachListeners();
135: }
136: }
137:
138: /**
139: * Called when the NaCl module fails to load.
140: *
141: * This event listener is registered in createNaClModule above.
142: */
143: function handleError(event) {
144: // We can't use common.naclModule yet because the module has not been
145: // loaded.
146: console.log('%c[handleError, common.js]', 'color: red;', event);
147: var moduleEl = document.getElementById('nacl_module');
148: updateStatus('ERROR [' + moduleEl.lastError + ']');
149: }
150:
151: /**
152: * Called when the Browser can not communicate with the Module
153: *
154: * This event listener is registered in attachDefaultListeners above.
155: */
156: function handleCrash(event) {
157: console.log('%c[handleCrash, common.js]', 'color: red;', event);
158: if (common.naclModule.exitStatus == -1) {
159: updateStatus('CRASHED');
160: } else {
161: updateStatus('EXITED [' + common.naclModule.exitStatus + ']');
162: }
163: if (typeof window.handleCrash !== 'undefined') {
164: window.handleCrash(common.naclModule.lastError);
165: }
166: }
167:
168: /**
169: * Called when the NaCl module is loaded.
170: *
171: * This event listener is registered in attachDefaultListeners above.
172: */
173: function moduleDidLoad() {
174: common.naclModule = document.getElementById('nacl_module');
175: updateStatus('RUNNING');
176: if (typeof window.moduleDidLoad !== 'undefined') {
177: window.moduleDidLoad();
178: }
179: }
180:
181: /**
182: * Hide the NaCl module's embed element.
183: *
184: * We don't want to hide by default; if we do, it is harder to determine that
185: * a plugin failed to load. Instead, call this function inside the example's
186: * "moduleDidLoad" function.
187: *
188: */
189: function hideModule() {
190: // Setting common.naclModule.style.display = "None" doesn't work; the
191: // module will no longer be able to receive postMessages.
192: common.naclModule.style.height = '0';
193: }
194:
195: /**
196: * Remove the NaCl module from the page.
197: */
198: function removeModule() {
199: console.log('%c[removeModule, common.js]', 'color: gray;', "removing module...");
200: common.naclModule.parentNode.removeChild(common.naclModule);
201: common.naclModule = null;
202: }
203:
204: /**
205: * Return true when |s| starts with the string |prefix|.
206: *
207: * @param {string} s The string to search.
208: * @param {string} prefix The prefix to search for in |s|.
209: */
PS C:\Users\str> Show-Range (Join-Path $js 'common.js') 125 205
125: * C++).
126: */
127: function attachDefaultListeners() {
128: var listenerDiv = document.getElementById('listener');
129: listenerDiv.addEventListener('load', moduleDidLoad, true);
130: listenerDiv.addEventListener('message', handleMessage, true);
131: listenerDiv.addEventListener('error', handleError, true);
132: listenerDiv.addEventListener('crash', handleCrash, true);
133: if (typeof window.attachListeners !== 'undefined') {
134: window.attachListeners();
135: }
136: }
137:
138: /**
139: * Called when the NaCl module fails to load.
140: *
141: * This event listener is registered in createNaClModule above.
142: */
143: function handleError(event) {
144: // We can't use common.naclModule yet because the module has not been
145: // loaded.
146: console.log('%c[handleError, common.js]', 'color: red;', event);
147: var moduleEl = document.getElementById('nacl_module');
148: updateStatus('ERROR [' + moduleEl.lastError + ']');
149: }
150:
151: /**
152: * Called when the Browser can not communicate with the Module
153: *
154: * This event listener is registered in attachDefaultListeners above.
155: */
156: function handleCrash(event) {
157: console.log('%c[handleCrash, common.js]', 'color: red;', event);
158: if (common.naclModule.exitStatus == -1) {
159: updateStatus('CRASHED');
160: } else {
161: updateStatus('EXITED [' + common.naclModule.exitStatus + ']');
162: }
163: if (typeof window.handleCrash !== 'undefined') {
164: window.handleCrash(common.naclModule.lastError);
165: }
166: }
167:
168: /**
169: * Called when the NaCl module is loaded.
170: *
171: * This event listener is registered in attachDefaultListeners above.
172: */
173: function moduleDidLoad() {
174: common.naclModule = document.getElementById('nacl_module');
175: updateStatus('RUNNING');
176: if (typeof window.moduleDidLoad !== 'undefined') {
177: window.moduleDidLoad();
178: }
179: }
180:
181: /**
182: * Hide the NaCl module's embed element.
183: *
184: * We don't want to hide by default; if we do, it is harder to determine that
185: * a plugin failed to load. Instead, call this function inside the example's
186: * "moduleDidLoad" function.
187: *
188: */
189: function hideModule() {
190: // Setting common.naclModule.style.display = "None" doesn't work; the
191: // module will no longer be able to receive postMessages.
192: common.naclModule.style.height = '0';
193: }
194:
195: /**
196: * Remove the NaCl module from the page.
197: */
198: function removeModule() {
199: console.log('%c[removeModule, common.js]', 'color: gray;', "removing module...");
200: common.naclModule.parentNode.removeChild(common.naclModule);
201: common.naclModule = null;
202: }
203:
204: /**
205: * Return true when |s| starts with the string |prefix|.
206: *
207: * @param {string} s The string to search.
208: * @param {string} prefix The prefix to search for in |s|.
209: */
210: function startsWith(s, prefix) {
211: // indexOf would search the entire string, lastIndexOf(p, 0) only checks at
212: // the first index. See: http://stackoverflow.com/a/4579228
213: return s.lastIndexOf(prefix, 0) === 0;
214: }
215:
216: /** Maximum length of logMessageArray. */
217: var kMaxLogMessageLength = 20;
218:
219: /** An array of messages to display in the element with id "log". */
220: var logMessageArray = [];
221:
222: /**
223: * Add a message to an element with id "log".
224: *
225: * This function is used by the default "log:" message handler.
226: *
227: * @param {string} message The message to log.
228: */
229: function logMessage(message) {
230: logMessageArray.push(message);
231: if (logMessageArray.length > kMaxLogMessageLength) logMessageArray.shift();
232: document.getElementById('log').textContent = logMessageArray.join('\n');
233: console.log(message);
234: }
235:
236: /**
237: */
238: var defaultMessageTypes = {
239: 'alert': alert,
240: 'log': logMessage
241: };
242:
243: /**
244: * Called when the NaCl module sends a message to JavaScript (via
245: * PPB_Messaging.PostMessage())
246: *
247: * This event listener is registered in createNaClModule above.
248: *
249: * @param {Event} message_event A message event. message_event.data contains
250: * the data sent from the NaCl module.
251: */
252: function handleMessage(message_event) {
253: if (typeof message_event.data === 'string') {
254: for (var type in defaultMessageTypes) {
255: if (defaultMessageTypes.hasOwnProperty(type)) {
256: if (startsWith(message_event.data, type + ':')) {
257: func = defaultMessageTypes[type];
258: func(message_event.data.slice(type.length + 1));
259: return;
260: }
261: }
262: }
263: }
264: if (typeof window.handleMessage !== 'undefined') {
265: window.handleMessage(message_event);
266: } else {
267: logMessage('Unhandled message: ' + message_event.data);
268: }
269: }
270:
271: /**
272: * Called when the DOM content has loaded; i.e. the page's document is fully
273: * parsed. At this point, we can safely query any elements in the document via
274: * document.querySelector, document.getElementById, etc.
275: *
276: * @param {string} name The name of the example.
277: * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
278: * @param {string} path Directory name where .nmf file can be found.
279: * @param {number} width The width to create the plugin.
280: * @param {number} height The height to create the plugin.
281: * @param {Object} attrs Optional dictionary of additional attributes.
282: */
283: function domContentLoaded(name, tool, path, width, height, attrs) {
284: // If the page loads before the Native Client module loads, then set the
285: // status message indicating that the module is still loading. Otherwise,
286: // do not change the status message.
287: updateStatus('Page loaded.');
288: if (!browserSupportsNaCl(tool)) {
289: updateStatus('Browser does not support NaCl (' + tool + '), or NaCl is disabled');
290: } else if (common.naclModule == null) {
291: updateStatus('Browser supports NaCl (' + tool + ')');
292: updateStatus('Creating embed: ' + tool);
293:
294: // We use a non-zero sized embed to give Chrome space to place the bad
295: // plug-in graphic, if there is a problem.
296: width = typeof width !== 'undefined' ? width : 200;
297: height = typeof height !== 'undefined' ? height : 200;
298: attachDefaultListeners();
299: createNaClModule(name, tool, path, width, height, attrs);
300: } else {
301: // It's possible that the Native Client module onload event fired
302: // before the page's onload event. In this case, the status message
303: // will reflect 'SUCCESS', but won't be displayed. This call will
304: // display the current message.
305: updateStatus('Waiting.');
306: }
307: }
308:
309: /** Saved text to display in the element with id 'statusField'. */
310: var statusText = 'NO-STATUSES';
311:
312: /**
313: * Set the global status message. If the element with id 'statusField'
314: * exists, then set its HTML to the status message as well.
315: *
316: * @param {string} opt_message The message to set. If null or undefined, then
317: * set element 'statusField' to the message from the last call to
318: * updateStatus.
319: */
320: function updateStatus(opt_message) {
321: if (opt_message) {
322: statusText = opt_message;
323: console.log('%c[updateStatus, common.js]', 'color: gray;', statusText);
324: }
325: var statusField = document.getElementById('statusField');
326: if (statusField) {
327: statusField.innerHTML = statusText;
328: }
329: }
PS C:\Users\str>
PS C:\Users\str> Write-Host "`n===== MESSAGES.JS: ЗАГРУЗКА СЕРТИФИКАТОВ ====="
===== MESSAGES.JS: ЗАГРУЗКА СЕРТИФИКАТОВ =====
PS C:\Users\str> Show-Range (Join-Path $js 'messages.js') 1 125
1: var callbacks = {};
2: var callbacks_ids = 1;
3:
4: /**
5: * var sendMessage - Sends a message with arguments to the NaCl module
6: *
7: * @param {String} method A named method
8: * @param {(String|Array)} params An array of options or a signle string
9: * @return {void} The NaCl module calls back trought the handleMessage method
10: */
11: var sendMessage = function sendMessage(method, params) {
12: return new Promise(function (resolve, reject) {
13: var id = callbacks_ids++;
14: callbacks[id] = {
15: 'resolve': resolve,
16: 'reject': reject
17: };
18: common.naclModule.postMessage({
19: 'callbackId': id,
20: 'method': method,
21: 'params': params
22: });
23: });
24: };
25:
26: /**
27: * handleMessage - Handles messages from the NaCl module
28: *
29: * @param {Object} msg An object given by the NaCl module
30: * @return {void}
31: */
32: function handleMessage(msg) {
33: if (msg.data.callbackId && callbacks[msg.data.callbackId]) {
34: // if it's a callback, treat it as such
35: callbacks[msg.data.callbackId][msg.data.type](msg.data.ret);
36: delete callbacks[msg.data.callbackId];
37: } else {
38: // else, it's just info, or an event
39: console.log('%c[messages.js, handleMessage]', 'color:gray;', 'Message data: ', msg.data);
40: if (msg.data.indexOf('streamTerminated: ') === 0) {
41: // if it's a recognized event, notify the appropriate function
42: // Release our keep awake request
43: // if (runningOnChrome) {
44: // chrome.power.releaseKeepAwake();
45: // }
46:
47: // Show a termination snackbar message if the termination was unexpected
48: var errorCode = parseInt(msg.data.replace('streamTerminated: ', ''));
49: switch (errorCode) {
50: case 0:
51: // ML_ERROR_GRACEFUL_TERMINATION
52: break;
53: case -100:
54: // ML_ERROR_NO_VIDEO_TRAFFIC
55: snackbarLogLong("No video received from host. Check the host PC's firewall and port forwarding rules.");
56: break;
57: case -101:
58: // ML_ERROR_NO_VIDEO_FRAME
59: snackbarLogLong("Your network connection isn't performing well. Reduce your video bitrate setting or try a faster connection.");
60: break;
61: default:
62: snackbarLogLong("Connection terminated");
63: break;
64: }
65: api.refreshServerInfo().then(function (ret) {
66: // Return to app list with new currentgame
67: showApps(api);
68: }, function () {
69: // Return to app list anyway
70: showApps(api);
71: });
72: } else if (msg.data === 'Connection Established') {
73: $('#loadingSpinner').css('display', 'none');
74: $('body').css('backgroundColor', 'black');
75:
76: // Keep the display awake while streaming
77: // if (runningOnChrome) {
78: // chrome.power.requestKeepAwake("display");
79: // }
80: } else if (msg.data.indexOf('ProgressMsg: ') === 0) {
81: $('#loadingMessage').text(msg.data.replace('ProgressMsg: ', ''));
82: } else if (msg.data.indexOf('TransientMsg: ') === 0) {
83: snackbarLog(msg.data.replace('TransientMsg: ', ''));
84: } else if (msg.data.indexOf('DialogMsg: ') === 0) {
85: // FIXME: Really use a dialog
86: snackbarLogLong(msg.data.replace('DialogMsg: ', ''));
87: } else if (msg.data === 'displayVideo') {
88: // Show the video stream now
89: $("#nacl_module")[0].style.opacity = 1.0;
90: } else if (msg.data.indexOf('controllerRumble: ') === 0) {
91: var eventData = msg.data.split(' ')[1].split(',');
92: var gamepadIdx = parseInt(eventData[0]);
93: var weakMagnitude = parseFloat(eventData[1]);
94: var strongMagnitude = parseFloat(eventData[2]);
95: console.log("Playing rumble on gamepad " + gamepadIdx + " with weakMagnitude " + weakMagnitude + " and strongMagnitude " + strongMagnitude);
96:
97: // We may not actually have a gamepad at this index.
98: // Even if we do have a gamepad, it may not have a vibrationActuator associated with it.
99: gamepad.vibrationActuator.playEffect('dual-rumble', {
100: startDelay: 0,
101: duration: 5000,
102: // Moonlight should be sending another rumble event when stopping.
103: weakMagnitude: weakMagnitude,
104: strongMagnitude: strongMagnitude
105: });
106: }
107: }
108: }
PS C:\Users\str>
PS C:\Users\str> Write-Host "`n===== INDEX.JS: ЗАПУСК И ВОССТАНОВЛЕНИЕ UI ====="
===== INDEX.JS: ЗАПУСК И ВОССТАНОВЛЕНИЕ UI =====
PS C:\Users\str> Show-Range (Join-Path $js 'index.js') 55 115
55: return Navigation.left();
56: },
57: 15: function _() {
58: return Navigation.right();
59: }
60: };
61: if (gamepadMapping[key]) {
62: gamepadMapping[key]();
63: }
64: });
65: }
66: function changeUiModeForNaClLoad() {
67: $('#main-navigation').children().hide();
68: $("#main-content").children().not("#listener, #naclSpinner").hide();
69: $('#naclSpinnerMessage').text('Loading Moonlight plugin...');
70: $('#naclSpinner').css('display', 'inline-block');
71: }
72: function startPollingHosts() {
73: for (var hostUID in hosts) {
74: beginBackgroundPollingOfHost(hosts[hostUID]);
75: }
76: }
77: function stopPollingHosts() {
78: for (var hostUID in hosts) {
79: stopBackgroundPollingOfHost(hosts[hostUID]);
80: }
81: }
82: function restoreUiAfterNaClLoad() {
83: $('#main-navigation').children().not("#quitCurrentApp").show();
84: $("#main-content").children().not("#listener, #naclSpinner, #game-grid").show();
85: $('#naclSpinner').hide();
86: $('#loadingSpinner').css('display', 'none');
87: Navigation.push(Views.Hosts);
88: showHostsAndSettingsMode();
89: findNvService(function (finder, opt_error) {
90: if (finder.byService_['_nvstream._tcp']) {
91: var ips = Object.keys(finder.byService_['_nvstream._tcp']);
92: for (var i in ips) {
93: var ip = ips[i];
94: if (finder.byService_['_nvstream._tcp'][ip]) {
95: var mDnsDiscoveredHost = new NvHTTP(ip, myUniqueid);
96: mDnsDiscoveredHost.pollServer(function (returneMdnsDiscoveredHost) {
97: // Just drop this if the host doesn't respond
98: if (!returneMdnsDiscoveredHost.online) {
99: return;
100: }
101: if (hosts[returneMdnsDiscoveredHost.serverUid] != null) {
102: // if we're seeing a host we've already seen before, update it for the current local IP.
103: hosts[returneMdnsDiscoveredHost.serverUid].address = returneMdnsDiscoveredHost.address;
104: hosts[returneMdnsDiscoveredHost.serverUid].updateExternalAddressIP4();
105: } else {
106: // Host must be in the grid before starting background polling
107: addHostToGrid(returneMdnsDiscoveredHost, true);
108: beginBackgroundPollingOfHost(returneMdnsDiscoveredHost);
109: }
110: saveHosts();
111: });
112: }
113: }
114: }
115: });
116: }
117: function beginBackgroundPollingOfHost(host) {
118: var el = document.querySelector('#hostgrid-' + host.serverUid);
119: if (host.online) {
120: el.classList.remove('host-cell-inactive');
121: // The host was already online. Just start polling in the background now.
122: activePolls[host.serverUid] = window.setInterval(function () {
123: // every 5 seconds, poll at the address we know it was live at
124: host.pollServer(function () {
125: if (host.online) {
126: el.classList.remove('host-cell-inactive');
127: } else {
128: el.classList.add('host-cell-inactive');
129: }
130: });
131: }, 5000);
132: } else {
133: el.classList.add('host-cell-inactive');
134: // The host was offline, so poll immediately.
135: host.pollServer(function () {
136: if (host.online) {
137: el.classList.remove('host-cell-inactive');
138: } else {
139: el.classList.add('host-cell-inactive');
140: }
141:
142: // Now start background polling
143: activePolls[host.serverUid] = window.setInterval(function () {
144: // every 5 seconds, poll at the address we know it was live at
145: host.pollServer(function () {
146: if (host.online) {
147: el.classList.remove('host-cell-inactive');
148: } else {
149: el.classList.add('host-cell-inactive');
150: }
151: });
152: }, 5000);
153: });
154: }
155: }
156: function stopBackgroundPollingOfHost(host) {
157: console.log('%c[index.js, backgroundPolling]', 'color: green;', 'Stopping background polling of host ' + host.serverUid + '\n', host, host.toString()); //Logging both object (for console) and toString-ed object (for text logs)
158: window.clearInterval(activePolls[host.serverUid]);
159: delete activePolls[host.serverUid];
160: }
161: function snackbarLog(givenMessage) {
162: console.log('%c[index.js, snackbarLog]', 'color: green;', givenMessage);
163: var data = {
164: message: givenMessage,
165: timeout: 2000
166: };
167: document.querySelector('#snackbar').MaterialSnackbar.showSnackbar(data);
168: }
169: function snackbarLogLong(givenMessage) {
PS C:\Users\str> Show-Range (Join-Path $js 'index.js') 680 785
680: var status_code = $root.attr('status_code');
681: if (status_code != 200) {
682: var status_message = $root.attr('status_message');
683: if (status_code == 4294967295 && status_message == 'Invalid') {
684: // Special case handling an audio capture error which GFE doesn't
685: // provide any useful status message for.
686: status_code = 418;
687: status_message = 'Missing audio capture device. Reinstall GeForce Experience.';
688: }
689: snackbarLog('Error ' + status_code + ': ' + status_message);
690: showApps(host);
691: return;
692: }
693: sendMessage('startRequest', [host.address, streamWidth, streamHeight, frameRate, bitrate.toString(), rikey, rikeyid.toString(), mouse_lock_enabled, host.appVersion, host.gfeVersion, $root.find('sessionUrl0').text().trim()]);
694: }, function (failedLaunchApp) {
695: console.error('%c[index.js, launchApp]', 'color: green;', 'Failed to launch app width id: ' + appID + '\nReturned error was: ' + failedLaunchApp);
696: showApps(host);
697: return;
698: });
699: });
700: });
701: }
702: function playGameMode() {
703: console.log('%c[index.js, playGameMode]', 'color:green;', 'Entering play game mode');
704: isInGame = true;
705: $("#main-navigation").hide();
706: $("#main-content").children().not("#listener, #loadingSpinner").hide();
707: $("#main-content").addClass("fullscreen");
708: $("#listener").addClass("fullscreen");
709:
710: // Hide the NaCl module until the first frame is rendered
711: $("#nacl_module")[0].style.opacity = 0.0;
712: fullscreenNaclModule();
713: $('#loadingSpinner').css('display', 'inline-block');
714: Navigation.stop();
715: }
716:
717: // Maximize the size of the nacl module by scaling and resizing appropriately
718: function fullscreenNaclModule() {
719: var streamWidth = $('#selectResolution').data('value').split(':')[0];
720: var streamHeight = $('#selectResolution').data('value').split(':')[1];
721: var screenWidth = window.innerWidth;
722: var screenHeight = window.innerHeight;
723: var xRatio = screenWidth / streamWidth;
724: var yRatio = screenHeight / streamHeight;
725: var zoom = Math.min(xRatio, yRatio);
726: var module = $("#nacl_module")[0];
727: module.width = zoom * streamWidth;
728: module.height = zoom * streamHeight;
729: module.style.marginTop = (screenHeight - module.height) / 2 + "px";
730: }
731: function stopGameWithConfirmation() {
732: if (api.currentGame === 0) {
733: snackbarLog('Nothing was running');
734: } else {
735: api.getAppById(api.currentGame).then(function (currentGame) {
736: var quitAppDialog = document.querySelector('#quitAppDialog');
737: document.getElementById('quitAppDialogText').innerHTML = ' Are you sure you would like to quit ' + currentGame.title + '? Unsaved progress will be lost.';
738: quitAppDialog.showModal();
739: Navigation.push(Views.CloseAppDialog);
740: $('#cancelQuitApp').off('click');
741: $('#cancelQuitApp').on('click', function () {
742: console.log('%c[index.js, stopGameWithConfirmation]', 'color:green;', 'Closing app dialog, and returning');
743: quitAppDialog.close();
744: Navigation.pop();
745: });
746: $('#continueQuitApp').off('click');
747: $('#continueQuitApp').on('click', function () {
748: console.log('%c[index.js, stopGameWithConfirmation]', 'color:green;', 'Stopping game, and closing app dialog, and returning');
749: stopGame(api);
750: quitAppDialog.close();
751: Navigation.pop();
752: });
753: });
754: }
755: }
756: function stopGame(host, callbackFunction) {
757: isInGame = false;
758: if (!host.paired) {
759: return;
760: }
761: host.refreshServerInfo().then(function (ret) {
762: host.getAppById(host.currentGame).then(function (runningApp) {
763: if (!runningApp) {
764: snackbarLog('Nothing was running');
765: return;
766: }
767: var appName = runningApp.title;
768: snackbarLog('Stopping ' + appName);
769: host.quitApp().then(function (ret2) {
770: host.refreshServerInfo().then(function (ret3) {
771: // refresh to show no app is currently running.
772: showApps(host);
773: if (typeof callbackFunction === "function") callbackFunction();
774: }, function (failedRefreshInfo2) {
775: console.error('%c[index.js, stopGame]', 'color:green;', 'Failed to refresh server info! Returned error was:' + failedRefreshInfo + ' and failed server was:', host, host.toString());
776: });
777: }, function (failedQuitApp) {
778: console.error('%c[index.js, stopGame]', 'color:green;', 'Failed to quit app! Returned error was:' + failedQuitApp);
779: });
780: }, function (failedGetApp) {
781: console.error('%c[index.js, stopGame]', 'color:green;', 'Failed to get app ID! Returned error was:' + failedRefreshInfo);
782: });
783: }, function (failedRefreshInfo) {
784: console.error('%c[index.js, stopGame]', 'color:green;', 'Failed to refresh server info! Returned error was:' + failedRefreshInfo);
785: });
786: }
787: var indexedDB = null;
788: var dbVersion = 1.0;
789: var db = null;
790: var dbName = 'GameStreamingDB';
791: var storeName = 'GameStreamingStore';
792:
793: // Based on example from
794: // https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/
795: function createObjectStore(dataBase) {
796: if (!dataBase.objectStoreNames.contains(storeName)) {
797: dataBase.createObjectStore(storeName);
798: }
799: }
800: function openIndexDB(callback) {
801: if (db) {
802: // Database already opened
803: callback();
804: return;
805: }
806: console.log('Opening IndexDB');
807: if (!indexedDB) {
808: indexedDB = self.indexedDB;
809: }
810:
811: // Create/open database
812: var request = indexedDB.open(dbName, dbVersion);
813: request.onerror = function (event) {
814: console.error('Error creating/accessing IndexedDB database', event);
815: };
816: request.onsuccess = function (event) {
817: console.log('Success creating/accessing IndexedDB database');
818: db = request.result;
819: db.onerror = function (event) {
820: console.error('Error creating/accessing IndexedDB database', event);
821: };
822: callback();
823: };
824: request.onupgradeneeded = function (event) {
825: createObjectStore(event.target.result);
826: };
827: }
828: function callCb(key, value, callbackFunction) {
829: var obj = {};
830: obj[key] = value;
831: callbackFunction(obj);
832: }
833: function getData(key, callbackFunction) {
834: var cb = function cb() {
835: try {
836: var transaction = db.transaction(storeName, 'readonly');
837: var readRequest = transaction.objectStore(storeName).get(key);
838:
839: // Retrieve the data that was stored
840: readRequest.onsuccess = function (event) {
841: console.log('Read data from the DB key: ' + key + ' value: ' + readRequest.result);
842: var value = null;
843: if (readRequest.result) {
844: value = JSON.parse(readRequest.result);
845: }
846: callCb(key, value, callbackFunction);
847: };
848: transaction.onerror = function (e) {
849: console.error('Error reading data at key: "' + key + '" from IndexDB: ' + e);
850: callCb(key, value, callbackFunction);
851: };
852: } catch (e) {
853: console.log('getData: caught exception while reading key:' + key);
854: console.error(e);
855: callCb(key, value, callbackFunction);
856: }
857: };
858: if (db) {
859: cb();
860: } else {
861: openIndexDB(cb);
862: }
863: }
864: function storeData(key, data, callbackFunction) {
865: var cb = function cb() {
866: try {
867: var transaction = db.transaction(storeName, 'readwrite'); //open a transaction to the database
868: var put = transaction.objectStore(storeName).put(JSON.stringify(data), key);
869: transaction.oncomplete = function (e) {
870: console.log('Data at key: ' + key + ' stored as: ' + JSON.stringify(data));
871: if (callbackFunction) {
872: callbackFunction();
873: }
874: };
875: transaction.onerror = function (e) {
876: console.error('Error storing data in IndexDB: ' + e);
877: };
878: } catch (e) {
879: console.log('storeData: caught exception while storing key:' + key);
880: console.error(e);
881: }
882: };
883: if (db) {
884: cb();
885: } else {
886: openIndexDB(cb);
887: }
888: }
889: function saveResolution() {
890: var chosenResolution = $(this).data('value');
891: $('#selectResolution').text($(this).text()).data('value', chosenResolution);
892: storeData('resolution', chosenResolution, null);
893: updateDefaultBitrate();
894: Navigation.pop();
895: }
896: function saveOptimize() {
897: // MaterialDesignLight uses the mouseup trigger, so we give it some time to change the class name before
898: // checking the new state
899: setTimeout(function () {
900: var chosenOptimize = $("#optimizeGamesSwitch").parent().hasClass('is-checked');
901: console.log('%c[index.js, saveOptimize]', 'color: green;', 'Saving optimize state : ' + chosenOptimize);
902: storeData('optimize', chosenOptimize, null);
903: }, 100);
904: }
905: function saveFramerate() {
906: var chosenFramerate = $(this).data('value');
907: $('#selectFramerate').text($(this).text()).data('value', chosenFramerate);
908: storeData('frameRate', chosenFramerate, null);
909: updateDefaultBitrate();
910: Navigation.pop();
911: }
912:
913: // storing data in chrome.storage takes the data as an object, and shoves it into JSON to store
914: // unfortunately, objects with function instances (classes) are stripped of their function instances when converted to a raw object
915: // so we cannot forget to revive the object after we load it.
916: function saveHosts() {
917: storeData('hosts', hosts, null);
918: }
919: function saveBitrate() {
920: storeData('bitrate', $('#bitrateSlider').val(), null);
921: }
922: function saveRemoteAudio() {
923: // MaterialDesignLight uses the mouseup trigger, so we give it some time to change the class name before
924: // checking the new state
925: setTimeout(function () {
926: var remoteAudioState = $("#remoteAudioEnabledSwitch").parent().hasClass('is-checked');
927: console.log('%c[index.js, saveRemoteAudio]', 'color: green;', 'Saving remote audio state : ' + remoteAudioState);
928: storeData('remoteAudio', remoteAudioState, null);
929: }, 100);
930: }
931: function saveMouseLock() {
932: // MaterialDesignLight uses the mouseup trigger, so we give it some time to change the class name before
933: // checking the new state
934: setTimeout(function () {
935: var mouseLockState = $("#mouseLockEnabledSwitch").parent().hasClass('is-checked');
936: console.log('%c[index.js, saveMouseLock]', 'color: green;', 'Saving mouse lock state : ' + mouseLockState);
937: storeData('mouseLock', mouseLockState, null);
938: }, 100);
939: }
940: function updateDefaultBitrate() {
941: var res = $('#selectResolution').data('value');
942: var frameRate = $('#selectFramerate').data('value').toString();
943:
944: // These quality presets include video resolution like 480p, 720p, 1080p, 1440p, 2160p (4K) and video frame rate like 30 FPS and 60 FPS
945: if (res === "858:480") {
946: if (frameRate === "30") {
947: // 480p, 30 FPS
948: $('#bitrateSlider')[0].MaterialSlider.change('2');
949: } else {
950: // 480p, 60 FPS
951: $('#bitrateSlider')[0].MaterialSlider.change('4');
952: }
953: } else if (res === "1280:720") {
954: if (frameRate === "30") {
955: // 720p, 30 FPS
956: $('#bitrateSlider')[0].MaterialSlider.change('5');
957: } else {
958: // 720p, 60 FPS
959: $('#bitrateSlider')[0].MaterialSlider.change('10');
960: }
961: } else if (res === "1920:1080") {
962: if (frameRate === "30") {
963: // 1080p, 30 FPS
964: $('#bitrateSlider')[0].MaterialSlider.change('10');
965: } else {
966: // 1080p, 60 FPS
967: $('#bitrateSlider')[0].MaterialSlider.change('20');
968: }
969: } else if (res === "2560:1440") {
970: if (frameRate === "30") {
971: // 1440p, 30 FPS
972: $('#bitrateSlider')[0].MaterialSlider.change('20');
973: } else {
974: // 1440p, 60 FPS
975: $('#bitrateSlider')[0].MaterialSlider.change('40');
976: }
977: } else if (res === "3840:2160") {
978: if (frameRate === "30") {
979: // 2160p (4K), 30 FPS
980: $('#bitrateSlider')[0].MaterialSlider.change('40');
981: } else {
982: // 2160p (4K), 60 FPS
983: $('#bitrateSlider')[0].MaterialSlider.change('80');
984: }
985: } else {
986: // unrecognized option. In case someone screws with the JS to add custom resolutions
987: $('#bitrateSlider')[0].MaterialSlider.change('10');
988: }
989: updateBitrateField();
990: saveBitrate();
991: }
992: function initSamsungKeys() {
993: console.log('initializing keys');
994: var handler = {
995: initRemoteController: true,
996: buttonsToRegister: [
997: // https://developer.samsung.com/tv/develop/guides/user-interaction/keyboardime
998: 'ColorF0Red',
999: // F1
1000: 'ColorF1Green',
1001: // F2
1002: 'ColorF2Yellow',
1003: // F3
1004: 'ColorF3Blue',
1005: // F4
1006: // Not working...
1007: //'SmartHub', // F5
1008: 'Source',
1009: // F6
1010: 'ChannelList',
1011: // F7
1012: 'ChannelDown',
1013: // F11
1014: 'ChannelUp' // F12
1015: ],
1016: onKeydownListener: remoteControllerHandler
1017: };
1018: console.log('Initializing SamsungTV platform');
1019: platformOnLoad(handler);
1020: }
1021: function onWindowLoad() {
1022: console.log('%c[index.js]', 'color: green;', 'Moonlight\'s main window loaded');
1023: // don't show the game selection div
1024: $('#gameSelection').css('display', 'none');
1025: console.log('load stored resolution prefs');
1026: getData('resolution', function (previousValue) {
1027: if (previousValue.resolution != null) {
1028: $('.resolutionMenu li').each(function () {
1029: if ($(this).data('value') === previousValue.resolution) {
1030: $('#selectResolution').text($(this).text()).data('value', previousValue.resolution);
1031: }
1032: });
1033: }
1034: });
1035: console.log('Load stored remote audio prefs');
1036: getData('remoteAudio', function (previousValue) {
1037: if (previousValue.remoteAudio == null) {
1038: document.querySelector('#externalAudioBtn').MaterialIconToggle.uncheck();
1039: } else if (previousValue.remoteAudio == false) {
1040: document.querySelector('#externalAudioBtn').MaterialIconToggle.uncheck();
1041: } else {
1042: document.querySelector('#externalAudioBtn').MaterialIconToggle.check();
1043: }
1044: });
1045: console.log('load stored framerate prefs');
1046: getData('frameRate', function (previousValue) {
1047: if (previousValue.frameRate != null) {
1048: $('.framerateMenu li').each(function () {
1049: if ($(this).data('value') === previousValue.frameRate) {
1050: $('#selectFramerate').text($(this).text()).data('value', previousValue.frameRate);
1051: }
1052: });
1053: }
1054: });
1055: console.log('load stored optimization prefs');
1056: getData('optimize', function (previousValue) {
1057: if (previousValue.optimize == null) {
1058: document.querySelector('#optimizeGamesBtn').MaterialIconToggle.check();
1059: } else if (previousValue.optimize == false) {
1060: document.querySelector('#optimizeGamesBtn').MaterialIconToggle.uncheck();
1061: } else {
1062: document.querySelector('#optimizeGamesBtn').MaterialIconToggle.check();
1063: }
1064: });
1065: console.log('load stored bitrate prefs');
1066: getData('bitrate', function (previousValue) {
1067: $('#bitrateSlider')[0].MaterialSlider.change(previousValue.bitrate != null ? previousValue.bitrate : '20');
1068: updateBitrateField();
1069: });
1070: initSamsungKeys();
1071: }
1072: window.onload = onWindowLoad;
1073:
1074: // Required on TizenTV, to get gamepad events.
1075: window.addEventListener('gamepadconnected', function (event) {
1076: var connectedGamepad = event.gamepad;
1077: console.log('%c[index.js, gamepadconnected] gamepad connected: ', 'color: green;', connectedGamepad);
1078: if (connectedGamepad.vibrationActuator) {
1079: // Check if the gamepad supports rumble
1080: console.log('Gamepad supports vibration.');
1081: connectedGamepad.vibrationActuator.playEffect('dual-rumble', {
1082: duration: 1000,
1083: strongMagnitude: 1.0,
1084: weakMagnitude: 1.0
1085: });
1086: } else {
1087: console.log('Gamepad does not support vibration.');
1088: }
1089: });
1090: window.addEventListener('gamepaddisconnected', function (event) {
1091: console.log('%c[index.js, gamepaddisconnected] gamepad disconnected: ' + JSON.stringify(event.gamepad), event.gamepad);
1092: });
PS C:\Users\str>
PS C:\Users\str> Write-Host "`n===== NAVIGATION.JS: ПОЛНАЯ ЛОГИКА ФОКУСА ====="
===== NAVIGATION.JS: ПОЛНАЯ ЛОГИКА ФОКУСА =====
PS C:\Users\str> Show-Range (Join-Path $js 'navigation.js') 1 75
1: var hoveredClassName = 'hovered';
2: var gameCard;
3: function mark(value) {
4: var element = typeof value === 'string' ? document.getElementById(value) : value;
5: if (element) {
6: element.classList.add(hoveredClassName);
7: element.dispatchEvent(new Event('mouseenter'));
8: if (!element.classList.contains('mdl-menu__item')) {
9: //#FIXME: needed to properly show the restart dialog. Doesn't allow focus() for mdl-menu__item.
10: element.focus();
11: }
12: }
13: }
14: function unmark(value) {
15: var element = typeof value === 'string' ? document.getElementById(value) : value;
16: if (element) {
17: element.classList.remove(hoveredClassName);
18: element.dispatchEvent(new Event('mouseleave'));
19: if (!element.classList.contains('mdl-menu__item')) {
20: //#FIXME
21: element.blur();
22: }
23: }
24: }
25: function isPopupActive(id) {
26: return document.getElementById(id).parentNode.children[1].classList.contains('is-visible');
27: }
28: function ListView(func) {
29: this.index = 0;
30: this.func = func;
31: }
32: ListView.prototype.prev = function () {
33: var array = this.func();
34: unmark(array[this.index]);
35: this.index = (this.index - 1 + array.length) % array.length;
36: mark(array[this.index]);
37: return array[this.index];
38: };
39: ListView.prototype.next = function () {
40: var array = this.func();
41: unmark(array[this.index]);
42: this.index = (this.index + 1) % array.length;
43: mark(array[this.index]);
44: return array[this.index];
45: };
46: ListView.prototype.current = function () {
47: return this.func()[this.index];
48: };
49: function navigateGameCards(offset) {
50: //helper function for Apps view
51: var gameCards = Array.from(document.getElementById('game-grid').children);
52: var currentIndex = gameCards.indexOf(gameCard);
53: var newIndex = currentIndex + offset;
54: if (newIndex >= 0 && newIndex < gameCards.length) {
55: gameCard = gameCards[newIndex];
56: gameCard.focus();
57: }
58: }
59: var Views = {
60: Hosts: {
61: view: new ListView(function () {
62: return document.getElementById('host-grid').children;
63: }),
64: up: function up() {
65: Navigation.change(Views.HostsNav);
66: },
67: down: function down() {
68: if ($('#gamepad-grid').children().length > 0) {
69: Navigation.change(Views.Gamepads);
70: }
71: },
72: left: function left() {
73: this.view.prev();
74: },
75: right: function right() {
PS C:\Users\str> Show-Range (Join-Path $js 'navigation.js') 270 465
270: },
271: AppsNav: {
272: view: new ListView(function () {
273: return ['backIcon', 'quitCurrentApp'];
274: }),
275: down: function down() {
276: Navigation.change(Views.Apps);
277: },
278: left: function left() {
279: this.view.prev();
280: },
281: right: function right() {
282: this.view.next();
283: },
284: accept: function accept() {
285: document.getElementById(this.view.current()).click();
286: },
287: back: function back() {
288: document.getElementById('backIcon').click();
289: },
290: enter: function enter() {
291: document.getElementById(this.view.current()).focus();
292: },
293: leave: function leave() {
294: document.getElementById(this.view.current()).blur();
295: }
296: },
297: Apps: {
298: view: new ListView(function () {
299: return document.getElementById('game-grid').children;
300: }),
301: up: function up() {
302: var gameCards = Array.from(document.getElementById('game-grid').children);
303: var currentIndex = gameCards.indexOf(gameCard);
304: var cardsPerRow = Math.min(6, gameCards.length);
305: if (currentIndex >= cardsPerRow) {
306: navigateGameCards(-cardsPerRow);
307: } else {
308: Navigation.change(Views.AppsNav);
309: }
310: },
311: down: function down() {
312: var gameCards = Array.from(document.getElementById('game-grid').children);
313: var currentIndex = gameCards.indexOf(gameCard);
314: var cardsPerRow = Math.min(6, gameCards.length);
315: if (currentIndex + cardsPerRow < gameCards.length) {
316: navigateGameCards(cardsPerRow);
317: }
318: },
319: left: function left() {
320: navigateGameCards(-1);
321: },
322: right: function right() {
323: navigateGameCards(1);
324: },
325: accept: function accept() {
326: gameCard.click();
327: },
328: back: function back() {
329: document.getElementById('backIcon').click();
330: },
331: enter: function enter() {
332: if (gameCard) {
333: gameCard.focus();
334: }
335: },
336: leave: function leave() {
337: unmark(this.view.current());
338: }
339: },
340: CloseAppDialog: {
341: isActive: function isActive() {
342: return isDialogActive('quitAppDialog');
343: },
344: view: new ListView(function () {
345: return ['continueQuitApp', 'cancelQuitApp'];
346: }),
347: down: function down() {
348: Navigation.change(Views.Apps);
349: },
350: left: function left() {
351: this.view.prev();
352: },
353: right: function right() {
354: this.view.next();
355: },
356: accept: function accept() {
357: document.getElementById(this.view.current()).click();
358: },
359: back: function back() {
360: document.getElementById('cancelQuitApp').click();
361: },
362: enter: function enter() {
363: mark(this.view.current());
364: },
365: leave: function leave() {
366: unmark(this.view.current());
367: }
368: }
369: };
370: var Navigation = function () {
371: var hasFocus = false;
372: var Stack = function () {
373: var viewStack = [];
374: function push(view) {
375: if (get()) {
376: get().leave();
377: }
378: viewStack.push(view);
379: get().enter();
380: }
381: function change(view) {
382: if (viewStack.length > 0) {
383: get().leave();
384: viewStack[viewStack.length - 1] = view;
385: get().enter();
386: } else {
387: push(view);
388: }
389: }
390: function pop() {
391: if (viewStack.length > 1) {
392: get().leave();
393: viewStack.pop();
394: get().enter();
395: }
396: }
397: function get() {
398: return viewStack[viewStack.length - 1];
399: }
400: return {
401: get: get,
402: push: push,
403: change: change,
404: pop: pop
405: };
406: }();
407: var State = function () {
408: var running = false;
409: function start() {
410: if (!running) {
411: running = true;
412: window.addEventListener('mousemove', loseFocus);
413: }
414: }
415: function stop() {
416: if (running) {
417: running = false;
418: window.removeEventListener('mousemove', loseFocus);
419: }
420: }
421: function isRunning() {
422: return running;
423: }
424: return {
425: start: start,
426: stop: stop,
427: isRunning: isRunning
428: };
429: }();
430: function loseFocus() {
431: if (hasFocus) {
432: hasFocus = false;
433: if (Stack.get()) {
434: Stack.get().leave();
435: }
436: }
437: }
438: function focus() {
439: if (!hasFocus) {
440: hasFocus = true;
441: if (Stack.get()) {
442: Stack.get().enter();
443: }
444: }
445: }
446: function runOp(name) {
447: return function () {
448: if (!State.isRunning()) {
449: return;
450: }
451: if (!hasFocus) {
452: focus();
453: return;
454: }
455: var view = Stack.get();
456: if (view && typeof view[name] === 'function') {
457: view[name]();
458: }
459: };
460: }
461: return {
462: accept: runOp('accept'),
463: back: runOp('back'),
464: left: runOp('left'),
465: right: runOp('right'),
466: up: runOp('up'),
467: down: runOp('down'),
468: startBtn: runOp('startBtn'),
469: push: Stack.push,
470: change: Stack.change,
471: pop: Stack.pop,
472: start: State.start,
473: stop: State.stop
474: };
475: }();
PS C:\Users\str>
PS C:\Users\str> Write-Host "`n===== CSS: ВЕСЬ ФАЙЛ ====="
===== CSS: ВЕСЬ ФАЙЛ =====
PS C:\Users\str> Get-Content (Join-Path $root 'static\css\style.css') -Raw
body {
background-color: #282C38;
color: #fff;
font-family: 'Roboto', sans-serif;
}
.page-title {
font-weight: 300;
font-size: 26px;
margin-top: 20px;
margin-bottom: 30px;
width: 100%;
text-align: center;
}
span.mdl-layout-title {
font-weight: 300;
}
span.mdl-layout-title > span {
font-weight: 900;
color: #00A3C6;
}
.mdl-layout__header-row {
padding: 0 80px 0 80px;
}
main {
padding: 0 80px 0 80px;
}
@media screen and (max-width: 600px) {
#host-grid .mdl-card {
flex-basis: 50% !important;
}
#game-grid .mdl-card {
height: 100px !important;
width: 75px !important;
}
}
@media screen and (min-width: 600px) and (max-width: 800px) {
#host-grid .mdl-card {
flex-basis: 33% !important;
}
#game-grid .mdl-card {
height: 150px !important;
width: 112.5px !important;
}
}
@media screen and (min-width: 800px) and (max-width: 1024px) {
main {
padding: 0 72px 0 72px !important;
}
.mdl-layout__header-row {
padding: 0 72px 0 72px !important;
}
#host-grid .mdl-card {
flex-basis: 25% !important;
}
#game-grid .mdl-card {
height: 200px !important;
width: 150px !important;
}
}
@media screen and (min-width: 1024px) {
#game-grid .mdl-card {
height: 300px !important;
width: 225px !important;
}
}
.nav-menu-parent {
position: relative;
margin: 0 4px;
}
.mdl-menu__outline {
background-color: #333846;
color: white;
}
.mdl-menu__item {
color: white;
}
.mdl-menu__item:hover, .mdl-menu__item.hovered, .mdl-menu__item:focus {
background-color: #00A3C6;
}
#bitrateField {
width: 100px;
height: 36px;
overflow: hidden;
text-transform: none;
}
.bitrateMenu {
width: 170px;
}
.mdl-button {
color: #fff !important;
}
.mdl-grid {
width: 100%;
}
.mdl-cell {
text-align: center;
color:#fff;
padding:25px;
}
#backIcon {
position: fixed;
left: 28px;
}
#backIcon:hover {
cursor: pointer;
}
.mdl-dialog {
width: 400px;
background-color: #333846;
color: white;
}
.mdl-dialog__title {
padding: 24px 24px 0;
margin: 0;
font-size: 2.5rem;
}
.mdl-dialog__content {
padding: 20px 24px 24px 24px;
color: rgba(255, 255, 255, 0.90);
}
.mdl-textfield__input {
border-bottom: 1px solid rgba(255, 255, 255, 0.90);
}
.mdl-textfield__label {
color: rgba(255, 255, 255, 0.90);
}
#naclSpinner {
display: none;
z-index: 2;
position: fixed;
left: 50%;
bottom: 50%;
transform: translate(-50%, -50%);
margin: 0 auto;
text-align: center;
}
#loadingSpinner {
display: none;
z-index: 1;
position: fixed;
left: 50%;
bottom: 50%;
transform: translate(-50%, -50%);
margin: 0 auto;
color: white;
text-align: center;
}
#snackButton {
width: 0px;
height: 0px;
display: none;
}
.mdl-snackbar__text {
padding: 14px 30px 14px 30px;
}
.mdl-snackbar {
min-width:0px;
}
#host-grid, #game-grid {
padding: 0;
margin: 0;
-webkit-flex: 1;
flex: 1;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
}
#host-grid .mdl-card {
flex-basis: 15%;
}
#game-grid .mdl-card {
position: relative;
background: url('../res/placeholder_game.svg') rgba(29, 29, 29, 1) center/cover no-repeat;
}
#host-grid .mdl-card, #game-grid .mdl-card {
text-align: center;
width: 170px;
height: 170px;
min-height: 170px;
margin: 15px;
cursor: pointer;
transition: all .2s ease-in-out;
will-change: transform;
}
#host-grid .mdl-card:hover, #host-grid .mdl-card:focus, #host-grid .mdl-card:active, #game-grid .mdl-card:focus, #game-grid .mdl-card:active {
transform: scale(1.15);
outline : #00A3C6 solid 2px;;
}
#host-grid .mdl-card__title {
padding: 0;
}
#host-grid .mdl-card__title .mdl-card__title-text {
width: 100%;
font-size: 14px;
padding: 10px 15px;
background-color: rgba(0,0,0,0.7);
}
#game-grid .mdl-card img {
height: 100%;
width: 100%;
opacity: 0;
transition: opacity .3s;
z-index: -1;
}
#game-grid .mdl-card img.fade-in {
opacity: 1;
}
#game-grid .game-title {
position: absolute;
bottom: 0;
min-height: 20px;
font-size: 13px;
font-weight: 300;
padding: 5px 0;
width: 100%;
color: white;
text-align: center;
background-color: rgba(0, 0, 0, 0.6);
}
#game-grid .game-title span {
padding: 0 10px;
}
.add-host-card > .mdl-card__title {
color: #fff;
background:
url('../res/ic_add_to_queue_white_48px.svg') center no-repeat #3E4454;
}
.host-container > .mdl-card__title {
color: #fff;
background:
url('../res/ic_tv_white_48px.svg') center no-repeat #3E4454;
}
.mdl-card.hovered {
background-color: initial;
outline: #00A3C6 solid 2px;
transform: scale(1.15);
}
#host-grid p {
margin: 0;
}
#host-grid .mdl-textfield {
width: 200px;
margin-right: 20px;
margin-bottom: 0px;
}
#host-grid #GFEHostIPField {
padding-bottom: 0px;
}
#host-grid #selectHost {
padding: 0px;
line-height: 20px;
height: 20px;
margin-top: 10px;
margin-bottom: 10px;
margin-right: 20px;
background: none;
}
#host-grid .button-holder {
padding: 0px;
margin-top: 10px;
margin-bottom: 10px;
}
.remove-host {
position:absolute;
right:5px;
top:5px;
width:24px;
height:24px;
z-index: 5;
background-image: url('../res/ic_remove_circle_outline_white_48px.svg');
background-repeat: no-repeat;
background-size: 20px 20px;
background-position: center;
border: 0;
cursor: pointer;
}
/*.remove-host:hover, .remove-host:focus {
background-image: url('\\static\\res\\ic_remove_circle_white_24px.svg');
}*/
#pairButton {
margin: 3px;
}
#showAppsButton {
margin: 3px;
}
#listener {
overflow: hidden;
margin-top: 0px;
height: 0px;
}
.fullscreen {
height: 100vh !important;
overflow: hidden !important;
margin: auto !important;
padding: 0 !important;
border: none !important;
}
.current-game {
outline: auto #8BC34A;
}
.host-cell-inactive {
outline: auto #F44336;
}
.host-cell:hover {
cursor: pointer;
color: #000 !important;
}
.cancel-current:hover {
cursor: pointer;
}
.cancel-current {
border: 2px solid white;
padding: 5px;
border-radius: 5px;
}
.cancel-current img {
margin-right: 5px;
}
.cancel-current .game-title {
color: #fff;
}
#nacl_module {
cursor: none;
}
PS C:\Users\str>
PS C:\Users\str> Write-Host "`n===== CONFIG.XML: ПРИВИЛЕГИИ И ПРОФИЛЬ ====="
===== CONFIG.XML: ПРИВИЛЕГИИ И ПРОФИЛЬ =====
PS C:\Users\str> Select-String -Path (Join-Path $root 'config.xml') `
>> -Pattern 'profile|privilege|feature|content|tizen:application' -Context 1,2
C:\Temp\pepper42-build\wgt-staging\config.xml:4: </access>
> C:\Temp\pepper42-build\wgt-staging\config.xml:5: <tizen:application id="ChqHQExU28.MoonlightNaCl" package="ChqHQExU2
8" required_version="2.4" />
> C:\Temp\pepper42-build\wgt-staging\config.xml:6: <content src="index.html" />
> C:\Temp\pepper42-build\wgt-staging\config.xml:7: <feature name="http://tizen.org/feature/screen.size.all" />
> C:\Temp\pepper42-build\wgt-staging\config.xml:8: <feature name="http://www.samsungdforum.com/feature/Keyboard" />
> C:\Temp\pepper42-build\wgt-staging\config.xml:9: <feature name="http://www.samsungdforum.com/feature/Mouse" />
> C:\Temp\pepper42-build\wgt-staging\config.xml:10: <feature name="http://www.samsungdforum.com/feature/External_Devic
e" />
C:\Temp\pepper42-build\wgt-staging\config.xml:11: <icon src="icon.png" />
C:\Temp\pepper42-build\wgt-staging\config.xml:12: <tizen:metadata key="http://samsung.com/tv/metadata/prelaunch.supp
ort" value="true" />
C:\Temp\pepper42-build\wgt-staging\config.xml:16: <name>MoonlightNaCl</name>
> C:\Temp\pepper42-build\wgt-staging\config.xml:17: <tizen:privilege name="http://developer.samsung.com/privilege/netw
ork.public" />
> C:\Temp\pepper42-build\wgt-staging\config.xml:18: <tizen:privilege name="http://tizen.org/privilege/application.laun
ch" />
> C:\Temp\pepper42-build\wgt-staging\config.xml:19: <tizen:privilege name="http://tizen.org/privilege/tv.inputdevice"
/>
> C:\Temp\pepper42-build\wgt-staging\config.xml:20: <tizen:profile name="tv-samsung" />
C:\Temp\pepper42-build\wgt-staging\config.xml:21: <tizen:setting screen-orientation="landscape" context-menu="enable
" background-support="disable" encryption="disable" install-location="auto" hwkey-event="enable" />
C:\Temp\pepper42-build\wgt-staging\config.xml:22:</widget>
PS C:\Users\str>