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 { type appArgs struct {
ShowHelp bool ShowHelp bool
Domain string Domain string
VideoFlowId string VideoDomain string
AudioFlowId string AudioDomain string
IsFullscreen bool VideoFlowId string
PlaybackId uint32 AudioFlowId string
GpuId uint32 IsFullscreen bool
IsVerbose bool PlaybackId uint32
ListAudio bool GpuId uint32
ListGPU bool IsVerbose bool
ListAudio bool
ListGPU bool
SyncRequested bool
MaxAttempts int
} }
func printCliHelp(fs *pflag.FlagSet) { func printCliHelp(fs *pflag.FlagSet) {
BIN
View File
Binary file not shown.