summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Devaev <[email protected]>2025-01-18 21:57:48 +0200
committerMaxim Devaev <[email protected]>2025-01-18 21:57:48 +0200
commit78557b0c47f1b2bd7fac30d319ce957892aa34e9 (patch)
tree68eecc23ca71e44bc33662b24133041d47c19239
parente1e360563008b1e1742e4c6bfbe85869320b7881 (diff)
parentf042ed38e0926557f475f58e8b904ccb1a8beade (diff)
Merge branch 'mic'
-rw-r--r--kvmd/apps/__init__.py5
-rw-r--r--kvmd/apps/otg/__init__.py16
-rw-r--r--web/kvm/index.html9
-rw-r--r--web/kvm/navbar-system.pug4
-rw-r--r--web/share/js/kvm/stream.js13
-rw-r--r--web/share/js/kvm/stream_janus.js24
6 files changed, 64 insertions, 7 deletions
diff --git a/kvmd/apps/__init__.py b/kvmd/apps/__init__.py
index 091319ca..5ad38d90 100644
--- a/kvmd/apps/__init__.py
+++ b/kvmd/apps/__init__.py
@@ -611,6 +611,11 @@ def _get_config_scheme() -> dict:
"kvm_mac": Option("", type=valid_mac, if_empty=""),
},
+ "audio": {
+ "enabled": Option(False, type=valid_bool),
+ "start": Option(True, type=valid_bool),
+ },
+
"drives": {
"enabled": Option(False, type=valid_bool),
"start": Option(True, type=valid_bool),
diff --git a/kvmd/apps/otg/__init__.py b/kvmd/apps/otg/__init__.py
index f21fdf4e..c50626c0 100644
--- a/kvmd/apps/otg/__init__.py
+++ b/kvmd/apps/otg/__init__.py
@@ -112,6 +112,18 @@ class _GadgetConfig:
self.__msd_instance = 0
_mkdir(meta_path)
+ def add_audio_capture(self, start: bool) -> None:
+ eps = 2
+ func = "uac2.usb0"
+ func_path = self.__create_function(func)
+ _write(join(func_path, "c_chmask"), 0)
+ _write(join(func_path, "p_chmask"), 0b11)
+ _write(join(func_path, "p_srate"), 48000)
+ _write(join(func_path, "p_ssize"), 2)
+ if start:
+ self.__start_function(func, eps)
+ self.__create_meta(func, "Audio Capture", eps)
+
def add_serial(self, start: bool) -> None:
eps = 3
func = "acm.usb0"
@@ -295,6 +307,10 @@ def _cmd_start(config: Section) -> None: # pylint: disable=too-many-statements,
logger.info("===== Serial =====")
gc.add_serial(cod.serial.start)
+ if cod.audio.enabled:
+ logger.info("===== Audio Capture =====")
+ gc.add_audio_capture(cod.audio.start)
+
logger.info("===== Preparing complete =====")
logger.info("Enabling the gadget ...")
diff --git a/web/kvm/index.html b/web/kvm/index.html
index 713e1c84..9427e3f8 100644
--- a/web/kvm/index.html
+++ b/web/kvm/index.html
@@ -262,6 +262,15 @@
</td>
<td class="value-number" id="stream-audio-volume-value"></td>
</tr>
+ <tr class="feature-disabled" id="stream-mic">
+ <td>Microphone:</td>
+ <td align="right">
+ <div class="switch-box">
+ <input disabled type="checkbox" id="stream-mic-switch">
+ <label for="stream-mic-switch"><span class="switch-inner"></span><span class="switch"></span></label>
+ </div>
+ </td>
+ </tr>
</table>
<hr>
<div class="buttons buttons-row">
diff --git a/web/kvm/navbar-system.pug b/web/kvm/navbar-system.pug
index 55d70757..5c675601 100644
--- a/web/kvm/navbar-system.pug
+++ b/web/kvm/navbar-system.pug
@@ -67,10 +67,12 @@ li(id="system-dropdown" class="right")
label(for="stream-orient-radio-180") 180&deg;
input(type="radio" id="stream-orient-radio-270" name="stream-orient-radio" value="270")
label(for="stream-orient-radio-270") 270&deg;
- tr(id="stream-audio", class="feature-disabled")
+ tr(id="stream-audio" class="feature-disabled")
td Audio volume:
td(class="value-slider") #[input(type="range" id="stream-audio-volume-slider" class="slider")]
td(id="stream-audio-volume-value" class="value-number")
+ tr(id="stream-mic" class="feature-disabled")
+ +menu_switch_notable("stream-mic-switch", "Microphone", false, false)
hr
div(class="buttons buttons-row")
button(data-force-hide-menu data-show-window="stream-window" class="row33") &bull; Show stream
diff --git a/web/share/js/kvm/stream.js b/web/share/js/kvm/stream.js
index 7d947736..2de3d469 100644
--- a/web/share/js/kvm/stream.js
+++ b/web/share/js/kvm/stream.js
@@ -94,6 +94,15 @@ export function Streamer() {
__resetStream();
}
}
+ tools.el.setEnabled($("stream-mic-switch"), !!value);
+ });
+
+ tools.storage.bindSimpleSwitch($("stream-mic-switch"), "stream.mic", false, function(allow_mic) {
+ if (__streamer.getMode() === "janus") {
+ if (__streamer.isMicAllowed() !== allow_mic) {
+ __resetStream();
+ }
+ }
});
tools.el.setOnClick($("stream-screenshot-button"), __clickScreenshotButton);
@@ -206,6 +215,7 @@ export function Streamer() {
tools.feature.setEnabled($("stream-mode"), f.h264);
if (!f.h264) {
tools.feature.setEnabled($("stream-audio"), false);
+ tools.feature.setEnabled($("stream-mic"), false);
}
let mode = tools.storage.get("stream.mode", "janus");
@@ -291,7 +301,7 @@ export function Streamer() {
__streamer.stopStream();
if (mode === "janus") {
__streamer = new JanusStreamer(__setActive, __setInactive, __setInfo,
- tools.storage.getInt("stream.orient", 0), !$("stream-video").muted);
+ tools.storage.getInt("stream.orient", 0), !$("stream-video").muted, $("stream-mic-switch").checked);
// Firefox doesn't support RTP orientation:
// - https://bugzilla.mozilla.org/show_bug.cgi?id=1316448
tools.feature.setEnabled($("stream-orient"), !tools.browser.is_firefox);
@@ -303,6 +313,7 @@ export function Streamer() {
}
tools.feature.setEnabled($("stream-orient"), false);
tools.feature.setEnabled($("stream-audio"), false); // Enabling in stream_janus.js
+ tools.feature.setEnabled($("stream-mic"), false); // Ditto
}
if (wm.isWindowVisible($("stream-window"))) {
__streamer.ensureStream((__state && __state.streamer !== undefined) ? __state.streamer : null);
diff --git a/web/share/js/kvm/stream_janus.js b/web/share/js/kvm/stream_janus.js
index 09ee75da..449450b7 100644
--- a/web/share/js/kvm/stream_janus.js
+++ b/web/share/js/kvm/stream_janus.js
@@ -29,11 +29,13 @@ import {tools, $} from "../tools.js";
var _Janus = null;
-export function JanusStreamer(__setActive, __setInactive, __setInfo, __orient, __allow_audio) {
+export function JanusStreamer(__setActive, __setInactive, __setInfo, __orient, __allow_audio, __allow_mic) {
var self = this;
/************************************************************************/
+ __allow_mic = (__allow_audio && __allow_mic); // XXX: Mic only with audio
+
var __stop = false;
var __ensuring = false;
@@ -51,8 +53,18 @@ export function JanusStreamer(__setActive, __setInactive, __setInfo, __orient, _
self.getOrientation = () => __orient;
self.isAudioAllowed = () => __allow_audio;
-
- self.getName = () => (__allow_audio ? "WebRTC H.264 + Audio" : "WebRTC H.264");
+ self.isMicAllowed = () => __allow_mic;
+
+ self.getName = function() {
+ let name = "WebRTC H.264";
+ if (__allow_audio) {
+ name += " + Audio";
+ if (__allow_mic) {
+ name += " + Mic";
+ }
+ }
+ return name;
+ };
self.getMode = () => "janus";
self.getResolution = function() {
@@ -229,6 +241,7 @@ export function JanusStreamer(__setActive, __setInactive, __setInfo, __orient, _
__setInfo(false, false, "");
} else if (msg.result.status === "features") {
tools.feature.setEnabled($("stream-audio"), msg.result.features.audio);
+ tools.feature.setEnabled($("stream-mic"), msg.result.features.mic);
}
} else if (msg.error_code || msg.error) {
__logError("Got uStreamer error message:", msg.error_code, "-", msg.error);
@@ -251,7 +264,7 @@ export function JanusStreamer(__setActive, __setInactive, __setInfo, __orient, _
__logInfo("Handling SDP:", jsep);
let tracks = [{"type": "video", "capture": false, "recv": true, "add": true}];
if (__allow_audio) {
- tracks.push({"type": "audio", "capture": false, "recv": true, "add": true});
+ tracks.push({"type": "audio", "capture": __allow_mic, "recv": true, "add": true});
}
__handle.createAnswer({
"jsep": jsep,
@@ -354,11 +367,12 @@ export function JanusStreamer(__setActive, __setInactive, __setInfo, __orient, _
var __sendWatch = function() {
if (__handle) {
- __logInfo(`Sending WATCH(orient=${__orient}, audio=${__allow_audio}) + FEATURES ...`);
+ __logInfo(`Sending WATCH(orient=${__orient}, audio=${__allow_audio}, mic=${__allow_mic}) + FEATURES ...`);
__handle.send({"message": {"request": "features"}});
__handle.send({"message": {"request": "watch", "params": {
"orientation": __orient,
"audio": __allow_audio,
+ "mic": __allow_mic,
}}});
}
};