GUI fields now trim leading and trailing whitespace:
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"mxl-player/internal/playback"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -17,6 +18,10 @@ func resolveDomain(shared, override string) string {
|
||||
return shared
|
||||
}
|
||||
|
||||
func normalizeFeedInput(domain, uuid string) (string, string) {
|
||||
return strings.TrimSpace(domain), strings.TrimSpace(uuid)
|
||||
}
|
||||
|
||||
func resolveRetryPolicy(
|
||||
cli playback.RetryPolicy,
|
||||
cliMaxAttemptsSet bool,
|
||||
|
||||
@@ -183,3 +183,16 @@ func TestResolveRetryPolicy(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeFeedInput(t *testing.T) {
|
||||
domain, uuid := normalizeFeedInput(
|
||||
" \t/dev/shm/mxl\n",
|
||||
"\r 5fbec3b1-1b0f-417d-9059-8b94a47197ef \t",
|
||||
)
|
||||
if domain != "/dev/shm/mxl" {
|
||||
t.Fatalf("domain = %q", domain)
|
||||
}
|
||||
if uuid != "5fbec3b1-1b0f-417d-9059-8b94a47197ef" {
|
||||
t.Fatalf("UUID = %q", uuid)
|
||||
}
|
||||
}
|
||||
|
||||
+28
-1
@@ -22,7 +22,7 @@ import (
|
||||
|
||||
const (
|
||||
APP_NAME = "MXL Player"
|
||||
APP_VER = "0.1.0"
|
||||
APP_VER = "1.0.0"
|
||||
WIN_WIDTH int32 = 1280
|
||||
WIN_HEIGHT int32 = 720
|
||||
)
|
||||
@@ -377,6 +377,8 @@ func main() {
|
||||
}
|
||||
}
|
||||
doReconnect := func() {
|
||||
videoDomainStr, videoStr = normalizeFeedInput(videoDomainStr, videoStr)
|
||||
audioDomainStr, audioStr = normalizeFeedInput(audioDomainStr, audioStr)
|
||||
videoActive = videoStr != ""
|
||||
audioActive = audioStr != ""
|
||||
|
||||
@@ -470,6 +472,8 @@ func main() {
|
||||
displayedVideoWidth uint32 = placeholderWidth
|
||||
displayedVideoHeight uint32 = placeholderHeight
|
||||
displayedVideoStride uint32 = placeholderStride
|
||||
displayedVideoSource playback.FeedConfig
|
||||
hasDisplayedVideo bool
|
||||
|
||||
fps float64
|
||||
dropTracker videoDropTracker
|
||||
@@ -575,6 +579,16 @@ func main() {
|
||||
}
|
||||
|
||||
snapshot, hasSnapshot := player.Controller.Snapshot()
|
||||
desiredVideo := desiredVideoFeed(snapshot, hasSnapshot)
|
||||
if !desiredVideo.Active ||
|
||||
desiredVideo.Domain != displayedVideoSource.Domain ||
|
||||
desiredVideo.UUID != displayedVideoSource.UUID {
|
||||
hasDisplayedVideo = false
|
||||
}
|
||||
if hasFrame {
|
||||
displayedVideoSource = shownSource
|
||||
hasDisplayedVideo = shouldShowVideo(desiredVideo, shownSource)
|
||||
}
|
||||
|
||||
// stats
|
||||
if hasFrame {
|
||||
@@ -722,7 +736,13 @@ func main() {
|
||||
drawFeedsSections := func() {
|
||||
cimgui.SeparatorText("Video")
|
||||
cimgui.InputTextWithHint("Video domain", "/dev/shm/mxl", &videoDomainStr, 0, nil)
|
||||
if cimgui.IsItemDeactivatedAfterEdit() {
|
||||
videoDomainStr, _ = normalizeFeedInput(videoDomainStr, "")
|
||||
}
|
||||
cimgui.InputTextWithHint("Video UUID", "", &videoStr, 0, nil)
|
||||
if cimgui.IsItemDeactivatedAfterEdit() {
|
||||
_, videoStr = normalizeFeedInput("", videoStr)
|
||||
}
|
||||
if videoActive {
|
||||
cimgui.SameLine()
|
||||
if cimgui.Button("Stop##video") {
|
||||
@@ -747,7 +767,13 @@ func main() {
|
||||
}
|
||||
cimgui.SeparatorText("Audio")
|
||||
cimgui.InputTextWithHint("Audio domain", "/dev/shm/mxl", &audioDomainStr, 0, nil)
|
||||
if cimgui.IsItemDeactivatedAfterEdit() {
|
||||
audioDomainStr, _ = normalizeFeedInput(audioDomainStr, "")
|
||||
}
|
||||
cimgui.InputTextWithHint("Audio UUID", "", &audioStr, 0, nil)
|
||||
if cimgui.IsItemDeactivatedAfterEdit() {
|
||||
_, audioStr = normalizeFeedInput("", audioStr)
|
||||
}
|
||||
if audioActive {
|
||||
cimgui.SameLine()
|
||||
if cimgui.Button("Stop##audio") {
|
||||
@@ -1062,6 +1088,7 @@ func main() {
|
||||
displayedVideoWidth,
|
||||
displayedVideoHeight,
|
||||
displayedVideoStride,
|
||||
hasDisplayedVideo,
|
||||
)
|
||||
if errors.Is(err, renderer.ErrOutOfDate) {
|
||||
if rerr := r.RecreateSwapchain(); rerr != nil {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import "mxl-player/internal/playback"
|
||||
|
||||
func desiredVideoFeed(
|
||||
snapshot playback.SessionSnapshot,
|
||||
available bool,
|
||||
) playback.FeedConfig {
|
||||
if !available {
|
||||
return playback.FeedConfig{}
|
||||
}
|
||||
switch snapshot.Plan.Topology {
|
||||
case playback.TopologyIndependent:
|
||||
if snapshot.Plan.Video.Active {
|
||||
return snapshot.Plan.Video
|
||||
}
|
||||
case playback.TopologySynchronized:
|
||||
if snapshot.Plan.Sync.Active() {
|
||||
return snapshot.Plan.Sync.Video
|
||||
}
|
||||
}
|
||||
return playback.FeedConfig{}
|
||||
}
|
||||
|
||||
func shouldShowVideo(
|
||||
desired playback.FeedConfig,
|
||||
delivered playback.FeedConfig,
|
||||
) bool {
|
||||
return desired.Active && sameVideoSource(desired, delivered)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"mxl-player/internal/playback"
|
||||
)
|
||||
|
||||
func TestDesiredVideoFeed(t *testing.T) {
|
||||
video := playback.FeedConfig{Domain: "/video", UUID: "video", Active: true}
|
||||
tests := []struct {
|
||||
name string
|
||||
available bool
|
||||
plan playback.SessionPlan
|
||||
want playback.FeedConfig
|
||||
}{
|
||||
{name: "snapshot unavailable"},
|
||||
{name: "idle", available: true, plan: playback.SessionPlan{Topology: playback.TopologyIdle}},
|
||||
{name: "audio only", available: true, plan: playback.SessionPlan{Topology: playback.TopologyIndependent}},
|
||||
{name: "independent video", available: true, plan: playback.SessionPlan{Topology: playback.TopologyIndependent, Video: video}, want: video},
|
||||
{name: "synchronized video", available: true, plan: playback.SessionPlan{Topology: playback.TopologySynchronized, Sync: playback.SyncPairConfig{Video: video, Audio: playback.FeedConfig{Active: true}}}, want: video},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got := desiredVideoFeed(playback.SessionSnapshot{Plan: test.plan}, test.available)
|
||||
if got != test.want {
|
||||
t.Fatalf("desiredVideoFeed() = %#v, want %#v", got, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldShowVideoRequiresDesiredSource(t *testing.T) {
|
||||
desired := playback.FeedConfig{Domain: "/video", UUID: "video", Active: true}
|
||||
if !shouldShowVideo(desired, desired) {
|
||||
t.Fatal("matching active video was hidden")
|
||||
}
|
||||
if shouldShowVideo(playback.FeedConfig{}, desired) {
|
||||
t.Fatal("video was shown without an active desired feed")
|
||||
}
|
||||
other := desired
|
||||
other.UUID = "other"
|
||||
if shouldShowVideo(desired, other) {
|
||||
t.Fatal("frame from old source was shown")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user