summaryrefslogtreecommitdiff
path: root/web/share/js/kvm/stream.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/share/js/kvm/stream.js')
-rw-r--r--web/share/js/kvm/stream.js221
1 files changed, 221 insertions, 0 deletions
diff --git a/web/share/js/kvm/stream.js b/web/share/js/kvm/stream.js
new file mode 100644
index 00000000..01ded5bc
--- /dev/null
+++ b/web/share/js/kvm/stream.js
@@ -0,0 +1,221 @@
+function Streamer() {
+ var self = this;
+
+ /********************************************************************************/
+
+ var __resolution = {width: 640, height: 480};
+ var __size_factor = 1;
+ var __client_key = tools.makeId();
+ var __client_id = "";
+ var __client_fps = -1;
+ var __prev = false;
+
+ var __init__ = function() {
+ $("stream-led").title = "Stream inactive";
+
+ $("stream-quality-slider").min = 5;
+ $("stream-quality-slider").max = 100;
+ $("stream-quality-slider").step = 5;
+ $("stream-quality-slider").value = 80;
+ tools.setOnUpSlider($("stream-quality-slider"), 1000, __updateQualityValue, (value) => __sendParam("quality", value));
+
+ $("stream-desired-fps-slider").min = 0;
+ $("stream-desired-fps-slider").max = 30;
+ $("stream-desired-fps-slider").step = 1;
+ $("stream-desired-fps-slider").value = 0;
+ tools.setOnUpSlider($("stream-desired-fps-slider"), 1000, __updateDesiredFpsValue, (value) => __sendParam("desired_fps", value));
+
+ $("stream-size-slider").min = 20;
+ $("stream-size-slider").max = 200;
+ $("stream-size-slider").step = 5;
+ $("stream-size-slider").value = 100;
+ $("stream-size-slider").oninput = () => __resize();
+ $("stream-size-slider").onchange = () => __resize();
+
+ tools.setOnClick($("stream-screenshot-button"), __clickScreenshotButton);
+ tools.setOnClick($("stream-reset-button"), __clickResetButton);
+ };
+
+ /********************************************************************************/
+
+ self.setState = function(state) {
+ if (state && state.state) {
+ var source = state.state.source;
+ var stream = state.state.stream;
+
+ if (!__prev) {
+ $("stream-quality-slider").activated = false;
+ $("stream-desired-fps-slider").activated = false;
+ }
+
+ if (!$("stream-quality-slider").activated) {
+ wm.switchDisabled($("stream-quality-slider"), false);
+ if ($("stream-quality-slider").value !== source.quality) {
+ $("stream-quality-slider").value = source.quality;
+ __updateQualityValue(source.quality);
+ }
+ }
+
+ if (!$("stream-desired-fps-slider").activated) {
+ wm.switchDisabled($("stream-desired-fps-slider"), false);
+ if ($("stream-desired-fps-slider").value !== source.desired_fps) {
+ $("stream-desired-fps-slider").value = source.desired_fps;
+ __updateDesiredFpsValue(source.desired_fps);
+ }
+ }
+
+ if (__resolution.width !== source.resolution.width || __resolution.height !== source.resolution.height) {
+ __resolution = source.resolution;
+ if ($("stream-auto-resize-checkbox").checked) {
+ __adjustSizeFactor();
+ } else {
+ __applySizeFactor();
+ }
+ }
+
+ var stream_client = tools.getCookie("stream_client");
+ if (!__client_id && stream_client && stream_client.startsWith(__client_key + "/")) {
+ tools.info("Stream: found acceptable stream_client cookie:", stream_client);
+ __client_id = stream_client.slice(stream_client.indexOf("/") + 1);
+ }
+
+ if (stream.clients_stat.hasOwnProperty(__client_id)) {
+ __client_fps = stream.clients_stat[__client_id].fps;
+ } else {
+ __clearState();
+ }
+
+ if (!__prev) {
+ var path = "/streamer/stream?key=" + __client_key;
+ if (tools.browser.is_chrome || tools.browser.is_blink) {
+ // uStreamer fix for Blink https://bugs.chromium.org/p/chromium/issues/detail?id=527446
+ tools.info("Stream: using advance_headers=1 to fix Blink MJPG bugs");
+ path += "&advance_headers=1";
+ } else if (tools.browser.is_safari || tools.browser.is_ios) {
+ // uStreamer fix for WebKit
+ tools.info("Stream: using dual_final_frames=1 to fix WebKit MJPG bugs");
+ path += "&dual_final_frames=1";
+ }
+ $("stream-image").src = path;
+ $("stream-image").className = "stream-image-active";
+ $("stream-box").classList.remove("stream-box-inactive");
+ $("stream-led").className = "led-green";
+ $("stream-led").title = "Stream is active";
+ wm.switchDisabled($("stream-screenshot-button"), false);
+ wm.switchDisabled($("stream-reset-button"), false);
+ tools.info("Stream: acquired");
+ __prev = true;
+ }
+
+ __updateStreamHeader(true);
+
+ } else {
+ __clearState();
+ }
+ };
+
+ var __clearState = function() {
+ tools.info("Stream: refreshing ...");
+
+ $("stream-image").className = "stream-image-inactive";
+ $("stream-box").classList.add("stream-box-inactive");
+ $("stream-led").className = "led-gray";
+ $("stream-led").title = "Stream inactive";
+ wm.switchDisabled($("stream-screenshot-button"), true);
+ wm.switchDisabled($("stream-reset-button"), true);
+ wm.switchDisabled($("stream-quality-slider"), true);
+ wm.switchDisabled($("stream-desired-fps-slider"), true);
+
+ __client_key = tools.makeId();
+ __client_id = "";
+ __client_fps = -1;
+ __prev = false;
+ __updateStreamHeader(false);
+ };
+
+ var __updateQualityValue = function(value) {
+ $("stream-quality-value").innerHTML = value + "%";
+ };
+
+ var __updateDesiredFpsValue = function(value) {
+ $("stream-desired-fps-value").innerHTML = (value === 0 ? "Unlimited" : value);
+ };
+
+ var __updateStreamHeader = function(online) {
+ var el_grab = document.querySelector("#stream-window-header .window-grab");
+ var el_info = $("stream-info");
+ if (online) {
+ var fps_suffix = (__client_fps >= 0 ? ` / ${__client_fps} fps` : "");
+ el_grab.innerHTML = el_info.innerHTML = `Stream – ${__resolution.width}x${__resolution.height}${fps_suffix}`;
+ } else {
+ el_grab.innerHTML = el_info.innerHTML = "Stream – offline";
+ }
+ };
+
+ var __clickScreenshotButton = function() {
+ var el_a = document.createElement("a");
+ el_a.href = "/streamer/snapshot";
+ el_a.target = "_blank";
+ document.body.appendChild(el_a);
+ el_a.click();
+ setTimeout(() => document.body.removeChild(el_a), 0);
+ };
+
+ var __clickResetButton = function() {
+ var http = tools.makeRequest("POST", "/kvmd/streamer/reset", function() {
+ if (http.readyState === 4) {
+ if (http.status !== 200) {
+ wm.error("Can't reset stream:<br>", http.responseText);
+ }
+ }
+ });
+ };
+
+ var __sendParam = function(name, value) {
+ var http = tools.makeRequest("POST", `/kvmd/streamer/set_params?${name}=${value}`, function() {
+ if (http.readyState === 4) {
+ if (http.status !== 200) {
+ wm.error("Can't configure stream:<br>", http.responseText);
+ }
+ }
+ });
+ };
+
+ var __resize = function(center=false) {
+ var size = $("stream-size-slider").value;
+ $("stream-size-value").innerHTML = size + "%";
+ __size_factor = size / 100;
+ __applySizeFactor(center);
+ };
+
+ var __adjustSizeFactor = function() {
+ var el_window = $("stream-window");
+ var el_slider = $("stream-size-slider");
+ var view = wm.getViewGeometry();
+
+ for (var size = 100; size >= el_slider.min; size -= el_slider.step) {
+ tools.info("Stream: adjusting size:", size);
+ $("stream-size-slider").value = size;
+ __resize(true);
+
+ var rect = el_window.getBoundingClientRect();
+ if (
+ rect.bottom <= view.bottom
+ && rect.top >= view.top
+ && rect.left >= view.left
+ && rect.right <= view.right
+ ) {
+ break;
+ }
+ }
+ };
+
+ var __applySizeFactor = function(center=false) {
+ var el_stream_image = $("stream-image");
+ el_stream_image.style.width = __resolution.width * __size_factor + "px";
+ el_stream_image.style.height = __resolution.height * __size_factor + "px";
+ wm.showWindow($("stream-window"), false, center);
+ };
+
+ __init__();
+}