CLI args parse basic
This commit is contained in:
+84
-47
@@ -3,12 +3,13 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mxl-player/internal/renderer"
|
||||
"mxl-player/internal/sdl"
|
||||
"mxl-player/internal/source"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
"unsafe"
|
||||
@@ -25,7 +26,7 @@ const (
|
||||
WIN_HEIGHT int32 = 720
|
||||
)
|
||||
|
||||
type CliArgs struct {
|
||||
type appArgs struct {
|
||||
ShowHelp bool
|
||||
Domain string
|
||||
VideoFlowId string
|
||||
@@ -40,7 +41,7 @@ type CliArgs struct {
|
||||
|
||||
func printCliHelp(fs *pflag.FlagSet) {
|
||||
fmt.Printf("%s %s\n", APP_NAME, APP_VER)
|
||||
fmt.Println("Usage: mxl-player -d <domain> (-v <uuid> | -a <uuid>) [-f] [-h]...")
|
||||
fmt.Println("Usage: mxl-player -d <domain> (-v <uuid> | -a <uuid>) [-f] [-h]")
|
||||
fmt.Println(" [-g <gpu-id>] [-p <playback-id>] [--verbose]")
|
||||
fmt.Println(" or: mxl-player [--list-playback] [--list-gpu]")
|
||||
fmt.Println(" or: mxl-player (and set everything in GUI)")
|
||||
@@ -48,50 +49,62 @@ func printCliHelp(fs *pflag.FlagSet) {
|
||||
fs.PrintDefaults()
|
||||
}
|
||||
|
||||
func printUsage(w io.Writer) {
|
||||
fmt.Fprintln(w, "Usage: mxl-player -d <domain> (-v <uuid> | -a <uuid>) [-f] [-h]")
|
||||
fmt.Fprintln(w, "Try 'mxl-player -h' for more information.")
|
||||
}
|
||||
|
||||
func checkMXLargs(args appArgs) {
|
||||
if args.Domain == "" {
|
||||
fmt.Fprintln(os.Stderr, "You should provide valid MXL domain and UUID of at least one flow")
|
||||
printUsage(os.Stderr)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
fi, err := os.Stat(args.Domain)
|
||||
if err != nil || !fi.IsDir() {
|
||||
fmt.Fprintln(os.Stderr, "Invalid MXL domain:", args.Domain)
|
||||
fmt.Fprintln(os.Stderr, "Domain must be a directory in tmpfs")
|
||||
printUsage(os.Stderr)
|
||||
os.Exit(2)
|
||||
}
|
||||
if args.VideoFlowId == "" && args.AudioFlowId == "" {
|
||||
fmt.Fprintln(os.Stderr, "You must provide at least 1 MXL flow UUID")
|
||||
printUsage(os.Stderr)
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// CLI args TODO:
|
||||
// help + sample of good usage
|
||||
// domain (-d, --domain)
|
||||
// video flow UUID (-v, --video)
|
||||
// audio flow UUID (-a, --audio)
|
||||
// list-audio for list audio playback devices (-la, --list-playback)
|
||||
// list-video fpr list video playback devices (-lg, --list-gpu)
|
||||
// gpu-id for GPU selection (-p, --playback-id)
|
||||
// playback-id for playback id selection (-g, --gpu-id)
|
||||
// verbose flag, which turn on logs (-vb,--verbose)
|
||||
//
|
||||
// video: 5fbec3b1-1b0f-417d-9059-8b94a47197ed
|
||||
// audio: 5fbec3b1-1b0f-417d-9059-8b94a47197ec
|
||||
|
||||
var args CliArgs
|
||||
flagSet := pflag.NewFlagSet(APP_NAME, pflag.ExitOnError)
|
||||
var args appArgs
|
||||
flagSet := pflag.NewFlagSet(APP_NAME, pflag.ContinueOnError)
|
||||
flagSet.Usage = func() { printUsage(os.Stderr) }
|
||||
flagSet.BoolVarP(&args.ShowHelp, "help", "h", false, "Show help message and exit")
|
||||
flagSet.StringVarP(&args.Domain, "domain", "d", "", "MXL domain directory")
|
||||
flagSet.StringVarP(&args.VideoFlowId, "video", "v", "", "Video flow UUID")
|
||||
flagSet.StringVarP(&args.AudioFlowId, "audio", "a", "", "Audio flow UUID")
|
||||
flagSet.BoolVarP(&args.IsFullscreen, "fullscreen", "f", false, "Run app in fullscreen mode")
|
||||
flagSet.Uint32VarP(&args.GpuId, "gpu-id", "g", 0, "GPU id")
|
||||
flagSet.Uint32VarP(&args.GpuId, "gpu-id", "g", 0, "GPU id [TODO]")
|
||||
flagSet.Uint32VarP(&args.PlaybackId, "playback-id", "p", 0, "Playback audio device id")
|
||||
flagSet.BoolVar(&args.IsVerbose, "verbose", false, "Verbose output")
|
||||
flagSet.BoolVar(&args.IsVerbose, "verbose", false, "Verbose output [TODO]")
|
||||
flagSet.BoolVar(&args.ListAudio, "list-playback", false, "List audio playback devices and exit")
|
||||
flagSet.BoolVar(&args.ListGPU, "list-gpu", false, "List GPU's and exit")
|
||||
pflag.Parse()
|
||||
flagSet.BoolVar(&args.ListGPU, "list-gpu", false, "List GPUs and exit")
|
||||
|
||||
if args.Domain == "" || args.ShowHelp {
|
||||
// TODO. Fix after polishing GUI
|
||||
// Cause required/optional will be changed
|
||||
if err := flagSet.Parse(os.Args[1:]); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
printUsage(os.Stderr)
|
||||
os.Exit(2)
|
||||
}
|
||||
if args.ShowHelp {
|
||||
printCliHelp(flagSet)
|
||||
}
|
||||
return
|
||||
|
||||
var videoFlowId, audioFlowId string
|
||||
mxlDomain := flag.String("d", "/dev/shm/mxl", "MXL domain")
|
||||
mxlVideoFlowID := flag.String("v", videoFlowId, "MXL video flow UUID")
|
||||
mxlAudioFlowID := flag.String("a", audioFlowId, "MXL audio flow UUID")
|
||||
flag.Parse()
|
||||
if *mxlVideoFlowID == "" && *mxlAudioFlowID == "" {
|
||||
log.Fatal("need at least -v <video-flow> or -a <audio-flow>")
|
||||
}
|
||||
if !args.ListAudio && !args.ListGPU {
|
||||
checkMXLargs(args)
|
||||
}
|
||||
// end of cli args parse
|
||||
|
||||
runtime.LockOSThread()
|
||||
if err := sdl.Load(); err != nil {
|
||||
@@ -102,6 +115,21 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
sdlAudioDevice := sdl.AudioDeviceDefaultPlayback
|
||||
if args.PlaybackId != 0 {
|
||||
sdlAudioDevice = args.PlaybackId
|
||||
}
|
||||
// List audio playback devices and exit
|
||||
if args.ListAudio {
|
||||
devs := sdl.GetAudioPlaybackDevices()
|
||||
fmt.Println("Available playback audio devices")
|
||||
fmt.Println("id name")
|
||||
for _, d := range devs {
|
||||
fmt.Println(d.ID, d.Name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
windowHandler := sdl.CreateWindow(fmt.Sprintf("%s %s", APP_NAME, APP_VER), WIN_WIDTH, WIN_HEIGHT, sdl.WindowVulkan|sdl.WindowResizable)
|
||||
if windowHandler == 0 {
|
||||
sdl.Quit()
|
||||
@@ -144,9 +172,15 @@ func main() {
|
||||
if err != nil || len(devices) == 0 {
|
||||
panic("No Vulkan devices")
|
||||
}
|
||||
for _, pd := range devices {
|
||||
// List GPU's and exit
|
||||
if args.ListGPU {
|
||||
fmt.Println("Available Vulkan physical devices:")
|
||||
fmt.Println("id name (type)")
|
||||
for i, pd := range devices {
|
||||
info := pd.Info()
|
||||
fmt.Printf("%s (%s)\n", info.Name, info.Type)
|
||||
fmt.Printf("%2d %s (%s)\n", i, info.Name, info.Type)
|
||||
}
|
||||
return
|
||||
}
|
||||
vkPhysDevice := devices[0]
|
||||
|
||||
@@ -194,8 +228,8 @@ func main() {
|
||||
}
|
||||
|
||||
switch {
|
||||
case *mxlVideoFlowID != "" && *mxlAudioFlowID != "":
|
||||
syncSrc, err = source.OpenSync(*mxlDomain, *mxlVideoFlowID, *mxlAudioFlowID)
|
||||
case args.VideoFlowId != "" && args.AudioFlowId != "":
|
||||
syncSrc, err = source.OpenSync(args.Domain, args.VideoFlowId, args.AudioFlowId)
|
||||
if err != nil {
|
||||
log.Fatalf("sync source: %v", err)
|
||||
}
|
||||
@@ -204,7 +238,7 @@ func main() {
|
||||
if audioBatch == 0 {
|
||||
audioBatch = 1
|
||||
}
|
||||
audioStream = sdl.OpenAudioDeviceStream(sdl.AudioDeviceDefaultPlayback, sdl.AudioSpec{
|
||||
audioStream = sdl.OpenAudioDeviceStream(sdlAudioDevice, sdl.AudioSpec{
|
||||
Format: sdl.AudioF32,
|
||||
Channels: int32(aChans),
|
||||
Freq: int32(syncSrc.AudioRate().Num / syncSrc.AudioRate().Den),
|
||||
@@ -215,16 +249,16 @@ func main() {
|
||||
sdl.ResumeAudioStreamDevice(audioStream)
|
||||
fmt.Printf("sync: video %dx%d audio %dch batch=%d\n",
|
||||
syncSrc.Width(), syncSrc.Height(), aChans, audioBatch)
|
||||
case args.VideoFlowId != "":
|
||||
|
||||
case *mxlVideoFlowID != "":
|
||||
videoSrc, err = source.Open(*mxlDomain, *mxlVideoFlowID)
|
||||
videoSrc, err = source.Open(args.Domain, args.VideoFlowId)
|
||||
if err != nil {
|
||||
log.Fatalf("source: %v", err)
|
||||
}
|
||||
fmt.Printf("video: %dx%d stride=%d\n", videoSrc.Width(), videoSrc.Height(), videoSrc.Stride())
|
||||
|
||||
default:
|
||||
audioSrc, err = source.OpenAudio(*mxlDomain, *mxlAudioFlowID)
|
||||
audioSrc, err = source.OpenAudio(args.Domain, args.AudioFlowId)
|
||||
if err != nil {
|
||||
log.Fatalf("audio source: %v", err)
|
||||
}
|
||||
@@ -233,7 +267,7 @@ func main() {
|
||||
if audioBatch == 0 {
|
||||
audioBatch = 1
|
||||
}
|
||||
audioStream = sdl.OpenAudioDeviceStream(sdl.AudioDeviceDefaultPlayback, sdl.AudioSpec{
|
||||
audioStream = sdl.OpenAudioDeviceStream(sdlAudioDevice, sdl.AudioSpec{
|
||||
Format: sdl.AudioF32,
|
||||
Channels: int32(aChans),
|
||||
Freq: int32(audioSrc.Rate().Num / audioSrc.Rate().Den),
|
||||
@@ -261,7 +295,7 @@ func main() {
|
||||
}
|
||||
|
||||
var r *renderer.Renderer
|
||||
if *mxlVideoFlowID != "" {
|
||||
if args.VideoFlowId != "" {
|
||||
var w, h, stride uint32
|
||||
if syncSrc != nil {
|
||||
w, h, stride = syncSrc.Width(), syncSrc.Height(), syncSrc.Stride()
|
||||
@@ -309,7 +343,7 @@ func main() {
|
||||
default:
|
||||
}
|
||||
if syncSrc != nil {
|
||||
s, e := source.OpenSync(*mxlDomain, *mxlVideoFlowID, *mxlAudioFlowID)
|
||||
s, e := source.OpenSync(args.Domain, args.VideoFlowId, args.AudioFlowId)
|
||||
if e == nil {
|
||||
if r != nil {
|
||||
newSize := vk.DeviceSize(s.Stride()) * vk.DeviceSize(s.Height())
|
||||
@@ -324,7 +358,7 @@ func main() {
|
||||
}
|
||||
log.Printf("source: reopen retry: %v", e)
|
||||
} else if videoSrc != nil {
|
||||
s, e := source.Open(*mxlDomain, *mxlVideoFlowID)
|
||||
s, e := source.Open(args.Domain, args.VideoFlowId)
|
||||
if e == nil {
|
||||
if r != nil {
|
||||
newSize := vk.DeviceSize(s.Stride()) * vk.DeviceSize(s.Height())
|
||||
@@ -339,7 +373,7 @@ func main() {
|
||||
}
|
||||
log.Printf("source: reopen retry: %v", e)
|
||||
} else if audioSrc != nil {
|
||||
s, e := source.OpenAudio(*mxlDomain, *mxlAudioFlowID)
|
||||
s, e := source.OpenAudio(args.Domain, args.AudioFlowId)
|
||||
if e == nil {
|
||||
audioSrc = s
|
||||
return nil
|
||||
@@ -477,7 +511,10 @@ func main() {
|
||||
running := true
|
||||
resized := false
|
||||
granted := false
|
||||
fullscreen := false
|
||||
fullscreen := args.IsFullscreen
|
||||
if fullscreen {
|
||||
sdl.SetWindowFullscreen(windowHandler, true)
|
||||
}
|
||||
var (
|
||||
lastIndex uint64
|
||||
dropped uint64
|
||||
|
||||
Reference in New Issue
Block a user