Refactoring #3
+186
-140
@@ -99,6 +99,8 @@ func main() {
|
|||||||
// timelapse audio: 5fbec3b1-1b0f-417d-9059-8b94a47197ec
|
// timelapse audio: 5fbec3b1-1b0f-417d-9059-8b94a47197ec
|
||||||
// f1 video: 5fbec3b1-1b0f-417d-9059-8b94a47197ef
|
// f1 video: 5fbec3b1-1b0f-417d-9059-8b94a47197ef
|
||||||
// f1 audio: 5fbec3b1-1b0f-417d-9059-8b94a47197eb
|
// f1 audio: 5fbec3b1-1b0f-417d-9059-8b94a47197eb
|
||||||
|
// sync video: 2618979d-76a5-45e0-83cb-0f192978d1cd
|
||||||
|
// sync audio: 9d2a041b-01cf-4ee4-bffa-188fe093c99b
|
||||||
var args appArgs
|
var args appArgs
|
||||||
flagSet := pflag.NewFlagSet(APP_NAME, pflag.ContinueOnError)
|
flagSet := pflag.NewFlagSet(APP_NAME, pflag.ContinueOnError)
|
||||||
flagSet.SortFlags = false
|
flagSet.SortFlags = false
|
||||||
@@ -200,6 +202,19 @@ func main() {
|
|||||||
// ImGui init
|
// ImGui init
|
||||||
gui := imgui.New()
|
gui := imgui.New()
|
||||||
defer gui.Destroy()
|
defer gui.Destroy()
|
||||||
|
fontConfig := cimgui.NewFontConfig()
|
||||||
|
font := gui.IO().Fonts().AddFontFromFileTTFV(
|
||||||
|
"/home/itten/Downloads/JetBrainsMono/JetBrainsMonoNLNerdFontMono-Regular.ttf",
|
||||||
|
18,
|
||||||
|
fontConfig,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
fontConfig.Destroy()
|
||||||
|
if font == nil || font.CData == nil {
|
||||||
|
log.Fatal("failed to load ImGui font")
|
||||||
|
}
|
||||||
|
gui.IO().SetFontDefault(font)
|
||||||
|
// sdl keys handler
|
||||||
sdl.StartTextInput(windowHandler)
|
sdl.StartTextInput(windowHandler)
|
||||||
defer sdl.StopTextInput(windowHandler)
|
defer sdl.StopTextInput(windowHandler)
|
||||||
// fin on ImGui init
|
// fin on ImGui init
|
||||||
@@ -421,6 +436,12 @@ func main() {
|
|||||||
)
|
)
|
||||||
lastFrame = time.Now()
|
lastFrame = time.Now()
|
||||||
|
|
||||||
|
// ImGui
|
||||||
|
var (
|
||||||
|
settingWindowWidth float32 = 700
|
||||||
|
settingsWindowState bool = true
|
||||||
|
)
|
||||||
|
|
||||||
for running {
|
for running {
|
||||||
frameStart := time.Now()
|
frameStart := time.Now()
|
||||||
var event [128]byte
|
var event [128]byte
|
||||||
@@ -447,6 +468,8 @@ func main() {
|
|||||||
resized = true
|
resized = true
|
||||||
case sdl.KeyF1:
|
case sdl.KeyF1:
|
||||||
showStats = !showStats
|
showStats = !showStats
|
||||||
|
case sdl.KeyF2:
|
||||||
|
settingsWindowState = !settingsWindowState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gui.ProcessEvent(&event)
|
gui.ProcessEvent(&event)
|
||||||
@@ -523,8 +546,6 @@ func main() {
|
|||||||
// end of stats
|
// end of stats
|
||||||
if r != nil {
|
if r != nil {
|
||||||
gui.BeginFrame(time.Since(lastFrame), int32(r.Extent().Width), int32(r.Extent().Height))
|
gui.BeginFrame(time.Since(lastFrame), int32(r.Extent().Width), int32(r.Extent().Height))
|
||||||
// test widget
|
|
||||||
// cimgui.Begin("Test")
|
|
||||||
if showStats {
|
if showStats {
|
||||||
cimgui.SetNextWindowPos(cimgui.Vec2{X: 10, Y: 10})
|
cimgui.SetNextWindowPos(cimgui.Vec2{X: 10, Y: 10})
|
||||||
cimgui.SetNextWindowSize(cimgui.Vec2{X: 200, Y: 200})
|
cimgui.SetNextWindowSize(cimgui.Vec2{X: 200, Y: 200})
|
||||||
@@ -540,13 +561,9 @@ func main() {
|
|||||||
displayedVideoHeight,
|
displayedVideoHeight,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
cimgui.Text("\nPress F1 to hide stats")
|
|
||||||
cimgui.Text("Q or Esc to quit")
|
|
||||||
cimgui.Text("F for fullscreen")
|
|
||||||
cimgui.End()
|
cimgui.End()
|
||||||
}
|
}
|
||||||
cimgui.Begin("Connection")
|
// settings & info window
|
||||||
|
|
||||||
snapshot, hasSnapshot := player.Controller.Snapshot()
|
snapshot, hasSnapshot := player.Controller.Snapshot()
|
||||||
videoConfigured := videoStr != ""
|
videoConfigured := videoStr != ""
|
||||||
audioConfigured := audioStr != ""
|
audioConfigured := audioStr != ""
|
||||||
@@ -556,147 +573,176 @@ func main() {
|
|||||||
videoConfigured = snapshot.Desired.Video.IsConfigured()
|
videoConfigured = snapshot.Desired.Video.IsConfigured()
|
||||||
audioConfigured = snapshot.Desired.Audio.IsConfigured()
|
audioConfigured = snapshot.Desired.Audio.IsConfigured()
|
||||||
syncRequested = snapshot.Desired.SyncRequested
|
syncRequested = snapshot.Desired.SyncRequested
|
||||||
cimgui.Text(fmt.Sprintf(
|
|
||||||
"Topology: %s (generation %d)",
|
|
||||||
snapshot.Plan.Topology,
|
|
||||||
snapshot.Generation,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
cimgui.Text("Topology: starting")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cimgui.Separator()
|
drawSettingsContents := func() {
|
||||||
cimgui.InputTextWithHint("Video domain", "/dev/shm/mxl", &videoDomainStr, 0, nil)
|
var collapsingHeaderFlags cimgui.TreeNodeFlags = cimgui.TreeNodeFlagsDefaultOpen
|
||||||
cimgui.InputTextWithHint("Video UUID", "", &videoStr, 0, nil)
|
drawFeedsSections := func() {
|
||||||
cimgui.InputTextWithHint("Audio domain", "/dev/shm/mxl", &audioDomainStr, 0, nil)
|
cimgui.SeparatorText("Video")
|
||||||
cimgui.InputTextWithHint("Audio UUID", "", &audioStr, 0, nil)
|
cimgui.InputTextWithHint("Video domain", "/dev/shm/mxl", &videoDomainStr, 0, nil)
|
||||||
if cimgui.Button("Apply feeds") {
|
cimgui.InputTextWithHint("Video UUID", "", &videoStr, 0, nil)
|
||||||
doReconnect()
|
if videoActive {
|
||||||
}
|
cimgui.SameLine()
|
||||||
cimgui.SameLine()
|
if cimgui.Button("Stop##video") {
|
||||||
if videoActive || audioActive {
|
videoActive = false
|
||||||
if cimgui.Button("Stop all") {
|
enqueueCommand(playback.SessionCommand{Kind: playback.CommandStopVideo})
|
||||||
enqueueCommand(playback.SessionCommand{Kind: playback.CommandStopAll})
|
}
|
||||||
}
|
}
|
||||||
}
|
if !videoActive && videoConfigured {
|
||||||
if (videoConfigured && !videoActive) || (audioConfigured && !audioActive) {
|
cimgui.SameLine()
|
||||||
if videoActive || audioActive {
|
if cimgui.Button("Resume##video") {
|
||||||
|
videoActive = true
|
||||||
|
enqueueCommand(playback.SessionCommand{Kind: playback.CommandResumeVideo})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if videoConfigured {
|
||||||
|
cimgui.SameLine()
|
||||||
|
if cimgui.Button("Remove##video") {
|
||||||
|
videoActive = false
|
||||||
|
videoStr = ""
|
||||||
|
enqueueCommand(playback.SessionCommand{Kind: playback.CommandRemoveVideo})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cimgui.SeparatorText("Audio")
|
||||||
|
cimgui.InputTextWithHint("Audio domain", "/dev/shm/mxl", &audioDomainStr, 0, nil)
|
||||||
|
cimgui.InputTextWithHint("Audio UUID", "", &audioStr, 0, nil)
|
||||||
|
if audioActive {
|
||||||
|
cimgui.SameLine()
|
||||||
|
if cimgui.Button("Stop##audio") {
|
||||||
|
audioActive = false
|
||||||
|
enqueueCommand(playback.SessionCommand{Kind: playback.CommandStopAudio})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !audioActive && audioConfigured {
|
||||||
|
cimgui.SameLine()
|
||||||
|
if cimgui.Button("Resume##audio") {
|
||||||
|
audioActive = true
|
||||||
|
enqueueCommand(playback.SessionCommand{Kind: playback.CommandResumeAudio})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if audioConfigured {
|
||||||
|
cimgui.SameLine()
|
||||||
|
if cimgui.Button("Remove##audio") {
|
||||||
|
audioActive = false
|
||||||
|
audioStr = ""
|
||||||
|
enqueueCommand(playback.SessionCommand{Kind: playback.CommandRemoveAudio})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cimgui.SeparatorText("Controls")
|
||||||
|
if cimgui.Button("Apply feeds") {
|
||||||
|
doReconnect()
|
||||||
|
}
|
||||||
cimgui.SameLine()
|
cimgui.SameLine()
|
||||||
}
|
if videoActive || audioActive {
|
||||||
if cimgui.Button("Resume all") {
|
if cimgui.Button("Stop all") {
|
||||||
enqueueCommand(playback.SessionCommand{Kind: playback.CommandResumeAll})
|
enqueueCommand(playback.SessionCommand{Kind: playback.CommandStopAll})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if cimgui.Checkbox("Synchronize", &syncRequested) {
|
|
||||||
kind := playback.CommandDisableSync
|
|
||||||
if syncRequested {
|
|
||||||
kind = playback.CommandEnableSync
|
|
||||||
}
|
|
||||||
enqueueCommand(playback.SessionCommand{Kind: kind})
|
|
||||||
}
|
|
||||||
if hasSnapshot && syncRequested && snapshot.Plan.Topology != playback.TopologySynchronized {
|
|
||||||
switch {
|
|
||||||
case !videoConfigured || !audioConfigured:
|
|
||||||
cimgui.TextWrapped("Sync requested: waiting for both feeds to be configured.")
|
|
||||||
case !videoActive || !audioActive:
|
|
||||||
cimgui.TextWrapped("Sync requested: waiting for both feeds to be active.")
|
|
||||||
case snapshot.Desired.Video.Domain != snapshot.Desired.Audio.Domain:
|
|
||||||
cimgui.TextWrapped("Sync requested, but native MXL sync requires matching domains. Playing independently.")
|
|
||||||
default:
|
|
||||||
cimgui.TextWrapped("Sync requested but currently unavailable. Playing independently.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cimgui.Separator()
|
|
||||||
cimgui.Text("Video")
|
|
||||||
if videoActive {
|
|
||||||
if cimgui.Button("Stop video") {
|
|
||||||
videoActive = false
|
|
||||||
enqueueCommand(playback.SessionCommand{Kind: playback.CommandStopVideo})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !videoActive && videoConfigured {
|
|
||||||
cimgui.SameLine()
|
|
||||||
if cimgui.Button("Resume video") {
|
|
||||||
videoActive = true
|
|
||||||
enqueueCommand(playback.SessionCommand{Kind: playback.CommandResumeVideo})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if videoConfigured {
|
|
||||||
cimgui.SameLine()
|
|
||||||
if cimgui.Button("Remove video") {
|
|
||||||
videoActive = false
|
|
||||||
videoStr = ""
|
|
||||||
enqueueCommand(playback.SessionCommand{Kind: playback.CommandRemoveVideo})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if videoActive {
|
|
||||||
cimgui.Text("Video desired: active")
|
|
||||||
} else if videoConfigured {
|
|
||||||
cimgui.Text("Video desired: stopped")
|
|
||||||
} else {
|
|
||||||
cimgui.Text("Video desired: not configured")
|
|
||||||
}
|
|
||||||
|
|
||||||
cimgui.Separator()
|
|
||||||
cimgui.Text("Audio")
|
|
||||||
if audioActive {
|
|
||||||
if cimgui.Button("Stop audio") {
|
|
||||||
audioActive = false
|
|
||||||
enqueueCommand(playback.SessionCommand{Kind: playback.CommandStopAudio})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !audioActive && audioConfigured {
|
|
||||||
cimgui.SameLine()
|
|
||||||
if cimgui.Button("Resume audio") {
|
|
||||||
audioActive = true
|
|
||||||
enqueueCommand(playback.SessionCommand{Kind: playback.CommandResumeAudio})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if audioConfigured {
|
|
||||||
cimgui.SameLine()
|
|
||||||
if cimgui.Button("Remove audio") {
|
|
||||||
audioActive = false
|
|
||||||
audioStr = ""
|
|
||||||
enqueueCommand(playback.SessionCommand{Kind: playback.CommandRemoveAudio})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if audioActive {
|
|
||||||
cimgui.Text("Audio desired: active")
|
|
||||||
} else if audioConfigured {
|
|
||||||
cimgui.Text("Audio desired: stopped")
|
|
||||||
} else {
|
|
||||||
cimgui.Text("Audio desired: not configured")
|
|
||||||
}
|
|
||||||
|
|
||||||
cimgui.Separator()
|
|
||||||
cimgui.Text("Current playback")
|
|
||||||
if hasSnapshot {
|
|
||||||
switch snapshot.Plan.Topology {
|
|
||||||
case playback.TopologySynchronized:
|
|
||||||
drawUnitStatus("Synchronized group", playback.UnitSync)
|
|
||||||
case playback.TopologyIndependent:
|
|
||||||
if snapshot.Plan.Video.Active {
|
|
||||||
drawUnitStatus("Video", playback.UnitVideo)
|
|
||||||
}
|
}
|
||||||
if snapshot.Plan.Audio.Active {
|
if (videoConfigured && !videoActive) || (audioConfigured && !audioActive) {
|
||||||
drawUnitStatus("Audio", playback.UnitAudio)
|
if videoActive || audioActive {
|
||||||
|
cimgui.SameLine()
|
||||||
|
}
|
||||||
|
if cimgui.Button("Resume all") {
|
||||||
|
enqueueCommand(playback.SessionCommand{Kind: playback.CommandResumeAll})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case playback.TopologyIdle:
|
cimgui.SameLine()
|
||||||
cimgui.Text("No active feeds")
|
if cimgui.Checkbox("Synchronize", &syncRequested) {
|
||||||
|
kind := playback.CommandDisableSync
|
||||||
|
if syncRequested {
|
||||||
|
kind = playback.CommandEnableSync
|
||||||
|
}
|
||||||
|
enqueueCommand(playback.SessionCommand{Kind: kind})
|
||||||
|
}
|
||||||
|
cimgui.SeparatorText("Feeds stats")
|
||||||
|
cimgui.Checkbox("Show stats", &showStats)
|
||||||
|
}
|
||||||
|
if cimgui.CollapsingHeaderTreeNodeFlagsV("Feeds", collapsingHeaderFlags) {
|
||||||
|
drawFeedsSections()
|
||||||
|
}
|
||||||
|
|
||||||
|
drawHotkeysSection := func() {
|
||||||
|
cimgui.Text("F1 - show/hide stats")
|
||||||
|
cimgui.Text("F2 - show/hide settings")
|
||||||
|
cimgui.Text("F - toggle fullscreen")
|
||||||
|
cimgui.Text("Q or Esc - quit")
|
||||||
|
}
|
||||||
|
if cimgui.CollapsingHeaderTreeNodeFlagsV("Hotkeys", collapsingHeaderFlags) {
|
||||||
|
drawHotkeysSection()
|
||||||
|
}
|
||||||
|
|
||||||
|
drawDebugSection := func() {
|
||||||
|
if hasSnapshot {
|
||||||
|
cimgui.Text(fmt.Sprintf(
|
||||||
|
"Topology: %s (generation %d)",
|
||||||
|
snapshot.Plan.Topology,
|
||||||
|
snapshot.Generation,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
cimgui.Text("Topology: starting")
|
||||||
|
}
|
||||||
|
if hasSnapshot && syncRequested && snapshot.Plan.Topology != playback.TopologySynchronized {
|
||||||
|
switch {
|
||||||
|
case !videoConfigured || !audioConfigured:
|
||||||
|
cimgui.TextWrapped("Sync requested: waiting for both feeds to be configured.")
|
||||||
|
case !videoActive || !audioActive:
|
||||||
|
cimgui.TextWrapped("Sync requested: waiting for both feeds to be active.")
|
||||||
|
case snapshot.Desired.Video.Domain != snapshot.Desired.Audio.Domain:
|
||||||
|
cimgui.TextWrapped("Sync requested, but native MXL sync requires matching domains. Playing independently.")
|
||||||
|
default:
|
||||||
|
cimgui.TextWrapped("Sync requested but currently unavailable. Playing independently.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cimgui.Separator()
|
||||||
|
cimgui.Text("Current playback")
|
||||||
|
if hasSnapshot {
|
||||||
|
switch snapshot.Plan.Topology {
|
||||||
|
case playback.TopologySynchronized:
|
||||||
|
drawUnitStatus("Synchronized group", playback.UnitSync)
|
||||||
|
case playback.TopologyIndependent:
|
||||||
|
if snapshot.Plan.Video.Active {
|
||||||
|
drawUnitStatus("Video", playback.UnitVideo)
|
||||||
|
}
|
||||||
|
if snapshot.Plan.Audio.Active {
|
||||||
|
drawUnitStatus("Audio", playback.UnitAudio)
|
||||||
|
}
|
||||||
|
case playback.TopologyIdle:
|
||||||
|
cimgui.Text("No active feeds")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cimgui.Text("Playback controller is starting")
|
||||||
|
}
|
||||||
|
cimgui.Separator()
|
||||||
|
if videoActive {
|
||||||
|
cimgui.Text("Video desired: active")
|
||||||
|
} else if videoConfigured {
|
||||||
|
cimgui.Text("Video desired: stopped")
|
||||||
|
} else {
|
||||||
|
cimgui.Text("Video desired: not configured")
|
||||||
|
}
|
||||||
|
if audioActive {
|
||||||
|
cimgui.Text("Audio desired: active")
|
||||||
|
} else if audioConfigured {
|
||||||
|
cimgui.Text("Audio desired: stopped")
|
||||||
|
} else {
|
||||||
|
cimgui.Text("Audio desired: not configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if cimgui.CollapsingHeaderTreeNodeFlagsV("Debug Info", collapsingHeaderFlags) {
|
||||||
|
drawDebugSection()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
cimgui.Text("Playback controller is starting")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cimgui.Separator()
|
if settingsWindowState {
|
||||||
cimgui.Checkbox("Show stats", &showStats)
|
cimgui.SetNextWindowPos(cimgui.Vec2{X: float32(r.Extent().Width) - settingWindowWidth, Y: 0})
|
||||||
|
cimgui.SetNextWindowSize(cimgui.Vec2{X: settingWindowWidth, Y: float32(r.Extent().Height)})
|
||||||
cimgui.End()
|
if cimgui.BeginV("Settings & Info", &settingsWindowState, cimgui.WindowFlagsNone) {
|
||||||
|
drawSettingsContents()
|
||||||
|
}
|
||||||
|
cimgui.End()
|
||||||
|
}
|
||||||
gui.EndFrame()
|
gui.EndFrame()
|
||||||
lastFrame = time.Now()
|
lastFrame = time.Now()
|
||||||
// end of test widget
|
// end of test widget
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[Window][Debug##Default]
|
[Window][Debug##Default]
|
||||||
Pos=60,60
|
Pos=519,181
|
||||||
Size=400,400
|
Size=400,398
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Test]
|
[Window][Test]
|
||||||
@@ -14,7 +14,27 @@ Size=200,200
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Connection]
|
[Window][Connection]
|
||||||
Pos=322,130
|
Pos=42,264
|
||||||
Size=661,444
|
Size=605,416
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Test slider]
|
||||||
|
Pos=1370,0
|
||||||
|
Size=550,1080
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Settings]
|
||||||
|
Pos=730,0
|
||||||
|
Size=550,720
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Settings & Info]
|
||||||
|
Pos=1220,0
|
||||||
|
Size=700,1080
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Seetings & Info]
|
||||||
|
Pos=1220,0
|
||||||
|
Size=700,1080
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const (
|
|||||||
KeyF uint32 = 0x66
|
KeyF uint32 = 0x66
|
||||||
KeyQ uint32 = 0x71
|
KeyQ uint32 = 0x71
|
||||||
KeyF1 uint32 = 0x4000003A
|
KeyF1 uint32 = 0x4000003A
|
||||||
|
KeyF2 uint32 = 0x4000003B
|
||||||
|
|
||||||
InitAudio uint32 = 0x00000010
|
InitAudio uint32 = 0x00000010
|
||||||
AudioDeviceDefaultPlayback uint32 = 0xFFFFFFFF
|
AudioDeviceDefaultPlayback uint32 = 0xFFFFFFFF
|
||||||
|
|||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
VIDEO_ID="2618979d-76a5-45e0-83cb-0f192978d1cd"
|
||||||
|
AUDIO_ID="9d2a041b-01cf-4ee4-bffa-188fe093c99b"
|
||||||
|
VIDEO_URI=$1
|
||||||
|
if [[ -z "${VIDEO_URI}" ]] then
|
||||||
|
VIDEO_URI="${HOME}/Videos/test-vid/motogp.ts"
|
||||||
|
fi
|
||||||
|
export GST_PLUGIN_PATH="${HOME}/.gst-plugin:${GST_PLUGIN_PATH}"
|
||||||
|
mxl-gst-looping-filesrc -d /dev/shm/mxl -i "${VIDEO_URI}" --video-id "${VIDEO_ID}" --audio-id "${AUDIO_ID}" 2>/dev/null
|
||||||
|
# sleep 5
|
||||||
|
# kill -9 $(pidof "mxl-gst-looping-filesrc")
|
||||||
|
# echo -e "\ngst-looping-filesrc killed"
|
||||||
Reference in New Issue
Block a user