switch to own libmpv binding
This commit is contained in:
@@ -8,7 +8,6 @@ require (
|
|||||||
github.com/dweymouth/go-subsonic v0.0.0-20230210044542-537b9238299b
|
github.com/dweymouth/go-subsonic v0.0.0-20230210044542-537b9238299b
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/pelletier/go-toml v1.9.3
|
github.com/pelletier/go-toml v1.9.3
|
||||||
github.com/wildeyedskies/go-mpv v0.0.0-20221204042335-e8961dc66756
|
|
||||||
github.com/zalando/go-keyring v0.2.1
|
github.com/zalando/go-keyring v0.2.1
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -287,8 +287,6 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
|
|||||||
github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA=
|
github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA=
|
||||||
github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg=
|
github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg=
|
||||||
github.com/urfave/cli/v2 v2.4.0/go.mod h1:NX9W0zmTvedE5oDoOMs2RTC8RvdK98NTYZE5LbaEYPg=
|
github.com/urfave/cli/v2 v2.4.0/go.mod h1:NX9W0zmTvedE5oDoOMs2RTC8RvdK98NTYZE5LbaEYPg=
|
||||||
github.com/wildeyedskies/go-mpv v0.0.0-20221204042335-e8961dc66756 h1:lB4C5hJIjUpbfaSuMT/cl/+ZqCxyqTzJeI0ZvFItwWg=
|
|
||||||
github.com/wildeyedskies/go-mpv v0.0.0-20221204042335-e8961dc66756/go.mod h1:RhhuJvJB4LWzwW2ls4J+4II6vFVd8WCiw6iKnrz2W68=
|
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
|||||||
+33
-30
@@ -5,8 +5,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/wildeyedskies/go-mpv/mpv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error returned by many Player functions if called before the player has not been initialized.
|
// Error returned by many Player functions if called before the player has not been initialized.
|
||||||
@@ -43,7 +41,8 @@ const (
|
|||||||
// Player encapsulates the mpv instance and provides functions
|
// Player encapsulates the mpv instance and provides functions
|
||||||
// to control it and to check its status.
|
// to control it and to check its status.
|
||||||
type Player struct {
|
type Player struct {
|
||||||
mpv *mpv.Mpv
|
mpv libmpv
|
||||||
|
initialized bool
|
||||||
vol int
|
vol int
|
||||||
status Status
|
status Status
|
||||||
seeking bool
|
seeking bool
|
||||||
@@ -79,8 +78,11 @@ func NewWithClientName(c string) *Player {
|
|||||||
// Initializes the Player and makes it ready for playback.
|
// Initializes the Player and makes it ready for playback.
|
||||||
// Most Player functions will return ErrUnitialized if called before Init.
|
// Most Player functions will return ErrUnitialized if called before Init.
|
||||||
func (p *Player) Init() error {
|
func (p *Player) Init() error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
m := mpv.Create()
|
m, err := CreateMPV()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
m.SetOptionString("idle", "yes")
|
m.SetOptionString("idle", "yes")
|
||||||
m.SetOptionString("video", "no")
|
m.SetOptionString("video", "no")
|
||||||
m.SetOptionString("audio-display", "no")
|
m.SetOptionString("audio-display", "no")
|
||||||
@@ -92,7 +94,7 @@ func (p *Player) Init() error {
|
|||||||
if p.vol < 0 {
|
if p.vol < 0 {
|
||||||
p.vol = 100
|
p.vol = 100
|
||||||
}
|
}
|
||||||
m.SetOption("volume", mpv.FORMAT_INT64, p.vol)
|
m.SetOption("volume", MPVFormatInt64, p.vol)
|
||||||
|
|
||||||
if p.clientName != "" {
|
if p.clientName != "" {
|
||||||
m.SetOptionString("audio-client-name", p.clientName)
|
m.SetOptionString("audio-client-name", p.clientName)
|
||||||
@@ -106,6 +108,7 @@ func (p *Player) Init() error {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
go p.eventHandler(ctx)
|
go p.eventHandler(ctx)
|
||||||
p.bgCancel = cancel
|
p.bgCancel = cancel
|
||||||
|
p.initialized = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +116,7 @@ func (p *Player) Init() error {
|
|||||||
// Note that the Player API does not provide methods to read
|
// Note that the Player API does not provide methods to read
|
||||||
// the play queue. Clients are expected to maintain their own play queue model.
|
// the play queue. Clients are expected to maintain their own play queue model.
|
||||||
func (p *Player) AppendFile(url string) error {
|
func (p *Player) AppendFile(url string) error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return ErrUnitialized
|
return ErrUnitialized
|
||||||
}
|
}
|
||||||
return p.mpv.Command([]string{"loadfile", url, "append"})
|
return p.mpv.Command([]string{"loadfile", url, "append"})
|
||||||
@@ -121,7 +124,7 @@ func (p *Player) AppendFile(url string) error {
|
|||||||
|
|
||||||
// Plays the specified file, clearing the previous play queue, if any.
|
// Plays the specified file, clearing the previous play queue, if any.
|
||||||
func (p *Player) PlayFile(url string) error {
|
func (p *Player) PlayFile(url string) error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return ErrUnitialized
|
return ErrUnitialized
|
||||||
}
|
}
|
||||||
err := p.mpv.Command([]string{"loadfile", url, "replace"})
|
err := p.mpv.Command([]string{"loadfile", url, "replace"})
|
||||||
@@ -133,7 +136,7 @@ func (p *Player) PlayFile(url string) error {
|
|||||||
|
|
||||||
// Removes the item at the given index from the internal playqueue.
|
// Removes the item at the given index from the internal playqueue.
|
||||||
func (p *Player) RemoveTrackAt(idx int) error {
|
func (p *Player) RemoveTrackAt(idx int) error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return ErrUnitialized
|
return ErrUnitialized
|
||||||
}
|
}
|
||||||
return p.mpv.Command([]string{"playlist-remove", strconv.Itoa(idx)})
|
return p.mpv.Command([]string{"playlist-remove", strconv.Itoa(idx)})
|
||||||
@@ -141,7 +144,7 @@ func (p *Player) RemoveTrackAt(idx int) error {
|
|||||||
|
|
||||||
// Stops playback and clears the play queue.
|
// Stops playback and clears the play queue.
|
||||||
func (p *Player) Stop() error {
|
func (p *Player) Stop() error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return ErrUnitialized
|
return ErrUnitialized
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
@@ -161,7 +164,7 @@ func (p *Player) Stop() error {
|
|||||||
|
|
||||||
// Clears the play queue, except for the currently playing file.
|
// Clears the play queue, except for the currently playing file.
|
||||||
func (p *Player) ClearPlayQueue() error {
|
func (p *Player) ClearPlayQueue() error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return ErrUnitialized
|
return ErrUnitialized
|
||||||
}
|
}
|
||||||
return p.mpv.Command([]string{"playlist-clear"})
|
return p.mpv.Command([]string{"playlist-clear"})
|
||||||
@@ -170,7 +173,7 @@ func (p *Player) ClearPlayQueue() error {
|
|||||||
// Seeks within the currently playing track.
|
// Seeks within the currently playing track.
|
||||||
// See MPV seek command documentation for more details.
|
// See MPV seek command documentation for more details.
|
||||||
func (p *Player) Seek(target string, mode SeekMode) error {
|
func (p *Player) Seek(target string, mode SeekMode) error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return ErrUnitialized
|
return ErrUnitialized
|
||||||
}
|
}
|
||||||
p.seeking = true
|
p.seeking = true
|
||||||
@@ -184,7 +187,7 @@ func (p *Player) Seek(target string, mode SeekMode) error {
|
|||||||
//
|
//
|
||||||
// Else seeks to the beginning of the previous track.
|
// Else seeks to the beginning of the previous track.
|
||||||
func (p *Player) SeekBackOrPrevious() error {
|
func (p *Player) SeekBackOrPrevious() error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return ErrUnitialized
|
return ErrUnitialized
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +202,7 @@ func (p *Player) SeekBackOrPrevious() error {
|
|||||||
|
|
||||||
// Seeks to the next track in the play queue, if any.
|
// Seeks to the next track in the play queue, if any.
|
||||||
func (p *Player) SeekNext() error {
|
func (p *Player) SeekNext() error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return ErrUnitialized
|
return ErrUnitialized
|
||||||
}
|
}
|
||||||
return p.mpv.Command([]string{"playlist-next"})
|
return p.mpv.Command([]string{"playlist-next"})
|
||||||
@@ -214,8 +217,8 @@ func (p *Player) SetVolume(vol int) error {
|
|||||||
} else if vol < 0 {
|
} else if vol < 0 {
|
||||||
vol = 0
|
vol = 0
|
||||||
}
|
}
|
||||||
if p.mpv != nil {
|
if p.initialized {
|
||||||
err := p.mpv.SetProperty("volume", mpv.FORMAT_INT64, vol)
|
err := p.mpv.SetProperty("volume", MPVFormatInt64, vol)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
p.vol = vol
|
p.vol = vol
|
||||||
}
|
}
|
||||||
@@ -231,7 +234,7 @@ func (p *Player) GetVolume() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) setPaused(paused bool) error {
|
func (p *Player) setPaused(paused bool) error {
|
||||||
return p.mpv.SetProperty("pause", mpv.FORMAT_FLAG, paused)
|
return p.mpv.SetProperty("pause", MPVFormatFlag, paused)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start playback from the first track in the play queue.
|
// Start playback from the first track in the play queue.
|
||||||
@@ -258,7 +261,7 @@ func (p *Player) PlayTrackAt(idx int) error {
|
|||||||
// Begins playback if there is anything in the play queue and player is stopped or paused.
|
// Begins playback if there is anything in the play queue and player is stopped or paused.
|
||||||
// If player is playing, pauses playback.
|
// If player is playing, pauses playback.
|
||||||
func (p *Player) PlayPause() error {
|
func (p *Player) PlayPause() error {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return ErrUnitialized
|
return ErrUnitialized
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,12 +296,12 @@ func (p *Player) PlayPause() error {
|
|||||||
|
|
||||||
// Get the current status of the player.
|
// Get the current status of the player.
|
||||||
func (p *Player) GetStatus() Status {
|
func (p *Player) GetStatus() Status {
|
||||||
if p.mpv == nil {
|
if !p.initialized {
|
||||||
return p.status
|
return p.status
|
||||||
}
|
}
|
||||||
|
|
||||||
pos, _ := p.mpv.GetProperty("playback-time", mpv.FORMAT_DOUBLE)
|
pos, _ := p.mpv.GetProperty("playback-time", MPVFormatDouble)
|
||||||
dur, _ := p.mpv.GetProperty("duration", mpv.FORMAT_DOUBLE)
|
dur, _ := p.mpv.GetProperty("duration", MPVFormatDouble)
|
||||||
if pos != nil {
|
if pos != nil {
|
||||||
p.status.TimePos = pos.(float64)
|
p.status.TimePos = pos.(float64)
|
||||||
}
|
}
|
||||||
@@ -312,7 +315,7 @@ func (p *Player) GetStatus() Status {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) getInt64Property(propName string) (int64, error) {
|
func (p *Player) getInt64Property(propName string) (int64, error) {
|
||||||
playpos, err := p.mpv.GetProperty(propName, mpv.FORMAT_INT64)
|
playpos, err := p.mpv.GetProperty(propName, MPVFormatInt64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
@@ -359,10 +362,10 @@ func (p *Player) Destroy() {
|
|||||||
if p.bgCancel != nil {
|
if p.bgCancel != nil {
|
||||||
p.bgCancel()
|
p.bgCancel()
|
||||||
}
|
}
|
||||||
if p.mpv != nil {
|
if p.initialized {
|
||||||
p.mpv.Command([]string{"stop"})
|
p.mpv.Command([]string{"stop"})
|
||||||
p.mpv.TerminateDestroy()
|
p.mpv.TerminateDestroy()
|
||||||
p.mpv = nil
|
p.initialized = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,19 +408,19 @@ func (p *Player) eventHandler(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
e := p.mpv.WaitEvent(1 /*timeout seconds*/)
|
e := p.mpv.WaitEvent(1 /*timeout seconds*/)
|
||||||
if e.Event_Id != mpv.EVENT_NONE {
|
if e.ID != MPVEventNone {
|
||||||
//log.Printf("mpv event: %+v\n", e)
|
//log.Printf("mpv event: %+v\n", e)
|
||||||
}
|
}
|
||||||
switch e.Event_Id {
|
switch e.ID {
|
||||||
case mpv.EVENT_PLAYBACK_RESTART:
|
case MPVEventPlaybackRestart:
|
||||||
if p.seeking {
|
if p.seeking {
|
||||||
p.seeking = false
|
p.seeking = false
|
||||||
}
|
}
|
||||||
case mpv.EVENT_SEEK:
|
case MPVEventSeek:
|
||||||
for _, cb := range p.onSeek {
|
for _, cb := range p.onSeek {
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
case mpv.EVENT_FILE_LOADED:
|
case MPVEventFileLoaded:
|
||||||
if p.status.State == Paused {
|
if p.status.State == Paused {
|
||||||
// seek while paused switches to a new file
|
// seek while paused switches to a new file
|
||||||
// mpv does not fire seek event in this case
|
// mpv does not fire seek event in this case
|
||||||
@@ -433,7 +436,7 @@ func (p *Player) eventHandler(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case mpv.EVENT_IDLE:
|
case MPVEventIdle:
|
||||||
p.status.Duration = 0
|
p.status.Duration = 0
|
||||||
p.status.TimePos = 0
|
p.status.TimePos = 0
|
||||||
p.setState(Stopped)
|
p.setState(Stopped)
|
||||||
|
|||||||
Reference in New Issue
Block a user