diff --git a/domain/types.go b/domain/types.go index ffb7a11..337f7ce 100644 --- a/domain/types.go +++ b/domain/types.go @@ -4,4 +4,5 @@ package domain type AppState struct { ContainerRunning bool IngressLive bool + IngressURL string } diff --git a/main.go b/main.go index ea8170f..513ad8f 100644 --- a/main.go +++ b/main.go @@ -43,7 +43,7 @@ func run(ctx context.Context) error { if err != nil { return fmt.Errorf("start media server: %w", err) } - state.ContainerRunning = true + applyServerState(srv.State(), state) ui, err := terminal.StartActor(ctx, terminal.StartActorParams{Logger: logger.With("component", "ui")}) if err != nil { @@ -61,8 +61,7 @@ func run(ctx context.Context) error { return nil case serverState, ok := <-srv.C(): if ok { - state.ContainerRunning = serverState.ContainerRunning - state.IngressLive = serverState.IngressLive + applyServerState(serverState, state) updateUI() } else { logger.Info("State channel closed, shutting down...") @@ -71,3 +70,9 @@ func run(ctx context.Context) error { } } } + +func applyServerState(serverState mediaserver.State, appState *domain.AppState) { + appState.ContainerRunning = serverState.ContainerRunning + appState.IngressLive = serverState.IngressLive + appState.IngressURL = serverState.IngressURL +} diff --git a/mediaserver/actor.go b/mediaserver/actor.go index 3644072..bc5f4f4 100644 --- a/mediaserver/actor.go +++ b/mediaserver/actor.go @@ -13,12 +13,16 @@ import ( "git.netflux.io/rob/termstream/container" ) -const imageNameMediaMTX = "bluenviron/mediamtx" +const ( + imageNameMediaMTX = "bluenviron/mediamtx" + rtmpPath = "live" +) // State contains the current state of the media server. type State struct { ContainerRunning bool IngressLive bool + IngressURL string } // action is an action to be performed by the actor. @@ -79,7 +83,9 @@ func StartActor(ctx context.Context, params StartActorParams) (*Actor, error) { if err != nil { return nil, fmt.Errorf("run container: %w", err) } + actor.state.ContainerRunning = true + actor.state.IngressURL = "rtmp://localhost:1935/" + rtmpPath go actor.actorLoop(containerDone) @@ -192,7 +198,7 @@ func (s *Actor) fetchIngressStateFromServer() (bool, error) { } for _, conn := range resp.Items { - if conn.Path == "live" && conn.State == "publish" { + if conn.Path == rtmpPath && conn.State == "publish" { return true, nil } } diff --git a/mediaserver/actor_test.go b/mediaserver/actor_test.go index 18774f3..fb17699 100644 --- a/mediaserver/actor_test.go +++ b/mediaserver/actor_test.go @@ -47,7 +47,10 @@ func TestMediaServerStartStop(t *testing.T) { "container not in RUNNING state", ) - require.False(t, actor.State().IngressLive) + state := actor.State() + assert.False(t, state.IngressLive) + assert.Equal(t, "rtmp://localhost:1935/live", state.IngressURL) + launchFFMPEG(t, "rtmp://localhost:1935/live") require.Eventually( t, diff --git a/terminal/actor.go b/terminal/actor.go index b5f08c4..3abb26c 100644 --- a/terminal/actor.go +++ b/terminal/actor.go @@ -48,7 +48,7 @@ func StartActor(ctx context.Context, params StartActorParams) (*Actor, error) { flex := tview.NewFlex(). SetDirection(tview.FlexRow). - AddItem(serverBox, 7, 0, false). + AddItem(serverBox, 9, 0, false). AddItem(destBox, 0, 1, false) container := tview.NewFlex(). @@ -127,20 +127,27 @@ func generateServerStatus(state domain.AppState) string { var s strings.Builder s.WriteString("\n") - s.WriteString("Container status: ") + + s.WriteString("[grey]Container status: ") if state.ContainerRunning { - s.WriteString("[green]running[white]") + s.WriteString("[green]running") } else { - s.WriteString("[red]stopped[white]") + s.WriteString("[red]stopped") } s.WriteString("\n\n") - s.WriteString("Ingress stream: ") - if state.IngressLive { - s.WriteString("[green]on-air[white]") - } else { - s.WriteString("[yellow]off-air[white]") + + s.WriteString("[grey]RTMP URL: ") + if state.IngressURL != "" { + s.WriteString("[white:grey]" + state.IngressURL) + } + s.WriteString("\n\n") + + s.WriteString("[grey:black]Ingress stream: ") + if state.IngressLive { + s.WriteString("[green]on-air") + } else { + s.WriteString("[yellow]off-air") } - s.WriteString("\n\n\n") return s.String() }