Skip to content

Commit

Permalink
macos mediaplayer init works, rework so MPRIS2 and macos MediaPlayer …
Browse files Browse the repository at this point in the history
…use common player interface, callbacks not yet implemented though
  • Loading branch information
spezifisch committed Oct 31, 2023
1 parent ad84c91 commit 4ad8243
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 24 deletions.
2 changes: 1 addition & 1 deletion gui_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func makeSongHandler(entity *subsonic.SubsonicEntity, ui *Ui, fallbackArtist str
duration := entity.Duration

return func() {
if err := ui.player.Play(id, uri, title, artist, duration); err != nil {
if err := ui.player.PlayUri(id, uri, title, artist, duration); err != nil {
ui.logger.PrintError("SongHandler Play", err)
return
}
Expand Down
57 changes: 53 additions & 4 deletions mpvplayer/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/wildeyedskies/go-mpv/mpv"
"github.com/wildeyedskies/stmp/logger"
"github.com/wildeyedskies/stmp/remote"
)

type PlayerQueue []QueueItem
Expand All @@ -24,6 +25,8 @@ type Player struct {
stopped bool
}

var _ remote.ControlledPlayer = (*Player)(nil)

func NewPlayer(logger logger.LoggerInterface) (player *Player, err error) {
m := mpv.Create()

Expand Down Expand Up @@ -109,7 +112,7 @@ func (p *Player) PlayNextTrack() error {
return nil
}

func (p *Player) Play(id string, uri string, title string, artist string, duration int) error {
func (p *Player) PlayUri(id string, uri string, title string, artist string, duration int) error {
p.queue = []QueueItem{{id, uri, title, artist, duration}}
p.replaceInProgress = true
if ip, e := p.IsPaused(); ip && e == nil {
Expand Down Expand Up @@ -216,7 +219,7 @@ func (p *Player) Pause() (err error) {
return
}

func (p *Player) SetVolume(percentValue int64) error {
func (p *Player) SetVolume(percentValue int) error {
if percentValue > 100 {
percentValue = 100
} else if percentValue < 0 {
Expand All @@ -226,7 +229,7 @@ func (p *Player) SetVolume(percentValue int64) error {
return p.instance.SetProperty("volume", mpv.FORMAT_INT64, percentValue)
}

func (p *Player) AdjustVolume(increment int64) error {
func (p *Player) AdjustVolume(increment int) error {
volume, err := p.instance.GetProperty("volume", mpv.FORMAT_INT64)
if err != nil {
return err
Expand All @@ -235,7 +238,7 @@ func (p *Player) AdjustVolume(increment int64) error {
return nil
}

return p.SetVolume(volume.(int64) + increment)
return p.SetVolume(volume.(int) + increment)
}

func (p *Player) Volume() (int64, error) {
Expand Down Expand Up @@ -308,3 +311,49 @@ func (p *Player) GetPlayingTrack() (QueueItem, error) {
currentSong := p.queue[0]
return currentSong, nil
}

func (p *Player) IsSeeking() (bool, error) {
return false, nil
}

// Registers a callback which is invoked when the player transitions to the Paused state.
func (p *Player) OnPaused(cb func()) {}

// Registers a callback which is invoked when the player transitions to the Stopped state.
func (p *Player) OnStopped(cb func()) {}

// Registers a callback which is invoked when the player transitions to the Playing state.
func (p *Player) OnPlaying(cb func()) {}

// Registers a callback which is invoked whenever a seek event occurs.
func (p *Player) OnSeek(cb func()) {}

func (p *Player) OnSongChange(func(track remote.TrackInterface)) {}

func (p *Player) GetTimePos() float64 {
return 0
}

func (p *Player) SeekAbsolute(float64) error {
return nil
}

func (p *Player) Play() error {
if isPlaying, err := p.IsPlaying(); err != nil {
return err
} else if !isPlaying {
p.Pause()
}
return nil
}

func (p *Player) NextTrack() error {
return p.PlayNextTrack()
}

func (p *Player) PreviousTrack() (err error) {
if err = p.Stop(); err != nil {
return
}
return p.Pause()
}
16 changes: 11 additions & 5 deletions remote/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package remote

type ControlledPlayer interface {
// Returns true if a seek is currently in progress.
IsSeeking()
IsSeeking() (bool, error)
IsPaused() (bool, error)
IsPlaying() (bool, error)

// Registers a callback which is invoked when the player transitions to the Paused state.
OnPaused(cb func())
Expand All @@ -20,10 +22,14 @@ type ControlledPlayer interface {

GetTimePos() float64

Play()
Pause()
PlayNextTrack()
Stop()
Play() error
Pause() error
Stop() error
SeekAbsolute(float64) error
NextTrack() error
PreviousTrack() error

SetVolume(percentValue int) error
}

type TrackInterface interface {
Expand Down
7 changes: 3 additions & 4 deletions remote/mpmedia_mac.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,22 +159,21 @@ func (mp *MPMediaHandler) OnCommandNextTrack() {
if mp == nil || mp.player == nil {
return
}
mp.player.PlayNextTrack()
mp.player.NextTrack()
}

// MPMediaHandler instance received OS command 'previous track'
func (mp *MPMediaHandler) OnCommandPreviousTrack() {
if mp == nil || mp.player == nil {
return
}
mp.player.Stop()
mp.player.PlayNextTrack()
mp.player.PreviousTrack()
}

// MPMediaHandler instance received OS command to 'seek'
func (mp *MPMediaHandler) OnCommandSeek(positionSeconds float64) {
if mp == nil || mp.player == nil {
return
}
//mp.player.Seek(fmt.Sprintf("%0.2f", positionSeconds), player.SeekAbsolute)
mp.player.SeekAbsolute(positionSeconds)
}
16 changes: 6 additions & 10 deletions remote/mpris2.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,17 @@ import (
"github.com/godbus/dbus/v5/introspect"
"github.com/godbus/dbus/v5/prop"
"github.com/wildeyedskies/stmp/logger"
"github.com/wildeyedskies/stmp/mpvplayer"
)

type MprisPlayer struct {
dbus *dbus.Conn
player *mpvplayer.Player
player ControlledPlayer
logger logger.LoggerInterface

lastVolume float64
}

func RegisterMprisPlayer(player *mpvplayer.Player, logger_ logger.LoggerInterface) (mpp *MprisPlayer, err error) {
func RegisterMprisPlayer(player ControlledPlayer, logger_ logger.LoggerInterface) (mpp *MprisPlayer, err error) {
conn, err := dbus.ConnectSessionBus()
if err != nil {
return
Expand Down Expand Up @@ -127,7 +126,7 @@ func (m *MprisPlayer) Stop() {
}

func (m *MprisPlayer) Next() {
if err := m.player.PlayNextTrack(); err != nil {
if err := m.player.NextTrack(); err != nil {
m.logger.PrintError("mpp PlayNextTrack", err)
}
//TODO updateQueueList(ui.player, ui.queueList, ui.starIdList)
Expand Down Expand Up @@ -178,17 +177,14 @@ func (m *MprisPlayer) SetPosition(string, int) {
}

func (m *MprisPlayer) volumeChange(c *prop.Change) *dbus.Error {
// get volume change value as float where 1.0 = 100%
fVol := c.Value.(float64)
fDelta := fVol - m.lastVolume
m.lastVolume = fVol

// convert to %
pcDelta := int64(math.Round(fDelta * 100))
if err := m.player.AdjustVolume(pcDelta); err != nil {
percentVol := int(math.Round(fVol * 100))
if err := m.player.SetVolume(percentVol); err != nil {
m.logger.PrintError("volumeChange", err)
} else {
m.logger.Printf("mpris: adjust volume %f d%f -> %d%%", fVol, fDelta, pcDelta)
m.logger.Printf("mpris: adjust volume %f -> %d%%", fVol, percentVol)
}
return nil
}
13 changes: 13 additions & 0 deletions stmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"flag"
"fmt"
"os"
"runtime"

"github.com/spf13/viper"
"github.com/wildeyedskies/stmp/logger"
Expand Down Expand Up @@ -68,12 +69,14 @@ func main() {
os.Exit(1)
}

// init mpv engine
player, err := mpvplayer.NewPlayer(logger)
if err != nil {
fmt.Println("Unable to initialize mpv. Is mpv installed?")
os.Exit(1)
}

// init mpris2 player control (linux only but fails gracefully on other systems)
if *enableMpris {
mpris, err := remote.RegisterMprisPlayer(player, logger)
if err != nil {
Expand All @@ -84,6 +87,16 @@ func main() {
defer mpris.Close()
}

// init macos mediaplayer control
if runtime.GOOS == "darwin" {
if err = remote.RegisterMPMediaHandler(player, logger); err != nil {
fmt.Printf("Unable to initialize MediaPlayer bindings: %s\n", err)
os.Exit(1)
} else {
logger.Print("MacOS MediaPlayer registered")
}
}

ui := InitGui(&indexResponse.Indexes.Index,
&playlistResponse.Playlists.Playlists,
connection,
Expand Down

0 comments on commit 4ad8243

Please sign in to comment.