Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 27dcbd1b40 | |||
| 8d400dab7a |
+53
-35
@@ -15,6 +15,7 @@ import (
|
|||||||
"mxl-player/internal/source"
|
"mxl-player/internal/source"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -109,6 +110,12 @@ func main() {
|
|||||||
flagSet.StringVarP(&args.Domain, "domain", "d", "", "MXL domain directory")
|
flagSet.StringVarP(&args.Domain, "domain", "d", "", "MXL domain directory")
|
||||||
flagSet.StringVarP(&args.VideoFlowId, "video", "v", "", "Video flow UUID")
|
flagSet.StringVarP(&args.VideoFlowId, "video", "v", "", "Video flow UUID")
|
||||||
flagSet.StringVarP(&args.AudioFlowId, "audio", "a", "", "Audio flow UUID")
|
flagSet.StringVarP(&args.AudioFlowId, "audio", "a", "", "Audio flow UUID")
|
||||||
|
flagSet.BoolVarP(
|
||||||
|
&args.SyncRequested,
|
||||||
|
"sync", "s",
|
||||||
|
false,
|
||||||
|
"Start configured audio and video as a synchronized group",
|
||||||
|
)
|
||||||
flagSet.IntVar(
|
flagSet.IntVar(
|
||||||
&args.MaxAttempts,
|
&args.MaxAttempts,
|
||||||
"max-attempts",
|
"max-attempts",
|
||||||
@@ -149,8 +156,10 @@ func main() {
|
|||||||
checkMXLargs(args)
|
checkMXLargs(args)
|
||||||
}
|
}
|
||||||
// path selection
|
// path selection
|
||||||
useVideoSlot := args.AudioFlowId == ""
|
useLegacySync := args.SyncRequested &&
|
||||||
useAudioSlot := args.AudioFlowId != "" && args.VideoFlowId == ""
|
args.VideoFlowId != "" &&
|
||||||
|
args.AudioFlowId != ""
|
||||||
|
useIndependentSlots := !useLegacySync
|
||||||
|
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
if err := sdl.Load(); err != nil {
|
if err := sdl.Load(); err != nil {
|
||||||
@@ -281,8 +290,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case args.VideoFlowId != "" && args.AudioFlowId != "":
|
case useLegacySync:
|
||||||
syncSrc, err = source.OpenSameDomainSync(args.Domain, args.VideoFlowId, args.AudioFlowId)
|
syncSrc, err = source.OpenSameDomainSync(
|
||||||
|
args.Domain,
|
||||||
|
args.VideoFlowId,
|
||||||
|
args.AudioFlowId,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("sync source: %v", err)
|
log.Fatalf("sync source: %v", err)
|
||||||
}
|
}
|
||||||
@@ -302,12 +315,9 @@ func main() {
|
|||||||
sdl.ResumeAudioStreamDevice(audioStream)
|
sdl.ResumeAudioStreamDevice(audioStream)
|
||||||
fmt.Printf("sync: video %dx%d audio %dch batch=%d\n",
|
fmt.Printf("sync: video %dx%d audio %dch batch=%d\n",
|
||||||
syncSrc.Width(), syncSrc.Height(), aChans, audioBatch)
|
syncSrc.Width(), syncSrc.Height(), aChans, audioBatch)
|
||||||
case args.VideoFlowId != "":
|
|
||||||
// VideoSlot owns opening and closing the video reader.
|
|
||||||
case args.AudioFlowId != "":
|
|
||||||
// AudioSlot owns opening and closing the audio reader.
|
|
||||||
default:
|
default:
|
||||||
// No configured feeds. Renderer and GUI use the placeholder.
|
// Independent slots own their readers.
|
||||||
|
// Empty startup opens nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -374,7 +384,7 @@ func main() {
|
|||||||
showStats bool = true
|
showStats bool = true
|
||||||
)
|
)
|
||||||
videoActive := args.VideoFlowId != ""
|
videoActive := args.VideoFlowId != ""
|
||||||
audioActive := useAudioSlot
|
audioActive := args.AudioFlowId != ""
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -535,34 +545,30 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
doReconnect := func() {
|
doReconnect := func() {
|
||||||
if useVideoSlot {
|
if useIndependentSlots {
|
||||||
videoActive = videoStr != ""
|
videoActive = videoStr != ""
|
||||||
|
audioActive = audioStr != ""
|
||||||
|
|
||||||
config := playback.FeedConfig{}
|
videoConfig := playback.FeedConfig{}
|
||||||
if videoStr != "" {
|
if videoStr != "" {
|
||||||
config = playback.FeedConfig{
|
videoConfig = playback.FeedConfig{
|
||||||
Domain: domainStr,
|
Domain: domainStr,
|
||||||
UUID: videoStr,
|
UUID: videoStr,
|
||||||
Active: true,
|
Active: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enqueueVideoConfig(config)
|
audioConfig := playback.FeedConfig{}
|
||||||
return
|
|
||||||
}
|
|
||||||
if useAudioSlot {
|
|
||||||
audioActive = audioStr != ""
|
|
||||||
|
|
||||||
config := playback.FeedConfig{}
|
|
||||||
if audioStr != "" {
|
if audioStr != "" {
|
||||||
config = playback.FeedConfig{
|
audioConfig = playback.FeedConfig{
|
||||||
Domain: domainStr,
|
Domain: domainStr,
|
||||||
UUID: audioStr,
|
UUID: audioStr,
|
||||||
Active: true,
|
Active: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enqueueAudioConfig(config)
|
enqueueVideoConfig(videoConfig)
|
||||||
|
enqueueAudioConfig(audioConfig)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// legacy
|
// legacy
|
||||||
@@ -577,7 +583,13 @@ func main() {
|
|||||||
go func() {
|
go func() {
|
||||||
defer close(playbackDone)
|
defer close(playbackDone)
|
||||||
|
|
||||||
if useVideoSlot {
|
if useIndependentSlots {
|
||||||
|
var slots sync.WaitGroup
|
||||||
|
slots.Add(2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer slots.Done()
|
||||||
|
|
||||||
err := videoSlot.Run(
|
err := videoSlot.Run(
|
||||||
ctx,
|
ctx,
|
||||||
playback.FeedConfig{
|
playback.FeedConfig{
|
||||||
@@ -590,9 +602,11 @@ func main() {
|
|||||||
if err != nil && !errors.Is(err, context.Canceled) {
|
if err != nil && !errors.Is(err, context.Canceled) {
|
||||||
log.Printf("video slot: %v", err)
|
log.Printf("video slot: %v", err)
|
||||||
}
|
}
|
||||||
return
|
}()
|
||||||
}
|
|
||||||
if useAudioSlot {
|
go func() {
|
||||||
|
defer slots.Done()
|
||||||
|
|
||||||
err := audioSlot.Run(
|
err := audioSlot.Run(
|
||||||
ctx,
|
ctx,
|
||||||
playback.FeedConfig{
|
playback.FeedConfig{
|
||||||
@@ -605,6 +619,10 @@ func main() {
|
|||||||
if err != nil && !errors.Is(err, context.Canceled) {
|
if err != nil && !errors.Is(err, context.Canceled) {
|
||||||
log.Printf("audio slot: %v", err)
|
log.Printf("audio slot: %v", err)
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-ctx.Done()
|
||||||
|
slots.Wait()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -926,12 +944,12 @@ func main() {
|
|||||||
cimgui.InputTextWithHint("Domain", "/dev/shm/mxl", &domainStr, 0, nil)
|
cimgui.InputTextWithHint("Domain", "/dev/shm/mxl", &domainStr, 0, nil)
|
||||||
cimgui.InputTextWithHint("Video UUID", "", &videoStr, 0, nil)
|
cimgui.InputTextWithHint("Video UUID", "", &videoStr, 0, nil)
|
||||||
cimgui.InputTextWithHint("Audio UUID", "", &audioStr, 0, nil)
|
cimgui.InputTextWithHint("Audio UUID", "", &audioStr, 0, nil)
|
||||||
cimgui.Checkbox("Show stats", &showStats)
|
|
||||||
if cimgui.Button("Connect") {
|
if cimgui.Button("Connect") {
|
||||||
doReconnect()
|
doReconnect()
|
||||||
}
|
}
|
||||||
if useVideoSlot && videoActive {
|
|
||||||
cimgui.SameLine()
|
cimgui.SameLine()
|
||||||
|
cimgui.Checkbox("Show stats", &showStats)
|
||||||
|
if useIndependentSlots && videoActive {
|
||||||
if cimgui.Button("Stop video") {
|
if cimgui.Button("Stop video") {
|
||||||
videoActive = false
|
videoActive = false
|
||||||
enqueueVideoConfig(
|
enqueueVideoConfig(
|
||||||
@@ -942,7 +960,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if useVideoSlot && !videoActive && videoStr != "" {
|
if useIndependentSlots && !videoActive && videoStr != "" {
|
||||||
cimgui.SameLine()
|
cimgui.SameLine()
|
||||||
if cimgui.Button("Resume video") {
|
if cimgui.Button("Resume video") {
|
||||||
videoActive = true
|
videoActive = true
|
||||||
@@ -953,14 +971,14 @@ func main() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if useVideoSlot && videoStr != "" {
|
if useIndependentSlots && videoStr != "" {
|
||||||
if cimgui.Button("Remove video") {
|
if cimgui.Button("Remove video") {
|
||||||
videoActive = false
|
videoActive = false
|
||||||
videoStr = ""
|
videoStr = ""
|
||||||
enqueueVideoConfig(playback.FeedConfig{})
|
enqueueVideoConfig(playback.FeedConfig{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if useVideoSlot {
|
if useIndependentSlots {
|
||||||
if videoActive {
|
if videoActive {
|
||||||
cimgui.Text("Video desired: active")
|
cimgui.Text("Video desired: active")
|
||||||
} else if videoStr != "" {
|
} else if videoStr != "" {
|
||||||
@@ -994,7 +1012,7 @@ func main() {
|
|||||||
cimgui.Text("Video actual: not started")
|
cimgui.Text("Video actual: not started")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if useAudioSlot && audioActive {
|
if useIndependentSlots && audioActive {
|
||||||
if cimgui.Button("Stop audio") {
|
if cimgui.Button("Stop audio") {
|
||||||
audioActive = false
|
audioActive = false
|
||||||
enqueueAudioConfig(playback.FeedConfig{
|
enqueueAudioConfig(playback.FeedConfig{
|
||||||
@@ -1005,7 +1023,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if useAudioSlot && !audioActive && audioStr != "" {
|
if useIndependentSlots && !audioActive && audioStr != "" {
|
||||||
if cimgui.Button("Resume audio") {
|
if cimgui.Button("Resume audio") {
|
||||||
audioActive = true
|
audioActive = true
|
||||||
enqueueAudioConfig(playback.FeedConfig{
|
enqueueAudioConfig(playback.FeedConfig{
|
||||||
@@ -1016,7 +1034,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if useAudioSlot && audioStr != "" {
|
if useIndependentSlots && audioStr != "" {
|
||||||
if cimgui.Button("Remove audio") {
|
if cimgui.Button("Remove audio") {
|
||||||
audioActive = false
|
audioActive = false
|
||||||
audioStr = ""
|
audioStr = ""
|
||||||
@@ -1024,7 +1042,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if useAudioSlot {
|
if useIndependentSlots {
|
||||||
if audioActive {
|
if audioActive {
|
||||||
cimgui.Text("Audio desired: active")
|
cimgui.Text("Audio desired: active")
|
||||||
} else if audioStr != "" {
|
} else if audioStr != "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user