add audio support, trying to manage MSD device
This commit is contained in:
@@ -1,11 +1,20 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"rkkvm/config"
|
||||
"rkkvm/http/hw/hid"
|
||||
"rkkvm/http/hw/stream"
|
||||
"rkkvm/http/middleware"
|
||||
"rkkvm/http/reqrsp"
|
||||
"rkkvm/http/ws"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func Api(e *gin.Engine) {
|
||||
@@ -15,7 +24,141 @@ func Api(e *gin.Engine) {
|
||||
api.GET("/stream/audio", stream.AudioHandler)
|
||||
api.GET("/ws", ws.ConnHandler)
|
||||
|
||||
api.POST("/stream/webrtc", stream.WebRTCHandshake)
|
||||
|
||||
api.POST("/stream/webrtc", stream.WebRTCPeerConnect)
|
||||
api.GET("/stream/webrtc", stream.WebRTCSettings)
|
||||
|
||||
api.POST("/storage/image", uploadHandler)
|
||||
api.GET("/storage/image", listHandler)
|
||||
api.GET("/storage/image/mounted", mountedHandler)
|
||||
api.POST("/storage/image/mount", mountHandler)
|
||||
api.POST("/storage/image/unmount", unmountHandler)
|
||||
}
|
||||
|
||||
func uploadHandler(c *gin.Context) {
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to get file"})
|
||||
return
|
||||
}
|
||||
|
||||
filePath := filepath.Join(config.Get().ISOPath, file.Filename)
|
||||
if err := c.SaveUploadedFile(file, filePath); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "File uploaded successfully"})
|
||||
}
|
||||
|
||||
func listHandler(c *gin.Context) {
|
||||
files, err := os.ReadDir(config.Get().ISOPath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{
|
||||
Code: -2,
|
||||
Msg: "get images failed",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var fileNames []string
|
||||
for _, f := range files {
|
||||
if !f.IsDir() {
|
||||
fname := strings.ToLower(f.Name())
|
||||
if strings.HasSuffix(fname, ".iso") || strings.HasSuffix(fname, ".img") {
|
||||
fileNames = append(fileNames, f.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{
|
||||
Msg: reqrsp.MsgSuccess,
|
||||
Data: reqrsp.FilesRsp{
|
||||
Files: fileNames,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func mountHandler(c *gin.Context) {
|
||||
var request struct {
|
||||
Filename string `json:"file"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, reqrsp.NanoKVMRsp{
|
||||
Code: -1,
|
||||
Msg: "invalid arguments",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
imageFile := filepath.Join(config.Get().ISOPath, request.Filename)
|
||||
_, err := os.Stat(imageFile)
|
||||
if os.IsNotExist(err) {
|
||||
c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{
|
||||
Code: -2,
|
||||
Msg: "file not exists: " + request.Filename,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
hid.GetHid().Close()
|
||||
|
||||
cmds := []string{
|
||||
config.RootFS + "/hid.sh detach",
|
||||
config.RootFS + "/hid.sh mount_iso " + imageFile, //+ strconv.Quote(imageFile),
|
||||
config.RootFS + "/hid.sh attach",
|
||||
}
|
||||
|
||||
for _, cmd := range cmds {
|
||||
log.Debugf("Executing: %s", cmd)
|
||||
cc := exec.Command("sh", "-c", cmd)
|
||||
cc.Stdout = os.Stdout
|
||||
cc.Stderr = os.Stderr
|
||||
if err := cc.Run(); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{
|
||||
Code: -2,
|
||||
Msg: "execute command failed: " + cmd,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
hid.GetHid().Open()
|
||||
|
||||
c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{
|
||||
Msg: reqrsp.MsgSuccess,
|
||||
})
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func unmountHandler(c *gin.Context) {
|
||||
if output, err := exec.Command(config.RootFS + "/hid.sh unmount_iso").Output(); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{
|
||||
Code: -2,
|
||||
Msg: "execute command failed: " + string(output),
|
||||
})
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{
|
||||
Msg: reqrsp.MsgSuccess,
|
||||
})
|
||||
}
|
||||
|
||||
func mountedHandler(c *gin.Context) {
|
||||
cmd := exec.Command(config.RootFS+"/hid.sh", "mounted_iso")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{
|
||||
Code: -2,
|
||||
Msg: "read failed",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{
|
||||
Msg: reqrsp.MsgSuccess,
|
||||
Data: reqrsp.FileRsp{
|
||||
File: string(output),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
90
http/route/nanokvm_ui.go
Normal file
90
http/route/nanokvm_ui.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"rkkvm/http/hw/stream"
|
||||
"rkkvm/http/middleware"
|
||||
"rkkvm/http/reqrsp"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type LoginReq struct {
|
||||
Username string `validate:"required"`
|
||||
Password string `validate:"required"`
|
||||
}
|
||||
|
||||
type LoginRsp struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type ChangePasswordReq struct {
|
||||
Username string `json:"username" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
}
|
||||
|
||||
func Auth(r *gin.Engine) {
|
||||
r.POST("/api/auth/login", login)
|
||||
|
||||
api := r.Group("/api").Use(middleware.CheckToken())
|
||||
|
||||
api.POST("/auth/password", func(ctx *gin.Context) {})
|
||||
}
|
||||
|
||||
func VM(r *gin.Engine) {
|
||||
api := r.Group("/api").Use(middleware.CheckToken())
|
||||
|
||||
api.POST("/vm/screen", SetScreen)
|
||||
api.GET("/vm/gpio", func(ctx *gin.Context) {}) // just to not space in front log
|
||||
}
|
||||
|
||||
type SetScreenReq struct {
|
||||
Type string `validate:"required"` // resolution / fps / quality
|
||||
Value int `validate:"number"` // value
|
||||
}
|
||||
|
||||
func SetScreen(c *gin.Context) {
|
||||
var req SetScreenReq
|
||||
|
||||
if err := c.ShouldBind(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, reqrsp.NanoKVMRsp{
|
||||
Code: -1,
|
||||
Msg: "invalid arguments",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ffmpeg := stream.GetFFmpeg()
|
||||
switch req.Type {
|
||||
case "fps":
|
||||
ffmpeg.SetFPS(req.Value)
|
||||
case "quality":
|
||||
ffmpeg.SetBitrate(req.Value * 100)
|
||||
case "resolution":
|
||||
ffmpeg.SetResolution(req.Value)
|
||||
default:
|
||||
c.JSON(http.StatusBadRequest, reqrsp.NanoKVMRsp{
|
||||
Code: -2,
|
||||
Msg: "invalid type",
|
||||
})
|
||||
return
|
||||
}
|
||||
ffmpeg.Stop()
|
||||
ffmpeg.Start()
|
||||
|
||||
log.Debugf("update screen: %+v", req)
|
||||
c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{
|
||||
Msg: reqrsp.MsgSuccess,
|
||||
})
|
||||
}
|
||||
|
||||
// FIXME: auth disabled while backend doesn't have key features
|
||||
func login(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{
|
||||
Msg: reqrsp.MsgSuccess,
|
||||
Data: gin.H{
|
||||
"token": "disabled",
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user