Compare commits

..

No commits in common. "master" and "v2.8.12" have entirely different histories.

14 changed files with 35 additions and 55 deletions

View File

@ -3,9 +3,7 @@ FROM $BASE_IMAGE
# latest working version with EGL: 111.0.5563.146, revert when resolved # latest working version with EGL: 111.0.5563.146, revert when resolved
# 112.0.5615.49 fails: https://github.com/VirtualGL/virtualgl/issues/229 # 112.0.5615.49 fails: https://github.com/VirtualGL/virtualgl/issues/229
# google does not provide a direct link to the deb file anymore ARG SRC_URL="https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_111.0.5563.146-1_amd64.deb"
# ARG SRC_URL="https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_111.0.5563.146-1_amd64.deb"
ARG SRC_URL="https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"
# #
# install google chrome # install google chrome

View File

@ -313,15 +313,7 @@
} }
get clipboard_read_available() { get clipboard_read_available() {
return ( return 'clipboard' in navigator && typeof navigator.clipboard.readText === 'function'
'clipboard' in navigator &&
typeof navigator.clipboard.readText === 'function' &&
// Firefox 122+ incorrectly reports that it can read the clipboard but it can't
// instead it hangs when reading clipboard, until user clicks on the page
// and the click itself is not handled by the page at all, also the clipboard
// reads always fail with "Clipboard read operation is not allowed."
navigator.userAgent.indexOf('Firefox') == -1
)
} }
get clipboard_write_available() { get clipboard_write_available() {
@ -638,7 +630,7 @@
} }
async syncClipboard() { async syncClipboard() {
if (this.clipboard_read_available && window.document.hasFocus()) { if (this.clipboard_read_available) {
try { try {
const text = await navigator.clipboard.readText() const text = await navigator.clipboard.readText()
if (this.clipboard !== text) { if (this.clipboard !== text) {

View File

@ -6,7 +6,6 @@
- Added nvidia support for firefox. - Added nvidia support for firefox.
- Added `?lang=<lang>` parameter to the URL, which will set the language of the interface (by @mbattista). - Added `?lang=<lang>` parameter to the URL, which will set the language of the interface (by @mbattista).
- Added `?show_side=1` and `?mute_chat=1` parameter to the URL, for chat mute and show side (by @mbattista). - Added `?show_side=1` and `?mute_chat=1` parameter to the URL, for chat mute and show side (by @mbattista).
- Added `NEKO_BROADCAST_AUTOSTART` to automatically start or do not start broadcasting when the room is created. By default, it is set to `true` because it was the previous behavior.
### Bugs ### Bugs
- Fix incorrect version sorting for chromium, microsoft-edge, opera and ungoogledchromium. - Fix incorrect version sorting for chromium, microsoft-edge, opera and ungoogledchromium.

View File

@ -107,11 +107,9 @@ nat1to1: <ip>
#### `NEKO_BROADCAST_PIPELINE`: #### `NEKO_BROADCAST_PIPELINE`:
- Makes it possible to create custom gstreamer pipeline used for broadcasting, strings `{url}`, `{device}` and `{display}` will be replaced. - Makes it possible to create custom gstreamer pipeline used for broadcasting, strings `{url}`, `{device}` and `{display}` will be replaced.
#### `NEKO_BROADCAST_URL`: #### `NEKO_BROADCAST_URL`:
- Set a default URL for broadcast streams. It can be disabled/changed later by admins in the GUI. - Set a default URL for broadcast streams. Setting this value will automatically enable broadcasting when n.eko starts. It can be disabled/changed later by admins in the GUI.
- e.g. `rtmp://<your-server>:1935/ingest/<stream-key>` - e.g. `rtmp://<your-server>:1935/ingest/<stream-key>`
#### `NEKO_BROADCAST_AUTOSTART`:
- Automatically start broadcasting when neko starts and broadcast_url is set.
- e.g. `true`
### Server ### Server
#### `NEKO_BIND`: #### `NEKO_BIND`:

View File

@ -22,7 +22,7 @@ type BroacastManagerCtx struct {
started bool started bool
} }
func broadcastNew(pipelineFn func(url string) (string, error), url string, started bool) *BroacastManagerCtx { func broadcastNew(pipelineFn func(url string) (string, error), defaultUrl string) *BroacastManagerCtx {
logger := log.With(). logger := log.With().
Str("module", "capture"). Str("module", "capture").
Str("submodule", "broadcast"). Str("submodule", "broadcast").
@ -31,8 +31,8 @@ func broadcastNew(pipelineFn func(url string) (string, error), url string, start
return &BroacastManagerCtx{ return &BroacastManagerCtx{
logger: logger, logger: logger,
pipelineFn: pipelineFn, pipelineFn: pipelineFn,
url: url, url: defaultUrl,
started: started && url != "", started: defaultUrl != "",
} }
} }

View File

@ -31,7 +31,7 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
// sinks // sinks
broadcast: broadcastNew(func(url string) (string, error) { broadcast: broadcastNew(func(url string) (string, error) {
return NewBroadcastPipeline(config.AudioDevice, config.Display, config.BroadcastPipeline, url) return NewBroadcastPipeline(config.AudioDevice, config.Display, config.BroadcastPipeline, url)
}, config.BroadcastUrl, config.BroadcastAutostart), }, config.BroadcastUrl),
audio: streamSinkNew(config.AudioCodec, func() (string, error) { audio: streamSinkNew(config.AudioCodec, func() (string, error) {
return NewAudioPipeline(config.AudioCodec, config.AudioDevice, config.AudioPipeline, config.AudioBitrate) return NewAudioPipeline(config.AudioCodec, config.AudioDevice, config.AudioPipeline, config.AudioBitrate)
}, "audio"), }, "audio"),

View File

@ -34,9 +34,8 @@ type Capture struct {
AudioPipeline string AudioPipeline string
// broadcast // broadcast
BroadcastPipeline string BroadcastPipeline string
BroadcastUrl string BroadcastUrl string
BroadcastAutostart bool
} }
func (Capture) Init(cmd *cobra.Command) error { func (Capture) Init(cmd *cobra.Command) error {
@ -156,16 +155,11 @@ func (Capture) Init(cmd *cobra.Command) error {
return err return err
} }
cmd.PersistentFlags().String("broadcast_url", "", "a default default URL for broadcast streams, can be disabled/changed later by admins in the GUI") cmd.PersistentFlags().String("broadcast_url", "", "URL for broadcasting, setting this value will automatically enable broadcasting")
if err := viper.BindPFlag("broadcast_url", cmd.PersistentFlags().Lookup("broadcast_url")); err != nil { if err := viper.BindPFlag("broadcast_url", cmd.PersistentFlags().Lookup("broadcast_url")); err != nil {
return err return err
} }
cmd.PersistentFlags().Bool("broadcast_autostart", true, "automatically start broadcasting when neko starts and broadcast_url is set")
if err := viper.BindPFlag("broadcast_autostart", cmd.PersistentFlags().Lookup("broadcast_autostart")); err != nil {
return err
}
return nil return nil
} }
@ -253,5 +247,4 @@ func (s *Capture) Set() {
s.BroadcastPipeline = viper.GetString("broadcast_pipeline") s.BroadcastPipeline = viper.GetString("broadcast_pipeline")
s.BroadcastUrl = viper.GetString("broadcast_url") s.BroadcastUrl = viper.GetString("broadcast_url")
s.BroadcastAutostart = viper.GetBool("broadcast_autostart")
} }

View File

@ -46,9 +46,9 @@ const (
) )
const ( const (
BROADCAST_STATUS = "broadcast/status" BORADCAST_STATUS = "broadcast/status"
BROADCAST_CREATE = "broadcast/create" BORADCAST_CREATE = "broadcast/create"
BROADCAST_DESTROY = "broadcast/destroy" BORADCAST_DESTROY = "broadcast/destroy"
) )
const ( const (

View File

@ -175,7 +175,7 @@ func (h *MessageHandler) adminGive(id string, session types.Session, payload *me
ID: id, ID: id,
Target: payload.ID, Target: payload.ID,
}, nil); err != nil { }, nil); err != nil {
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.CONTROL_GIVE) h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.CONTROL_LOCKED)
return err return err
} }
@ -207,7 +207,7 @@ func (h *MessageHandler) adminMute(id string, session types.Session, payload *me
Target: target.ID(), Target: target.ID(),
ID: id, ID: id,
}, nil); err != nil { }, nil); err != nil {
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.ADMIN_MUTE) h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.ADMIN_UNMUTE)
return err return err
} }

View File

@ -6,7 +6,7 @@ import (
"m1k1o/neko/internal/types/message" "m1k1o/neko/internal/types/message"
) )
func (h *MessageHandler) broadcastCreate(session types.Session, payload *message.BroadcastCreate) error { func (h *MessageHandler) boradcastCreate(session types.Session, payload *message.BroadcastCreate) error {
broadcast := h.capture.Broadcast() broadcast := h.capture.Broadcast()
if !session.Admin() { if !session.Admin() {
@ -44,14 +44,14 @@ func (h *MessageHandler) broadcastCreate(session types.Session, payload *message
} }
} }
if err := h.broadcastStatus(nil); err != nil { if err := h.boradcastStatus(nil); err != nil {
return err return err
} }
return nil return nil
} }
func (h *MessageHandler) broadcastDestroy(session types.Session) error { func (h *MessageHandler) boradcastDestroy(session types.Session) error {
broadcast := h.capture.Broadcast() broadcast := h.capture.Broadcast()
if !session.Admin() { if !session.Admin() {
@ -70,18 +70,18 @@ func (h *MessageHandler) broadcastDestroy(session types.Session) error {
broadcast.Stop() broadcast.Stop()
if err := h.broadcastStatus(nil); err != nil { if err := h.boradcastStatus(nil); err != nil {
return err return err
} }
return nil return nil
} }
func (h *MessageHandler) broadcastStatus(session types.Session) error { func (h *MessageHandler) boradcastStatus(session types.Session) error {
broadcast := h.capture.Broadcast() broadcast := h.capture.Broadcast()
msg := message.BroadcastStatus{ msg := message.BroadcastStatus{
Event: event.BROADCAST_STATUS, Event: event.BORADCAST_STATUS,
IsActive: broadcast.Started(), IsActive: broadcast.Started(),
URL: broadcast.Url(), URL: broadcast.Url(),
} }
@ -89,7 +89,7 @@ func (h *MessageHandler) broadcastStatus(session types.Session) error {
// if no session, broadcast change // if no session, broadcast change
if session == nil { if session == nil {
if err := h.sessions.AdminBroadcast(msg, nil); err != nil { if err := h.sessions.AdminBroadcast(msg, nil); err != nil {
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.BROADCAST_STATUS) h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.BORADCAST_STATUS)
return err return err
} }
@ -102,7 +102,7 @@ func (h *MessageHandler) broadcastStatus(session types.Session) error {
} }
if err := session.Send(msg); err != nil { if err := session.Send(msg); err != nil {
h.logger.Warn().Err(err).Msgf("sending event %s has failed", event.BROADCAST_STATUS) h.logger.Warn().Err(err).Msgf("sending event %s has failed", event.BORADCAST_STATUS)
return err return err
} }

View File

@ -17,7 +17,7 @@ func (h *MessageHandler) chat(id string, session types.Session, payload *message
Content: payload.Content, Content: payload.Content,
ID: id, ID: id,
}, nil); err != nil { }, nil); err != nil {
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.CHAT_MESSAGE) h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.CONTROL_RELEASE)
return err return err
} }
return nil return nil
@ -34,7 +34,7 @@ func (h *MessageHandler) chatEmote(id string, session types.Session, payload *me
Emote: payload.Emote, Emote: payload.Emote,
ID: id, ID: id,
}, nil); err != nil { }, nil); err != nil {
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.CHAT_EMOTE) h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.CONTROL_RELEASE)
return err return err
} }
return nil return nil

View File

@ -115,7 +115,7 @@ func (h *MessageHandler) controlGive(id string, session types.Session, payload *
ID: id, ID: id,
Target: payload.ID, Target: payload.ID,
}, nil); err != nil { }, nil); err != nil {
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.CONTROL_GIVE) h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.CONTROL_LOCKED)
return err return err
} }

View File

@ -148,15 +148,15 @@ func (h *MessageHandler) Message(id string, raw []byte) error {
return h.screenSet(id, session, payload) return h.screenSet(id, session, payload)
}), "%s failed", header.Event) }), "%s failed", header.Event)
// Broadcast Events // Boradcast Events
case event.BROADCAST_CREATE: case event.BORADCAST_CREATE:
payload := &message.BroadcastCreate{} payload := &message.BroadcastCreate{}
return errors.Wrapf( return errors.Wrapf(
utils.Unmarshal(payload, raw, func() error { utils.Unmarshal(payload, raw, func() error {
return h.broadcastCreate(session, payload) return h.boradcastCreate(session, payload)
}), "%s failed", header.Event) }), "%s failed", header.Event)
case event.BROADCAST_DESTROY: case event.BORADCAST_DESTROY:
return errors.Wrapf(h.broadcastDestroy(session), "%s failed", header.Event) return errors.Wrapf(h.boradcastDestroy(session), "%s failed", header.Event)
// Admin Events // Admin Events
case event.ADMIN_LOCK: case event.ADMIN_LOCK:

View File

@ -30,7 +30,7 @@ func (h *MessageHandler) SessionCreated(id string, session types.Session) error
} }
// send broadcast status if admin // send broadcast status if admin
if err := h.broadcastStatus(session); err != nil { if err := h.boradcastStatus(session); err != nil {
return err return err
} }
} }
@ -78,7 +78,7 @@ func (h *MessageHandler) SessionConnected(id string, session types.Session) erro
Event: event.MEMBER_CONNECTED, Event: event.MEMBER_CONNECTED,
Member: session.Member(), Member: session.Member(),
}, nil); err != nil { }, nil); err != nil {
h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.MEMBER_CONNECTED) h.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.CONTROL_RELEASE)
return err return err
} }