Skip to content

Commit

Permalink
Implement UI for controlilng ATEN-specific settings
Browse files Browse the repository at this point in the history
Add video settings change callback to Ast2100Decoder for UI integration.

Implement slider widget (used to select AST2100 quantization tables).
  • Loading branch information
kelleyk committed Jan 16, 2017
1 parent 0d048ac commit 048c9b2
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 25 deletions.
5 changes: 5 additions & 0 deletions app/styles/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ input[type=button]:active, select:active {
background: linear-gradient(to top, rgb(255, 255, 255), rgb(250, 250, 250));
}

/* Settings slider: video quality (quantization table selector) in AST2100 mode. */
#noVNC_settings #noVNC_setting_ast2100_quality {
margin: 0 10px;
}

/* ----------------------------------------
* WebKit centering hacks
* ----------------------------------------
Expand Down
107 changes: 105 additions & 2 deletions app/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ var UI;
lastKeyboardinput: null,
defaultKeyboardinputLen: 100,

// True if we are connected to an ATEN iKVM server speaking the AST2100 video encoding.
// This variable tracks whether the extra UI elements used to configure video settings
// for the AST2100 encoding have been shown yet; it's set on the first FramebufferUpdate
// message that we receive.
_ast2100_videoSettingsInitialized: false,

// Setup rfb object, load settings from browser storage, then call
// UI.init to setup the UI/menus
load: function(callback) {
Expand Down Expand Up @@ -392,7 +398,9 @@ var UI;
'onBell': UI.bell,
'onFBUComplete': UI.initialResize,
'onFBResize': UI.updateSessionSize,
'onDesktopName': UI.updateDesktopName});
'onDesktopName': UI.updateDesktopName,
'ast2100_onVideoSettingsChanged': UI.ast2100_handleVideoSettingsChanged
});
return true;
} catch (exc) {
var msg = "Unable to create RFB client -- " + exc;
Expand Down Expand Up @@ -436,7 +444,9 @@ var UI;
document.documentElement.classList.add("noVNC_disconnecting");
break;
case 'disconnected':
UI.connected = false;
UI.showStatus(_("Disconnected"));
UI.ast2100_reset();
break;
default:
msg = "Invalid UI state";
Expand Down Expand Up @@ -843,6 +853,15 @@ var UI;
UI.saveSetting('path');
UI.saveSetting('repeaterID');
UI.saveSetting('logging');

if (UI._ast2100_videoSettingsInitialized) {
var videoSettings = UI.ast2100_getConfiguredSettings();
if (videoSettings != UI._ast2100_serverVideoSettings)
UI.rfb.atenChangeVideoSettings(
videoSettings.quantTableSelectorLuma,
videoSettings.quantTableSelectorChroma,
videoSettings.subsamplingMode);
}

// Settings with immediate (non-connected related) effect
WebUtil.init_logging(UI.getSetting('logging'));
Expand Down Expand Up @@ -963,9 +982,93 @@ var UI;
/* ------^-------
* /XVP
* ==============
* CLIPBOARD
* AST2100
* ------v------*/

ast2100_handleVideoSettingsChanged: function (settings) {
if (!UI._ast2100_videoSettingsInitialized)
UI.ast2100_setDefaultSettings(settings);
UI.ast2100_updateVideoSettings(settings);
},

// Called the first time we receive a FramebufferUpdate object. Responsible
// for telling the server about any configured default settings.
ast2100_setDefaultSettings: function (settings) {
// Convert the settings that noVNC has been configured to set for all
// AST2100 servers to the familiar videoSettings format.
var defaultQuality = parseInt(UI.ast2100_quality);
var defaultSettings = {
quantTableSelectorLuma: defaultQuality,
quantTableSelectorChroma: defaultQuality,
subsamplingMode: parseInt(UI.ast2100_subsamplingMode)
};

// If defaults were not given or were invalid, stick with what the
// server is already using.
if (!(defaultSettings.subsamplingMode == 422 || defaultSettings.subsamplingMode == 444))
defaultSettings.subsamplingMode = settings.subsamplingMode;
if (!inRangeIncl(defaultQuality, 0x0, 0xB)) {
defaultSettings.quantTableSelectorLuma = settings.quantTableSelectorLuma;
defaultSettings.quantTableSelectorChroma = settings.quantTableSelectorChroma;
}

if (defaultSettings != settings)
UI.rfb.atenChangeVideoSettings(
defaultSettings.quantTableSelectorLuma,
defaultSettings.quantTableSelectorChroma,
defaultSettings.subsamplingMode);
},

// Should be called at init time and after disconnects. This is sort
// of the opposite of _init().
ast2100_reset: function() {
document.getElementById("noVNC_ast2100_settings").classList.add('noVNC_hidden');
UI._ast2100_videoSettingsInitialized = false;
UI._ast2100_serverVideoSettings = undefined;
},

// Updates the UI to reflect values received from the server.
ast2100_updateVideoSettings: function (videoSettings) {
Util.Info("AST2100 video settings changed:");
Util.Info(videoSettings);

// We use this to tell if the user changed anything when they apply
// settings.
UI._ast2100_serverVideoSettings = videoSettings;

// First run: tell UI to show video quality controls, now that we
// know we are on a machine that supports them, and we know their
// current values.
if (!UI._ast2100_videoSettingsInitialized) {
document.getElementById("noVNC_ast2100_settings").classList.remove('noVNC_hidden');
UI._ast2100_videoSettingsInitialized = true;
}

// Average the two quant table selectors as a poor way of dealing
// with the fact that they can, technically, be different.
var quality = ~~((videoSettings.quantTableSelectorLuma + videoSettings.quantTableSelectorChroma) / 2);
document.getElementById("noVNC_setting_ast2100_quality").value = quality;

// Either 444 or 422 (which is really 4:2:0).
document.getElementById("noVNC_setting_ast2100_subsampling").value = videoSettings.subsamplingMode;
},

// Returns the current state of the UI.
ast2100_getConfiguredSettings: function () {
var quality = +document.getElementById("noVNC_setting_ast2100_quality").value;
return {
quantTableSelectorLuma: quality,
quantTableSelectorChroma: quality,
subsamplingMode: +document.getElementById("noVNC_setting_ast2100_subsampling").value
};
},

/* ------^-------
* /AST2100
* ==============
* CLIPBOARD
* ------v------*/

openClipboardPanel: function() {
UI.closeAllPanels();
UI.openControlbar();
Expand Down
22 changes: 22 additions & 0 deletions core/ast2100/ast2100.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ var Ast2100Decoder;
Ast2100Decoder = function (defaults) {

this._blitCallback = defaults.blitCallback;
this._videoSettingsChangedCallback = defaults.videoSettingsChangedCallback;
this._frame_width = defaults.width;
this._frame_height = defaults.height;

Expand Down Expand Up @@ -157,6 +158,18 @@ var Ast2100Decoder;
this._frame_width = width;
this._frame_height = height;
},

// Each quant table selector is between 0x0 (lowest quality) and 0xB (highest quality). The ATEN client shows a
// single quality slider, which changes both values in tandem. The server sends all three values with each
// FramebufferUpdate message, so these values are updated with every call to decode(). They will be -1 before
// the first frame is decoded.
getVideoSettings: function () {
return {
quantTableSelectorLuma: this._loadedQuantTables[0],
quantTableSelectorChroma: this._loadedQuantTables[1],
subsamplingMode: this.subsamplingMode
};
},

decode: function (data) {

Expand All @@ -174,10 +187,13 @@ var Ast2100Decoder;
var quantTableSelectorLuma = data[0]; // 0 <= x <= 0xB
var quantTableSelectorChroma = data[1]; // 0 <= x <= 0xB
var subsamplingMode = (data[2] << 8) | data[3]; // 422u or 444u

var changedSettings = false;
if (this.subsamplingMode != subsamplingMode) {
if (verboseVideoSettings)
console.log('decode(): new subsampling mode: '+subsamplingMode);
this.subsamplingMode = subsamplingMode;
changedSettings = true;
}

// The remainder of the stream is byte-swapped in four-byte chunks.
Expand All @@ -193,6 +209,7 @@ var Ast2100Decoder;
console.log('decode(): loading new luma quant table: '+fmt_u8(quantTableSelectorLuma));
this._loadQuantTable(0, ATEN_QT_LUMA[quantTableSelectorLuma]);
this._loadedQuantTables[0] = quantTableSelectorLuma;
changedSettings = true;
}
if (quantTableSelectorChroma != this._loadedQuantTables[1]) {
if (!inRangeIncl(quantTableSelectorChroma, 0, 0xB))
Expand All @@ -201,9 +218,14 @@ var Ast2100Decoder;
console.log('decode(): loading new chroma quant table: '+fmt_u8(quantTableSelectorChroma));
this._loadQuantTable(1, ATEN_QT_CHROMA[quantTableSelectorChroma]);
this._loadedQuantTables[1] = quantTableSelectorChroma;
changedSettings = true;
}

if (this.subsamplingMode != 422 && this.subsamplingMode != 444)
throw 'Unexpected value for subsamplingMode: 0x' + fmt_u16(this.subsamplingMode);

if (changedSettings && this._videoSettingsChangedCallback)
this._videoSettingsChangedCallback(this.getVideoSettings());

// The remainder of the stream is byte-swapped in four-byte chunks. BitStream takes care of this.
this._stream = new BitStream({data: data});
Expand Down
Loading

0 comments on commit 048c9b2

Please sign in to comment.