mirror of
https://github.com/xaionaro-go/streamctl.git
synced 2025-11-01 11:22:33 +08:00
Initial commit, pt. 45
This commit is contained in:
@@ -126,7 +126,7 @@ func main() {
|
||||
cfg,
|
||||
_ui,
|
||||
func(ctx context.Context, c config.Config) error {
|
||||
return config.WriteConfigToPath(ctx, configPathExpanded, cfg)
|
||||
return config.WriteConfigToPath(ctx, configPathExpanded, c)
|
||||
},
|
||||
belt.CtxBelt(ctx),
|
||||
)
|
||||
|
||||
@@ -748,7 +748,7 @@ func (d *StreamD) StartStreamServer(
|
||||
return fmt.Errorf("unable to start stream server: %w", err)
|
||||
}
|
||||
|
||||
d.Config.StreamServer = d.StreamServer.Config
|
||||
logger.Tracef(ctx, "new StreamServer.Servers config == %#+v", d.Config.StreamServer.Servers)
|
||||
err = d.SaveConfig(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to save config: %w", err)
|
||||
@@ -789,7 +789,6 @@ func (d *StreamD) StopStreamServer(
|
||||
return fmt.Errorf("unable to stop server %#+v: %w", *srv, err)
|
||||
}
|
||||
|
||||
d.Config.StreamServer = d.StreamServer.Config
|
||||
err = d.SaveConfig(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to save the config: %w", err)
|
||||
@@ -859,7 +858,6 @@ func (d *StreamD) AddStreamDestination(
|
||||
return fmt.Errorf("unable to add stream destination server: %w", err)
|
||||
}
|
||||
|
||||
d.Config.StreamServer = d.StreamServer.Config
|
||||
err = d.SaveConfig(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to save the config: %w", err)
|
||||
@@ -883,7 +881,6 @@ func (d *StreamD) RemoveStreamDestination(
|
||||
return fmt.Errorf("unable to remove stream destination server: %w", err)
|
||||
}
|
||||
|
||||
d.Config.StreamServer = d.StreamServer.Config
|
||||
err = d.SaveConfig(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to save the config: %w", err)
|
||||
@@ -941,7 +938,6 @@ func (d *StreamD) AddStreamForward(
|
||||
return fmt.Errorf("unable to add the stream forwarding: %w", err)
|
||||
}
|
||||
|
||||
d.Config.StreamServer = d.StreamServer.Config
|
||||
err = d.SaveConfig(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to save the config: %w", err)
|
||||
@@ -970,7 +966,6 @@ func (d *StreamD) RemoveStreamForward(
|
||||
return fmt.Errorf("unable to remove the stream forwarding: %w", err)
|
||||
}
|
||||
|
||||
d.Config.StreamServer = d.StreamServer.Config
|
||||
err = d.SaveConfig(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to save the config: %w", err)
|
||||
|
||||
@@ -160,10 +160,22 @@ func (p *Panel) displayStreamServers(
|
||||
logger.Debugf(ctx, "displayStreamServers")
|
||||
defer logger.Debugf(ctx, "/displayStreamServers")
|
||||
|
||||
for _, srv := range streamServers {
|
||||
_ = srv
|
||||
}
|
||||
c := widget.NewList(
|
||||
func() int {
|
||||
return len(streamServers)
|
||||
},
|
||||
func() fyne.CanvasObject {
|
||||
return widget.NewLabel("")
|
||||
},
|
||||
func(idx widget.ListItemID, co fyne.CanvasObject) {
|
||||
o := co.(*widget.Label)
|
||||
srv := streamServers[idx]
|
||||
o.SetText(fmt.Sprintf("%s://%s", srv.Type, srv.ListenAddr))
|
||||
},
|
||||
)
|
||||
|
||||
p.streamServersWidget.RemoveAll()
|
||||
p.streamServersWidget.Add(c)
|
||||
}
|
||||
|
||||
func (p *Panel) openAddStreamWindow() {}
|
||||
|
||||
@@ -58,7 +58,7 @@ func New(
|
||||
err := ln.Close()
|
||||
errmon.ObserveErrorCtx(ctx, err)
|
||||
}()
|
||||
logger.Infof(ctx, "started RTMP server at %d", cfg.Listen)
|
||||
logger.Infof(ctx, "started RTMP server at %s", cfg.Listen)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
|
||||
@@ -72,7 +72,7 @@ func New(
|
||||
err := ln.Close()
|
||||
errmon.ObserveErrorCtx(ctx, err)
|
||||
}()
|
||||
logger.Infof(ctx, "started RTSP server at %d", cfg.ListenAddr)
|
||||
logger.Infof(ctx, "started RTSP server at %s", cfg.ListenAddr)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
type StreamServer struct {
|
||||
sync.Mutex
|
||||
Config types.Config
|
||||
Config *types.Config
|
||||
StreamHandler *streams.StreamHandler
|
||||
ServerHandlers []types.ServerHandler
|
||||
StreamDestinations []types.StreamDestination
|
||||
@@ -23,6 +23,12 @@ func New(cfg *types.Config) *StreamServer {
|
||||
if cfg == nil {
|
||||
cfg = &types.Config{}
|
||||
}
|
||||
if cfg.Streams == nil {
|
||||
cfg.Streams = map[types.StreamID]*types.StreamConfig{}
|
||||
}
|
||||
if cfg.Destinations == nil {
|
||||
cfg.Destinations = map[types.DestinationID]*types.DestinationConfig{}
|
||||
}
|
||||
s := streams.NewStreamHandler()
|
||||
|
||||
s.HandleFunc("rtmp", rtmpserver.StreamsHandle)
|
||||
@@ -37,35 +43,38 @@ func New(cfg *types.Config) *StreamServer {
|
||||
|
||||
return &StreamServer{
|
||||
StreamHandler: s,
|
||||
Config: *cfg,
|
||||
Config: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StreamServer) Init(ctx context.Context) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
cfg := s.Config
|
||||
|
||||
for _, srv := range cfg.Servers {
|
||||
err := s.StartServer(ctx, srv.Type, srv.Listen)
|
||||
err := s.startServer(ctx, srv.Type, srv.Listen)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to initialize %s server at %s: %w", srv.Type, srv.Listen, err)
|
||||
}
|
||||
}
|
||||
|
||||
for dstID, dstCfg := range cfg.Destinations {
|
||||
err := s.AddStreamDestination(ctx, dstID, dstCfg.URL)
|
||||
err := s.addStreamDestination(ctx, dstID, dstCfg.URL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to initialize stream destination '%s' to %#+v: %w", dstID, dstCfg, err)
|
||||
}
|
||||
}
|
||||
|
||||
for streamID, streamCfg := range cfg.Streams {
|
||||
err := s.AddIncomingStream(ctx, streamID)
|
||||
err := s.addIncomingStream(ctx, streamID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to initialize stream '%s': %w", streamID, err)
|
||||
}
|
||||
|
||||
for _, fwd := range streamCfg.Forwardings {
|
||||
err := s.AddStreamForward(ctx, streamID, fwd)
|
||||
err := s.addStreamForward(ctx, streamID, fwd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to launch stream forward from '%s' to '%s': %w", streamID, fwd, err)
|
||||
}
|
||||
@@ -89,6 +98,24 @@ func (s *StreamServer) StartServer(
|
||||
ctx context.Context,
|
||||
serverType types.ServerType,
|
||||
listenAddr string,
|
||||
) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
err := s.startServer(ctx, serverType, listenAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Config.Servers = append(s.Config.Servers, types.Server{
|
||||
Type: serverType,
|
||||
Listen: listenAddr,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StreamServer) startServer(
|
||||
ctx context.Context,
|
||||
serverType types.ServerType,
|
||||
listenAddr string,
|
||||
) error {
|
||||
var srv types.ServerHandler
|
||||
var err error
|
||||
@@ -108,13 +135,7 @@ func (s *StreamServer) StartServer(
|
||||
return err
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.ServerHandlers = append(s.ServerHandlers, srv)
|
||||
s.Config.Servers = append(s.Config.Servers, types.Server{
|
||||
Type: serverType,
|
||||
Listen: listenAddr,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -136,6 +157,12 @@ func (s *StreamServer) StopServer(
|
||||
) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
for idx, srv := range s.Config.Servers {
|
||||
if srv.Listen == server.ListenAddr() {
|
||||
s.Config.Servers = append(s.Config.Servers[:idx], s.Config.Servers[idx+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
return s.stopServer(ctx, server)
|
||||
}
|
||||
|
||||
@@ -143,13 +170,6 @@ func (s *StreamServer) stopServer(
|
||||
ctx context.Context,
|
||||
server types.ServerHandler,
|
||||
) error {
|
||||
for idx, srv := range s.Config.Servers {
|
||||
if srv.Listen == server.ListenAddr() {
|
||||
s.Config.Servers = append(s.Config.Servers[:idx], s.Config.Servers[idx+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
idx, err := s.findServer(ctx, server)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -165,7 +185,12 @@ func (s *StreamServer) AddIncomingStream(
|
||||
) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.addIncomingStream(ctx, streamID)
|
||||
err := s.addIncomingStream(ctx, streamID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Config.Streams[streamID] = &types.StreamConfig{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StreamServer) addIncomingStream(
|
||||
@@ -179,7 +204,6 @@ func (s *StreamServer) addIncomingStream(
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the stream '%s': %w", streamID, err)
|
||||
}
|
||||
s.Config.Streams[streamID] = &types.StreamConfig{}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -216,6 +240,7 @@ func (s *StreamServer) RemoveIncomingStream(
|
||||
) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
delete(s.Config.Streams, streamID)
|
||||
return s.removeIncomingStream(ctx, streamID)
|
||||
}
|
||||
|
||||
@@ -227,7 +252,6 @@ func (s *StreamServer) removeIncomingStream(
|
||||
return fmt.Errorf("stream '%s' does not exist", streamID)
|
||||
}
|
||||
s.StreamHandler.Delete(string(streamID))
|
||||
delete(s.Config.Streams, streamID)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -243,7 +267,13 @@ func (s *StreamServer) AddStreamForward(
|
||||
) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.addStreamForward(ctx, streamID, destinationID)
|
||||
err := s.addStreamForward(ctx, streamID, destinationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
streamConfig := s.Config.Streams[streamID]
|
||||
streamConfig.Forwardings = append(streamConfig.Forwardings, destinationID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StreamServer) addStreamForward(
|
||||
@@ -263,8 +293,6 @@ func (s *StreamServer) addStreamForward(
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to start publishing '%s' to '%s': %w", streamID, dst.URL, err)
|
||||
}
|
||||
streamConfig := s.Config.Streams[streamID]
|
||||
streamConfig.Forwardings = append(streamConfig.Forwardings, destinationID)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -307,14 +335,6 @@ func (s *StreamServer) RemoveStreamForward(
|
||||
) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.removeStreamForward(ctx, streamID, dstID)
|
||||
}
|
||||
|
||||
func (s *StreamServer) removeStreamForward(
|
||||
ctx context.Context,
|
||||
streamID types.StreamID,
|
||||
dstID types.DestinationID,
|
||||
) error {
|
||||
streamCfg := s.Config.Streams[streamID]
|
||||
for idx, _dstID := range streamCfg.Forwardings {
|
||||
if _dstID != dstID {
|
||||
@@ -323,7 +343,14 @@ func (s *StreamServer) removeStreamForward(
|
||||
streamCfg.Forwardings = append(streamCfg.Forwardings[:idx], streamCfg.Forwardings[idx+1:]...)
|
||||
break
|
||||
}
|
||||
return s.removeStreamForward(ctx, streamID, dstID)
|
||||
}
|
||||
|
||||
func (s *StreamServer) removeStreamForward(
|
||||
ctx context.Context,
|
||||
streamID types.StreamID,
|
||||
dstID types.DestinationID,
|
||||
) error {
|
||||
stream := s.StreamHandler.Get(string(streamID))
|
||||
if stream == nil {
|
||||
return fmt.Errorf("unable to find a source stream with ID '%s'", streamID)
|
||||
@@ -370,7 +397,12 @@ func (s *StreamServer) AddStreamDestination(
|
||||
) error {
|
||||
s.Mutex.Lock()
|
||||
defer s.Mutex.Unlock()
|
||||
return s.addStreamDestination(ctx, destinationID, url)
|
||||
err := s.addStreamDestination(ctx, destinationID, url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Config.Destinations[destinationID] = &types.DestinationConfig{URL: url}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StreamServer) addStreamDestination(
|
||||
@@ -382,7 +414,6 @@ func (s *StreamServer) addStreamDestination(
|
||||
ID: destinationID,
|
||||
URL: url,
|
||||
})
|
||||
s.Config.Destinations[destinationID] = &types.DestinationConfig{URL: url}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -392,7 +423,23 @@ func (s *StreamServer) RemoveStreamDestination(
|
||||
) error {
|
||||
s.Mutex.Lock()
|
||||
defer s.Mutex.Unlock()
|
||||
for _, streamCfg := range s.Config.Streams {
|
||||
for fIdx, destID := range streamCfg.Forwardings {
|
||||
if destID != destinationID {
|
||||
continue
|
||||
}
|
||||
streamCfg.Forwardings = append(streamCfg.Forwardings[:fIdx], streamCfg.Forwardings[fIdx+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
delete(s.Config.Destinations, destinationID)
|
||||
return s.removeStreamDestination(ctx, destinationID)
|
||||
}
|
||||
|
||||
func (s *StreamServer) removeStreamDestination(
|
||||
ctx context.Context,
|
||||
destinationID types.DestinationID,
|
||||
) error {
|
||||
streamForwards, err := s.listStreamForwards(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to list stream forwardings: %w", err)
|
||||
@@ -403,8 +450,6 @@ func (s *StreamServer) RemoveStreamDestination(
|
||||
}
|
||||
}
|
||||
|
||||
delete(s.Config.Destinations, destinationID)
|
||||
|
||||
for i := range s.StreamDestinations {
|
||||
if s.StreamDestinations[i].ID == destinationID {
|
||||
s.StreamDestinations = append(s.StreamDestinations[:i], s.StreamDestinations[i+1:]...)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/goccy/go-yaml"
|
||||
)
|
||||
|
||||
type ServerType int
|
||||
@@ -11,6 +14,7 @@ const (
|
||||
ServerTypeUndefined = ServerType(iota)
|
||||
ServerTypeRTMP
|
||||
ServerTypeRTSP
|
||||
endOfServerType
|
||||
)
|
||||
|
||||
func (t ServerType) String() string {
|
||||
@@ -26,6 +30,54 @@ func (t ServerType) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (t ServerType) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(t.String())
|
||||
}
|
||||
|
||||
func ParseServerType(s string) (ServerType, error) {
|
||||
for c := ServerTypeUndefined; c < endOfServerType; c++ {
|
||||
if c.String() == s {
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
|
||||
return ServerTypeUndefined, fmt.Errorf("unexpected server type value '%s'", s)
|
||||
}
|
||||
|
||||
func (t *ServerType) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
err := json.Unmarshal(b, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := ParseServerType(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*t = c
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t ServerType) MarshalYAML() ([]byte, error) {
|
||||
return yaml.Marshal(t.String())
|
||||
}
|
||||
|
||||
func (t *ServerType) UnmarshalYAML(b []byte) error {
|
||||
var s string
|
||||
err := yaml.Unmarshal(b, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := ParseServerType(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*t = c
|
||||
return nil
|
||||
}
|
||||
|
||||
type ServerHandler interface {
|
||||
io.Closer
|
||||
|
||||
|
||||
Reference in New Issue
Block a user