Add backend/internal/moonlight/launcher.go
This commit is contained in:
parent
06c286c82e
commit
c890bfd1c3
1 changed files with 85 additions and 0 deletions
85
backend/internal/moonlight/launcher.go
Normal file
85
backend/internal/moonlight/launcher.go
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// Package moonlight handles launching the Moonlight client.
|
||||
// It locates the Moonlight executable and launches a stream session
|
||||
// to a specific host and app.
|
||||
package moonlight
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// DefaultPaths are the well-known install locations per platform.
|
||||
var DefaultPaths = map[string][]string{
|
||||
"windows": {
|
||||
`C:\Program Files\Moonlight Game Streaming\Moonlight.exe`,
|
||||
`C:\Program Files (x86)\Moonlight Game Streaming\Moonlight.exe`,
|
||||
},
|
||||
"darwin": {
|
||||
"/Applications/Moonlight.app/Contents/MacOS/Moonlight",
|
||||
},
|
||||
"linux": {
|
||||
"/usr/bin/moonlight",
|
||||
"/usr/local/bin/moonlight",
|
||||
},
|
||||
}
|
||||
|
||||
// Launcher knows how to start Moonlight.
|
||||
type Launcher struct {
|
||||
execPath string
|
||||
}
|
||||
|
||||
// New creates a Launcher, auto-detecting the Moonlight binary.
|
||||
// Pass an empty string to use auto-detection.
|
||||
func New(overridePath string) (*Launcher, error) {
|
||||
if overridePath != "" {
|
||||
if path, err := exec.LookPath(overridePath); err == nil {
|
||||
return &Launcher{execPath: path}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("moonlight not found at %q", overridePath)
|
||||
}
|
||||
|
||||
// Try PATH first
|
||||
if path, err := exec.LookPath("moonlight"); err == nil {
|
||||
return &Launcher{execPath: path}, nil
|
||||
}
|
||||
|
||||
// Try well-known locations
|
||||
for _, candidate := range DefaultPaths[runtime.GOOS] {
|
||||
if path, err := exec.LookPath(candidate); err == nil {
|
||||
return &Launcher{execPath: path}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Return a launcher even if not found — we'll surface the error at connect time
|
||||
return &Launcher{}, nil
|
||||
}
|
||||
|
||||
// ExecPath returns the resolved path to the Moonlight binary.
|
||||
func (l *Launcher) ExecPath() string {
|
||||
return l.execPath
|
||||
}
|
||||
|
||||
// Stream launches a Moonlight stream to the given host + app.
|
||||
// app is typically "Desktop" for a full desktop stream.
|
||||
func (l *Launcher) Stream(hostIP, app string) error {
|
||||
if l.execPath == "" {
|
||||
return fmt.Errorf("Moonlight executable not found — please install Moonlight or set MOONLIGHT_PATH")
|
||||
}
|
||||
// moonlight stream <host> <app>
|
||||
cmd := exec.Command(l.execPath, "stream", hostIP, app)
|
||||
cmd.Stdout = nil
|
||||
cmd.Stderr = nil
|
||||
return cmd.Start() // non-blocking — let Moonlight own its window
|
||||
}
|
||||
|
||||
// Pair runs the Moonlight pairing flow for a host.
|
||||
func (l *Launcher) Pair(hostIP string) error {
|
||||
if l.execPath == "" {
|
||||
return fmt.Errorf("Moonlight executable not found")
|
||||
}
|
||||
cmd := exec.Command(l.execPath, "pair", hostIP)
|
||||
cmd.Stdout = nil
|
||||
cmd.Stderr = nil
|
||||
return cmd.Start()
|
||||
}
|
||||
Loading…
Reference in a new issue