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)
}
})
}
}
+14 -10
View File
@@ -28,16 +28,20 @@ const (
)
type appArgs struct {
ShowHelp bool
Domain string
VideoFlowId string
AudioFlowId string
IsFullscreen bool
PlaybackId uint32
GpuId uint32
IsVerbose bool
ListAudio bool
ListGPU bool
ShowHelp bool
Domain string
VideoDomain string
AudioDomain string
VideoFlowId string
AudioFlowId string
IsFullscreen bool
PlaybackId uint32
GpuId uint32
IsVerbose bool
ListAudio bool
ListGPU bool
SyncRequested bool
MaxAttempts int
}
func printCliHelp(fs *pflag.FlagSet) {