From 2a22f234f89f678a6ef1772ddb6508160e3c144e Mon Sep 17 00:00:00 2001 From: Siyuan Miao Date: Thu, 25 Sep 2025 17:57:50 +0000 Subject: [PATCH] show video debugging info --- internal/native/cgo/ctrl.c | 4 ++ internal/native/cgo/ctrl.h | 1 + internal/native/cgo_linux.go | 10 ++++ internal/native/cgo_notlinux.go | 5 ++ internal/native/lib/libjknative.a | Bin 3119462 -> 3119150 bytes internal/native/video.go | 7 +++ jsonrpc.go | 5 ++ ui/src/routes/devices.$id.settings.video.tsx | 48 ++++++++++++++++++- 8 files changed, 78 insertions(+), 2 deletions(-) diff --git a/internal/native/cgo/ctrl.c b/internal/native/cgo/ctrl.c index 8ea06bd3..d8c4cdb2 100644 --- a/internal/native/cgo/ctrl.c +++ b/internal/native/cgo/ctrl.c @@ -393,6 +393,10 @@ jetkvm_video_state_t *jetkvm_video_get_status() { return &state; } +char *jetkvm_video_log_status() { + return videoc_log_status(); +} + int jetkvm_video_init() { return video_init(); } diff --git a/internal/native/cgo/ctrl.h b/internal/native/cgo/ctrl.h index 254fdf7b..a87070a0 100644 --- a/internal/native/cgo/ctrl.h +++ b/internal/native/cgo/ctrl.h @@ -59,6 +59,7 @@ int jetkvm_video_set_quality_factor(float quality_factor); float jetkvm_video_get_quality_factor(); int jetkvm_video_set_edid(const char *edid_hex); char *jetkvm_video_get_edid_hex(); +char *jetkvm_video_log_status(); jetkvm_video_state_t *jetkvm_video_get_status(); void video_report_format(bool ready, const char *error, u_int16_t width, u_int16_t height, double frame_per_second); diff --git a/internal/native/cgo_linux.go b/internal/native/cgo_linux.go index 54d57b55..b7ea7220 100644 --- a/internal/native/cgo_linux.go +++ b/internal/native/cgo_linux.go @@ -162,6 +162,16 @@ func videoStop() { C.jetkvm_video_stop() } +func videoLogStatus() string { + cgoLock.Lock() + defer cgoLock.Unlock() + + logStatus := C.jetkvm_video_log_status() + defer C.free(unsafe.Pointer(logStatus)) + + return C.GoString(logStatus) +} + func uiSetVar(name string, value string) { cgoLock.Lock() defer cgoLock.Unlock() diff --git a/internal/native/cgo_notlinux.go b/internal/native/cgo_notlinux.go index 1b23ab5e..6dc14c9c 100644 --- a/internal/native/cgo_notlinux.go +++ b/internal/native/cgo_notlinux.go @@ -108,6 +108,11 @@ func videoSetStreamQualityFactor(factor float64) error { return nil } +func videoLogStatus() string { + panicPlatformNotSupported() + return "" +} + func videoGetEDID() (string, error) { panicPlatformNotSupported() return "", nil diff --git a/internal/native/lib/libjknative.a b/internal/native/lib/libjknative.a index 91bb75c42e167289b5fd8f26fd9c7bd8efb2036b..effa575ec0442ee622634d88295dd799db283207 100644 GIT binary patch delta 12166 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 V6=lA!1IkBR^ch~`3itTT{|6E>*R=ou delta 12416 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 Nn2_Y`T~Sn<^8c&L9W(#{ diff --git a/internal/native/video.go b/internal/native/video.go index b354b2e5..77291eb7 100644 --- a/internal/native/video.go +++ b/internal/native/video.go @@ -36,6 +36,13 @@ func (n *Native) VideoGetEDID() (string, error) { return videoGetEDID() } +func (n *Native) VideoLogStatus() (string, error) { + n.videoLock.Lock() + defer n.videoLock.Unlock() + + return videoLogStatus(), nil +} + func (n *Native) VideoStop() error { n.videoLock.Lock() defer n.videoLock.Unlock() diff --git a/jsonrpc.go b/jsonrpc.go index 32f9bb8a..14faccc8 100644 --- a/jsonrpc.go +++ b/jsonrpc.go @@ -251,6 +251,10 @@ func rpcSetEDID(edid string) error { return nil } +func rpcGetVideoLogStatus() (string, error) { + return nativeInstance.VideoLogStatus() +} + func rpcGetDevChannelState() (bool, error) { return config.IncludePreRelease, nil } @@ -1207,6 +1211,7 @@ var rpcHandlers = map[string]RPCHandler{ "setAutoUpdateState": {Func: rpcSetAutoUpdateState, Params: []string{"enabled"}}, "getEDID": {Func: rpcGetEDID}, "setEDID": {Func: rpcSetEDID, Params: []string{"edid"}}, + "getVideoLogStatus": {Func: rpcGetVideoLogStatus}, "getDevChannelState": {Func: rpcGetDevChannelState}, "setDevChannelState": {Func: rpcSetDevChannelState, Params: []string{"enabled"}}, "getLocalVersion": {Func: rpcGetLocalVersion}, diff --git a/ui/src/routes/devices.$id.settings.video.tsx b/ui/src/routes/devices.$id.settings.video.tsx index ea1a101a..963b6d81 100644 --- a/ui/src/routes/devices.$id.settings.video.tsx +++ b/ui/src/routes/devices.$id.settings.video.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import { Button } from "@/components/Button"; import { TextAreaWithLabel } from "@/components/TextArea"; @@ -52,7 +52,7 @@ export default function SettingsVideoRoute() { const [customEdidValue, setCustomEdidValue] = useState(null); const [edid, setEdid] = useState(null); const [edidLoading, setEdidLoading] = useState(false); - + const { debugMode } = useSettingsStore(); // Video enhancement settings from store const { videoSaturation, @@ -132,6 +132,26 @@ export default function SettingsVideoRoute() { }); }; + const [debugInfo, setDebugInfo] = useState(null); + const [debugInfoLoading, setDebugInfoLoading] = useState(false); + const getDebugInfo = useCallback(() => { + setDebugInfoLoading(true); + send("getVideoLogStatus", {}, (resp: JsonRpcResponse) => { + if ("error" in resp) { + notifications.error(`Failed to get debug info: ${resp.error.data || "Unknown error"}`); + setDebugInfoLoading(false); + return; + } + const data = resp.result as string; + setDebugInfo(data + .split("\n") + .map(line => line.trim().replace(/^\[\s*\d+\.\d+\]\s*/, "")) + .join("\n") + ); + setDebugInfoLoading(false); + }); + }, [send]); + return (
@@ -279,6 +299,30 @@ export default function SettingsVideoRoute() { )}
+ + + {debugMode && ( +
+ +
+ )}