diff --git a/app/ui.js b/app/ui.js index ef5a2245a..c5eff3c13 100644 --- a/app/ui.js +++ b/app/ui.js @@ -1104,6 +1104,7 @@ const UI = { if (val === null) { val = WebUtil.readSetting(name, defVal); } + val = UI.sanitizeSetting(name, val); WebUtil.setSetting(name, val); UI.updateSetting(name); return val; @@ -1111,6 +1112,7 @@ const UI = { // Set the new value, update and disable form control setting forceSetting(name, val, disable=true) { + val = UI.sanitizeSetting(name, val); WebUtil.setSetting(name, val); UI.updateSetting(name); if (disable) { @@ -1149,6 +1151,26 @@ const UI = { } }, + // Ensure settings stay within supported bounds + sanitizeSetting(name, value) { + switch (name) { + case 'framerate': { + let numeric = parseInt(value, 10); + if (!Number.isFinite(numeric)) { + numeric = 30; + } + if (numeric < 10) { + numeric = 10; + } else if (numeric > 120) { + numeric = 120; + } + return String(numeric); + } + default: + return value; + } + }, + // Save control setting to cookie saveSetting(name) { const ctrl = document.getElementById('noVNC_setting_' + name); @@ -1160,6 +1182,13 @@ const UI = { } else { val = ctrl.value; } + const sanitized = UI.sanitizeSetting(name, val); + if (sanitized !== val) { + if (ctrl && typeof ctrl.value !== 'undefined') { + ctrl.value = sanitized; + } + val = sanitized; + } WebUtil.writeSetting(name, val); //Log.Debug("Setting saved '" + name + "=" + val + "'"); return val; @@ -1179,8 +1208,12 @@ const UI = { val = true; } } - - return val; + const sanitized = UI.sanitizeSetting(name, val); + const currentStr = (val === null || typeof val === 'undefined') ? null : String(val); + if (sanitized !== val && sanitized !== currentStr) { + WebUtil.writeSetting(name, sanitized); + } + return sanitized; }, // These helpers compensate for the lack of parent-selectors and diff --git a/core/encodings.js b/core/encodings.js index af2f4493d..e59f60c1f 100644 --- a/core/encodings.js +++ b/core/encodings.js @@ -46,8 +46,8 @@ export const encodings = { pseudoEncodingVideoTimeLevel0: -870, pseudoEncodingVideoTimeLevel100: -770, - pseudoEncodingFrameRateLevel10: -2048, - pseudoEncodingFrameRateLevel60: -1998, + pseudoEncodingFrameRateLevel10: -4096, + pseudoEncodingFrameRateLevel120: -3986, pseudoEncodingMaxVideoResolution: -1997, pseudoEncodingVideoScalingLevel0: -1996, pseudoEncodingVideoScalingLevel9: -1987, diff --git a/core/rfb.js b/core/rfb.js index 73e6bc809..9a213948c 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -622,8 +622,8 @@ export default class RFB extends EventTargetMixin { get frameRate() { return this._frameRate; } set frameRate(value) { - if (!Number.isInteger(value) || value < 1 || value > 120) { - Log.Error("frame rate must be an integer between 1 and 120"); + if (!Number.isInteger(value) || value < 10 || value > 120) { + Log.Error("frame rate must be an integer between 10 and 120"); return; } @@ -3179,7 +3179,11 @@ export default class RFB extends EventTargetMixin { encs.push(encodings.pseudoEncodingVideoTimeLevel0 + this.videoTime); encs.push(encodings.pseudoEncodingVideoOutTimeLevel1 + this.videoOutTime - 1); encs.push(encodings.pseudoEncodingVideoScalingLevel0 + this.videoScaling); - encs.push(encodings.pseudoEncodingFrameRateLevel10 + this.frameRate - 10); + const frameRate = Math.round(Math.max(10, Math.min(120, this.frameRate))); + if (frameRate !== this.frameRate) { + Log.Warn("Frame rate value " + this.frameRate + " adjusted to " + frameRate); + } + encs.push(encodings.pseudoEncodingFrameRateLevel10 + frameRate - 10); encs.push(encodings.pseudoEncodingMaxVideoResolution); // preferBandwidth choses preset settings. Since we expose all the settings, lets not pass this diff --git a/index.html b/index.html index 24956467a..79f3b3ca0 100644 --- a/index.html +++ b/index.html @@ -387,7 +387,7 @@