split remote to desktop and capture.
This commit is contained in:
parent
0bca8c9d02
commit
de4f6b45e5
@ -19,7 +19,8 @@ func init() {
|
|||||||
configs := []config.Config{
|
configs := []config.Config{
|
||||||
neko.Service.Server,
|
neko.Service.Server,
|
||||||
neko.Service.WebRTC,
|
neko.Service.WebRTC,
|
||||||
neko.Service.Remote,
|
neko.Service.Capture,
|
||||||
|
neko.Service.Desktop,
|
||||||
neko.Service.Broadcast,
|
neko.Service.Broadcast,
|
||||||
neko.Service.WebSocket,
|
neko.Service.WebSocket,
|
||||||
}
|
}
|
||||||
|
@ -14,16 +14,16 @@ type BroadcastManager struct {
|
|||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
pipeline *gst.Pipeline
|
pipeline *gst.Pipeline
|
||||||
remote *config.Remote
|
capture *config.Capture
|
||||||
config *config.Broadcast
|
config *config.Broadcast
|
||||||
enabled bool
|
enabled bool
|
||||||
url string
|
url string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(remote *config.Remote, config *config.Broadcast) *BroadcastManager {
|
func New(capture *config.Capture, config *config.Broadcast) *BroadcastManager {
|
||||||
return &BroadcastManager{
|
return &BroadcastManager{
|
||||||
logger: log.With().Str("module", "remote").Logger(),
|
logger: log.With().Str("module", "broadcast").Logger(),
|
||||||
remote: remote,
|
capture: capture,
|
||||||
config: config,
|
config: config,
|
||||||
enabled: config.Enabled,
|
enabled: config.Enabled,
|
||||||
url: config.URL,
|
url: config.URL,
|
||||||
@ -42,8 +42,8 @@ func (manager *BroadcastManager) Start() error {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
manager.pipeline, err = gst.CreateRTMPPipeline(
|
manager.pipeline, err = gst.CreateRTMPPipeline(
|
||||||
manager.remote.Device,
|
manager.capture.Device,
|
||||||
manager.remote.Display,
|
manager.capture.Display,
|
||||||
manager.config.Pipeline,
|
manager.config.Pipeline,
|
||||||
manager.url,
|
manager.url,
|
||||||
)
|
)
|
||||||
@ -54,8 +54,8 @@ func (manager *BroadcastManager) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
manager.logger.Info().
|
manager.logger.Info().
|
||||||
Str("audio_device", manager.remote.Device).
|
Str("audio_device", manager.capture.Device).
|
||||||
Str("video_display", manager.remote.Display).
|
Str("video_display", manager.capture.Display).
|
||||||
Str("rtmp_pipeline_src", manager.pipeline.Src).
|
Str("rtmp_pipeline_src", manager.pipeline.Src).
|
||||||
Msgf("RTMP pipeline is starting...")
|
Msgf("RTMP pipeline is starting...")
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package remote
|
package capture
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"m1k1o/neko/internal/desktop/xorg"
|
||||||
"m1k1o/neko/internal/gst"
|
"m1k1o/neko/internal/gst"
|
||||||
"m1k1o/neko/internal/remote/xorg"
|
|
||||||
"m1k1o/neko/internal/types"
|
"m1k1o/neko/internal/types"
|
||||||
"m1k1o/neko/internal/types/config"
|
"m1k1o/neko/internal/types/config"
|
||||||
|
|
||||||
@ -14,47 +14,41 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RemoteManager struct {
|
type CaptureManagerCtx struct {
|
||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
video *gst.Pipeline
|
video *gst.Pipeline
|
||||||
audio *gst.Pipeline
|
audio *gst.Pipeline
|
||||||
config *config.Remote
|
config *config.Capture
|
||||||
broadcast types.BroadcastManager
|
broadcast types.BroadcastManager
|
||||||
|
desktop types.DesktopManager
|
||||||
cleanup *time.Ticker
|
cleanup *time.Ticker
|
||||||
shutdown chan bool
|
shutdown chan bool
|
||||||
emmiter events.EventEmmiter
|
emmiter events.EventEmmiter
|
||||||
streaming bool
|
streaming bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config *config.Remote, broadcast types.BroadcastManager) *RemoteManager {
|
func New(desktop types.DesktopManager, broadcast types.BroadcastManager, config *config.Capture) *CaptureManagerCtx {
|
||||||
return &RemoteManager{
|
return &CaptureManagerCtx{
|
||||||
logger: log.With().Str("module", "remote").Logger(),
|
logger: log.With().Str("module", "capture").Logger(),
|
||||||
cleanup: time.NewTicker(1 * time.Second),
|
cleanup: time.NewTicker(1 * time.Second),
|
||||||
shutdown: make(chan bool),
|
shutdown: make(chan bool),
|
||||||
emmiter: events.New(),
|
emmiter: events.New(),
|
||||||
config: config,
|
config: config,
|
||||||
broadcast: broadcast,
|
broadcast: broadcast,
|
||||||
|
desktop: desktop,
|
||||||
streaming: false,
|
streaming: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *RemoteManager) VideoCodec() string {
|
func (manager *CaptureManagerCtx) VideoCodec() string {
|
||||||
return manager.config.VideoCodec
|
return manager.config.VideoCodec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *RemoteManager) AudioCodec() string {
|
func (manager *CaptureManagerCtx) AudioCodec() string {
|
||||||
return manager.config.AudioCodec
|
return manager.config.AudioCodec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *RemoteManager) Start() {
|
func (manager *CaptureManagerCtx) 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.createPipelines()
|
manager.createPipelines()
|
||||||
if err := manager.broadcast.Start(); err != nil {
|
if err := manager.broadcast.Start(); err != nil {
|
||||||
manager.logger.Panic().Err(err).Msg("unable to create rtmp pipeline")
|
manager.logger.Panic().Err(err).Msg("unable to create rtmp pipeline")
|
||||||
@ -74,14 +68,14 @@ func (manager *RemoteManager) Start() {
|
|||||||
case sample := <-manager.audio.Sample:
|
case sample := <-manager.audio.Sample:
|
||||||
manager.emmiter.Emit("audio", sample)
|
manager.emmiter.Emit("audio", sample)
|
||||||
case <-manager.cleanup.C:
|
case <-manager.cleanup.C:
|
||||||
xorg.CheckKeys(time.Second * 10)
|
// TODO: refactor.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *RemoteManager) Shutdown() error {
|
func (manager *CaptureManagerCtx) Shutdown() error {
|
||||||
manager.logger.Info().Msgf("remote shutting down")
|
manager.logger.Info().Msgf("capture shutting down")
|
||||||
manager.video.Stop()
|
manager.video.Stop()
|
||||||
manager.audio.Stop()
|
manager.audio.Stop()
|
||||||
manager.broadcast.Stop()
|
manager.broadcast.Stop()
|
||||||
@ -91,19 +85,19 @@ func (manager *RemoteManager) Shutdown() error {
|
|||||||
return nil
|
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{}) {
|
manager.emmiter.On("video", func(payload ...interface{}) {
|
||||||
listener(payload[0].(types.Sample))
|
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{}) {
|
manager.emmiter.On("audio", func(payload ...interface{}) {
|
||||||
listener(payload[0].(types.Sample))
|
listener(payload[0].(types.Sample))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *RemoteManager) StartStream() {
|
func (manager *CaptureManagerCtx) StartStream() {
|
||||||
manager.createPipelines()
|
manager.createPipelines()
|
||||||
|
|
||||||
manager.logger.Info().
|
manager.logger.Info().
|
||||||
@ -113,7 +107,6 @@ func (manager *RemoteManager) StartStream() {
|
|||||||
Str("audio_codec", manager.config.AudioCodec).
|
Str("audio_codec", manager.config.AudioCodec).
|
||||||
Str("audio_pipeline_src", manager.audio.Src).
|
Str("audio_pipeline_src", manager.audio.Src).
|
||||||
Str("video_pipeline_src", manager.video.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...")
|
Msgf("Pipelines starting...")
|
||||||
|
|
||||||
manager.video.Start()
|
manager.video.Start()
|
||||||
@ -121,21 +114,21 @@ func (manager *RemoteManager) StartStream() {
|
|||||||
manager.streaming = true
|
manager.streaming = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *RemoteManager) StopStream() {
|
func (manager *CaptureManagerCtx) StopStream() {
|
||||||
manager.logger.Info().Msgf("Pipelines shutting down...")
|
manager.logger.Info().Msgf("Pipelines shutting down...")
|
||||||
manager.video.Stop()
|
manager.video.Stop()
|
||||||
manager.audio.Stop()
|
manager.audio.Stop()
|
||||||
manager.streaming = false
|
manager.streaming = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *RemoteManager) Streaming() bool {
|
func (manager *CaptureManagerCtx) Streaming() bool {
|
||||||
return manager.streaming
|
return manager.streaming
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *RemoteManager) createPipelines() {
|
func (manager *CaptureManagerCtx) createPipelines() {
|
||||||
// handle maximum fps
|
// handle maximum fps
|
||||||
rate := manager.config.ScreenRate
|
rate := int(manager.desktop.GetScreenSize().Rate)
|
||||||
if manager.config.MaxFPS != 0 && manager.config.MaxFPS < manager.config.ScreenRate {
|
if manager.config.MaxFPS != 0 && manager.config.MaxFPS < rate {
|
||||||
rate = manager.config.MaxFPS
|
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) {
|
if !xorg.ValidScreenSize(width, height, rate) {
|
||||||
return fmt.Errorf("unknown configuration")
|
return fmt.Errorf("unknown configuration")
|
||||||
}
|
}
|
11
server/internal/desktop/clipboard.go
Normal file
11
server/internal/desktop/clipboard.go
Normal 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)
|
||||||
|
}
|
65
server/internal/desktop/manager.go
Normal file
65
server/internal/desktop/manager.go
Normal 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
|
||||||
|
}
|
52
server/internal/desktop/xorg.go
Normal file
52
server/internal/desktop/xorg.go
Normal 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)
|
||||||
|
}
|
@ -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)
|
|
||||||
}
|
|
@ -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)
|
|
||||||
}
|
|
@ -12,11 +12,11 @@ import (
|
|||||||
"m1k1o/neko/internal/utils"
|
"m1k1o/neko/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(remote types.RemoteManager) *SessionManager {
|
func New(capture types.CaptureManager) *SessionManager {
|
||||||
return &SessionManager{
|
return &SessionManager{
|
||||||
logger: log.With().Str("module", "session").Logger(),
|
logger: log.With().Str("module", "session").Logger(),
|
||||||
host: "",
|
host: "",
|
||||||
remote: remote,
|
capture: capture,
|
||||||
members: make(map[string]*Session),
|
members: make(map[string]*Session),
|
||||||
emmiter: events.New(),
|
emmiter: events.New(),
|
||||||
}
|
}
|
||||||
@ -26,7 +26,7 @@ type SessionManager struct {
|
|||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
host string
|
host string
|
||||||
remote types.RemoteManager
|
capture types.CaptureManager
|
||||||
members map[string]*Session
|
members map[string]*Session
|
||||||
emmiter events.EventEmmiter
|
emmiter events.EventEmmiter
|
||||||
// TODO: Handle locks in sessions as flags.
|
// 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.mu.Lock()
|
||||||
manager.members[id] = session
|
manager.members[id] = session
|
||||||
if !manager.remote.Streaming() && len(manager.members) > 0 {
|
if !manager.capture.Streaming() && len(manager.members) > 0 {
|
||||||
manager.remote.StartStream()
|
manager.capture.StartStream()
|
||||||
}
|
}
|
||||||
manager.mu.Unlock()
|
manager.mu.Unlock()
|
||||||
|
|
||||||
@ -160,8 +160,8 @@ func (manager *SessionManager) Destroy(id string) {
|
|||||||
err := session.destroy()
|
err := session.destroy()
|
||||||
delete(manager.members, id)
|
delete(manager.members, id)
|
||||||
|
|
||||||
if manager.remote.Streaming() && len(manager.members) <= 0 {
|
if manager.capture.Streaming() && len(manager.members) <= 0 {
|
||||||
manager.remote.StopStream()
|
manager.capture.StopStream()
|
||||||
}
|
}
|
||||||
manager.mu.Unlock()
|
manager.mu.Unlock()
|
||||||
|
|
||||||
|
14
server/internal/types/capture.go
Normal file
14
server/internal/types/capture.go
Normal 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
|
||||||
|
}
|
@ -1,14 +1,11 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Remote struct {
|
type Capture struct {
|
||||||
Display string
|
Display string
|
||||||
Device string
|
Device string
|
||||||
AudioCodec string
|
AudioCodec string
|
||||||
@ -18,13 +15,10 @@ type Remote struct {
|
|||||||
VideoCodec string
|
VideoCodec string
|
||||||
VideoParams string
|
VideoParams string
|
||||||
VideoBitrate uint
|
VideoBitrate uint
|
||||||
ScreenWidth int
|
|
||||||
ScreenHeight int
|
|
||||||
ScreenRate int
|
|
||||||
MaxFPS 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")
|
cmd.PersistentFlags().String("display", ":99.0", "XDisplay to capture")
|
||||||
if err := viper.BindPFlag("display", cmd.PersistentFlags().Lookup("display")); err != nil {
|
if err := viper.BindPFlag("display", cmd.PersistentFlags().Lookup("display")); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -55,11 +49,6 @@ func (Remote) Init(cmd *cobra.Command) error {
|
|||||||
return err
|
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")
|
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 {
|
if err := viper.BindPFlag("max_fps", cmd.PersistentFlags().Lookup("max_fps")); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -111,7 +100,7 @@ func (Remote) Init(cmd *cobra.Command) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Remote) Set() {
|
func (s *Capture) Set() {
|
||||||
audioCodec := "Opus"
|
audioCodec := "Opus"
|
||||||
if viper.GetBool("opus") {
|
if viper.GetBool("opus") {
|
||||||
audioCodec = "Opus"
|
audioCodec = "Opus"
|
||||||
@ -146,24 +135,5 @@ func (s *Remote) Set() {
|
|||||||
s.VideoParams = viper.GetString("video")
|
s.VideoParams = viper.GetString("video")
|
||||||
s.VideoBitrate = viper.GetUint("video_bitrate")
|
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")
|
s.MaxFPS = viper.GetInt("max_fps")
|
||||||
}
|
}
|
51
server/internal/types/config/desktop.go
Normal file
51
server/internal/types/config/desktop.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +1,21 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
type RemoteManager interface {
|
type DesktopManager interface {
|
||||||
VideoCodec() string
|
|
||||||
AudioCodec() string
|
|
||||||
Start()
|
Start()
|
||||||
Shutdown() error
|
Shutdown() error
|
||||||
OnVideoFrame(listener func(sample Sample))
|
// clipboard
|
||||||
OnAudioFrame(listener func(sample Sample))
|
ReadClipboard() string
|
||||||
StartStream()
|
WriteClipboard(data string)
|
||||||
StopStream()
|
// xorg
|
||||||
Streaming() bool
|
|
||||||
ChangeResolution(width int, height int, rate int) error
|
|
||||||
GetScreenSize() *ScreenSize
|
|
||||||
ScreenConfigurations() map[int]ScreenConfiguration
|
|
||||||
Move(x, y int)
|
Move(x, y int)
|
||||||
Scroll(x, y int)
|
Scroll(x, y int)
|
||||||
ButtonDown(code int) error
|
ButtonDown(code int) error
|
||||||
KeyDown(code uint64) error
|
KeyDown(code uint64) error
|
||||||
ButtonUp(code int) error
|
ButtonUp(code int) error
|
||||||
KeyUp(code uint64) error
|
KeyUp(code uint64) error
|
||||||
ReadClipboard() string
|
|
||||||
WriteClipboard(data string)
|
|
||||||
ResetKeys()
|
ResetKeys()
|
||||||
|
ScreenConfigurations() map[int]ScreenConfiguration
|
||||||
|
GetScreenSize() *ScreenSize
|
||||||
SetKeyboardLayout(layout string)
|
SetKeyboardLayout(layout string)
|
||||||
SetKeyboardModifiers(NumLock int, CapsLock int, ScrollLock int)
|
SetKeyboardModifiers(NumLock int, CapsLock int, ScrollLock int)
|
||||||
}
|
}
|
@ -64,7 +64,7 @@ func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.remote.Move(int(payload.X), int(payload.Y))
|
manager.desktop.Move(int(payload.X), int(payload.Y))
|
||||||
case OP_SCROLL:
|
case OP_SCROLL:
|
||||||
payload := &PayloadScroll{}
|
payload := &PayloadScroll{}
|
||||||
if err := binary.Read(buffer, binary.LittleEndian, payload); err != nil {
|
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))).
|
Str("y", strconv.Itoa(int(payload.Y))).
|
||||||
Msg("scroll")
|
Msg("scroll")
|
||||||
|
|
||||||
manager.remote.Scroll(int(payload.X), int(payload.Y))
|
manager.desktop.Scroll(int(payload.X), int(payload.Y))
|
||||||
case OP_KEY_DOWN:
|
case OP_KEY_DOWN:
|
||||||
payload := &PayloadKey{}
|
payload := &PayloadKey{}
|
||||||
if err := binary.Read(buffer, binary.LittleEndian, payload); err != nil {
|
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 {
|
if payload.Key < 8 {
|
||||||
err := manager.remote.ButtonDown(int(payload.Key))
|
err := manager.desktop.ButtonDown(int(payload.Key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
manager.logger.Warn().Err(err).Msg("button down failed")
|
manager.logger.Warn().Err(err).Msg("button down failed")
|
||||||
return nil
|
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)
|
manager.logger.Debug().Msgf("button down %d", payload.Key)
|
||||||
} else {
|
} else {
|
||||||
err := manager.remote.KeyDown(uint64(payload.Key))
|
err := manager.desktop.KeyDown(uint64(payload.Key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
manager.logger.Warn().Err(err).Msg("key down failed")
|
manager.logger.Warn().Err(err).Msg("key down failed")
|
||||||
return nil
|
return nil
|
||||||
@ -109,7 +109,7 @@ func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if payload.Key < 8 {
|
if payload.Key < 8 {
|
||||||
err := manager.remote.ButtonUp(int(payload.Key))
|
err := manager.desktop.ButtonUp(int(payload.Key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
manager.logger.Warn().Err(err).Msg("button up failed")
|
manager.logger.Warn().Err(err).Msg("button up failed")
|
||||||
return nil
|
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)
|
manager.logger.Debug().Msgf("button up %d", payload.Key)
|
||||||
} else {
|
} else {
|
||||||
err := manager.remote.KeyUp(uint64(payload.Key))
|
err := manager.desktop.KeyUp(uint64(payload.Key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
manager.logger.Warn().Err(err).Msg("key up failed")
|
manager.logger.Warn().Err(err).Msg("key up failed")
|
||||||
return nil
|
return nil
|
||||||
|
@ -18,10 +18,11 @@ import (
|
|||||||
"m1k1o/neko/internal/types/config"
|
"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{
|
return &WebRTCManager{
|
||||||
logger: log.With().Str("module", "webrtc").Logger(),
|
logger: log.With().Str("module", "webrtc").Logger(),
|
||||||
remote: remote,
|
capture: capture,
|
||||||
|
desktop: desktop,
|
||||||
sessions: sessions,
|
sessions: sessions,
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
@ -34,30 +35,31 @@ type WebRTCManager struct {
|
|||||||
videoCodec webrtc.RTPCodecParameters
|
videoCodec webrtc.RTPCodecParameters
|
||||||
audioCodec webrtc.RTPCodecParameters
|
audioCodec webrtc.RTPCodecParameters
|
||||||
sessions types.SessionManager
|
sessions types.SessionManager
|
||||||
remote types.RemoteManager
|
capture types.CaptureManager
|
||||||
|
desktop types.DesktopManager
|
||||||
config *config.WebRTC
|
config *config.WebRTC
|
||||||
api *webrtc.API
|
api *webrtc.API
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *WebRTCManager) Start() {
|
func (manager *WebRTCManager) Start() {
|
||||||
var err error
|
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 {
|
if err != nil {
|
||||||
manager.logger.Panic().Err(err).Msg("unable to create audio track")
|
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 {
|
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.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 {
|
if err != nil {
|
||||||
manager.logger.Panic().Err(err).Msg("unable to create video track")
|
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 {
|
if err := manager.videoTrack.WriteSample(media.Sample(sample)); err != nil && err != io.ErrClosedPipe {
|
||||||
manager.logger.Warn().Err(err).Msg("video pipeline failed to write")
|
manager.logger.Warn().Err(err).Msg("video pipeline failed to write")
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ func (h *MessageHandler) controlClipboard(id string, session types.Session, payl
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
h.remote.WriteClipboard(payload.Text)
|
h.desktop.WriteClipboard(payload.Text)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ func (h *MessageHandler) controlKeyboard(id string, session types.Session, paylo
|
|||||||
|
|
||||||
// change layout
|
// change layout
|
||||||
if payload.Layout != nil {
|
if payload.Layout != nil {
|
||||||
h.remote.SetKeyboardLayout(*payload.Layout)
|
h.desktop.SetKeyboardLayout(*payload.Layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set num lock
|
// set num lock
|
||||||
@ -177,6 +177,6 @@ func (h *MessageHandler) controlKeyboard(id string, session types.Session, paylo
|
|||||||
Int("ScrollLock", ScrollLock).
|
Int("ScrollLock", ScrollLock).
|
||||||
Msg("setting keyboard modifiers")
|
Msg("setting keyboard modifiers")
|
||||||
|
|
||||||
h.remote.SetKeyboardModifiers(NumLock, CapsLock, ScrollLock)
|
h.desktop.SetKeyboardModifiers(NumLock, CapsLock, ScrollLock)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@ type MessageHandler struct {
|
|||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
sessions types.SessionManager
|
sessions types.SessionManager
|
||||||
webrtc types.WebRTCManager
|
webrtc types.WebRTCManager
|
||||||
remote types.RemoteManager
|
desktop types.DesktopManager
|
||||||
|
capture types.CaptureManager
|
||||||
broadcast types.BroadcastManager
|
broadcast types.BroadcastManager
|
||||||
banned map[string]string // IP -> session ID (that banned it)
|
banned map[string]string // IP -> session ID (that banned it)
|
||||||
locked map[string]string // resource name -> session ID (that locked it)
|
locked map[string]string // resource name -> session ID (that locked it)
|
||||||
|
@ -12,7 +12,7 @@ func (h *MessageHandler) screenSet(id string, session types.Session, payload *me
|
|||||||
return nil
|
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")
|
h.logger.Warn().Err(err).Msgf("unable to change screen size")
|
||||||
return err
|
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 {
|
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{
|
if err := session.Send(message.ScreenResolution{
|
||||||
Event: event.SCREEN_RESOLUTION,
|
Event: event.SCREEN_RESOLUTION,
|
||||||
Width: size.Width,
|
Width: size.Width,
|
||||||
@ -56,7 +56,7 @@ func (h *MessageHandler) screenConfigurations(id string, session types.Session)
|
|||||||
|
|
||||||
if err := session.Send(message.ScreenConfigurations{
|
if err := session.Send(message.ScreenConfigurations{
|
||||||
Event: event.SCREEN_CONFIGURATIONS,
|
Event: event.SCREEN_CONFIGURATIONS,
|
||||||
Configurations: h.remote.ScreenConfigurations(),
|
Configurations: h.desktop.ScreenConfigurations(),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
h.logger.Warn().Err(err).Msgf("sending event %s has failed", event.SCREEN_CONFIGURATIONS)
|
h.logger.Warn().Err(err).Msgf("sending event %s has failed", event.SCREEN_CONFIGURATIONS)
|
||||||
return err
|
return err
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
|
|
||||||
const CONTROL_PROTECTION_SESSION = "by_control_protection"
|
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()
|
logger := log.With().Str("module", "websocket").Logger()
|
||||||
|
|
||||||
locks := make(map[string]string)
|
locks := make(map[string]string)
|
||||||
@ -45,7 +45,8 @@ func New(sessions types.SessionManager, remote types.RemoteManager, broadcast ty
|
|||||||
shutdown: make(chan interface{}),
|
shutdown: make(chan interface{}),
|
||||||
conf: conf,
|
conf: conf,
|
||||||
sessions: sessions,
|
sessions: sessions,
|
||||||
remote: remote,
|
desktop: desktop,
|
||||||
|
|
||||||
upgrader: websocket.Upgrader{
|
upgrader: websocket.Upgrader{
|
||||||
CheckOrigin: func(r *http.Request) bool {
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
return true
|
return true
|
||||||
@ -53,7 +54,8 @@ func New(sessions types.SessionManager, remote types.RemoteManager, broadcast ty
|
|||||||
},
|
},
|
||||||
handler: &MessageHandler{
|
handler: &MessageHandler{
|
||||||
logger: logger.With().Str("subsystem", "handler").Logger(),
|
logger: logger.With().Str("subsystem", "handler").Logger(),
|
||||||
remote: remote,
|
desktop: desktop,
|
||||||
|
capture: capture,
|
||||||
broadcast: broadcast,
|
broadcast: broadcast,
|
||||||
sessions: sessions,
|
sessions: sessions,
|
||||||
webrtc: webrtc,
|
webrtc: webrtc,
|
||||||
@ -73,7 +75,7 @@ type WebSocketHandler struct {
|
|||||||
shutdown chan interface{}
|
shutdown chan interface{}
|
||||||
upgrader websocket.Upgrader
|
upgrader websocket.Upgrader
|
||||||
sessions types.SessionManager
|
sessions types.SessionManager
|
||||||
remote types.RemoteManager
|
desktop types.DesktopManager
|
||||||
conf *config.WebSocket
|
conf *config.WebSocket
|
||||||
handler *MessageHandler
|
handler *MessageHandler
|
||||||
|
|
||||||
@ -175,7 +177,7 @@ func (ws *WebSocketHandler) Start() {
|
|||||||
ws.wg.Done()
|
ws.wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
current := ws.remote.ReadClipboard()
|
current := ws.desktop.ReadClipboard()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -188,7 +190,7 @@ func (ws *WebSocketHandler) Start() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
text := ws.remote.ReadClipboard()
|
text := ws.desktop.ReadClipboard()
|
||||||
if text == current {
|
if text == current {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,9 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"m1k1o/neko/internal/broadcast"
|
"m1k1o/neko/internal/broadcast"
|
||||||
|
"m1k1o/neko/internal/capture"
|
||||||
|
"m1k1o/neko/internal/desktop"
|
||||||
"m1k1o/neko/internal/http"
|
"m1k1o/neko/internal/http"
|
||||||
"m1k1o/neko/internal/remote"
|
|
||||||
"m1k1o/neko/internal/session"
|
"m1k1o/neko/internal/session"
|
||||||
"m1k1o/neko/internal/types/config"
|
"m1k1o/neko/internal/types/config"
|
||||||
"m1k1o/neko/internal/webrtc"
|
"m1k1o/neko/internal/webrtc"
|
||||||
@ -61,7 +62,8 @@ func init() {
|
|||||||
},
|
},
|
||||||
Root: &config.Root{},
|
Root: &config.Root{},
|
||||||
Server: &config.Server{},
|
Server: &config.Server{},
|
||||||
Remote: &config.Remote{},
|
Capture: &config.Capture{},
|
||||||
|
Desktop: &config.Desktop{},
|
||||||
Broadcast: &config.Broadcast{},
|
Broadcast: &config.Broadcast{},
|
||||||
WebRTC: &config.WebRTC{},
|
WebRTC: &config.WebRTC{},
|
||||||
WebSocket: &config.WebSocket{},
|
WebSocket: &config.WebSocket{},
|
||||||
@ -100,7 +102,8 @@ func (i *Version) Details() string {
|
|||||||
type Neko struct {
|
type Neko struct {
|
||||||
Version *Version
|
Version *Version
|
||||||
Root *config.Root
|
Root *config.Root
|
||||||
Remote *config.Remote
|
Capture *config.Capture
|
||||||
|
Desktop *config.Desktop
|
||||||
Broadcast *config.Broadcast
|
Broadcast *config.Broadcast
|
||||||
Server *config.Server
|
Server *config.Server
|
||||||
WebRTC *config.WebRTC
|
WebRTC *config.WebRTC
|
||||||
@ -109,7 +112,8 @@ type Neko struct {
|
|||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
server *http.Server
|
server *http.Server
|
||||||
sessionManager *session.SessionManager
|
sessionManager *session.SessionManager
|
||||||
remoteManager *remote.RemoteManager
|
captureManager *capture.CaptureManagerCtx
|
||||||
|
desktopManager *desktop.DesktopManagerCtx
|
||||||
broadcastManager *broadcast.BroadcastManager
|
broadcastManager *broadcast.BroadcastManager
|
||||||
webRTCManager *webrtc.WebRTCManager
|
webRTCManager *webrtc.WebRTCManager
|
||||||
webSocketHandler *websocket.WebSocketHandler
|
webSocketHandler *websocket.WebSocketHandler
|
||||||
@ -120,17 +124,20 @@ func (neko *Neko) Preflight() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (neko *Neko) Start() {
|
func (neko *Neko) Start() {
|
||||||
broadcastManager := broadcast.New(neko.Remote, neko.Broadcast)
|
broadcastManager := broadcast.New(neko.Capture, neko.Broadcast)
|
||||||
|
|
||||||
remoteManager := remote.New(neko.Remote, broadcastManager)
|
desktopManager := desktop.New(neko.Desktop, broadcastManager)
|
||||||
remoteManager.Start()
|
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()
|
webRTCManager.Start()
|
||||||
|
|
||||||
webSocketHandler := websocket.New(sessionManager, remoteManager, broadcastManager, webRTCManager, neko.WebSocket)
|
webSocketHandler := websocket.New(sessionManager, desktopManager, captureManager, broadcastManager, webRTCManager, neko.WebSocket)
|
||||||
webSocketHandler.Start()
|
webSocketHandler.Start()
|
||||||
|
|
||||||
server := http.New(neko.Server, webSocketHandler)
|
server := http.New(neko.Server, webSocketHandler)
|
||||||
@ -138,7 +145,8 @@ func (neko *Neko) Start() {
|
|||||||
|
|
||||||
neko.broadcastManager = broadcastManager
|
neko.broadcastManager = broadcastManager
|
||||||
neko.sessionManager = sessionManager
|
neko.sessionManager = sessionManager
|
||||||
neko.remoteManager = remoteManager
|
neko.captureManager = captureManager
|
||||||
|
neko.desktopManager = desktopManager
|
||||||
neko.webRTCManager = webRTCManager
|
neko.webRTCManager = webRTCManager
|
||||||
neko.webSocketHandler = webSocketHandler
|
neko.webSocketHandler = webSocketHandler
|
||||||
neko.server = server
|
neko.server = server
|
||||||
@ -150,8 +158,11 @@ func (neko *Neko) Shutdown() {
|
|||||||
err = neko.broadcastManager.Shutdown()
|
err = neko.broadcastManager.Shutdown()
|
||||||
neko.logger.Err(err).Msg("broadcast manager shutdown")
|
neko.logger.Err(err).Msg("broadcast manager shutdown")
|
||||||
|
|
||||||
err = neko.remoteManager.Shutdown()
|
err = neko.desktopManager.Shutdown()
|
||||||
neko.logger.Err(err).Msg("remote manager 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()
|
err = neko.webRTCManager.Shutdown()
|
||||||
neko.logger.Err(err).Msg("webrtc manager shutdown")
|
neko.logger.Err(err).Msg("webrtc manager shutdown")
|
||||||
|
Reference in New Issue
Block a user