summaryrefslogtreecommitdiff
path: root/web/share/js
diff options
context:
space:
mode:
authorMaxim Devaev <[email protected]>2024-10-23 19:27:24 +0300
committerMaxim Devaev <[email protected]>2024-10-23 19:31:39 +0300
commita26aee3543883faf9a5b83832b274604f4f69263 (patch)
tree73c2910bb663431374f5bc77af20ce6295ec2d58 /web/share/js
parent0e4a70e7b9cdde53b1063686a896057d3c940e35 (diff)
partial streamer events
Diffstat (limited to 'web/share/js')
-rw-r--r--web/share/js/kvm/session.js7
-rw-r--r--web/share/js/kvm/stream.js198
-rw-r--r--web/share/js/kvm/stream_janus.js2
-rw-r--r--web/share/js/kvm/stream_mjpeg.js8
-rw-r--r--web/share/js/tools.js8
5 files changed, 127 insertions, 96 deletions
diff --git a/web/share/js/kvm/session.js b/web/share/js/kvm/session.js
index 22cefe89..1e7fefcd 100644
--- a/web/share/js/kvm/session.js
+++ b/web/share/js/kvm/session.js
@@ -57,7 +57,7 @@ export function Session() {
var __info_fan_state = null;
var __init__ = function() {
- __startSession();
+ __streamer.ensureDeps(() => __startSession());
};
/************************************************************************/
@@ -281,11 +281,6 @@ export function Session() {
tools.feature.setEnabled($("system-tool-webterm"), has_webterm);
$("webterm-window").show_hook = show_hook;
$("webterm-window").close_hook = close_hook;
-
- __streamer.setJanusEnabled(
- (state.janus && (state.janus.enabled || state.janus.started))
- || (state.janus_static && (state.janus_static.enabled || state.janus_static.started))
- );
};
var __startSession = function() {
diff --git a/web/share/js/kvm/stream.js b/web/share/js/kvm/stream.js
index f96f02d2..7c1296dc 100644
--- a/web/share/js/kvm/stream.js
+++ b/web/share/js/kvm/stream.js
@@ -35,11 +35,11 @@ export function Streamer() {
/************************************************************************/
- var __janus_enabled = null;
+ var __janus_imported = null;
var __streamer = null;
var __state = null;
- var __resolution = {"width": 640, "height": 480};
+ var __res = {"width": 640, "height": 480};
var __init__ = function() {
__streamer = new MjpegStreamer(__setActive, __setInactive, __setInfo);
@@ -47,22 +47,22 @@ export function Streamer() {
$("stream-led").title = "Stream inactive";
tools.slider.setParams($("stream-quality-slider"), 5, 100, 5, 80, function(value) {
- $("stream-quality-value").innerHTML = `${value}%`;
+ $("stream-quality-value").innerText = `${value}%`;
});
tools.slider.setOnUpDelayed($("stream-quality-slider"), 1000, (value) => __sendParam("quality", value));
tools.slider.setParams($("stream-h264-bitrate-slider"), 25, 20000, 25, 5000, function(value) {
- $("stream-h264-bitrate-value").innerHTML = value;
+ $("stream-h264-bitrate-value").innerText = value;
});
tools.slider.setOnUpDelayed($("stream-h264-bitrate-slider"), 1000, (value) => __sendParam("h264_bitrate", value));
tools.slider.setParams($("stream-h264-gop-slider"), 0, 60, 1, 30, function(value) {
- $("stream-h264-gop-value").innerHTML = value;
+ $("stream-h264-gop-value").innerText = value;
});
tools.slider.setOnUpDelayed($("stream-h264-gop-slider"), 1000, (value) => __sendParam("h264_gop", value));
tools.slider.setParams($("stream-desired-fps-slider"), 0, 120, 1, 0, function(value) {
- $("stream-desired-fps-value").innerHTML = (value === 0 ? "Unlimited" : value);
+ $("stream-desired-fps-value").innerText = (value === 0 ? "Unlimited" : value);
});
tools.slider.setOnUpDelayed($("stream-desired-fps-slider"), 1000, (value) => __sendParam("desired_fps", value));
@@ -86,7 +86,7 @@ export function Streamer() {
tools.slider.setParams($("stream-audio-volume-slider"), 0, 100, 1, 0, function(value) {
$("stream-video").muted = !value;
$("stream-video").volume = value / 100;
- $("stream-audio-volume-value").innerHTML = value + "%";
+ $("stream-audio-volume-value").innerText = value + "%";
if (__streamer.getMode() === "janus") {
let allow_audio = !$("stream-video").muted;
if (__streamer.isAudioAllowed() !== allow_audio) {
@@ -104,6 +104,13 @@ export function Streamer() {
/************************************************************************/
+ self.ensureDeps = function(callback) {
+ JanusStreamer.ensure_janus(function(avail) {
+ __janus_imported = avail;
+ callback();
+ });
+ };
+
self.getGeometry = function() {
// Первоначально обновление геометрии считалось через ResizeObserver.
// Но оно не ловило некоторые события, например в последовательности:
@@ -126,90 +133,106 @@ export function Streamer() {
};
};
- self.setJanusEnabled = function(enabled) {
- let has_webrtc = JanusStreamer.is_webrtc_available();
- let has_h264 = JanusStreamer.is_h264_available();
-
- let set_enabled = function(imported) {
- tools.hidden.setVisible($("stream-message-no-webrtc"), enabled && !has_webrtc);
- tools.hidden.setVisible($("stream-message-no-h264"), enabled && !has_h264);
- __janus_enabled = (enabled && has_webrtc && imported); // Don't check has_h264 for sure
- tools.feature.setEnabled($("stream-mode"), __janus_enabled);
- tools.info(
- `Stream: Janus WebRTC state: enabled=${enabled},`
- + ` webrtc=${has_webrtc}, h264=${has_h264}, imported=${imported}`
- );
- let mode = (__janus_enabled ? tools.storage.get("stream.mode", "janus") : "mjpeg");
- tools.radio.clickValue("stream-mode-radio", mode);
- if (!__janus_enabled) {
- tools.feature.setEnabled($("stream-audio"), false); // Enabling in stream_janus.js
+ self.setState = function(state) {
+ if (state) {
+ if (!__state) {
+ __state = {};
}
- self.setState(__state);
- };
-
- if (enabled && has_webrtc) {
- JanusStreamer.ensure_janus(set_enabled);
+ if (state.features) {
+ __state.features = state.features;
+ __state.limits = state.limits; // Following together with features
+ }
+ if (__state.features && state.streamer !== undefined) {
+ __state.streamer = state.streamer;
+ }
+ __setControlsEnabled(!!state.streamer);
} else {
- set_enabled(false);
+ __state = null;
}
+ let visible = wm.isWindowVisible($("stream-window"));
+ __applyState((visible && __state && __state.features) ? state : null);
};
- self.setState = function(state) {
- __state = state;
- if (__janus_enabled !== null) {
- __applyState(wm.isWindowVisible($("stream-window")) ? __state : null);
+ var __applyState = function(state) {
+ if (__janus_imported === null) {
+ alert("__janus_imported is null, please report");
+ return;
}
- };
- var __applyState = function(state) {
- if (state) {
- tools.feature.setEnabled($("stream-quality"), state.features.quality && (state.streamer === null || state.streamer.encoder.quality > 0));
- tools.feature.setEnabled($("stream-h264-bitrate"), state.features.h264 && __janus_enabled);
- tools.feature.setEnabled($("stream-h264-gop"), state.features.h264 && __janus_enabled);
- tools.feature.setEnabled($("stream-resolution"), state.features.resolution);
+ if (!state) {
+ __streamer.stopStream();
+ return;
+ }
+
+ if (state.features) {
+ let f = state.features;
+ let l = state.limits;
+ let has_webrtc = JanusStreamer.is_webrtc_available();
+ let has_h264 = JanusStreamer.is_h264_available();
+ let has_janus = (__janus_imported && f.h264 && has_webrtc); // Don't check has_h264 for sure
- if (state.streamer) {
- tools.el.setEnabled($("stream-quality-slider"), true);
- tools.slider.setValue($("stream-quality-slider"), state.streamer.encoder.quality);
+ tools.info(
+ `Stream: Janus WebRTC state: features.h264=${f.h264},`
+ + ` webrtc=${has_webrtc}, h264=${has_h264}, janus_imported=${__janus_imported}`
+ );
- if (state.features.h264 && __janus_enabled) {
- __setLimitsAndValue($("stream-h264-bitrate-slider"), state.limits.h264_bitrate, state.streamer.h264.bitrate);
- tools.el.setEnabled($("stream-h264-bitrate-slider"), true);
+ tools.hidden.setVisible($("stream-message-no-webrtc"), __janus_imported && f.h264 && !has_webrtc);
+ tools.hidden.setVisible($("stream-message-no-h264"), __janus_imported && f.h264 && !has_h264);
- __setLimitsAndValue($("stream-h264-gop-slider"), state.limits.h264_gop, state.streamer.h264.gop);
- tools.el.setEnabled($("stream-h264-gop-slider"), true);
+ tools.slider.setRange($("stream-desired-fps-slider"), l.desired_fps.min, l.desired_fps.max);
+ if (f.resolution) {
+ let el = $("stream-resolution-selector");
+ el.options.length = 0;
+ for (let res of l.available_resolutions) {
+ tools.selector.addOption(el, res, res);
}
+ } else {
+ $("stream-resolution-selector").options.length = 0;
+ }
+ if (has_janus) {
+ tools.slider.setRange($("stream-h264-bitrate-slider"), l.h264_bitrate.min, l.h264_bitrate.max);
+ tools.slider.setRange($("stream-h264-gop-slider"), l.h264_gop.min, l.h264_gop.max);
+ }
- __setLimitsAndValue($("stream-desired-fps-slider"), state.limits.desired_fps, state.streamer.source.desired_fps);
- tools.el.setEnabled($("stream-desired-fps-slider"), true);
+ // tools.feature.setEnabled($("stream-quality"), f.quality); // Only on s.encoder.quality
+ tools.feature.setEnabled($("stream-resolution"), f.resolution);
+ tools.feature.setEnabled($("stream-h264-bitrate"), has_janus);
+ tools.feature.setEnabled($("stream-h264-gop"), has_janus);
+ tools.feature.setEnabled($("stream-mode"), has_janus);
+ if (!has_janus) {
+ tools.feature.setEnabled($("stream-audio"), false);
+ }
- let resolution_str = __makeStringResolution(state.streamer.source.resolution);
- if (__makeStringResolution(__resolution) !== resolution_str) {
- __resolution = state.streamer.source.resolution;
- }
+ let mode = (has_janus ? tools.storage.get("stream.mode", "janus") : "mjpeg");
+ tools.radio.clickValue("stream-mode-radio", mode);
+ }
+
+ if (state.streamer !== undefined) {
+ let ok = (state.streamer !== null);
+ if (ok) {
+ let s = state.streamer;
+ __res = s.source.resolution;
- if (state.features.resolution) {
+ {
+ let res = `${__res.width}x${__res.height}`;
let el = $("stream-resolution-selector");
- if (!state.limits.available_resolutions.includes(resolution_str)) {
- state.limits.available_resolutions.push(resolution_str);
+ if (!tools.selector.hasValue(el, res)) {
+ tools.selector.addOption(el, res, res);
}
- tools.selector.setValues(el, state.limits.available_resolutions);
- tools.selector.setSelectedValue(el, resolution_str);
- tools.el.setEnabled(el, true);
+ el.value = res;
+ }
+ tools.slider.setValue($("stream-quality-slider"), Math.max(s.encoder.quality, 1));
+ tools.slider.setValue($("stream-desired-fps-slider"), s.source.desired_fps);
+ if (s.h264 && s.h264.bitrate) {
+ tools.slider.setValue($("stream-h264-bitrate-slider"), s.h264.bitrate);
+ tools.slider.setValue($("stream-h264-gop-slider"), s.h264.gop); // Following together with gop
}
- } else {
- tools.el.setEnabled($("stream-quality-slider"), false);
- tools.el.setEnabled($("stream-h264-bitrate-slider"), false);
- tools.el.setEnabled($("stream-h264-gop-slider"), false);
- tools.el.setEnabled($("stream-desired-fps-slider"), false);
- tools.el.setEnabled($("stream-resolution-selector"), false);
- }
-
- __streamer.ensureStream(state.streamer);
+ tools.feature.setEnabled($("stream-quality"), (s.encoder.quality > 0));
- } else {
- __streamer.stopStream();
+ __streamer.ensureStream(s);
+ }
+ __setControlsEnabled(ok);
}
};
@@ -223,16 +246,24 @@ export function Streamer() {
$("stream-led").title = "Stream inactive";
};
+ var __setControlsEnabled = function(enabled) {
+ tools.el.setEnabled($("stream-quality-slider"), enabled);
+ tools.el.setEnabled($("stream-desired-fps-slider"), enabled);
+ tools.el.setEnabled($("stream-resolution-selector"), enabled);
+ tools.el.setEnabled($("stream-h264-bitrate-slider"), enabled);
+ tools.el.setEnabled($("stream-h264-gop-slider"), enabled);
+ };
+
var __setInfo = function(is_active, online, text) {
$("stream-box").classList.toggle("stream-box-offline", !online);
let el_grab = document.querySelector("#stream-window-header .window-grab");
let el_info = $("stream-info");
- let title = `${__streamer.getName()} &ndash; `;
+ let title = `${__streamer.getName()} - `;
if (is_active) {
if (!online) {
title += "No signal / ";
}
- title += __makeStringResolution(__resolution);
+ title += `${__res.width}x${__res.height}`;
if (text.length > 0) {
title += " / " + text;
}
@@ -243,12 +274,7 @@ export function Streamer() {
title += "Inactive";
}
}
- el_grab.innerHTML = el_info.innerHTML = title;
- };
-
- var __setLimitsAndValue = function(el, limits, value) {
- tools.slider.setRange(el, limits.min, limits.max);
- tools.slider.setValue(el, value);
+ el_grab.innerText = el_info.innerText = title;
};
var __resetStream = function(mode=null) {
@@ -268,7 +294,7 @@ export function Streamer() {
tools.feature.setEnabled($("stream-audio"), false); // Enabling in stream_janus.js
}
if (wm.isWindowVisible($("stream-window"))) {
- __streamer.ensureStream(__state ? __state.streamer : null);
+ __streamer.ensureStream((__state && __state.streamer !== undefined) ? __state.streamer : null);
}
};
@@ -305,6 +331,12 @@ export function Streamer() {
};
var __sendParam = function(name, value) {
+ tools.el.setEnabled($("stream-quality-slider"), false);
+ tools.el.setEnabled($("stream-desired-fps-slider"), false);
+ tools.el.setEnabled($("stream-resolution-selector"), false);
+ tools.el.setEnabled($("stream-h264-bitrate-slider"), false);
+ tools.el.setEnabled($("stream-h264-gop-slider"), false);
+
tools.httpPost("/api/streamer/set_params", {[name]: value}, function(http) {
if (http.status !== 200) {
wm.error("Can't configure stream", http.responseText);
@@ -312,9 +344,5 @@ export function Streamer() {
});
};
- var __makeStringResolution = function(resolution) {
- return `${resolution.width}x${resolution.height}`;
- };
-
__init__();
}
diff --git a/web/share/js/kvm/stream_janus.js b/web/share/js/kvm/stream_janus.js
index be62dbbd..27d3f55d 100644
--- a/web/share/js/kvm/stream_janus.js
+++ b/web/share/js/kvm/stream_janus.js
@@ -383,7 +383,7 @@ export function JanusStreamer(__setActive, __setInactive, __setInfo, __orient, _
};
var __isOnline = function() {
- return !!(__state && __state.source && __state.source.online);
+ return !!(__state && __state.source.online);
};
var __sendWatch = function() {
diff --git a/web/share/js/kvm/stream_mjpeg.js b/web/share/js/kvm/stream_mjpeg.js
index c914140d..6efbff7d 100644
--- a/web/share/js/kvm/stream_mjpeg.js
+++ b/web/share/js/kvm/stream_mjpeg.js
@@ -117,10 +117,10 @@ export function MjpegStreamer(__setActive, __setInactive, __setInfo) {
};
var __findId = function() {
- let stream_client = tools.cookies.get("stream_client");
- if (__id.length === 0 && stream_client && stream_client.startsWith(__key + "/")) {
- __logInfo("Found acceptable stream_client cookie:", stream_client);
- __id = stream_client.slice(stream_client.indexOf("/") + 1);
+ let sc = tools.cookies.get("stream_client");
+ if (__id.length === 0 && sc && sc.startsWith(__key + "/")) {
+ __logInfo("Found acceptable stream_client cookie:", sc);
+ __id = sc.slice(sc.indexOf("/") + 1);
}
};
diff --git a/web/share/js/tools.js b/web/share/js/tools.js
index 604f9711..97eb0abf 100644
--- a/web/share/js/tools.js
+++ b/web/share/js/tools.js
@@ -309,6 +309,14 @@ export var tools = new function() {
self.selector.addComment(el, "\u2500".repeat(repeat));
}
},
+ "hasValue": function(el, value) {
+ for (let el_op of el.options) {
+ if (el_op.value === value) {
+ return true;
+ }
+ }
+ return false;
+ },
"setValues": function(el, values, empty_title=null) {
if (values.constructor == Object) {