package player import ( "context" "errors" "io" "os" "os/exec" "path/filepath" ) type VLC struct { session *exec.Cmd ctx context.Context cancelFunc context.CancelFunc wr *writer } func NewVLC(ctx context.Context) (Player, error) { r := new(VLC) if err := r.Available(ctx); err != nil { return nil, err } return r, nil } func (p *VLC) Available(ctx context.Context) error { p.ctx, p.cancelFunc = context.WithCancel(ctx) home, err := os.UserHomeDir() if err != nil { return err } var ( paths = []string{ filepath.Join("/", "Applications", "VLC.app", "Contents", "MacOS", "VLC"), filepath.Join("/", "Applications", "VLC.app", "Contents", "MacOS", "vlc"), filepath.Join("/", "Applications", "MacPorts", "VLC.app", "Contents", "MacOS", "VLC"), filepath.Join("/", "Applications", "MacPorts", "VLC.app", "Contents", "MacOS", "vlc"), filepath.Join(home, "Applications", "VLC.app", "Contents", "MacOS", "vlc"), filepath.Join(home, "Applications", "VLC.app", "Contents", "MacOS", "vlc"), } f *os.File s os.FileInfo ) for _, path := range paths { if f, err = os.Open(path); err != nil { continue } if s, err = f.Stat(); err != nil { continue } if s.IsDir() { continue } p.session = exec.CommandContext(p.ctx, path, "-") return nil } return errors.New("could not find installed VLC player") } func (p *VLC) Start(stop chan error) error { if p.session == nil { return errors.New("illegal state: player session was not established") } var ( pipe io.WriteCloser err error ) if pipe, err = p.session.StdinPipe(); err != nil { return err } if err = p.session.Start(); err != nil { return err } p.wr = Writer(pipe) go p.wr.Run(stop) return nil } func (p *VLC) Write(d []byte) error { if p.wr == nil { return io.ErrClosedPipe } return p.wr.Write(d) } func (p *VLC) Close() error { if p.cancelFunc != nil { p.cancelFunc() } if p.wr != nil { _ = p.wr.Close() } p.session = nil return nil }