mirror of
https://github.com/sipeed/NanoKVM.git
synced 2026-09-12 18:32:58 -05:00
Adding HDMI Enable/Disable Toggle for PCIe
This commit is contained in:
@@ -35,7 +35,10 @@ func vmRouter(r *gin.Engine) {
|
||||
api.GET("/vm/oled", service.GetOLED) // get OLED configuration
|
||||
api.POST("/vm/oled", service.SetOLED) // set OLED configuration
|
||||
|
||||
api.POST("/vm/hdmi/reset", service.ResetHdmi) // reset hdmi (pcie only)
|
||||
api.GET("/vm/hdmi", service.GetHdmiState) // get HDMI state
|
||||
api.POST("/vm/hdmi/reset", service.ResetHdmi) // reset hdmi (pcie only)
|
||||
api.POST("/vm/hdmi/enable", service.EnableHdmi) // enable hdmi
|
||||
api.POST("/vm/hdmi/disable", service.DisableHdmi) // disable hdmi
|
||||
|
||||
api.GET("/vm/ssh", service.GetSSHState) // get SSH state
|
||||
api.POST("/vm/ssh/enable", service.EnableSSH) // enable SSH
|
||||
|
||||
@@ -9,6 +9,9 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ideally read state from the device
|
||||
var hdmiEnabled = true
|
||||
|
||||
func (s *Service) ResetHdmi(c *gin.Context) {
|
||||
var rsp proto.Response
|
||||
|
||||
@@ -17,7 +20,48 @@ func (s *Service) ResetHdmi(c *gin.Context) {
|
||||
vision.SetHDMI(false)
|
||||
time.Sleep(1 * time.Second)
|
||||
vision.SetHDMI(true)
|
||||
hdmiEnabled = true
|
||||
|
||||
rsp.OkRsp(c)
|
||||
log.Debug("reset hdmi")
|
||||
}
|
||||
|
||||
func (s *Service) EnableHdmi(c *gin.Context) {
|
||||
var rsp proto.Response
|
||||
|
||||
vision := common.GetKvmVision()
|
||||
|
||||
vision.SetHDMI(true)
|
||||
hdmiEnabled = true
|
||||
|
||||
rsp.OkRsp(c)
|
||||
log.Debug("enable hdmi")
|
||||
}
|
||||
|
||||
func (s *Service) DisableHdmi(c *gin.Context) {
|
||||
var rsp proto.Response
|
||||
|
||||
vision := common.GetKvmVision()
|
||||
|
||||
vision.SetHDMI(false)
|
||||
hdmiEnabled = false
|
||||
|
||||
rsp.OkRsp(c)
|
||||
log.Debug("disable hdmi")
|
||||
}
|
||||
|
||||
func (s *Service) GetHdmiState(c *gin.Context) {
|
||||
var rsp proto.Response
|
||||
|
||||
if hdmiEnabled {
|
||||
rsp.OkRspWithData(c, &map[string]string{
|
||||
"state": "enabled",
|
||||
})
|
||||
} else {
|
||||
rsp.OkRspWithData(c, &map[string]string{
|
||||
"state": "disabled",
|
||||
})
|
||||
}
|
||||
|
||||
log.Debug("get hdmi state")
|
||||
}
|
||||
|
||||
@@ -62,6 +62,29 @@ export function resetHdmi() {
|
||||
return http.post('/api/vm/hdmi/reset');
|
||||
}
|
||||
|
||||
// get HDMI state
|
||||
export function getHdmiState() {
|
||||
return http.get('/api/vm/hdmi');
|
||||
}
|
||||
|
||||
// enable HDMI
|
||||
export function enableHdmi() {
|
||||
return http.post('/api/vm/hdmi/enable');
|
||||
}
|
||||
|
||||
// disable HDMI
|
||||
export function disableHdmi() {
|
||||
return http.post('/api/vm/hdmi/disable');
|
||||
}
|
||||
|
||||
// set HDMI state
|
||||
export function setHdmiState(state: string) {
|
||||
if (state === 'enabled') {
|
||||
return enableHdmi();
|
||||
}
|
||||
return disableHdmi();
|
||||
}
|
||||
|
||||
// get SSH state
|
||||
export function getSSHState() {
|
||||
return http.get('/api/vm/ssh');
|
||||
|
||||
@@ -64,7 +64,9 @@ const en = {
|
||||
frameDetect: 'Frame Detect',
|
||||
frameDetectTip:
|
||||
"Calculate the difference between frames. Stop transmitting video stream when no changes are detected on the remote host's screen.",
|
||||
resetHdmi: 'Reset HDMI'
|
||||
resetHdmi: 'Reset HDMI',
|
||||
enableHdmi: 'Enable HDMI',
|
||||
disableHdmi: 'Disable HDMI',
|
||||
},
|
||||
keyboard: {
|
||||
title: 'Keyboard',
|
||||
|
||||
4
web/src/jotai/hdmi.ts
Normal file
4
web/src/jotai/hdmi.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { atom } from 'jotai';
|
||||
|
||||
// hid mode: normal or hid-only
|
||||
export const hdmiEnabledAtom = atom<'enabled' | 'disabled'>('enabled');
|
||||
86
web/src/pages/desktop/menu/screen/hdmi-state.tsx
Normal file
86
web/src/pages/desktop/menu/screen/hdmi-state.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { useAtom } from 'jotai';
|
||||
import { PenIcon } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import * as api from '@/api/vm.ts';
|
||||
import { hdmiEnabledAtom } from '@/jotai/hdmi.ts';
|
||||
|
||||
|
||||
export const HdmiState = () => {
|
||||
const { t } = useTranslation();
|
||||
const [hdmiMode, setHdmiMode] = useAtom(hdmiEnabledAtom);
|
||||
const [isPcie, setIsPcie] = useState(true);
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [_, setErrMsg] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
getHdmiState();
|
||||
api.getHardware().then((rsp) => {
|
||||
if (rsp.code === 0) {
|
||||
setIsPcie(rsp.data?.version === 'PCIE');
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
function getHdmiState() {
|
||||
setIsLoading(true);
|
||||
|
||||
api
|
||||
.getHdmiState()
|
||||
.then((rsp) => {
|
||||
if (rsp.code !== 0) {
|
||||
setErrMsg(rsp.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
setHdmiMode(rsp.data.state);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
function updateHDMIState() {
|
||||
if (isLoading) return;
|
||||
setIsLoading(true);
|
||||
|
||||
const mode = hdmiMode === 'enabled' ? 'disabled' : 'enabled';
|
||||
|
||||
api
|
||||
.setHdmiState(mode)
|
||||
.then((rsp) => {
|
||||
setIsLoading(false);
|
||||
if (rsp.code !== 0) {
|
||||
console.log(rsp.msg);
|
||||
} else {
|
||||
setHdmiMode(mode);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
setIsLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isPcie ? (
|
||||
<div
|
||||
className={clsx(
|
||||
'flex h-[30px] cursor-pointer select-none items-center space-x-2 rounded px-3 hover:bg-neutral-700/70',
|
||||
'text-neutral-300'
|
||||
)}
|
||||
onClick={updateHDMIState}
|
||||
>
|
||||
<PenIcon size={18} />
|
||||
<span>{hdmiMode === 'enabled' ? t('screen.disableHdmi') : t('screen.enableHdmi')}</span>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -16,6 +16,7 @@ import { Quality } from './quality';
|
||||
import { Reset } from './reset.tsx';
|
||||
import { Resolution } from './resolution';
|
||||
import { VideoMode } from './video-mode.tsx';
|
||||
import { HdmiState } from './hdmi-state.tsx';
|
||||
|
||||
export const Screen = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -76,6 +77,7 @@ export const Screen = () => {
|
||||
<Fps fps={fps} setFps={setFps} />
|
||||
{videoMode === 'mjpeg' ? <FrameDetect /> : <Gop gop={gop} setGop={setGop} />}
|
||||
<Reset />
|
||||
<HdmiState />
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user