mirror of
https://github.com/AynaLivePlayer/AynaLivePlayer.git
synced 2026-05-19 09:15:47 +08:00
update wshub
This commit is contained in:
16
plugin/wshub/events.go
Normal file
16
plugin/wshub/events.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package wshub
|
||||
|
||||
import (
|
||||
"AynaLivePlayer/pkg/event"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type EventData struct {
|
||||
EventID event.EventId
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
type EventDataReceived struct {
|
||||
EventID event.EventId
|
||||
Data json.RawMessage
|
||||
}
|
||||
165
plugin/wshub/server.go
Normal file
165
plugin/wshub/server.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package wshub
|
||||
|
||||
import (
|
||||
"AynaLivePlayer/core/events"
|
||||
"AynaLivePlayer/global"
|
||||
"AynaLivePlayer/pkg/logger"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gorilla/websocket"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
type wsClient struct {
|
||||
conn *websocket.Conn
|
||||
Data chan []byte
|
||||
Close chan byte
|
||||
}
|
||||
|
||||
func (c *wsClient) start() {
|
||||
for {
|
||||
msgType, val, err := c.conn.ReadMessage()
|
||||
if err != nil {
|
||||
c.Close <- 1
|
||||
return
|
||||
}
|
||||
if msgType == websocket.TextMessage {
|
||||
return
|
||||
}
|
||||
var data EventDataReceived
|
||||
err = json.Unmarshal(val, &data)
|
||||
if err != nil {
|
||||
global.Logger.Warn("unmarshal event data failed", err)
|
||||
return
|
||||
}
|
||||
actualEventData, err := events.UnmarshalEventData(data.EventID, data.Data)
|
||||
if err != nil {
|
||||
global.Logger.Warn("unmarshal event data failed", err)
|
||||
return
|
||||
}
|
||||
global.EventManager.CallA(data.EventID, actualEventData)
|
||||
}
|
||||
}
|
||||
|
||||
type wsServer struct {
|
||||
Running bool
|
||||
Server *http.Server
|
||||
clients map[*wsClient]bool
|
||||
mux *http.ServeMux
|
||||
lock sync.RWMutex
|
||||
port *int
|
||||
log logger.ILogger
|
||||
}
|
||||
|
||||
func newWsServer(port *int) *wsServer {
|
||||
mux := http.NewServeMux()
|
||||
s := &wsServer{
|
||||
Running: false,
|
||||
clients: make(map[*wsClient]bool),
|
||||
mux: mux,
|
||||
port: port,
|
||||
log: global.Logger.WithPrefix("plugin.wshub.server"),
|
||||
}
|
||||
mux.HandleFunc("/wsinfo", s.handleWsInfo)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *wsServer) broadcast(data []byte) {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
for client := range s.clients {
|
||||
client.Data <- data
|
||||
}
|
||||
}
|
||||
|
||||
func (s *wsServer) register(client *wsClient) {
|
||||
s.lock.Lock()
|
||||
s.clients[client] = true
|
||||
s.lock.Unlock()
|
||||
}
|
||||
|
||||
func (s *wsServer) unregister(client *wsClient) {
|
||||
s.lock.Lock()
|
||||
delete(s.clients, client)
|
||||
s.lock.Unlock()
|
||||
}
|
||||
|
||||
func (s *wsServer) handleWsInfo(w http.ResponseWriter, r *http.Request) {
|
||||
s.log.Debug("connection start")
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
s.log.Warnf("upgrade error: %s", err)
|
||||
return
|
||||
}
|
||||
client := &wsClient{
|
||||
conn: conn,
|
||||
Data: make(chan []byte, 16),
|
||||
Close: make(chan byte, 1),
|
||||
}
|
||||
s.register(client)
|
||||
defer s.unregister(client)
|
||||
go client.start()
|
||||
for {
|
||||
select {
|
||||
case data := <-client.Data:
|
||||
err := client.conn.WriteMessage(websocket.TextMessage, data)
|
||||
if err != nil {
|
||||
s.log.Warn("write message failed", err)
|
||||
return
|
||||
}
|
||||
case _ = <-client.Close:
|
||||
s.log.Infof("client %s close", client.conn.RemoteAddr().String())
|
||||
if err := client.conn.Close(); err != nil {
|
||||
s.log.Warnf("close connection encouter an error: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *wsServer) Start() {
|
||||
s.log.Debug("WebInfoServer starting...")
|
||||
s.Running = true
|
||||
go func() {
|
||||
s.Server = &http.Server{
|
||||
Addr: fmt.Sprintf("localhost:%d", *s.port),
|
||||
Handler: s.mux,
|
||||
}
|
||||
err := s.Server.ListenAndServe()
|
||||
s.Running = false
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
s.log.Info("WebInfoServer closed")
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
s.log.Errorf("Failed to start webinfo server: %s", err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *wsServer) Stop() error {
|
||||
s.log.Debug("WebInfoServer stopping...")
|
||||
s.lock.Lock()
|
||||
s.clients = make(map[*wsClient]bool)
|
||||
s.lock.Unlock()
|
||||
if s.Server != nil {
|
||||
return s.Server.Shutdown(context.TODO())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *wsServer) getWsUrl() string {
|
||||
return fmt.Sprintf("ws://localhost:%d/wsinfo", *s.port)
|
||||
}
|
||||
175
plugin/wshub/wshub.go
Normal file
175
plugin/wshub/wshub.go
Normal file
@@ -0,0 +1,175 @@
|
||||
package wshub
|
||||
|
||||
import (
|
||||
"AynaLivePlayer/core/events"
|
||||
"AynaLivePlayer/global"
|
||||
"AynaLivePlayer/gui"
|
||||
"AynaLivePlayer/gui/component"
|
||||
"AynaLivePlayer/pkg/config"
|
||||
"AynaLivePlayer/pkg/event"
|
||||
"AynaLivePlayer/pkg/i18n"
|
||||
"AynaLivePlayer/pkg/logger"
|
||||
"encoding/json"
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/data/binding"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type WsHub struct {
|
||||
config.BaseConfig
|
||||
Enabled bool
|
||||
Port int
|
||||
panel fyne.CanvasObject
|
||||
server *wsServer
|
||||
log logger.ILogger
|
||||
}
|
||||
|
||||
func NewWsHub() *WsHub {
|
||||
return &WsHub{
|
||||
Enabled: false,
|
||||
Port: 29629,
|
||||
log: global.Logger.WithPrefix("plugin.wshub"),
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WsHub) Enable() error {
|
||||
config.LoadConfig(w)
|
||||
w.server = newWsServer(&w.Port)
|
||||
gui.AddConfigLayout(w)
|
||||
w.registerEvents()
|
||||
w.log.Info("webinfo loaded")
|
||||
if w.Enabled {
|
||||
w.log.Info("starting web backend server")
|
||||
w.server.Start()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *WsHub) Disable() error {
|
||||
if w.server.Running {
|
||||
err := w.server.Stop()
|
||||
if err != nil {
|
||||
w.log.Warnf("stop server have error: %s", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *WsHub) Name() string {
|
||||
return "WsHub"
|
||||
}
|
||||
|
||||
func (w *WsHub) Title() string {
|
||||
return i18n.T("plugin.wshub.title")
|
||||
}
|
||||
|
||||
func (w *WsHub) Description() string {
|
||||
return i18n.T("plugin.wshub.description")
|
||||
}
|
||||
|
||||
func (w *WsHub) CreatePanel() fyne.CanvasObject {
|
||||
if w.panel != nil {
|
||||
return w.panel
|
||||
}
|
||||
statusText := widget.NewLabel("")
|
||||
freshStatusText := func() {
|
||||
if w.server.Running {
|
||||
statusText.SetText(i18n.T("plugin.wshub.server_status.running"))
|
||||
return
|
||||
} else {
|
||||
statusText.SetText(i18n.T("plugin.wshub.server_status.stopped"))
|
||||
}
|
||||
}
|
||||
serverStatus := container.NewHBox(
|
||||
widget.NewLabel(i18n.T("plugin.wshub.server_status")),
|
||||
statusText,
|
||||
)
|
||||
autoStart := container.NewHBox(
|
||||
widget.NewLabel(i18n.T("plugin.wshub.autostart")),
|
||||
component.NewCheckOneWayBinding("", &w.Enabled, w.Enabled))
|
||||
freshStatusText()
|
||||
serverPort := container.NewBorder(nil, nil,
|
||||
widget.NewLabel(i18n.T("plugin.wshub.port")), nil,
|
||||
widget.NewEntryWithData(binding.IntToString(binding.BindInt(&w.Port))),
|
||||
)
|
||||
serverUrl := widget.NewEntry()
|
||||
serverUrl.SetText(w.server.getWsUrl())
|
||||
serverUrl.Disable()
|
||||
serverPreview := container.NewBorder(nil, nil,
|
||||
widget.NewLabel(i18n.T("plugin.wshub.server_link")), nil,
|
||||
serverUrl,
|
||||
)
|
||||
refreshServerUrl := func() {
|
||||
serverUrl.SetText(w.server.getWsUrl())
|
||||
}
|
||||
stopBtn := component.NewAsyncButtonWithIcon(
|
||||
i18n.T("plugin.wshub.server_control.stop"),
|
||||
theme.MediaStopIcon(),
|
||||
func() {
|
||||
if !w.server.Running {
|
||||
return
|
||||
}
|
||||
w.log.Info("User try stop webinfo server")
|
||||
err := w.server.Stop()
|
||||
if err != nil {
|
||||
w.log.Warnf("stop server have error: %s", err)
|
||||
}
|
||||
freshStatusText()
|
||||
},
|
||||
)
|
||||
startBtn := component.NewAsyncButtonWithIcon(
|
||||
i18n.T("plugin.wshub.server_control.start"),
|
||||
theme.MediaPlayIcon(),
|
||||
func() {
|
||||
if w.server.Running {
|
||||
return
|
||||
}
|
||||
w.log.Infof("User try start webinfo server with port %d", w.Port)
|
||||
w.server.Start()
|
||||
freshStatusText()
|
||||
refreshServerUrl()
|
||||
},
|
||||
)
|
||||
restartBtn := component.NewAsyncButtonWithIcon(
|
||||
i18n.T("plugin.wshub.server_control.restart"),
|
||||
theme.MediaReplayIcon(),
|
||||
func() {
|
||||
w.log.Infof("User try restart webinfo server with port %d", w.Port)
|
||||
if w.server.Running {
|
||||
if err := w.server.Stop(); err != nil {
|
||||
w.log.Warnf("stop server have error: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.server.Start()
|
||||
freshStatusText()
|
||||
refreshServerUrl()
|
||||
},
|
||||
)
|
||||
ctrlBtns := container.NewHBox(
|
||||
widget.NewLabel(i18n.T("plugin.wshub.server_control")),
|
||||
startBtn, stopBtn, restartBtn,
|
||||
)
|
||||
w.panel = container.NewVBox(serverStatus, autoStart, serverPreview, serverPort, ctrlBtns)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *WsHub) registerEvents() {
|
||||
for eid, _ := range events.EventsMapping {
|
||||
global.EventManager.RegisterA(eid,
|
||||
"plugin.wshub.event."+string(eid),
|
||||
func(e *event.Event) {
|
||||
val, err := json.Marshal(EventData{
|
||||
EventID: e.Id,
|
||||
Data: e.Data,
|
||||
})
|
||||
if err != nil {
|
||||
w.log.Errorf("failed to marshal event data %v", err)
|
||||
return
|
||||
}
|
||||
w.server.broadcast(val)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user