refactored PC tracking

- stores NvHTTP objects now
	- these require revival on loading
- ref #71
- likely contains bugs that I haven't found
This commit is contained in:
R. Aidan Campbell 2016-07-24 14:55:17 -04:00
parent bc5e277fb1
commit 68cfba608e
2 changed files with 65 additions and 35 deletions

View File

@ -1,4 +1,4 @@
var hosts = []; var hosts = {}; // hosts is an associative array of NvHTTP objects, keyed by server UID
var pairingCert; var pairingCert;
var myUniqueid; var myUniqueid;
var api; var api;
@ -66,7 +66,7 @@ function updateBitrateField() {
function moduleDidLoad() { function moduleDidLoad() {
if(!myUniqueid) { if(!myUniqueid) {
console.log("Failed to get uniqueId. Generating new one"); console.log("Failed to get uniqueId. We should have already generated one. Regenerating...");
myUniqueid = uniqueid(); myUniqueid = uniqueid();
storeData('uniqueid', myUniqueid, null); storeData('uniqueid', myUniqueid, null);
} }
@ -99,8 +99,8 @@ function moduleDidLoad() {
} }
} }
// pair to the given hostname or IP. Returns whether pairing was successful. // pair to the given NvHTTP host object. Returns whether pairing was successful.
function pairTo(host, onSuccess, onFailure) { function pairTo(nvhttpHost, onSuccess, onFailure) {
if(!pairingCert) { if(!pairingCert) {
snackbarLog('ERROR: cert has not been generated yet. Is NaCl initialized?'); snackbarLog('ERROR: cert has not been generated yet. Is NaCl initialized?');
console.log("User wants to pair, and we still have no cert. Problem = very yes."); console.log("User wants to pair, and we still have no cert. Problem = very yes.");
@ -108,7 +108,7 @@ function pairTo(host, onSuccess, onFailure) {
return; return;
} }
api = new NvHTTP(host, myUniqueid); api = nvhttpHost;
api.refreshServerInfo().then(function (ret) { api.refreshServerInfo().then(function (ret) {
if (api.paired) { if (api.paired) {
onSuccess(); onSuccess();
@ -119,14 +119,14 @@ function pairTo(host, onSuccess, onFailure) {
var pairingDialog = document.querySelector('#pairingDialog'); var pairingDialog = document.querySelector('#pairingDialog');
$('#pairingDialogText').html('Please enter the number ' + randomNumber + ' on the GFE dialog on the computer. This dialog will be dismissed once complete'); $('#pairingDialogText').html('Please enter the number ' + randomNumber + ' on the GFE dialog on the computer. This dialog will be dismissed once complete');
pairingDialog.showModal(); pairingDialog.showModal();
console.log('sending pairing request to ' + host + ' with random number ' + randomNumber); console.log('sending pairing request to ' + nvhttpHost.address + ' with random number ' + randomNumber);
api.pair(randomNumber).then(function (paired) { api.pair(randomNumber).then(function (paired) {
if (!paired) { if (!paired) {
if (api.currentGame != 0) { if (api.currentGame != 0) {
$('#pairingDialogText').html('Error: ' + host + ' is in app. Cannot pair until the app is stopped.'); $('#pairingDialogText').html('Error: ' + nvhttpHost.address + ' is in app. Cannot pair until the app is stopped.');
} else { } else {
$('#pairingDialogText').html('Error: failed to pair with ' + host + '. failure reason unknown.'); $('#pairingDialogText').html('Error: failed to pair with ' + nvhttpHost.address + '. failure reason unknown.');
} }
console.log('failed API object: '); console.log('failed API object: ');
console.log(api.toString()); console.log(api.toString());
@ -138,14 +138,14 @@ function pairTo(host, onSuccess, onFailure) {
pairingDialog.close(); pairingDialog.close();
onSuccess(); onSuccess();
}, function (failedPairing) { }, function (failedPairing) {
snackbarLog('Failed pairing to: ' + host); snackbarLog('Failed pairing to: ' + nvhttpHost.address);
console.log('pairing failed, and returned ' + failedPairing); console.log('pairing failed, and returned ' + failedPairing);
console.log('failed API object: '); console.log('failed API object: ');
console.log(api.toString()); console.log(api.toString());
onFailure(); onFailure();
}); });
}, function (failedRefreshInfo) { }, function (failedRefreshInfo) {
snackbarLog('Failed to connect to ' + host + '! Are you sure the host is on?'); snackbarLog('Failed to connect to ' + nvhttpHost.address + '! Are you sure the host is on?');
console.log('Returned error was: ' + failedRefreshInfo); console.log('Returned error was: ' + failedRefreshInfo);
console.log('failed API object: '); console.log('failed API object: ');
console.log(api.toString()); console.log(api.toString());
@ -157,22 +157,29 @@ function hostChosen(sourceEvent) {
if(sourceEvent && sourceEvent.srcElement) { if(sourceEvent && sourceEvent.srcElement) {
if (sourceEvent.srcElement.innerText == "") { if (sourceEvent.srcElement.innerText == "") {
console.log('user clicked image. we gotta hack to parse out the host.'); console.log('user clicked image. we gotta hack to parse out the host.');
var host = sourceEvent.currentTarget.childNodes[1].textContent; // TODO: parse server UID from the cell ID: 'hostgrid-' + host.serverUid
var serverUid = sourceEvent.currentTarget.id.substring("hostgrid-".length);
} else { } else {
console.log('parsing host from grid element.'); console.log('parsing host from grid element.');
var host = sourceEvent.srcElement.innerText; var serverUid = sourceEvent.srcElement.id.substring("hostgrid-".length);
} }
} else {
console.log('Failed to find host! This should never happen!');
console.log(sourceEvent);
} }
api = new NvHTTP(host, myUniqueid); api = hosts[serverUid];
if(!!api.refreshServerInfo == false) { // bang bang, you're a bool (cast the function into truthiness to check for existance)
console.log('error: revival of object failed!');
}
api.refreshServerInfo().then(function (ret) { api.refreshServerInfo().then(function (ret) {
if(!api.paired) { if(!api.paired) {
pairTo(host, function(){ showApps(); saveHosts(); }, function(){}); pairTo(api, function(){ showApps(); saveHosts(); }, function(){});
} else { } else {
showApps(); showApps();
} }
}, function (failedRefreshInfo) { }, function (failedRefreshInfo) {
snackbarLog('Failed to connect to ' + host + '! Are you sure the host is on?'); snackbarLog('Failed to connect to ' + api.address + '! Are you sure the host is on?');
console.log('Returned error was: ' + failedRefreshInfo); console.log('Returned error was: ' + failedRefreshInfo);
console.log('failed API object: '); console.log('failed API object: ');
console.log(api.toString()); console.log(api.toString());
@ -190,27 +197,26 @@ function cancelAddHost() {
document.querySelector('#addHostDialog').close(); document.querySelector('#addHostDialog').close();
} }
// host is an NvHTTP object
function addHostToGrid(host) { function addHostToGrid(host) {
var cell = document.createElement('div'); var cell = document.createElement('div');
cell.className += 'mdl-cell mdl-cell--3-col host-cell mdl-button mdl-js-button mdl-js-ripple-effect'; cell.className += 'mdl-cell mdl-cell--3-col host-cell mdl-button mdl-js-button mdl-js-ripple-effect';
cell.id = 'hostgrid-' + host; cell.id = 'hostgrid-' + host.serverUid;
cell.innerHTML = host; cell.innerHTML = host.hostname;
$(cell).prepend($("<img>", {src: "static/res/ic_desktop_windows_white_24px.svg"})); $(cell).prepend($("<img>", {src: "static/res/ic_desktop_windows_white_24px.svg"}));
$('#host-grid').append(cell); $('#host-grid').append(cell);
cell.onclick = hostChosen; cell.onclick = hostChosen;
if(hosts.indexOf(host) < 0) { hosts[host.serverUid] = host;
hosts.push(host);
}
} }
function continueAddHost() { function continueAddHost() {
var inputHost = $('#dialogInputHost').val(); var inputHost = $('#dialogInputHost').val();
var nvhttpHost = new NvHTTP(inputHost, myUniqueid);
pairTo(inputHost, pairTo(nvhttpHost,
function() { function() {
addHostToGrid(inputHost); addHostToGrid(nvhttpHost);
saveHosts(); saveHosts();
document.querySelector('#addHostDialog').close(); document.querySelector('#addHostDialog').close();
}, },
function() { function() {
snackbarLog('pairing to ' + inputHost + ' failed!'); snackbarLog('pairing to ' + inputHost + ' failed!');
@ -224,7 +230,7 @@ function continueAddHost() {
// https://github.com/GoogleChrome/chrome-app-samples/blob/master/samples/context-menu/main.js // https://github.com/GoogleChrome/chrome-app-samples/blob/master/samples/context-menu/main.js
function forgetHost(host) { function forgetHost(host) {
snackbarLog('Feature not yet ported to grid-ui'); snackbarLog('Feature not yet ported to grid-ui');
hosts.splice(hosts.indexOf(host), 1); // remove the host from the array; hosts.splice(hosts.indexOf(host.serverUid), 1); // remove the host from the array;
saveHosts(); saveHosts();
} }
@ -504,7 +510,14 @@ function saveFramerate() {
storeData('frameRate', $('#selectFramerate').val(), null); storeData('frameRate', $('#selectFramerate').val(), null);
} }
// storing data in chrome.storage takes the data as an object, and shoves it into JSON to store
// unfortunately, objects with function instances (classes) are stripped of their function instances when converted to a raw object
// so we cannot forget to revive the object after we load it.
function saveHosts() { function saveHosts() {
for(hostUID in hosts) {
// slim the object down to only store the necessary bytes, because we have limited storage
hosts[hostUID]._prepareForStorage();
}
storeData('hosts', hosts, null); storeData('hosts', hosts, null);
} }
@ -571,14 +584,6 @@ function onWindowLoad(){
chrome.storage.sync.get('frameRate', function(previousValue) { chrome.storage.sync.get('frameRate', function(previousValue) {
$('#selectFramerate').val(previousValue.frameRate != null ? previousValue.frameRate : '60'); $('#selectFramerate').val(previousValue.frameRate != null ? previousValue.frameRate : '60');
}); });
// load previously connected hosts
chrome.storage.sync.get('hosts', function(previousValue) {
hosts = previousValue.hosts != null ? previousValue.hosts : [];
for(var i = 0; i < hosts.length; i++) { // programmatically add each new host.
addHostToGrid(hosts[i]);
}
});
// load stored bitrate prefs // load stored bitrate prefs
chrome.storage.sync.get('bitrate', function(previousValue) { chrome.storage.sync.get('bitrate', function(previousValue) {
$('#bitrateSlider')[0].MaterialSlider.change(previousValue.bitrate != null ? previousValue.bitrate : '10'); $('#bitrateSlider')[0].MaterialSlider.change(previousValue.bitrate != null ? previousValue.bitrate : '10');
@ -593,6 +598,20 @@ function onWindowLoad(){
chrome.storage.sync.get('uniqueid', function(savedUniqueid) { chrome.storage.sync.get('uniqueid', function(savedUniqueid) {
if (savedUniqueid.uniqueid != null) { // we have a saved uniqueid if (savedUniqueid.uniqueid != null) { // we have a saved uniqueid
myUniqueid = savedUniqueid.uniqueid; myUniqueid = savedUniqueid.uniqueid;
} else {
myUniqueid = uniqueid();
storeData('uniqueid', myUniqueid, null);
}
});
// load previously connected hosts, and revive them back into a class
chrome.storage.sync.get('hosts', function(previousValue) {
hosts = previousValue.hosts != null ? previousValue.hosts : {};
for(hostUID in hosts) { // programmatically add each new host.
var revivedHost = new NvHTTP(hosts[hostUID].address, myUniqueid);
revivedHost.serverUid = hosts[hostUID].serverUid;
revivedHost.externalIP = hosts[hostUID].externalIP;
revivedHost.hostname = hosts[hostUID].hostname;
addHostToGrid(revivedHost);
} }
}); });
} }
@ -602,7 +621,7 @@ function onWindowLoad(){
var ips = Object.keys(finder.byService_['_nvstream._tcp']); var ips = Object.keys(finder.byService_['_nvstream._tcp']);
for (var ip in ips) { for (var ip in ips) {
if (finder.byService_['_nvstream._tcp'][ip]) { if (finder.byService_['_nvstream._tcp'][ip]) {
addHostToGrid(ip); addHostToGrid(new NvHTTP(ip, myUniqueid));
} }
} }
} }

View File

@ -47,6 +47,8 @@ function NvHTTP(address, clientUid) {
this.supportedDisplayModes = {}; // key: y-resolution:x-resolution, value: array of supported framerates (only ever seen 30 or 60, here) this.supportedDisplayModes = {}; // key: y-resolution:x-resolution, value: array of supported framerates (only ever seen 30 or 60, here)
this.gputype = ''; this.gputype = '';
this.numofapps = 0; this.numofapps = 0;
this.hostname = '';
this.externalIP = '';
_self = this; _self = this;
}; };
@ -100,6 +102,10 @@ NvHTTP.prototype = {
} }
return string; return string;
}, },
_prepareForStorage: function() {
_self._memCachedBoxArtArray = {};
},
_parseServerInfo: function(xmlStr) { _parseServerInfo: function(xmlStr) {
$xml = _self._parseXML(xmlStr); $xml = _self._parseXML(xmlStr);
@ -109,6 +115,9 @@ NvHTTP.prototype = {
return false; return false;
} }
console.log('parsing server info: ');
console.log($root);
_self.paired = $root.find("PairStatus").text().trim() == 1; _self.paired = $root.find("PairStatus").text().trim() == 1;
_self.currentGame = parseInt($root.find("currentgame").text().trim(), 10); _self.currentGame = parseInt($root.find("currentgame").text().trim(), 10);
_self.serverMajorVersion = parseInt($root.find("appversion").text().trim().substring(0, 1), 10); _self.serverMajorVersion = parseInt($root.find("appversion").text().trim().substring(0, 1), 10);
@ -116,6 +125,8 @@ NvHTTP.prototype = {
_self.GfeVersion = $root.find('GfeVersion').text().trim(); _self.GfeVersion = $root.find('GfeVersion').text().trim();
_self.gputype = $root.find('gputype').text().trim(); _self.gputype = $root.find('gputype').text().trim();
_self.numofapps = $root.find('numofapps').text().trim(); _self.numofapps = $root.find('numofapps').text().trim();
_self.hostname = $root.find('hostname').text().trim();
_self.externalIP = $root.find('ExternalIP').text().trim();
// now for the hard part: parsing the supported streaming // now for the hard part: parsing the supported streaming
$root.find('DisplayMode').each(function(index, value) { // for each resolution:FPS object $root.find('DisplayMode').each(function(index, value) { // for each resolution:FPS object
var yres = parseInt($(value).find('Height').text()); var yres = parseInt($(value).find('Height').text());