mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
format Go source code.
This commit is contained in:
parent
732764991b
commit
45679f1b86
@ -5,8 +5,8 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"demodesk/neko"
|
||||
"demodesk/neko/modules"
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/modules"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -3,8 +3,8 @@ package members
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"demodesk/neko/internal/utils"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
type MemberDataPayload struct {
|
||||
@ -29,11 +29,11 @@ func (h *MembersHandler) membersCreate(w http.ResponseWriter, r *http.Request) {
|
||||
data := &MemberDataPayload{
|
||||
// default values
|
||||
MemberProfile: &types.MemberProfile{
|
||||
IsAdmin: false,
|
||||
CanLogin: true,
|
||||
CanConnect: true,
|
||||
CanWatch: true,
|
||||
CanHost: true,
|
||||
IsAdmin: false,
|
||||
CanLogin: true,
|
||||
CanConnect: true,
|
||||
CanWatch: true,
|
||||
CanHost: true,
|
||||
CanAccessClipboard: true,
|
||||
},
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ import (
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
|
||||
"demodesk/neko/internal/http/auth"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
"demodesk/neko/internal/http/auth"
|
||||
)
|
||||
|
||||
type key int
|
||||
|
@ -3,14 +3,14 @@ package room
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"demodesk/neko/internal/utils"
|
||||
"demodesk/neko/internal/types/event"
|
||||
"demodesk/neko/internal/types/message"
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
type BroadcastStatusPayload struct {
|
||||
URL string `json:"url,omitempty"`
|
||||
IsActive bool `json:"is_active"`
|
||||
URL string `json:"url,omitempty"`
|
||||
IsActive bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (h *RoomHandler) broadcastStatus(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
//"strings"
|
||||
"net/http"
|
||||
|
||||
"demodesk/neko/internal/utils"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
type ClipboardPayload struct {
|
||||
|
@ -5,15 +5,15 @@ import (
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
|
||||
"demodesk/neko/internal/http/auth"
|
||||
"demodesk/neko/internal/types/event"
|
||||
"demodesk/neko/internal/types/message"
|
||||
"demodesk/neko/internal/utils"
|
||||
"demodesk/neko/internal/http/auth"
|
||||
)
|
||||
|
||||
type ControlStatusPayload struct {
|
||||
HasHost bool `json:"has_host"`
|
||||
HostId string `json:"host_id,omitempty"`
|
||||
HasHost bool `json:"has_host"`
|
||||
HostId string `json:"host_id,omitempty"`
|
||||
}
|
||||
|
||||
type ControlTargetPayload struct {
|
||||
@ -30,7 +30,7 @@ func (h *RoomHandler) controlStatus(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
utils.HttpSuccess(w, ControlStatusPayload{
|
||||
HasHost: true,
|
||||
HostId: host.ID(),
|
||||
HostId: host.ID(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/http/auth"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
|
@ -3,8 +3,8 @@ package room
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"demodesk/neko/internal/utils"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
type KeyboardMapData struct {
|
||||
@ -24,11 +24,11 @@ func (h *RoomHandler) keyboardMapSet(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
err := h.desktop.SetKeyboardMap(types.KeyboardMap{
|
||||
Layout: data.Layout,
|
||||
Layout: data.Layout,
|
||||
Variant: data.Variant,
|
||||
})
|
||||
|
||||
if err != nil{
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, "Unable to change keyboard map.")
|
||||
return
|
||||
}
|
||||
@ -39,13 +39,13 @@ func (h *RoomHandler) keyboardMapSet(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *RoomHandler) keyboardMapGet(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := h.desktop.GetKeyboardMap()
|
||||
|
||||
if err != nil{
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, "Unable to get keyboard map.")
|
||||
return
|
||||
}
|
||||
|
||||
utils.HttpSuccess(w, KeyboardMapData{
|
||||
Layout: data.Layout,
|
||||
Layout: data.Layout,
|
||||
Variant: data.Variant,
|
||||
})
|
||||
}
|
||||
@ -57,7 +57,7 @@ func (h *RoomHandler) keyboardModifiersSet(w http.ResponseWriter, r *http.Reques
|
||||
}
|
||||
|
||||
h.desktop.SetKeyboardModifiers(types.KeyboardModifiers{
|
||||
NumLock: data.NumLock,
|
||||
NumLock: data.NumLock,
|
||||
CapsLock: data.CapsLock,
|
||||
})
|
||||
utils.HttpSuccess(w)
|
||||
@ -67,7 +67,7 @@ func (h *RoomHandler) keyboardModifiersGet(w http.ResponseWriter, r *http.Reques
|
||||
data := h.desktop.GetKeyboardModifiers()
|
||||
|
||||
utils.HttpSuccess(w, KeyboardModifiersData{
|
||||
NumLock: data.NumLock,
|
||||
NumLock: data.NumLock,
|
||||
CapsLock: data.CapsLock,
|
||||
})
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package room
|
||||
import (
|
||||
"bytes"
|
||||
"image/jpeg"
|
||||
"strconv"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/types/event"
|
||||
@ -40,9 +40,9 @@ func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r *http.R
|
||||
}
|
||||
|
||||
if err := h.desktop.SetScreenSize(types.ScreenSize{
|
||||
Width: data.Width,
|
||||
Width: data.Width,
|
||||
Height: data.Height,
|
||||
Rate: data.Rate,
|
||||
Rate: data.Rate,
|
||||
}); err != nil {
|
||||
utils.HttpUnprocessableEntity(w, err)
|
||||
return
|
||||
|
@ -1,12 +1,12 @@
|
||||
package room
|
||||
|
||||
import (
|
||||
"os"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"net/http"
|
||||
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
@ -62,7 +62,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
defer srcFile.Close()
|
||||
|
||||
dstFile, err := os.OpenFile(path, os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0644)
|
||||
dstFile, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
return
|
||||
@ -125,7 +125,7 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
defer srcFile.Close()
|
||||
|
||||
dstFile, err := os.OpenFile(path, os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0644)
|
||||
dstFile, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
utils.HttpInternalServerError(w, err)
|
||||
return
|
||||
|
@ -7,10 +7,10 @@ import (
|
||||
|
||||
"demodesk/neko/internal/api/members"
|
||||
"demodesk/neko/internal/api/room"
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/http/auth"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
"demodesk/neko/internal/config"
|
||||
)
|
||||
|
||||
type ApiManagerCtx struct {
|
||||
|
@ -1,12 +1,12 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"time"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"demodesk/neko/internal/utils"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/http/auth"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
type SessionLoginPayload struct {
|
||||
@ -33,16 +33,16 @@ func (api *ApiManagerCtx) Login(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "neko-id",
|
||||
Value: session.ID(),
|
||||
Expires: time.Now().Add(365 * 24 * time.Hour),
|
||||
Name: "neko-id",
|
||||
Value: session.ID(),
|
||||
Expires: time.Now().Add(365 * 24 * time.Hour),
|
||||
HttpOnly: false,
|
||||
})
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "neko-secret",
|
||||
Value: data.Secret,
|
||||
Expires: time.Now().Add(365 * 24 * time.Hour),
|
||||
Name: "neko-secret",
|
||||
Value: data.Secret,
|
||||
Expires: time.Now().Add(365 * 24 * time.Hour),
|
||||
HttpOnly: true,
|
||||
})
|
||||
|
||||
@ -55,16 +55,16 @@ func (api *ApiManagerCtx) Login(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (api *ApiManagerCtx) Logout(w http.ResponseWriter, r *http.Request) {
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "neko-id",
|
||||
Value: "",
|
||||
Expires: time.Unix(0, 0),
|
||||
Name: "neko-id",
|
||||
Value: "",
|
||||
Expires: time.Unix(0, 0),
|
||||
HttpOnly: false,
|
||||
})
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "neko-secret",
|
||||
Value: "",
|
||||
Expires: time.Unix(0, 0),
|
||||
Name: "neko-secret",
|
||||
Value: "",
|
||||
Expires: time.Unix(0, 0),
|
||||
HttpOnly: true,
|
||||
})
|
||||
|
||||
|
@ -2,8 +2,8 @@ package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
@ -12,20 +12,20 @@ import (
|
||||
)
|
||||
|
||||
type BroacastManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
pipelineStr string
|
||||
pipeline *gst.Pipeline
|
||||
started bool
|
||||
url string
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
pipelineStr string
|
||||
pipeline *gst.Pipeline
|
||||
started bool
|
||||
url string
|
||||
}
|
||||
|
||||
func broadcastNew(pipelineStr string) *BroacastManagerCtx {
|
||||
return &BroacastManagerCtx{
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "broadcast").Logger(),
|
||||
pipelineStr: pipelineStr,
|
||||
started: false,
|
||||
url: "",
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "broadcast").Logger(),
|
||||
pipelineStr: pipelineStr,
|
||||
started: false,
|
||||
url: "",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,18 +8,18 @@ package gst
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
)
|
||||
|
||||
type Pipeline struct {
|
||||
Pipeline *C.GstElement
|
||||
Sample chan types.Sample
|
||||
Src string
|
||||
id int
|
||||
Pipeline *C.GstElement
|
||||
Sample chan types.Sample
|
||||
Src string
|
||||
id int
|
||||
}
|
||||
|
||||
var pipelines = make(map[int]*Pipeline)
|
||||
@ -45,14 +45,14 @@ func CreatePipeline(pipelineStr string) (*Pipeline, error) {
|
||||
|
||||
if gstError != nil {
|
||||
defer C.g_error_free(gstError)
|
||||
return nil, fmt.Errorf("(pipeline error) %s", C.GoString(gstError.message))
|
||||
return nil, fmt.Errorf("(pipeline error) %s", C.GoString(gstError.message))
|
||||
}
|
||||
|
||||
p := &Pipeline{
|
||||
Pipeline: gstPipeline,
|
||||
Sample: make(chan types.Sample),
|
||||
Src: pipelineStr,
|
||||
id: len(pipelines),
|
||||
Pipeline: gstPipeline,
|
||||
Sample: make(chan types.Sample),
|
||||
Src: pipelineStr,
|
||||
id: len(pipelines),
|
||||
}
|
||||
|
||||
pipelines[p.id] = p
|
||||
@ -96,7 +96,7 @@ func goHandlePipelineBuffer(buffer unsafe.Pointer, bufferLen C.int, duration C.i
|
||||
|
||||
if ok {
|
||||
pipeline.Sample <- types.Sample{
|
||||
Data: C.GoBytes(buffer, bufferLen),
|
||||
Data: C.GoBytes(buffer, bufferLen),
|
||||
Duration: time.Duration(duration),
|
||||
}
|
||||
} else {
|
||||
|
@ -7,20 +7,20 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/types/codec"
|
||||
"demodesk/neko/internal/config"
|
||||
)
|
||||
|
||||
type CaptureManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
desktop types.DesktopManager
|
||||
streaming bool
|
||||
broadcast *BroacastManagerCtx
|
||||
screencast *ScreencastManagerCtx
|
||||
audio *StreamManagerCtx
|
||||
videos map[string]*StreamManagerCtx
|
||||
videoIDs []string
|
||||
logger zerolog.Logger
|
||||
desktop types.DesktopManager
|
||||
streaming bool
|
||||
broadcast *BroacastManagerCtx
|
||||
screencast *ScreencastManagerCtx
|
||||
audio *StreamManagerCtx
|
||||
videos map[string]*StreamManagerCtx
|
||||
videoIDs []string
|
||||
}
|
||||
|
||||
func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCtx {
|
||||
@ -29,124 +29,124 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
|
||||
broadcastPipeline := config.BroadcastPipeline
|
||||
if broadcastPipeline == "" {
|
||||
broadcastPipeline = fmt.Sprintf(
|
||||
"flvmux name=mux ! rtmpsink location='{url} live=1' " +
|
||||
"pulsesrc device=%s " +
|
||||
"! audio/x-raw,channels=2 " +
|
||||
"! audioconvert " +
|
||||
"! queue " +
|
||||
"! voaacenc " +
|
||||
"! mux. " +
|
||||
"ximagesrc display-name=%s show-pointer=true use-damage=false " +
|
||||
"! video/x-raw " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! x264enc threads=4 bitrate=4096 key-int-max=15 byte-stream=true byte-stream=true tune=zerolatency speed-preset=veryfast " +
|
||||
"! mux.", config.Device, config.Display,
|
||||
"flvmux name=mux ! rtmpsink location='{url} live=1' "+
|
||||
"pulsesrc device=%s "+
|
||||
"! audio/x-raw,channels=2 "+
|
||||
"! audioconvert "+
|
||||
"! queue "+
|
||||
"! voaacenc "+
|
||||
"! mux. "+
|
||||
"ximagesrc display-name=%s show-pointer=true use-damage=false "+
|
||||
"! video/x-raw "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! x264enc threads=4 bitrate=4096 key-int-max=15 byte-stream=true byte-stream=true tune=zerolatency speed-preset=veryfast "+
|
||||
"! mux.", config.Device, config.Display,
|
||||
)
|
||||
}
|
||||
|
||||
screencastPipeline := config.ScreencastPipeline
|
||||
if screencastPipeline == "" {
|
||||
screencastPipeline = fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=true use-damage=false " +
|
||||
"! video/x-raw,framerate=%s " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! jpegenc quality=%s " +
|
||||
"ximagesrc display-name=%s show-pointer=true use-damage=false "+
|
||||
"! video/x-raw,framerate=%s "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! jpegenc quality=%s "+
|
||||
"! appsink name=appsink", config.Display, config.ScreencastRate, config.ScreencastQuality,
|
||||
)
|
||||
}
|
||||
|
||||
return &CaptureManagerCtx{
|
||||
logger: logger,
|
||||
desktop: desktop,
|
||||
streaming: false,
|
||||
broadcast: broadcastNew(broadcastPipeline),
|
||||
screencast: screencastNew(config.Screencast, screencastPipeline),
|
||||
audio: streamNew(config.AudioCodec, func() string {
|
||||
logger: logger,
|
||||
desktop: desktop,
|
||||
streaming: false,
|
||||
broadcast: broadcastNew(broadcastPipeline),
|
||||
screencast: screencastNew(config.Screencast, screencastPipeline),
|
||||
audio: streamNew(config.AudioCodec, func() string {
|
||||
if config.AudioPipeline != "" {
|
||||
return config.AudioPipeline
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
"pulsesrc device=%s " +
|
||||
"! audio/x-raw,channels=2 " +
|
||||
"! audioconvert " +
|
||||
"! queue " +
|
||||
"! %s " +
|
||||
"pulsesrc device=%s "+
|
||||
"! audio/x-raw,channels=2 "+
|
||||
"! audioconvert "+
|
||||
"! queue "+
|
||||
"! %s "+
|
||||
"! appsink name=appsink", config.Device, config.AudioCodec.Pipeline,
|
||||
)
|
||||
}),
|
||||
videos: map[string]*StreamManagerCtx{
|
||||
videos: map[string]*StreamManagerCtx{
|
||||
"hd": streamNew(codec.VP8(), func() string {
|
||||
screen := desktop.GetScreenSize()
|
||||
screen := desktop.GetScreenSize()
|
||||
bitrate := screen.Width * screen.Height * 12
|
||||
|
||||
return fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false " +
|
||||
"! video/x-raw,framerate=25/1 " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=6 max-quantizer=12 " +
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false "+
|
||||
"! video/x-raw,framerate=25/1 "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=6 max-quantizer=12 "+
|
||||
"! appsink name=appsink", config.Display, bitrate,
|
||||
)
|
||||
}),
|
||||
"hq": streamNew(codec.VP8(), func() string {
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width) / 6) * 5)
|
||||
height := int(math.Ceil(float64(screen.Height) / 6) * 5)
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width)/6) * 5)
|
||||
height := int(math.Ceil(float64(screen.Height)/6) * 5)
|
||||
bitrate := width * height * 12
|
||||
|
||||
return fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false " +
|
||||
"! video/x-raw,framerate=25/1 " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! videoscale " +
|
||||
"! video/x-raw,width=%d,height=%d " +
|
||||
"! queue " +
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=6 max-quantizer=12 " +
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false "+
|
||||
"! video/x-raw,framerate=25/1 "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! videoscale "+
|
||||
"! video/x-raw,width=%d,height=%d "+
|
||||
"! queue "+
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=6 max-quantizer=12 "+
|
||||
"! appsink name=appsink", config.Display, width, height, bitrate,
|
||||
)
|
||||
}),
|
||||
"mq": streamNew(codec.VP8(), func() string {
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width) / 6) * 4)
|
||||
height := int(math.Ceil(float64(screen.Height) / 6) * 4)
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width)/6) * 4)
|
||||
height := int(math.Ceil(float64(screen.Height)/6) * 4)
|
||||
bitrate := width * height * 8
|
||||
|
||||
return fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false " +
|
||||
"! video/x-raw,framerate=125/10 " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! videoscale " +
|
||||
"! video/x-raw,width=%d,height=%d " +
|
||||
"! queue " +
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=12 max-quantizer=24 " +
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false "+
|
||||
"! video/x-raw,framerate=125/10 "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! videoscale "+
|
||||
"! video/x-raw,width=%d,height=%d "+
|
||||
"! queue "+
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=12 max-quantizer=24 "+
|
||||
"! appsink name=appsink", config.Display, width, height, bitrate,
|
||||
)
|
||||
}),
|
||||
"lq": streamNew(codec.VP8(), func() string {
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width) / 6) * 3)
|
||||
height := int(math.Ceil(float64(screen.Height) / 6) * 3)
|
||||
screen := desktop.GetScreenSize()
|
||||
width := int(math.Ceil(float64(screen.Width)/6) * 3)
|
||||
height := int(math.Ceil(float64(screen.Height)/6) * 3)
|
||||
bitrate := width * height * 4
|
||||
|
||||
return fmt.Sprintf(
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false " +
|
||||
"! video/x-raw,framerate=125/10 " +
|
||||
"! videoconvert " +
|
||||
"! queue " +
|
||||
"! videoscale " +
|
||||
"! video/x-raw,width=%d,height=%d " +
|
||||
"! queue " +
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=12 max-quantizer=24 " +
|
||||
"ximagesrc display-name=%s show-pointer=false use-damage=false "+
|
||||
"! video/x-raw,framerate=125/10 "+
|
||||
"! videoconvert "+
|
||||
"! queue "+
|
||||
"! videoscale "+
|
||||
"! video/x-raw,width=%d,height=%d "+
|
||||
"! queue "+
|
||||
"! vp8enc target-bitrate=%d cpu-used=16 threads=4 deadline=100000 error-resilient=partitions keyframe-max-dist=15 auto-alt-ref=true min-quantizer=12 max-quantizer=24 "+
|
||||
"! appsink name=appsink", config.Display, width, height, bitrate,
|
||||
)
|
||||
}),
|
||||
},
|
||||
videoIDs: []string{ "hd", "hq", "mq", "lq" },
|
||||
videoIDs: []string{"hd", "hq", "mq", "lq"},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,41 +2,41 @@ package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/capture/gst"
|
||||
"demodesk/neko/internal/types"
|
||||
)
|
||||
|
||||
type ScreencastManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
pipelineStr string
|
||||
pipeline *gst.Pipeline
|
||||
enabled bool
|
||||
started bool
|
||||
emitStop chan bool
|
||||
emitUpdate chan bool
|
||||
expired int32
|
||||
sample chan types.Sample
|
||||
image types.Sample
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
pipelineStr string
|
||||
pipeline *gst.Pipeline
|
||||
enabled bool
|
||||
started bool
|
||||
emitStop chan bool
|
||||
emitUpdate chan bool
|
||||
expired int32
|
||||
sample chan types.Sample
|
||||
image types.Sample
|
||||
}
|
||||
|
||||
const screencastTimeout = 5 * time.Second
|
||||
|
||||
func screencastNew(enabled bool, pipelineStr string) *ScreencastManagerCtx {
|
||||
manager := &ScreencastManagerCtx{
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "screencast").Logger(),
|
||||
pipelineStr: pipelineStr,
|
||||
enabled: enabled,
|
||||
started: false,
|
||||
emitStop: make(chan bool),
|
||||
emitUpdate: make(chan bool),
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "screencast").Logger(),
|
||||
pipelineStr: pipelineStr,
|
||||
enabled: enabled,
|
||||
started: false,
|
||||
emitStop: make(chan bool),
|
||||
emitUpdate: make(chan bool),
|
||||
}
|
||||
|
||||
go func() {
|
||||
@ -146,7 +146,7 @@ func (manager *ScreencastManagerCtx) createPipeline() error {
|
||||
|
||||
manager.pipeline.Start()
|
||||
manager.sample = manager.pipeline.Sample
|
||||
manager.emitUpdate <-true
|
||||
manager.emitUpdate <- true
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -2,40 +2,40 @@ package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/capture/gst"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/types/codec"
|
||||
"demodesk/neko/internal/capture/gst"
|
||||
)
|
||||
|
||||
type StreamManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
codec codec.RTPCodec
|
||||
pipelineStr func() string
|
||||
pipeline *gst.Pipeline
|
||||
sample chan types.Sample
|
||||
listeners map[uintptr]*func(sample types.Sample)
|
||||
emitMu sync.Mutex
|
||||
emitUpdate chan bool
|
||||
emitStop chan bool
|
||||
started bool
|
||||
logger zerolog.Logger
|
||||
mu sync.Mutex
|
||||
codec codec.RTPCodec
|
||||
pipelineStr func() string
|
||||
pipeline *gst.Pipeline
|
||||
sample chan types.Sample
|
||||
listeners map[uintptr]*func(sample types.Sample)
|
||||
emitMu sync.Mutex
|
||||
emitUpdate chan bool
|
||||
emitStop chan bool
|
||||
started bool
|
||||
}
|
||||
|
||||
func streamNew(codec codec.RTPCodec, pipelineStr func() string) *StreamManagerCtx {
|
||||
manager := &StreamManagerCtx{
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "stream").Logger(),
|
||||
codec: codec,
|
||||
pipelineStr: pipelineStr,
|
||||
listeners: map[uintptr]*func(sample types.Sample){},
|
||||
emitUpdate: make(chan bool),
|
||||
emitStop: make(chan bool),
|
||||
started: false,
|
||||
logger: log.With().Str("module", "capture").Str("submodule", "stream").Logger(),
|
||||
codec: codec,
|
||||
pipelineStr: pipelineStr,
|
||||
listeners: map[uintptr]*func(sample types.Sample){},
|
||||
emitUpdate: make(chan bool),
|
||||
emitStop: make(chan bool),
|
||||
started: false,
|
||||
}
|
||||
|
||||
go func() {
|
||||
@ -146,7 +146,7 @@ func (manager *StreamManagerCtx) createPipeline() error {
|
||||
manager.pipeline.Start()
|
||||
|
||||
manager.sample = manager.pipeline.Sample
|
||||
manager.emitUpdate <-true
|
||||
manager.emitUpdate <- true
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -8,15 +8,15 @@ import (
|
||||
)
|
||||
|
||||
type Capture struct {
|
||||
Device string
|
||||
AudioCodec codec.RTPCodec
|
||||
AudioPipeline string
|
||||
Device string
|
||||
AudioCodec codec.RTPCodec
|
||||
AudioPipeline string
|
||||
|
||||
Display string
|
||||
//VideoCodec codec.RTPCodec
|
||||
//VideoPipeline string
|
||||
Display string
|
||||
//VideoCodec codec.RTPCodec
|
||||
//VideoPipeline string
|
||||
|
||||
BroadcastPipeline string
|
||||
BroadcastPipeline string
|
||||
|
||||
Screencast bool
|
||||
ScreencastRate string
|
||||
|
@ -1,8 +1,8 @@
|
||||
package desktop
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
@ -58,7 +58,7 @@ func (manager *DesktopManagerCtx) ClipboardSetBinary(mime string, data []byte) e
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
stdin, err := cmd.StdinPipe()
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
const (
|
||||
DROP_MOVE_REPEAT = 4
|
||||
DROP_DELAY = 100 * time.Millisecond
|
||||
DROP_DELAY = 100 * time.Millisecond
|
||||
)
|
||||
|
||||
func (manager *DesktopManagerCtx) DropFiles(x int, y int, files []string) bool {
|
||||
@ -49,10 +49,10 @@ func (manager *DesktopManagerCtx) DropFiles(x int, y int, files []string) bool {
|
||||
go drop.OpenWindow(files)
|
||||
|
||||
select {
|
||||
case succeeded := <- finished:
|
||||
case succeeded := <-finished:
|
||||
return succeeded
|
||||
case <-time.After(1 * time.Second):
|
||||
drop.CloseWindow();
|
||||
drop.CloseWindow()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ func OpenWindow(files []string) {
|
||||
defer mu.Unlock()
|
||||
|
||||
size := C.int(len(files))
|
||||
urisUnsafe := C.dragUrisMake(size);
|
||||
urisUnsafe := C.dragUrisMake(size)
|
||||
defer C.dragUrisFree(urisUnsafe, size)
|
||||
|
||||
for i, file := range files {
|
||||
|
@ -2,8 +2,8 @@ package desktop
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -19,19 +19,19 @@ func (manager *DesktopManagerCtx) HandleFileChooserDialog(uri string) error {
|
||||
// TODO: Use native API.
|
||||
err1 := exec.Command(
|
||||
"xdotool",
|
||||
"search", "--name", FILE_CHOOSER_DIALOG_NAME, "windowfocus",
|
||||
"sleep", FILE_CHOOSER_DIALOG_SHORT_SLEEP,
|
||||
"key", "--clearmodifiers", "ctrl+l",
|
||||
"type", "--args", "1", uri + "//",
|
||||
"sleep", FILE_CHOOSER_DIALOG_SHORT_SLEEP,
|
||||
"key", "Delete", // remove autocomplete results
|
||||
"sleep", FILE_CHOOSER_DIALOG_SHORT_SLEEP,
|
||||
"key", "Return",
|
||||
"sleep", FILE_CHOOSER_DIALOG_LONG_SLEEP,
|
||||
"key", "Down",
|
||||
"key", "--clearmodifiers", "ctrl+a",
|
||||
"key", "Return",
|
||||
"sleep", FILE_CHOOSER_DIALOG_LONG_SLEEP,
|
||||
"search", "--name", FILE_CHOOSER_DIALOG_NAME, "windowfocus",
|
||||
"sleep", FILE_CHOOSER_DIALOG_SHORT_SLEEP,
|
||||
"key", "--clearmodifiers", "ctrl+l",
|
||||
"type", "--args", "1", uri+"//",
|
||||
"sleep", FILE_CHOOSER_DIALOG_SHORT_SLEEP,
|
||||
"key", "Delete", // remove autocomplete results
|
||||
"sleep", FILE_CHOOSER_DIALOG_SHORT_SLEEP,
|
||||
"key", "Return",
|
||||
"sleep", FILE_CHOOSER_DIALOG_LONG_SLEEP,
|
||||
"key", "Down",
|
||||
"key", "--clearmodifiers", "ctrl+a",
|
||||
"key", "Return",
|
||||
"sleep", FILE_CHOOSER_DIALOG_LONG_SLEEP,
|
||||
).Run()
|
||||
|
||||
if err1 != nil {
|
||||
@ -41,7 +41,7 @@ func (manager *DesktopManagerCtx) HandleFileChooserDialog(uri string) error {
|
||||
// TODO: Use native API.
|
||||
err2 := exec.Command(
|
||||
"xdotool",
|
||||
"search", "--name", FILE_CHOOSER_DIALOG_NAME,
|
||||
"search", "--name", FILE_CHOOSER_DIALOG_NAME,
|
||||
).Run()
|
||||
|
||||
// if last command didn't return error, consider dialog as still open
|
||||
@ -61,7 +61,7 @@ func (manager *DesktopManagerCtx) CloseFileChooserDialog() {
|
||||
// TODO: Use native API.
|
||||
err := exec.Command(
|
||||
"xdotool",
|
||||
"search", "--name", FILE_CHOOSER_DIALOG_NAME, "windowfocus",
|
||||
"search", "--name", FILE_CHOOSER_DIALOG_NAME, "windowfocus",
|
||||
).Run()
|
||||
|
||||
if err != nil {
|
||||
@ -92,7 +92,7 @@ func (manager *DesktopManagerCtx) IsFileChooserDialogOpened() bool {
|
||||
// TODO: Use native API.
|
||||
err := exec.Command(
|
||||
"xdotool",
|
||||
"search", "--name", FILE_CHOOSER_DIALOG_NAME,
|
||||
"search", "--name", FILE_CHOOSER_DIALOG_NAME,
|
||||
).Run()
|
||||
|
||||
return err == nil
|
||||
|
@ -2,37 +2,37 @@ package desktop
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/go-events"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/desktop/xorg"
|
||||
"demodesk/neko/internal/desktop/xevent"
|
||||
"demodesk/neko/internal/desktop/xorg"
|
||||
)
|
||||
|
||||
var mu = sync.Mutex{}
|
||||
|
||||
type DesktopManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
cleanup *time.Ticker
|
||||
shutdown chan bool
|
||||
emmiter events.EventEmmiter
|
||||
display string
|
||||
config *config.Desktop
|
||||
logger zerolog.Logger
|
||||
cleanup *time.Ticker
|
||||
shutdown chan bool
|
||||
emmiter events.EventEmmiter
|
||||
display string
|
||||
config *config.Desktop
|
||||
}
|
||||
|
||||
func New(display string, config *config.Desktop) *DesktopManagerCtx {
|
||||
return &DesktopManagerCtx{
|
||||
logger: log.With().Str("module", "desktop").Logger(),
|
||||
cleanup: time.NewTicker(1 * time.Second),
|
||||
shutdown: make(chan bool),
|
||||
emmiter: events.New(),
|
||||
display: display,
|
||||
config: config,
|
||||
logger: log.With().Str("module", "desktop").Logger(),
|
||||
cleanup: time.NewTicker(1 * time.Second),
|
||||
shutdown: make(chan bool),
|
||||
emmiter: events.New(),
|
||||
display: display,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,9 @@ package xevent
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/go-events"
|
||||
)
|
||||
|
@ -2,11 +2,11 @@ package desktop
|
||||
|
||||
import (
|
||||
"image"
|
||||
"regexp"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/desktop/xorg"
|
||||
"demodesk/neko/internal/types"
|
||||
)
|
||||
|
||||
// TODO: Refactor.
|
||||
@ -119,7 +119,7 @@ func (manager *DesktopManagerCtx) GetKeyboardModifiers() types.KeyboardModifiers
|
||||
CapsLock := (modifiers & xorg.KBD_CAPS_LOCK) != 0
|
||||
|
||||
return types.KeyboardModifiers{
|
||||
NumLock: &NumLock,
|
||||
NumLock: &NumLock,
|
||||
CapsLock: &CapsLock,
|
||||
}
|
||||
}
|
||||
|
@ -236,13 +236,13 @@ func GetCursorImage() *types.CursorImage {
|
||||
height := uint16(cur.height)
|
||||
|
||||
return &types.CursorImage{
|
||||
Width: width,
|
||||
Width: width,
|
||||
Height: height,
|
||||
Xhot: uint16(cur.xhot),
|
||||
Yhot: uint16(cur.yhot),
|
||||
Xhot: uint16(cur.xhot),
|
||||
Yhot: uint16(cur.yhot),
|
||||
Serial: uint64(cur.cursor_serial),
|
||||
// Xlib stores 32-bit data in longs, even if longs are 64-bits long.
|
||||
Pixels: C.GoBytes(unsafe.Pointer(cur.pixels), C.int(width * height * 8)),
|
||||
Pixels: C.GoBytes(unsafe.Pointer(cur.pixels), C.int(width*height*8)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,7 +252,7 @@ func GetScreenshotImage() *image.RGBA {
|
||||
|
||||
var w, h C.int
|
||||
pixelsUnsafe := C.XGetScreenshot(&w, &h)
|
||||
pixels := C.GoBytes(unsafe.Pointer(pixelsUnsafe), w * h * 3)
|
||||
pixels := C.GoBytes(unsafe.Pointer(pixelsUnsafe), w*h*3)
|
||||
defer C.free(unsafe.Pointer(pixelsUnsafe))
|
||||
|
||||
width := int(w)
|
||||
@ -288,7 +288,7 @@ func goSetScreenRates(index C.int, rate_index C.int, rateC C.short) {
|
||||
rate := int16(rateC)
|
||||
|
||||
// filter out all irrelevant rates
|
||||
if rate > 60 || (rate > 30 && rate % 10 != 0){
|
||||
if rate > 60 || (rate > 30 && rate%10 != 0) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
@ -29,7 +29,7 @@ func New(WebSocketManager types.WebSocketManager, ApiManager types.ApiManager, c
|
||||
router := chi.NewRouter()
|
||||
router.Use(middleware.Recoverer) // Recover from panics without crashing server
|
||||
router.Use(cors.Handler(cors.Options{
|
||||
AllowOriginFunc: func(r *http.Request, origin string) bool {
|
||||
AllowOriginFunc: func(r *http.Request, origin string) bool {
|
||||
return conf.AllowOrigin(origin)
|
||||
},
|
||||
AllowedMethods: []string{"GET", "POST", "DELETE", "OPTIONS"},
|
||||
@ -39,7 +39,7 @@ func New(WebSocketManager types.WebSocketManager, ApiManager types.ApiManager, c
|
||||
MaxAge: 300, // Maximum value not ignored by any of major browsers
|
||||
}))
|
||||
router.Use(middleware.RequestID) // Create a request ID for each request
|
||||
router.Use(Logger) // Log API request calls using custom logger function
|
||||
router.Use(Logger) // Log API request calls using custom logger function
|
||||
|
||||
router.Route("/api", ApiManager.Route)
|
||||
|
||||
|
@ -55,4 +55,4 @@ func getAuthData(r *http.Request) (string, string, bool) {
|
||||
}
|
||||
|
||||
return "", "", false
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ func New() types.MembersDatabase {
|
||||
return &MembersDatabaseCtx{}
|
||||
}
|
||||
|
||||
type MembersDatabaseCtx struct {}
|
||||
type MembersDatabaseCtx struct{}
|
||||
|
||||
func (manager *MembersDatabaseCtx) Connect() error {
|
||||
return nil
|
||||
|
@ -2,9 +2,9 @@ package file
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
|
@ -1,11 +1,11 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/session/database/dummy"
|
||||
"demodesk/neko/internal/session/database/file"
|
||||
"demodesk/neko/internal/session/database/object"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/config"
|
||||
)
|
||||
|
||||
func New(config *config.Session) types.MembersDatabase {
|
||||
|
@ -8,9 +8,9 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/session/database"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/utils"
|
||||
)
|
||||
|
||||
@ -72,25 +72,25 @@ func (manager *SessionManagerCtx) Connect() error {
|
||||
|
||||
// create default admin account at startup
|
||||
_ = manager.add("admin", types.MemberProfile{
|
||||
Secret: manager.config.AdminPassword,
|
||||
Name: "Administrator",
|
||||
IsAdmin: true,
|
||||
CanLogin: true,
|
||||
CanConnect: true,
|
||||
CanWatch: true,
|
||||
CanHost: true,
|
||||
Secret: manager.config.AdminPassword,
|
||||
Name: "Administrator",
|
||||
IsAdmin: true,
|
||||
CanLogin: true,
|
||||
CanConnect: true,
|
||||
CanWatch: true,
|
||||
CanHost: true,
|
||||
CanAccessClipboard: true,
|
||||
})
|
||||
|
||||
// create default user account at startup
|
||||
_ = manager.add("user", types.MemberProfile{
|
||||
Secret: manager.config.Password,
|
||||
Name: "User",
|
||||
IsAdmin: false,
|
||||
CanLogin: true,
|
||||
CanConnect: true,
|
||||
CanWatch: true,
|
||||
CanHost: true,
|
||||
Secret: manager.config.Password,
|
||||
Name: "User",
|
||||
IsAdmin: false,
|
||||
CanLogin: true,
|
||||
CanConnect: true,
|
||||
CanWatch: true,
|
||||
CanHost: true,
|
||||
CanAccessClipboard: true,
|
||||
})
|
||||
|
||||
|
@ -19,14 +19,14 @@ func (codec *RTPCodec) Register(engine *webrtc.MediaEngine) error {
|
||||
|
||||
func VP8() RTPCodec {
|
||||
return RTPCodec{
|
||||
Name: "vp8",
|
||||
Name: "vp8",
|
||||
PayloadType: 96,
|
||||
Type: webrtc.RTPCodecTypeVideo,
|
||||
Type: webrtc.RTPCodecTypeVideo,
|
||||
Capability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypeVP8,
|
||||
ClockRate: 90000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
MimeType: webrtc.MimeTypeVP8,
|
||||
ClockRate: 90000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
// https://gstreamer.freedesktop.org/documentation/vpx/vp8enc.html
|
||||
@ -38,14 +38,14 @@ func VP8() RTPCodec {
|
||||
// TODO: Profile ID.
|
||||
func VP9() RTPCodec {
|
||||
return RTPCodec{
|
||||
Name: "vp9",
|
||||
Name: "vp9",
|
||||
PayloadType: 98,
|
||||
Type: webrtc.RTPCodecTypeVideo,
|
||||
Type: webrtc.RTPCodecTypeVideo,
|
||||
Capability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypeVP9,
|
||||
ClockRate: 90000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "profile-id=0",
|
||||
MimeType: webrtc.MimeTypeVP9,
|
||||
ClockRate: 90000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "profile-id=0",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
// https://gstreamer.freedesktop.org/documentation/vpx/vp9enc.html
|
||||
@ -57,14 +57,14 @@ func VP9() RTPCodec {
|
||||
// TODO: Profile ID.
|
||||
func H264() RTPCodec {
|
||||
return RTPCodec{
|
||||
Name: "h264",
|
||||
Name: "h264",
|
||||
PayloadType: 102,
|
||||
Type: webrtc.RTPCodecTypeVideo,
|
||||
Type: webrtc.RTPCodecTypeVideo,
|
||||
Capability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypeH264,
|
||||
ClockRate: 90000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f",
|
||||
MimeType: webrtc.MimeTypeH264,
|
||||
ClockRate: 90000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
// https://gstreamer.freedesktop.org/documentation/x264/index.html
|
||||
@ -78,14 +78,14 @@ func H264() RTPCodec {
|
||||
|
||||
func Opus() RTPCodec {
|
||||
return RTPCodec{
|
||||
Name: "opus",
|
||||
Name: "opus",
|
||||
PayloadType: 111,
|
||||
Type: webrtc.RTPCodecTypeAudio,
|
||||
Type: webrtc.RTPCodecTypeAudio,
|
||||
Capability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypeOpus,
|
||||
ClockRate: 48000,
|
||||
Channels: 2,
|
||||
SDPFmtpLine: "",
|
||||
MimeType: webrtc.MimeTypeOpus,
|
||||
ClockRate: 48000,
|
||||
Channels: 2,
|
||||
SDPFmtpLine: "",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
// https://gstreamer.freedesktop.org/documentation/opus/opusenc.html
|
||||
@ -96,14 +96,14 @@ func Opus() RTPCodec {
|
||||
|
||||
func G722() RTPCodec {
|
||||
return RTPCodec{
|
||||
Name: "g722",
|
||||
Name: "g722",
|
||||
PayloadType: 9,
|
||||
Type: webrtc.RTPCodecTypeAudio,
|
||||
Type: webrtc.RTPCodecTypeAudio,
|
||||
Capability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypeG722,
|
||||
ClockRate: 8000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
MimeType: webrtc.MimeTypeG722,
|
||||
ClockRate: 8000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
// https://gstreamer.freedesktop.org/documentation/libav/avenc_g722.html
|
||||
@ -114,14 +114,14 @@ func G722() RTPCodec {
|
||||
|
||||
func PCMU() RTPCodec {
|
||||
return RTPCodec{
|
||||
Name: "pcmu",
|
||||
Name: "pcmu",
|
||||
PayloadType: 0,
|
||||
Type: webrtc.RTPCodecTypeAudio,
|
||||
Type: webrtc.RTPCodecTypeAudio,
|
||||
Capability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypePCMU,
|
||||
ClockRate: 8000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
MimeType: webrtc.MimeTypePCMU,
|
||||
ClockRate: 8000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
// https://gstreamer.freedesktop.org/documentation/mulaw/mulawenc.html
|
||||
@ -132,14 +132,14 @@ func PCMU() RTPCodec {
|
||||
|
||||
func PCMA() RTPCodec {
|
||||
return RTPCodec{
|
||||
Name: "pcma",
|
||||
Name: "pcma",
|
||||
PayloadType: 8,
|
||||
Type: webrtc.RTPCodecTypeAudio,
|
||||
Type: webrtc.RTPCodecTypeAudio,
|
||||
Capability: webrtc.RTPCodecCapability{
|
||||
MimeType: webrtc.MimeTypePCMA,
|
||||
ClockRate: 8000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
MimeType: webrtc.MimeTypePCMA,
|
||||
ClockRate: 8000,
|
||||
Channels: 0,
|
||||
SDPFmtpLine: "",
|
||||
RTCPFeedback: nil,
|
||||
},
|
||||
// https://gstreamer.freedesktop.org/documentation/alaw/alawenc.html
|
||||
|
@ -73,7 +73,7 @@ type DesktopManager interface {
|
||||
OnEventError(listener func(error_code uint8, message string, request_code uint8, minor_code uint8))
|
||||
|
||||
// clipboard
|
||||
ClipboardGetText() (*ClipboardText, error)
|
||||
ClipboardGetText() (*ClipboardText, error)
|
||||
ClipboardSetText(data ClipboardText) error
|
||||
ClipboardGetBinary(mime string) ([]byte, error)
|
||||
ClipboardSetBinary(mime string, data []byte) error
|
||||
|
@ -15,20 +15,20 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
MEMBER_CREATED = "member/created"
|
||||
MEMBER_DELETED = "member/deleted"
|
||||
MEMBER_PROFILE = "member/profile"
|
||||
MEMBER_STATE = "member/state"
|
||||
MEMBER_CREATED = "member/created"
|
||||
MEMBER_DELETED = "member/deleted"
|
||||
MEMBER_PROFILE = "member/profile"
|
||||
MEMBER_STATE = "member/state"
|
||||
)
|
||||
|
||||
const (
|
||||
CONTROL_HOST = "control/host"
|
||||
CONTROL_RELEASE = "control/release"
|
||||
CONTROL_REQUEST = "control/request"
|
||||
CONTROL_MOVE = "control/move" // TODO: New. (fallback)
|
||||
CONTROL_SCROLL = "control/scroll" // TODO: New. (fallback)
|
||||
CONTROL_MOVE = "control/move" // TODO: New. (fallback)
|
||||
CONTROL_SCROLL = "control/scroll" // TODO: New. (fallback)
|
||||
CONTROL_KEYDOWN = "control/keydown" // TODO: New. (fallback)
|
||||
CONTROL_KEYUP = "control/keyup" // TODO: New. (fallback)
|
||||
CONTROL_KEYUP = "control/keyup" // TODO: New. (fallback)
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -25,9 +25,9 @@ type SystemInit struct {
|
||||
}
|
||||
|
||||
type SystemAdmin struct {
|
||||
Event string `json:"event,omitempty"`
|
||||
ScreenSizesList []ScreenSize `json:"screen_sizes_list"`
|
||||
BroadcastStatus BroadcastStatus `json:"broadcast_status"`
|
||||
Event string `json:"event,omitempty"`
|
||||
ScreenSizesList []ScreenSize `json:"screen_sizes_list"`
|
||||
BroadcastStatus BroadcastStatus `json:"broadcast_status"`
|
||||
}
|
||||
|
||||
type SystemDisconnect struct {
|
||||
@ -96,9 +96,9 @@ type MemberData struct {
|
||||
/////////////////////////////
|
||||
|
||||
type ControlHost struct {
|
||||
Event string `json:"event,omitempty"`
|
||||
HasHost bool `json:"has_host"`
|
||||
HostID string `json:"host_id,omitempty"`
|
||||
Event string `json:"event,omitempty"`
|
||||
HasHost bool `json:"has_host"`
|
||||
HostID string `json:"host_id,omitempty"`
|
||||
}
|
||||
|
||||
// TODO: New.
|
||||
@ -155,7 +155,7 @@ type KeyboardModifiers struct {
|
||||
Event string `json:"event,omitempty"`
|
||||
CapsLock *bool `json:"caps_lock"`
|
||||
NumLock *bool `json:"num_lock"`
|
||||
ScrollLock *bool `json:"scroll_lock"`
|
||||
ScrollLock *bool `json:"scroll_lock"`
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
|
@ -22,9 +22,9 @@ type MembersDatabase interface {
|
||||
Connect() error
|
||||
Disconnect() error
|
||||
|
||||
Insert(id string, profile MemberProfile) error
|
||||
Update(id string, profile MemberProfile) error
|
||||
Delete(id string) error
|
||||
Insert(id string, profile MemberProfile) error
|
||||
Update(id string, profile MemberProfile) error
|
||||
Delete(id string) error
|
||||
Select() (map[string]MemberProfile, error)
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,10 @@ package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"encoding/base64"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
)
|
||||
|
@ -1,10 +1,10 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
@ -9,11 +9,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
OP_MOVE = 0x01
|
||||
OP_SCROLL = 0x02
|
||||
OP_MOVE = 0x01
|
||||
OP_SCROLL = 0x02
|
||||
OP_KEY_DOWN = 0x03
|
||||
OP_KEY_UP = 0x04
|
||||
OP_KEY_CLK = 0x05
|
||||
OP_KEY_UP = 0x04
|
||||
OP_KEY_CLK = 0x05
|
||||
)
|
||||
|
||||
type PayloadHeader struct {
|
||||
|
@ -8,17 +8,17 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type nulllog struct {}
|
||||
type nulllog struct{}
|
||||
|
||||
func (l nulllog) Trace(msg string) {}
|
||||
func (l nulllog) Trace(msg string) {}
|
||||
func (l nulllog) Tracef(format string, args ...interface{}) {}
|
||||
func (l nulllog) Debug(msg string) {}
|
||||
func (l nulllog) Debug(msg string) {}
|
||||
func (l nulllog) Debugf(format string, args ...interface{}) {}
|
||||
func (l nulllog) Info(msg string) {}
|
||||
func (l nulllog) Infof(format string, args ...interface{}) {}
|
||||
func (l nulllog) Warn(msg string) {}
|
||||
func (l nulllog) Warnf(format string, args ...interface{}) {}
|
||||
func (l nulllog) Error(msg string) {}
|
||||
func (l nulllog) Info(msg string) {}
|
||||
func (l nulllog) Infof(format string, args ...interface{}) {}
|
||||
func (l nulllog) Warn(msg string) {}
|
||||
func (l nulllog) Warnf(format string, args ...interface{}) {}
|
||||
func (l nulllog) Error(msg string) {}
|
||||
func (l nulllog) Errorf(format string, args ...interface{}) {}
|
||||
|
||||
type logger struct {
|
||||
|
@ -3,39 +3,39 @@ package webrtc
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/pion/webrtc/v3"
|
||||
"github.com/pion/webrtc/v3/pkg/media"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/types/event"
|
||||
"demodesk/neko/internal/types/message"
|
||||
"demodesk/neko/internal/config"
|
||||
)
|
||||
|
||||
func New(desktop types.DesktopManager, capture types.CaptureManager, config *config.WebRTC) *WebRTCManagerCtx {
|
||||
return &WebRTCManagerCtx{
|
||||
logger: log.With().Str("module", "webrtc").Logger(),
|
||||
desktop: desktop,
|
||||
capture: capture,
|
||||
config: config,
|
||||
logger: log.With().Str("module", "webrtc").Logger(),
|
||||
desktop: desktop,
|
||||
capture: capture,
|
||||
config: config,
|
||||
// TODO: Refactor.
|
||||
curImgListeners: map[uintptr]*func(cur *types.CursorImage){},
|
||||
curPosListeners: map[uintptr]*func(x, y int){},
|
||||
curImgListeners: map[uintptr]*func(cur *types.CursorImage){},
|
||||
curPosListeners: map[uintptr]*func(x, y int){},
|
||||
}
|
||||
}
|
||||
|
||||
type WebRTCManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
audioTrack *webrtc.TrackLocalStaticSample
|
||||
audioStop func()
|
||||
desktop types.DesktopManager
|
||||
capture types.CaptureManager
|
||||
config *config.WebRTC
|
||||
logger zerolog.Logger
|
||||
audioTrack *webrtc.TrackLocalStaticSample
|
||||
audioStop func()
|
||||
desktop types.DesktopManager
|
||||
capture types.CaptureManager
|
||||
config *config.WebRTC
|
||||
// TODO: Refactor.
|
||||
curImgListeners map[uintptr]*func(cur *types.CursorImage)
|
||||
curPosListeners map[uintptr]*func(x, y int)
|
||||
@ -58,7 +58,7 @@ func (manager *WebRTCManagerCtx) Start() {
|
||||
}
|
||||
|
||||
audio.AddListener(&listener)
|
||||
manager.audioStop = func(){
|
||||
manager.audioStop = func() {
|
||||
audio.RemoveListener(&listener)
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, videoID strin
|
||||
if videoStream.ListenersCount() == 0 {
|
||||
videoStream.Stop()
|
||||
}
|
||||
|
||||
|
||||
videoStream = newVideoStream
|
||||
return nil
|
||||
}
|
||||
@ -234,10 +234,10 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, videoID strin
|
||||
}
|
||||
|
||||
peer := &WebRTCPeerCtx{
|
||||
api: api,
|
||||
connection: connection,
|
||||
changeVideo: changeVideo,
|
||||
dataChannel: dataChannel,
|
||||
api: api,
|
||||
connection: connection,
|
||||
changeVideo: changeVideo,
|
||||
dataChannel: dataChannel,
|
||||
}
|
||||
|
||||
cursorChange := func(cur *types.CursorImage) {
|
||||
|
@ -3,15 +3,15 @@ package webrtc
|
||||
import "github.com/pion/webrtc/v3"
|
||||
|
||||
type WebRTCPeerCtx struct {
|
||||
api *webrtc.API
|
||||
connection *webrtc.PeerConnection
|
||||
dataChannel *webrtc.DataChannel
|
||||
changeVideo func(videoID string) error
|
||||
api *webrtc.API
|
||||
connection *webrtc.PeerConnection
|
||||
dataChannel *webrtc.DataChannel
|
||||
changeVideo func(videoID string) error
|
||||
}
|
||||
|
||||
func (webrtc_peer *WebRTCPeerCtx) SignalAnswer(sdp string) error {
|
||||
return webrtc_peer.connection.SetRemoteDescription(webrtc.SessionDescription{
|
||||
SDP: sdp,
|
||||
SDP: sdp,
|
||||
Type: webrtc.SDPTypeAnswer,
|
||||
})
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package webrtc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/utils"
|
||||
@ -11,7 +11,7 @@ import (
|
||||
|
||||
const (
|
||||
OP_CURSOR_POSITION = 0x01
|
||||
OP_CURSOR_IMAGE = 0x02
|
||||
OP_CURSOR_IMAGE = 0x02
|
||||
)
|
||||
|
||||
type PayloadCursorPosition struct {
|
||||
@ -35,7 +35,7 @@ func (webrtc_peer *WebRTCPeerCtx) SendCursorPosition(x, y int) error {
|
||||
|
||||
data := PayloadCursorPosition{
|
||||
PayloadHeader: PayloadHeader{
|
||||
Event: OP_CURSOR_POSITION,
|
||||
Event: OP_CURSOR_POSITION,
|
||||
Length: 7,
|
||||
},
|
||||
X: uint16(x),
|
||||
@ -62,13 +62,13 @@ func (webrtc_peer *WebRTCPeerCtx) SendCursorImage(cur *types.CursorImage) error
|
||||
|
||||
data := PayloadCursorImage{
|
||||
PayloadHeader: PayloadHeader{
|
||||
Event: OP_CURSOR_IMAGE,
|
||||
Event: OP_CURSOR_IMAGE,
|
||||
Length: uint16(11 + len(img)),
|
||||
},
|
||||
Width: cur.Width,
|
||||
Width: cur.Width,
|
||||
Height: cur.Height,
|
||||
Xhot: cur.Xhot,
|
||||
Yhot: cur.Yhot,
|
||||
Xhot: cur.Xhot,
|
||||
Yhot: cur.Yhot,
|
||||
}
|
||||
|
||||
buffer := &bytes.Buffer{}
|
||||
|
@ -23,8 +23,8 @@ func (ws *WebSocketManagerCtx) fileChooserDialogEvents() {
|
||||
file_chooser_dialog_member = host
|
||||
|
||||
go ws.sessions.Broadcast(message.MemberID{
|
||||
Event: event.FILE_CHOOSER_DIALOG_OPENED,
|
||||
ID: host.ID(),
|
||||
Event: event.FILE_CHOOSER_DIALOG_OPENED,
|
||||
ID: host.ID(),
|
||||
}, nil)
|
||||
})
|
||||
|
||||
@ -35,11 +35,10 @@ func (ws *WebSocketManagerCtx) fileChooserDialogEvents() {
|
||||
file_chooser_dialog_member = nil
|
||||
|
||||
go ws.sessions.Broadcast(message.MemberID{
|
||||
Event: event.FILE_CHOOSER_DIALOG_CLOSED,
|
||||
Event: event.FILE_CHOOSER_DIALOG_CLOSED,
|
||||
}, nil)
|
||||
})
|
||||
|
||||
|
||||
// when new user joins, and someone holds dialog, he shouldd be notified about it.
|
||||
ws.sessions.OnConnected(func(session types.Session) {
|
||||
if file_chooser_dialog_member == nil {
|
||||
@ -47,8 +46,8 @@ func (ws *WebSocketManagerCtx) fileChooserDialogEvents() {
|
||||
}
|
||||
|
||||
if err := session.Send(message.MemberID{
|
||||
Event: event.FILE_CHOOSER_DIALOG_OPENED,
|
||||
ID: file_chooser_dialog_member.ID(),
|
||||
Event: event.FILE_CHOOSER_DIALOG_OPENED,
|
||||
ID: file_chooser_dialog_member.ID(),
|
||||
}); err != nil {
|
||||
ws.logger.Warn().
|
||||
Str("id", session.ID()).
|
||||
|
@ -21,20 +21,20 @@ func New(
|
||||
logger := log.With().Str("module", "handler").Logger()
|
||||
|
||||
return &MessageHandlerCtx{
|
||||
logger: logger,
|
||||
sessions: sessions,
|
||||
desktop: desktop,
|
||||
capture: capture,
|
||||
webrtc: webrtc,
|
||||
logger: logger,
|
||||
sessions: sessions,
|
||||
desktop: desktop,
|
||||
capture: capture,
|
||||
webrtc: webrtc,
|
||||
}
|
||||
}
|
||||
|
||||
type MessageHandlerCtx struct {
|
||||
logger zerolog.Logger
|
||||
sessions types.SessionManager
|
||||
webrtc types.WebRTCManager
|
||||
desktop types.DesktopManager
|
||||
capture types.CaptureManager
|
||||
logger zerolog.Logger
|
||||
sessions types.SessionManager
|
||||
webrtc types.WebRTCManager
|
||||
desktop types.DesktopManager
|
||||
capture types.CaptureManager
|
||||
}
|
||||
|
||||
func (h *MessageHandlerCtx) Message(session types.Session, raw []byte) bool {
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"demodesk/neko/internal/types/message"
|
||||
)
|
||||
|
||||
|
||||
func (h *MessageHandlerCtx) keyboardMap(session types.Session, payload *message.KeyboardMap) error {
|
||||
if !session.IsHost() {
|
||||
h.logger.Debug().Str("id", session.ID()).Msg("is not the host")
|
||||
@ -13,7 +12,7 @@ func (h *MessageHandlerCtx) keyboardMap(session types.Session, payload *message.
|
||||
}
|
||||
|
||||
return h.desktop.SetKeyboardMap(types.KeyboardMap{
|
||||
Layout: payload.Layout,
|
||||
Layout: payload.Layout,
|
||||
Variant: payload.Variant,
|
||||
})
|
||||
}
|
||||
@ -25,7 +24,7 @@ func (h *MessageHandlerCtx) keyboardModifiers(session types.Session, payload *me
|
||||
}
|
||||
|
||||
h.desktop.SetKeyboardModifiers(types.KeyboardModifiers{
|
||||
NumLock: payload.NumLock,
|
||||
NumLock: payload.NumLock,
|
||||
CapsLock: payload.CapsLock,
|
||||
})
|
||||
return nil
|
||||
|
@ -13,9 +13,9 @@ func (h *MessageHandlerCtx) screenSet(session types.Session, payload *message.Sc
|
||||
}
|
||||
|
||||
if err := h.desktop.SetScreenSize(types.ScreenSize{
|
||||
Width: payload.Width,
|
||||
Width: payload.Width,
|
||||
Height: payload.Height,
|
||||
Rate: payload.Rate,
|
||||
Rate: payload.Rate,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package handler
|
||||
|
||||
import (
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/types/message"
|
||||
"demodesk/neko/internal/types/event"
|
||||
"demodesk/neko/internal/types/message"
|
||||
)
|
||||
|
||||
func (h *MessageHandlerCtx) sendUnicast(session types.Session, payload *message.SendUnicast) error {
|
||||
@ -24,10 +24,10 @@ func (h *MessageHandlerCtx) sendUnicast(session types.Session, payload *message.
|
||||
|
||||
func (h *MessageHandlerCtx) sendBroadcast(session types.Session, payload *message.SendBroadcast) error {
|
||||
h.sessions.Broadcast(message.SendBroadcast{
|
||||
Event: event.SEND_BROADCAST,
|
||||
Sender: session.ID(),
|
||||
Subject: payload.Subject,
|
||||
Body: payload.Body,
|
||||
}, []string{ session.ID() })
|
||||
Event: event.SEND_BROADCAST,
|
||||
Sender: session.ID(),
|
||||
Subject: payload.Subject,
|
||||
Body: payload.Body,
|
||||
}, []string{session.ID()})
|
||||
return nil
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ func (h *MessageHandlerCtx) SessionDeleted(session types.Session) error {
|
||||
message.MemberID{
|
||||
Event: event.MEMBER_DELETED,
|
||||
ID: session.ID(),
|
||||
}, nil);
|
||||
}, nil)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ func (h *MessageHandlerCtx) signalVideo(session types.Session, payload *message.
|
||||
|
||||
return session.Send(
|
||||
message.SignalVideo{
|
||||
Event: event.SIGNAL_VIDEO,
|
||||
Video: payload.Video,
|
||||
Event: event.SIGNAL_VIDEO,
|
||||
Video: payload.Video,
|
||||
})
|
||||
}
|
||||
|
@ -34,10 +34,10 @@ func (h *MessageHandlerCtx) systemInit(session types.Session) error {
|
||||
|
||||
return session.Send(
|
||||
message.SystemInit{
|
||||
Event: event.SYSTEM_INIT,
|
||||
MemberId: session.ID(),
|
||||
ControlHost: controlHost,
|
||||
ScreenSize: message.ScreenSize{
|
||||
Event: event.SYSTEM_INIT,
|
||||
MemberId: session.ID(),
|
||||
ControlHost: controlHost,
|
||||
ScreenSize: message.ScreenSize{
|
||||
Width: size.Width,
|
||||
Height: size.Height,
|
||||
Rate: size.Rate,
|
||||
|
@ -8,10 +8,10 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"demodesk/neko/internal/websocket/handler"
|
||||
"demodesk/neko/internal/types"
|
||||
"demodesk/neko/internal/types/event"
|
||||
"demodesk/neko/internal/types/message"
|
||||
"demodesk/neko/internal/websocket/handler"
|
||||
)
|
||||
|
||||
func New(
|
||||
@ -23,11 +23,11 @@ func New(
|
||||
logger := log.With().Str("module", "websocket").Logger()
|
||||
|
||||
return &WebSocketManagerCtx{
|
||||
logger: logger,
|
||||
sessions: sessions,
|
||||
desktop: desktop,
|
||||
handler: handler.New(sessions, desktop, capture, webrtc),
|
||||
handlers: []types.HandlerFunction{},
|
||||
logger: logger,
|
||||
sessions: sessions,
|
||||
desktop: desktop,
|
||||
handler: handler.New(sessions, desktop, capture, webrtc),
|
||||
handlers: []types.HandlerFunction{},
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,12 +35,12 @@ func New(
|
||||
const pingPeriod = 60 * time.Second
|
||||
|
||||
type WebSocketManagerCtx struct {
|
||||
logger zerolog.Logger
|
||||
sessions types.SessionManager
|
||||
desktop types.DesktopManager
|
||||
handler *handler.MessageHandlerCtx
|
||||
handlers []types.HandlerFunction
|
||||
shutdown chan bool
|
||||
logger zerolog.Logger
|
||||
sessions types.SessionManager
|
||||
desktop types.DesktopManager
|
||||
handler *handler.MessageHandlerCtx
|
||||
handlers []types.HandlerFunction
|
||||
shutdown chan bool
|
||||
}
|
||||
|
||||
func (ws *WebSocketManagerCtx) Start() {
|
||||
|
54
neko.go
54
neko.go
@ -6,14 +6,14 @@ import (
|
||||
"os/signal"
|
||||
"runtime"
|
||||
|
||||
"demodesk/neko/internal/api"
|
||||
"demodesk/neko/internal/capture"
|
||||
"demodesk/neko/internal/config"
|
||||
"demodesk/neko/internal/desktop"
|
||||
"demodesk/neko/internal/capture"
|
||||
"demodesk/neko/internal/webrtc"
|
||||
"demodesk/neko/internal/session"
|
||||
"demodesk/neko/internal/websocket"
|
||||
"demodesk/neko/internal/api"
|
||||
"demodesk/neko/internal/http"
|
||||
"demodesk/neko/internal/session"
|
||||
"demodesk/neko/internal/webrtc"
|
||||
"demodesk/neko/internal/websocket"
|
||||
"demodesk/neko/modules"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
@ -62,12 +62,12 @@ func init() {
|
||||
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||
},
|
||||
Configs: &Configs{
|
||||
Root: &config.Root{},
|
||||
Desktop: &config.Desktop{},
|
||||
Capture: &config.Capture{},
|
||||
WebRTC: &config.WebRTC{},
|
||||
Session: &config.Session{},
|
||||
Server: &config.Server{},
|
||||
Root: &config.Root{},
|
||||
Desktop: &config.Desktop{},
|
||||
Capture: &config.Capture{},
|
||||
WebRTC: &config.WebRTC{},
|
||||
Session: &config.Session{},
|
||||
Server: &config.Server{},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -102,26 +102,26 @@ func (i *Version) Details() string {
|
||||
}
|
||||
|
||||
type Configs struct {
|
||||
Root *config.Root
|
||||
Desktop *config.Desktop
|
||||
Capture *config.Capture
|
||||
WebRTC *config.WebRTC
|
||||
Session *config.Session
|
||||
Server *config.Server
|
||||
Root *config.Root
|
||||
Desktop *config.Desktop
|
||||
Capture *config.Capture
|
||||
WebRTC *config.WebRTC
|
||||
Session *config.Session
|
||||
Server *config.Server
|
||||
}
|
||||
|
||||
type Neko struct {
|
||||
Version *Version
|
||||
Configs *Configs
|
||||
Version *Version
|
||||
Configs *Configs
|
||||
|
||||
logger zerolog.Logger
|
||||
desktopManager *desktop.DesktopManagerCtx
|
||||
captureManager *capture.CaptureManagerCtx
|
||||
webRTCManager *webrtc.WebRTCManagerCtx
|
||||
sessionManager *session.SessionManagerCtx
|
||||
webSocketManager *websocket.WebSocketManagerCtx
|
||||
apiManager *api.ApiManagerCtx
|
||||
httpManager *http.HttpManagerCtx
|
||||
logger zerolog.Logger
|
||||
desktopManager *desktop.DesktopManagerCtx
|
||||
captureManager *capture.CaptureManagerCtx
|
||||
webRTCManager *webrtc.WebRTCManagerCtx
|
||||
sessionManager *session.SessionManagerCtx
|
||||
webSocketManager *websocket.WebSocketManagerCtx
|
||||
apiManager *api.ApiManagerCtx
|
||||
httpManager *http.HttpManagerCtx
|
||||
}
|
||||
|
||||
func (neko *Neko) Preflight() {
|
||||
|
Loading…
Reference in New Issue
Block a user