map CLI arguments to playback config

This commit is contained in:
Dmitry Sergeev
2026-08-26 22:51:35 +03:00
parent 1b667dcdb3
commit 0b91a52b99
4 changed files with 194 additions and 10 deletions
+39
View File
@@ -0,0 +1,39 @@
package main
import (
"mxl-player/internal/playback"
"time"
)
const (
defaultInitialRetryDelay = 500 * time.Millisecond
defaultMaxRetryDelay = 10 * time.Second
)
func resolveDomain(shared, override string) string {
if override != "" {
return override
}
return shared
}
func (a appArgs) playbackConfig() playback.SessionConfig {
return playback.SessionConfig{
Video: playback.FeedConfig{
Domain: resolveDomain(a.Domain, a.VideoDomain),
UUID: a.VideoFlowId,
Active: a.VideoFlowId != "",
},
Audio: playback.FeedConfig{
Domain: resolveDomain(a.Domain, a.AudioDomain),
UUID: a.AudioFlowId,
Active: a.AudioFlowId != "",
},
SyncRequested: a.SyncRequested,
Retry: playback.RetryPolicy{
MaxAttempts: a.MaxAttempts,
InitialDelay: defaultInitialRetryDelay,
MaxDelay: defaultMaxRetryDelay,
},
}
}
+141
View File
@@ -0,0 +1,141 @@
package main
import "testing"
func TestAppArgsPlaybackConfig(t *testing.T) {
tests := []struct {
name string
args appArgs
wantVideoDomain string
wantAudioDomain string
wantVideoActive bool
wantAudioActive bool
wantSyncRequested bool
wantMaxAttempts int
}{
{
name: "shared domain applies to both feeds",
args: appArgs{
Domain: "/dev/shm/mxl",
VideoFlowId: "video-uuid",
AudioFlowId: "audio-uuid",
},
wantVideoDomain: "/dev/shm/mxl",
wantAudioDomain: "/dev/shm/mxl",
wantVideoActive: true,
wantAudioActive: true,
},
{
name: "video domain overrides shared domain",
args: appArgs{
Domain: "/dev/shm/default",
VideoDomain: "/dev/shm/video",
VideoFlowId: "video-uuid",
AudioFlowId: "audio-uuid",
},
wantVideoDomain: "/dev/shm/video",
wantAudioDomain: "/dev/shm/default",
wantVideoActive: true,
wantAudioActive: true,
},
{
name: "audio domain overrides shared domain",
args: appArgs{
Domain: "/dev/shm/default",
AudioDomain: "/dev/shm/audio",
VideoFlowId: "video-uuid",
AudioFlowId: "audio-uuid",
},
wantVideoDomain: "/dev/shm/default",
wantAudioDomain: "/dev/shm/audio",
wantVideoActive: true,
wantAudioActive: true,
},
{
name: "audio and video use different domain overrides",
args: appArgs{
Domain: "/dev/shm/default",
VideoDomain: "/dev/shm/video",
AudioDomain: "/dev/shm/audio",
VideoFlowId: "video-uuid",
AudioFlowId: "audio-uuid",
SyncRequested: true,
MaxAttempts: 5,
},
wantVideoDomain: "/dev/shm/video",
wantAudioDomain: "/dev/shm/audio",
wantVideoActive: true,
wantAudioActive: true,
wantSyncRequested: true,
wantMaxAttempts: 5,
},
{
name: "no UUIDs produce inactive slots",
args: appArgs{
Domain: "/dev/shm/mxl",
},
wantVideoDomain: "/dev/shm/mxl",
wantAudioDomain: "/dev/shm/mxl",
},
{
name: "video UUID activates only video",
args: appArgs{
Domain: "/dev/shm/mxl",
VideoFlowId: "video-uuid",
},
wantVideoDomain: "/dev/shm/mxl",
wantAudioDomain: "/dev/shm/mxl",
wantVideoActive: true,
},
{
name: "audio UUID activates only audio",
args: appArgs{
Domain: "/dev/shm/mxl",
AudioFlowId: "audio-uuid",
},
wantVideoDomain: "/dev/shm/mxl",
wantAudioDomain: "/dev/shm/mxl",
wantAudioActive: true,
},
{
name: "unlimited attempts and disabled sync are preserved",
args: appArgs{
Domain: "/dev/shm/mxl",
VideoFlowId: "video-uuid",
SyncRequested: false,
MaxAttempts: 0,
},
wantVideoDomain: "/dev/shm/mxl",
wantAudioDomain: "/dev/shm/mxl",
wantVideoActive: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.args.playbackConfig()
if got.Video.Domain != tt.wantVideoDomain {
t.Errorf("video domain = %q, want %q", got.Video.Domain, tt.wantVideoDomain)
}
if got.Audio.Domain != tt.wantAudioDomain {
t.Errorf("audio domain = %q, want %q", got.Audio.Domain, tt.wantAudioDomain)
}
if got.Video.Active != tt.wantVideoActive {
t.Errorf("video active = %t, want %t", got.Video.Active, tt.wantVideoActive)
}
if got.Audio.Active != tt.wantAudioActive {
t.Errorf("audio active = %t, want %t", got.Audio.Active, tt.wantAudioActive)
}
if got.SyncRequested != tt.wantSyncRequested {
t.Errorf("sync requested = %t, want %t", got.SyncRequested, tt.wantSyncRequested)
}
if got.Retry.MaxAttempts != tt.wantMaxAttempts {
t.Errorf("max attempts = %d, want %d", got.Retry.MaxAttempts, tt.wantMaxAttempts)
}
if err := got.Validate(); err != nil {
t.Fatalf("playbackConfig().Validate() returned error: %v", err)
}
})
}
}
+4
View File
@@ -30,6 +30,8 @@ const (
type appArgs struct { type appArgs struct {
ShowHelp bool ShowHelp bool
Domain string Domain string
VideoDomain string
AudioDomain string
VideoFlowId string VideoFlowId string
AudioFlowId string AudioFlowId string
IsFullscreen bool IsFullscreen bool
@@ -38,6 +40,8 @@ type appArgs struct {
IsVerbose bool IsVerbose bool
ListAudio bool ListAudio bool
ListGPU bool ListGPU bool
SyncRequested bool
MaxAttempts int
} }
func printCliHelp(fs *pflag.FlagSet) { func printCliHelp(fs *pflag.FlagSet) {
BIN
View File
Binary file not shown.