split remote to desktop and capture.

This commit is contained in:
Miroslav Šedivý 2022-09-12 22:12:47 +02:00
parent 0bca8c9d02
commit de4f6b45e5
26 changed files with 299 additions and 194 deletions

View File

@ -19,7 +19,8 @@ func init() {
configs := []config.Config{
neko.Service.Server,
neko.Service.WebRTC,
neko.Service.Remote,
neko.Service.Capture,
neko.Service.Desktop,
neko.Service.Broadcast,
neko.Service.WebSocket,
}

View File

@ -14,16 +14,16 @@ type BroadcastManager struct {
mu sync.Mutex
logger zerolog.Logger
pipeline *gst.Pipeline
remote *config.Remote
capture *config.Capture
config *config.Broadcast
enabled bool
url string
}
func New(remote *config.Remote, config *config.Broadcast) *BroadcastManager {
func New(capture *config.Capture, config *config.Broadcast) *BroadcastManager {
return &BroadcastManager{
logger: log.With().Str("module", "remote").Logger(),
remote: remote,
logger: log.With().Str("module", "broadcast").Logger(),
capture: capture,
config: config,
enabled: config.Enabled,
url: config.URL,
@ -42,8 +42,8 @@ func (manager *BroadcastManager) Start() error {
var err error
manager.pipeline, err = gst.CreateRTMPPipeline(
manager.remote.Device,
manager.remote.Display,
manager.capture.Device,
manager.capture.Display,
manager.config.Pipeline,
manager.url,
)
@ -54,8 +54,8 @@ func (manager *BroadcastManager) Start() error {
}
manager.logger.Info().
Str("audio_device", manager.remote.Device).
Str("video_display", manager.remote.Display).
Str("audio_device", manager.capture.Device).
Str("video_display", manager.capture.Display).
Str("rtmp_pipeline_src", manager.pipeline.Src).
Msgf("RTMP pipeline is starting...")

View File

@ -1,11 +1,11 @@
package remote
package capture
import (
"fmt"
"time"
"m1k1o/neko/internal/desktop/xorg"
"m1k1o/neko/internal/gst"
"m1k1o/neko/internal/remote/xorg"
"m1k1o/neko/internal/types"
"m1k1o/neko/internal/types/config"
@ -14,47 +14,41 @@ import (
"github.com/rs/zerolog/log"
)
type RemoteManager struct {
type CaptureManagerCtx struct {
logger zerolog.Logger
video *gst.Pipeline
audio *gst.Pipeline
config *config.Remote
config *config.Capture
broadcast types.BroadcastManager
desktop types.DesktopManager
cleanup *time.Ticker
shutdown chan bool
emmiter events.EventEmmiter
streaming bool
}
func New(config *config.Remote, broadcast types.BroadcastManager) *RemoteManager {
return &RemoteManager{
logger: log.With().Str("module", "remote").Logger(),
func New(desktop types.DesktopManager, broadcast types.BroadcastManager, config *config.Capture) *CaptureManagerCtx {
return &CaptureManagerCtx{
logger: log.With().Str("module", "capture").Logger(),
cleanup: time.NewTicker(1 * time.Second),
shutdown: make(chan bool),
emmiter: events.New(),
config: config,
broadcast: broadcast,
desktop: desktop,
streaming: false,
}
}
func (manager *RemoteManager) VideoCodec() string {
func (manager *CaptureManagerCtx) VideoCodec() string {
return manager.config.VideoCodec
}
func (manager *RemoteManager) AudioCodec() string {
func (manager *CaptureManagerCtx) AudioCodec() string {
return manager.config.AudioCodec
}
func (manager *RemoteManager) Start() {
xorg.Display(manager.config.Display)
if !xorg.ValidScreenSize(manager.config.ScreenWidth, manager.config.ScreenHeight, manager.config.ScreenRate) {
manager.logger.Warn().Msgf("invalid screen option %dx%d@%d", manager.config.ScreenWidth, manager.config.ScreenHeight, manager.config.ScreenRate)
} else if err := xorg.ChangeScreenSize(manager.config.ScreenWidth, manager.config.ScreenHeight, manager.config.ScreenRate); err != nil {
manager.logger.Warn().Err(err).Msg("unable to change screen size")
}
func (manager *CaptureManagerCtx) Start() {
manager.createPipelines()
if err := manager.broadcast.Start(); err != nil {
manager.logger.Panic().Err(err).Msg("unable to create rtmp pipeline")
@ -74,14 +68,14 @@ func (manager *RemoteManager) Start() {
case sample := <-manager.audio.Sample:
manager.emmiter.Emit("audio", sample)
case <-manager.cleanup.C:
xorg.CheckKeys(time.Second * 10)
// TODO: refactor.
}
}
}()
}
func (manager *RemoteManager) Shutdown() error {
manager.logger.Info().Msgf("remote shutting down")
func (manager *CaptureManagerCtx) Shutdown() error {
manager.logger.Info().Msgf("capture shutting down")
manager.video.Stop()
manager.audio.Stop()
manager.broadcast.Stop()
@ -91,19 +85,19 @@ func (manager *RemoteManager) Shutdown() error {
return nil
}
func (manager *RemoteManager) OnVideoFrame(listener func(sample types.Sample)) {
func (manager *CaptureManagerCtx) OnVideoFrame(listener func(sample types.Sample)) {
manager.emmiter.On("video", func(payload ...interface{}) {
listener(payload[0].(types.Sample))
})
}
func (manager *RemoteManager) OnAudioFrame(listener func(sample types.Sample)) {
func (manager *CaptureManagerCtx) OnAudioFrame(listener func(sample types.Sample)) {
manager.emmiter.On("audio", func(payload ...interface{}) {
listener(payload[0].(types.Sample))
})
}
func (manager *RemoteManager) StartStream() {
func (manager *CaptureManagerCtx) StartStream() {
manager.createPipelines()
manager.logger.Info().
@ -113,7 +107,6 @@ func (manager *RemoteManager) StartStream() {
Str("audio_codec", manager.config.AudioCodec).
Str("audio_pipeline_src", manager.audio.Src).
Str("video_pipeline_src", manager.video.Src).
Str("screen_resolution", fmt.Sprintf("%dx%d@%d", manager.config.ScreenWidth, manager.config.ScreenHeight, manager.config.ScreenRate)).
Msgf("Pipelines starting...")
manager.video.Start()
@ -121,21 +114,21 @@ func (manager *RemoteManager) StartStream() {
manager.streaming = true
}
func (manager *RemoteManager) StopStream() {
func (manager *CaptureManagerCtx) StopStream() {
manager.logger.Info().Msgf("Pipelines shutting down...")
manager.video.Stop()
manager.audio.Stop()
manager.streaming = false
}
func (manager *RemoteManager) Streaming() bool {
func (manager *CaptureManagerCtx) Streaming() bool {
return manager.streaming
}
func (manager *RemoteManager) createPipelines() {
func (manager *CaptureManagerCtx) createPipelines() {
// handle maximum fps
rate := manager.config.ScreenRate
if manager.config.MaxFPS != 0 && manager.config.MaxFPS < manager.config.ScreenRate {
rate := int(manager.desktop.GetScreenSize().Rate)
if manager.config.MaxFPS != 0 && manager.config.MaxFPS < rate {
rate = manager.config.MaxFPS
}
@ -165,7 +158,7 @@ func (manager *RemoteManager) createPipelines() {
}
}
func (manager *RemoteManager) ChangeResolution(width int, height int, rate int) error {
func (manager *CaptureManagerCtx) ChangeResolution(width int, height int, rate int) error {
if !xorg.ValidScreenSize(width, height, rate) {
return fmt.Errorf("unknown configuration")
}

View File

@ -0,0 +1,11 @@
package desktop
import "m1k1o/neko/internal/desktop/clipboard"
func (manager *DesktopManagerCtx) ReadClipboard() string {
return clipboard.Read()
}
func (manager *DesktopManagerCtx) WriteClipboard(data string) {
clipboard.Write(data)
}

View File

@ -0,0 +1,65 @@
package desktop
import (
"sync"
"time"
"m1k1o/neko/internal/desktop/xorg"
"m1k1o/neko/internal/types"
"m1k1o/neko/internal/types/config"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
type DesktopManagerCtx struct {
logger zerolog.Logger
wg sync.WaitGroup
shutdown chan struct{}
config *config.Desktop
}
func New(config *config.Desktop, broadcast types.BroadcastManager) *DesktopManagerCtx {
return &DesktopManagerCtx{
logger: log.With().Str("module", "desktop").Logger(),
shutdown: make(chan struct{}),
config: config,
}
}
func (manager *DesktopManagerCtx) Start() {
xorg.Display(manager.config.Display)
if !xorg.ValidScreenSize(manager.config.ScreenWidth, manager.config.ScreenHeight, manager.config.ScreenRate) {
manager.logger.Warn().Msgf("invalid screen option %dx%d@%d", manager.config.ScreenWidth, manager.config.ScreenHeight, manager.config.ScreenRate)
} else if err := xorg.ChangeScreenSize(manager.config.ScreenWidth, manager.config.ScreenHeight, manager.config.ScreenRate); err != nil {
manager.logger.Warn().Err(err).Msg("unable to change screen size")
}
manager.wg.Add(1)
go func() {
defer manager.wg.Done()
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-manager.shutdown:
return
case <-ticker.C:
xorg.CheckKeys(time.Second * 10)
}
}
}()
}
func (manager *DesktopManagerCtx) Shutdown() error {
manager.logger.Info().Msgf("desktop shutting down")
close(manager.shutdown)
manager.wg.Wait()
return nil
}

View File

@ -0,0 +1,52 @@
package desktop
import (
"os/exec"
"m1k1o/neko/internal/desktop/xorg"
"m1k1o/neko/internal/types"
)
func (manager *DesktopManagerCtx) Move(x, y int) {
xorg.Move(x, y)
}
func (manager *DesktopManagerCtx) Scroll(x, y int) {
xorg.Scroll(x, y)
}
func (manager *DesktopManagerCtx) ButtonDown(code int) error {
return xorg.ButtonDown(code)
}
func (manager *DesktopManagerCtx) KeyDown(code uint64) error {
return xorg.KeyDown(code)
}
func (manager *DesktopManagerCtx) ButtonUp(code int) error {
return xorg.ButtonUp(code)
}
func (manager *DesktopManagerCtx) KeyUp(code uint64) error {
return xorg.KeyUp(code)
}
func (manager *DesktopManagerCtx) ResetKeys() {
xorg.ResetKeys()
}
func (manager *DesktopManagerCtx) ScreenConfigurations() map[int]types.ScreenConfiguration {
return xorg.ScreenConfigurations
}
func (manager *DesktopManagerCtx) GetScreenSize() *types.ScreenSize {
return xorg.GetScreenSize()
}
func (manager *DesktopManagerCtx) SetKeyboardLayout(layout string) {
_ = exec.Command("setxkbmap", layout).Run()
}
func (manager *DesktopManagerCtx) SetKeyboardModifiers(NumLock int, CapsLock int, ScrollLock int) {
xorg.SetKeyboardModifiers(NumLock, CapsLock, ScrollLock)
}

View File

@ -1,11 +0,0 @@
package remote
import "m1k1o/neko/internal/remote/clipboard"
func (manager *RemoteManager) ReadClipboard() string {
return clipboard.Read()
}
func (manager *RemoteManager) WriteClipboard(data string) {
clipboard.Write(data)
}

View File

@ -1,51 +0,0 @@
package remote
import (
"m1k1o/neko/internal/remote/xorg"
"m1k1o/neko/internal/types"
"os/exec"
)
func (manager *RemoteManager) Move(x, y int) {
xorg.Move(x, y)
}
func (manager *RemoteManager) Scroll(x, y int) {
xorg.Scroll(x, y)
}
func (manager *RemoteManager) ButtonDown(code int) error {
return xorg.ButtonDown(code)
}
func (manager *RemoteManager) KeyDown(code uint64) error {
return xorg.KeyDown(code)
}
func (manager *RemoteManager) ButtonUp(code int) error {
return xorg.ButtonUp(code)
}
func (manager *RemoteManager) KeyUp(code uint64) error {
return xorg.KeyUp(code)
}
func (manager *RemoteManager) ResetKeys() {
xorg.ResetKeys()
}
func (manager *RemoteManager) ScreenConfigurations() map[int]types.ScreenConfiguration {
return xorg.ScreenConfigurations
}
func (manager *RemoteManager) GetScreenSize() *types.ScreenSize {
return xorg.GetScreenSize()
}
func (manager *RemoteManager) SetKeyboardLayout(layout string) {
_ = exec.Command("setxkbmap", layout).Run()
}
func (manager *RemoteManager) SetKeyboardModifiers(NumLock int, CapsLock int, ScrollLock int) {
xorg.SetKeyboardModifiers(NumLock, CapsLock, ScrollLock)
}

View File

@ -12,11 +12,11 @@ import (
"m1k1o/neko/internal/utils"
)
func New(remote types.RemoteManager) *SessionManager {
func New(capture types.CaptureManager) *SessionManager {
return &SessionManager{
logger: log.With().Str("module", "session").Logger(),
host: "",
remote: remote,
capture: capture,
members: make(map[string]*Session),
emmiter: events.New(),
}
@ -26,7 +26,7 @@ type SessionManager struct {
mu sync.Mutex
logger zerolog.Logger
host string
remote types.RemoteManager
capture types.CaptureManager
members map[string]*Session
emmiter events.EventEmmiter
// TODO: Handle locks in sessions as flags.
@ -45,8 +45,8 @@ func (manager *SessionManager) New(id string, admin bool, socket types.WebSocket
manager.mu.Lock()
manager.members[id] = session
if !manager.remote.Streaming() && len(manager.members) > 0 {
manager.remote.StartStream()
if !manager.capture.Streaming() && len(manager.members) > 0 {
manager.capture.StartStream()
}
manager.mu.Unlock()
@ -160,8 +160,8 @@ func (manager *SessionManager) Destroy(id string) {
err := session.destroy()
delete(manager.members, id)
if manager.remote.Streaming() && len(manager.members) <= 0 {
manager.remote.StopStream()
if manager.capture.Streaming() && len(manager.members) <= 0 {
manager.capture.StopStream()
}
manager.mu.Unlock()

View File

@ -0,0 +1,14 @@
package types
type CaptureManager interface {
VideoCodec() string
AudioCodec() string
Start()
Shutdown() error
OnVideoFrame(listener func(sample Sample))
OnAudioFrame(listener func(sample Sample))
StartStream()
StopStream()
Streaming() bool
ChangeResolution(width int, height int, rate int) error
}

View File

@ -1,14 +1,11 @@
package config
import (
"regexp"
"strconv"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
type Remote struct {
type Capture struct {
Display string
Device string
AudioCodec string
@ -18,13 +15,10 @@ type Remote struct {
VideoCodec string
VideoParams string
VideoBitrate uint
ScreenWidth int
ScreenHeight int
ScreenRate int
MaxFPS int
}
func (Remote) Init(cmd *cobra.Command) error {
func (Capture) Init(cmd *cobra.Command) error {
cmd.PersistentFlags().String("display", ":99.0", "XDisplay to capture")
if err := viper.BindPFlag("display", cmd.PersistentFlags().Lookup("display")); err != nil {
return err
@ -55,11 +49,6 @@ func (Remote) Init(cmd *cobra.Command) error {
return err
}
cmd.PersistentFlags().String("screen", "1280x720@30", "default screen resolution and framerate")
if err := viper.BindPFlag("screen", cmd.PersistentFlags().Lookup("screen")); err != nil {
return err
}
cmd.PersistentFlags().Int("max_fps", 25, "maximum fps delivered via WebRTC, 0 is for no maximum")
if err := viper.BindPFlag("max_fps", cmd.PersistentFlags().Lookup("max_fps")); err != nil {
return err
@ -111,7 +100,7 @@ func (Remote) Init(cmd *cobra.Command) error {
return nil
}
func (s *Remote) Set() {
func (s *Capture) Set() {
audioCodec := "Opus"
if viper.GetBool("opus") {
audioCodec = "Opus"
@ -146,24 +135,5 @@ func (s *Remote) Set() {
s.VideoParams = viper.GetString("video")
s.VideoBitrate = viper.GetUint("video_bitrate")
s.ScreenWidth = 1280
s.ScreenHeight = 720
s.ScreenRate = 30
r := regexp.MustCompile(`([0-9]{1,4})x([0-9]{1,4})@([0-9]{1,3})`)
res := r.FindStringSubmatch(viper.GetString("screen"))
if len(res) > 0 {
width, err1 := strconv.ParseInt(res[1], 10, 64)
height, err2 := strconv.ParseInt(res[2], 10, 64)
rate, err3 := strconv.ParseInt(res[3], 10, 64)
if err1 == nil && err2 == nil && err3 == nil {
s.ScreenWidth = int(width)
s.ScreenHeight = int(height)
s.ScreenRate = int(rate)
}
}
s.MaxFPS = viper.GetInt("max_fps")
}

View File

@ -0,0 +1,51 @@
package config
import (
"os"
"regexp"
"strconv"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
type Desktop struct {
Display string
ScreenWidth int
ScreenHeight int
ScreenRate int
}
func (Desktop) Init(cmd *cobra.Command) error {
cmd.PersistentFlags().String("screen", "1280x720@30", "default screen resolution and framerate")
if err := viper.BindPFlag("screen", cmd.PersistentFlags().Lookup("screen")); err != nil {
return err
}
return nil
}
func (s *Desktop) Set() {
// Display is provided by env variable
s.Display = os.Getenv("DISPLAY")
s.ScreenWidth = 1280
s.ScreenHeight = 720
s.ScreenRate = 30
r := regexp.MustCompile(`([0-9]{1,4})x([0-9]{1,4})@([0-9]{1,3})`)
res := r.FindStringSubmatch(viper.GetString("screen"))
if len(res) > 0 {
width, err1 := strconv.ParseInt(res[1], 10, 64)
height, err2 := strconv.ParseInt(res[2], 10, 64)
rate, err3 := strconv.ParseInt(res[3], 10, 64)
if err1 == nil && err2 == nil && err3 == nil {
s.ScreenWidth = int(width)
s.ScreenHeight = int(height)
s.ScreenRate = int(rate)
}
}
}

View File

@ -1,27 +1,21 @@
package types
type RemoteManager interface {
VideoCodec() string
AudioCodec() string
type DesktopManager interface {
Start()
Shutdown() error
OnVideoFrame(listener func(sample Sample))
OnAudioFrame(listener func(sample Sample))
StartStream()
StopStream()
Streaming() bool
ChangeResolution(width int, height int, rate int) error
GetScreenSize() *ScreenSize
ScreenConfigurations() map[int]ScreenConfiguration
// clipboard
ReadClipboard() string
WriteClipboard(data string)
// xorg
Move(x, y int)
Scroll(x, y int)
ButtonDown(code int) error
KeyDown(code uint64) error
ButtonUp(code int) error
KeyUp(code uint64) error
ReadClipboard() string
WriteClipboard(data string)
ResetKeys()
ScreenConfigurations() map[int]ScreenConfiguration
GetScreenSize() *ScreenSize
SetKeyboardLayout(layout string)
SetKeyboardModifiers(NumLock int, CapsLock int, ScrollLock int)
}

View File

@ -64,7 +64,7 @@ func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) e
return err
}
manager.remote.Move(int(payload.X), int(payload.Y))
manager.desktop.Move(int(payload.X), int(payload.Y))
case OP_SCROLL:
payload := &PayloadScroll{}
if err := binary.Read(buffer, binary.LittleEndian, payload); err != nil {
@ -77,7 +77,7 @@ func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) e
Str("y", strconv.Itoa(int(payload.Y))).
Msg("scroll")
manager.remote.Scroll(int(payload.X), int(payload.Y))
manager.desktop.Scroll(int(payload.X), int(payload.Y))
case OP_KEY_DOWN:
payload := &PayloadKey{}
if err := binary.Read(buffer, binary.LittleEndian, payload); err != nil {
@ -85,7 +85,7 @@ func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) e
}
if payload.Key < 8 {
err := manager.remote.ButtonDown(int(payload.Key))
err := manager.desktop.ButtonDown(int(payload.Key))
if err != nil {
manager.logger.Warn().Err(err).Msg("button down failed")
return nil
@ -93,7 +93,7 @@ func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) e
manager.logger.Debug().Msgf("button down %d", payload.Key)
} else {
err := manager.remote.KeyDown(uint64(payload.Key))
err := manager.desktop.KeyDown(uint64(payload.Key))
if err != nil {
manager.logger.Warn().Err(err).Msg("key down failed")
return nil
@ -109,7 +109,7 @@ func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) e
}
if payload.Key < 8 {
err := manager.remote.ButtonUp(int(payload.Key))
err := manager.desktop.ButtonUp(int(payload.Key))
if err != nil {
manager.logger.Warn().Err(err).Msg("button up failed")
return nil
@ -117,7 +117,7 @@ func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) e
manager.logger.Debug().Msgf("button up %d", payload.Key)
} else {
err := manager.remote.KeyUp(uint64(payload.Key))
err := manager.desktop.KeyUp(uint64(payload.Key))
if err != nil {
manager.logger.Warn().Err(err).Msg("key up failed")
return nil

View File

@ -18,10 +18,11 @@ import (
"m1k1o/neko/internal/types/config"
)
func New(sessions types.SessionManager, remote types.RemoteManager, config *config.WebRTC) *WebRTCManager {
func New(sessions types.SessionManager, capture types.CaptureManager, desktop types.DesktopManager, config *config.WebRTC) *WebRTCManager {
return &WebRTCManager{
logger: log.With().Str("module", "webrtc").Logger(),
remote: remote,
capture: capture,
desktop: desktop,
sessions: sessions,
config: config,
}
@ -34,30 +35,31 @@ type WebRTCManager struct {
videoCodec webrtc.RTPCodecParameters
audioCodec webrtc.RTPCodecParameters
sessions types.SessionManager
remote types.RemoteManager
capture types.CaptureManager
desktop types.DesktopManager
config *config.WebRTC
api *webrtc.API
}
func (manager *WebRTCManager) Start() {
var err error
manager.audioTrack, manager.audioCodec, err = manager.createTrack(manager.remote.AudioCodec())
manager.audioTrack, manager.audioCodec, err = manager.createTrack(manager.capture.AudioCodec())
if err != nil {
manager.logger.Panic().Err(err).Msg("unable to create audio track")
}
manager.remote.OnAudioFrame(func(sample types.Sample) {
manager.capture.OnAudioFrame(func(sample types.Sample) {
if err := manager.audioTrack.WriteSample(media.Sample(sample)); err != nil && err != io.ErrClosedPipe {
manager.logger.Warn().Err(err).Msg("audio pipeline failed to write")
}
})
manager.videoTrack, manager.videoCodec, err = manager.createTrack(manager.remote.VideoCodec())
manager.videoTrack, manager.videoCodec, err = manager.createTrack(manager.capture.VideoCodec())
if err != nil {
manager.logger.Panic().Err(err).Msg("unable to create video track")
}
manager.remote.OnVideoFrame(func(sample types.Sample) {
manager.capture.OnVideoFrame(func(sample types.Sample) {
if err := manager.videoTrack.WriteSample(media.Sample(sample)); err != nil && err != io.ErrClosedPipe {
manager.logger.Warn().Err(err).Msg("video pipeline failed to write")
}

View File

@ -131,7 +131,7 @@ func (h *MessageHandler) controlClipboard(id string, session types.Session, payl
return nil
}
h.remote.WriteClipboard(payload.Text)
h.desktop.WriteClipboard(payload.Text)
return nil
}
@ -144,7 +144,7 @@ func (h *MessageHandler) controlKeyboard(id string, session types.Session, paylo
// change layout
if payload.Layout != nil {
h.remote.SetKeyboardLayout(*payload.Layout)
h.desktop.SetKeyboardLayout(*payload.Layout)
}
// set num lock
@ -177,6 +177,6 @@ func (h *MessageHandler) controlKeyboard(id string, session types.Session, paylo
Int("ScrollLock", ScrollLock).
Msg("setting keyboard modifiers")
h.remote.SetKeyboardModifiers(NumLock, CapsLock, ScrollLock)
h.desktop.SetKeyboardModifiers(NumLock, CapsLock, ScrollLock)
return nil
}

View File

@ -16,7 +16,8 @@ type MessageHandler struct {
logger zerolog.Logger
sessions types.SessionManager
webrtc types.WebRTCManager
remote types.RemoteManager
desktop types.DesktopManager
capture types.CaptureManager
broadcast types.BroadcastManager
banned map[string]string // IP -> session ID (that banned it)
locked map[string]string // resource name -> session ID (that locked it)

View File

@ -12,7 +12,7 @@ func (h *MessageHandler) screenSet(id string, session types.Session, payload *me
return nil
}
if err := h.remote.ChangeResolution(payload.Width, payload.Height, payload.Rate); err != nil {
if err := h.capture.ChangeResolution(payload.Width, payload.Height, payload.Rate); err != nil {
h.logger.Warn().Err(err).Msgf("unable to change screen size")
return err
}
@ -33,7 +33,7 @@ func (h *MessageHandler) screenSet(id string, session types.Session, payload *me
}
func (h *MessageHandler) screenResolution(id string, session types.Session) error {
if size := h.remote.GetScreenSize(); size != nil {
if size := h.desktop.GetScreenSize(); size != nil {
if err := session.Send(message.ScreenResolution{
Event: event.SCREEN_RESOLUTION,
Width: size.Width,
@ -56,7 +56,7 @@ func (h *MessageHandler) screenConfigurations(id string, session types.Session)
if err := session.Send(message.ScreenConfigurations{
Event: event.SCREEN_CONFIGURATIONS,
Configurations: h.remote.ScreenConfigurations(),
Configurations: h.desktop.ScreenConfigurations(),
}); err != nil {
h.logger.Warn().Err(err).Msgf("sending event %s has failed", event.SCREEN_CONFIGURATIONS)
return err

View File

@ -20,7 +20,7 @@ import (
const CONTROL_PROTECTION_SESSION = "by_control_protection"
func New(sessions types.SessionManager, remote types.RemoteManager, broadcast types.BroadcastManager, webrtc types.WebRTCManager, conf *config.WebSocket) *WebSocketHandler {
func New(sessions types.SessionManager, desktop types.DesktopManager, capture types.CaptureManager, broadcast types.BroadcastManager, webrtc types.WebRTCManager, conf *config.WebSocket) *WebSocketHandler {
logger := log.With().Str("module", "websocket").Logger()
locks := make(map[string]string)
@ -45,7 +45,8 @@ func New(sessions types.SessionManager, remote types.RemoteManager, broadcast ty
shutdown: make(chan interface{}),
conf: conf,
sessions: sessions,
remote: remote,
desktop: desktop,
upgrader: websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
@ -53,7 +54,8 @@ func New(sessions types.SessionManager, remote types.RemoteManager, broadcast ty
},
handler: &MessageHandler{
logger: logger.With().Str("subsystem", "handler").Logger(),
remote: remote,
desktop: desktop,
capture: capture,
broadcast: broadcast,
sessions: sessions,
webrtc: webrtc,
@ -73,7 +75,7 @@ type WebSocketHandler struct {
shutdown chan interface{}
upgrader websocket.Upgrader
sessions types.SessionManager
remote types.RemoteManager
desktop types.DesktopManager
conf *config.WebSocket
handler *MessageHandler
@ -175,7 +177,7 @@ func (ws *WebSocketHandler) Start() {
ws.wg.Done()
}()
current := ws.remote.ReadClipboard()
current := ws.desktop.ReadClipboard()
for {
select {
@ -188,7 +190,7 @@ func (ws *WebSocketHandler) Start() {
continue
}
text := ws.remote.ReadClipboard()
text := ws.desktop.ReadClipboard()
if text == current {
continue
}

View File

@ -7,8 +7,9 @@ import (
"runtime"
"m1k1o/neko/internal/broadcast"
"m1k1o/neko/internal/capture"
"m1k1o/neko/internal/desktop"
"m1k1o/neko/internal/http"
"m1k1o/neko/internal/remote"
"m1k1o/neko/internal/session"
"m1k1o/neko/internal/types/config"
"m1k1o/neko/internal/webrtc"
@ -61,7 +62,8 @@ func init() {
},
Root: &config.Root{},
Server: &config.Server{},
Remote: &config.Remote{},
Capture: &config.Capture{},
Desktop: &config.Desktop{},
Broadcast: &config.Broadcast{},
WebRTC: &config.WebRTC{},
WebSocket: &config.WebSocket{},
@ -100,7 +102,8 @@ func (i *Version) Details() string {
type Neko struct {
Version *Version
Root *config.Root
Remote *config.Remote
Capture *config.Capture
Desktop *config.Desktop
Broadcast *config.Broadcast
Server *config.Server
WebRTC *config.WebRTC
@ -109,7 +112,8 @@ type Neko struct {
logger zerolog.Logger
server *http.Server
sessionManager *session.SessionManager
remoteManager *remote.RemoteManager
captureManager *capture.CaptureManagerCtx
desktopManager *desktop.DesktopManagerCtx
broadcastManager *broadcast.BroadcastManager
webRTCManager *webrtc.WebRTCManager
webSocketHandler *websocket.WebSocketHandler
@ -120,17 +124,20 @@ func (neko *Neko) Preflight() {
}
func (neko *Neko) Start() {
broadcastManager := broadcast.New(neko.Remote, neko.Broadcast)
broadcastManager := broadcast.New(neko.Capture, neko.Broadcast)
remoteManager := remote.New(neko.Remote, broadcastManager)
remoteManager.Start()
desktopManager := desktop.New(neko.Desktop, broadcastManager)
desktopManager.Start()
sessionManager := session.New(remoteManager)
captureManager := capture.New(desktopManager, broadcastManager, neko.Capture)
captureManager.Start()
webRTCManager := webrtc.New(sessionManager, remoteManager, neko.WebRTC)
sessionManager := session.New(captureManager)
webRTCManager := webrtc.New(sessionManager, captureManager, desktopManager, neko.WebRTC)
webRTCManager.Start()
webSocketHandler := websocket.New(sessionManager, remoteManager, broadcastManager, webRTCManager, neko.WebSocket)
webSocketHandler := websocket.New(sessionManager, desktopManager, captureManager, broadcastManager, webRTCManager, neko.WebSocket)
webSocketHandler.Start()
server := http.New(neko.Server, webSocketHandler)
@ -138,7 +145,8 @@ func (neko *Neko) Start() {
neko.broadcastManager = broadcastManager
neko.sessionManager = sessionManager
neko.remoteManager = remoteManager
neko.captureManager = captureManager
neko.desktopManager = desktopManager
neko.webRTCManager = webRTCManager
neko.webSocketHandler = webSocketHandler
neko.server = server
@ -150,8 +158,11 @@ func (neko *Neko) Shutdown() {
err = neko.broadcastManager.Shutdown()
neko.logger.Err(err).Msg("broadcast manager shutdown")
err = neko.remoteManager.Shutdown()
neko.logger.Err(err).Msg("remote manager shutdown")
err = neko.desktopManager.Shutdown()
neko.logger.Err(err).Msg("desktop manager shutdown")
err = neko.captureManager.Shutdown()
neko.logger.Err(err).Msg("capture manager shutdown")
err = neko.webRTCManager.Shutdown()
neko.logger.Err(err).Msg("webrtc manager shutdown")