more mpris features

This commit is contained in:
Drew Weymouth
2023-07-12 17:41:16 -07:00
parent 2a17718969
commit 61d5ad917d
4 changed files with 60 additions and 13 deletions
+29 -6
View File
@@ -38,7 +38,10 @@ type App struct {
Player *player.Player Player *player.Player
UpdateChecker UpdateChecker UpdateChecker UpdateChecker
MPRISHandler *MPRISHandler MPRISHandler *MPRISHandler
OnReactivate func()
// UI callbacks to be set in main
OnReactivate func()
OnExit func()
appName string appName string
appVersionTag string appVersionTag string
@@ -104,8 +107,7 @@ func StartupApp(appName, displayAppName, appVersionTag, configFile, latestReleas
_, _ = a.ImageManager.GetCoverThumbnail(coverID) _, _ = a.ImageManager.GetCoverThumbnail(coverID)
}) })
a.MPRISHandler = NewMPRISHandler(displayAppName, a.Player, a.PlaybackManager) a.setupMPRIS(displayAppName)
a.MPRISHandler.Start()
return a, nil return a, nil
} }
@@ -138,9 +140,7 @@ func (a *App) startSessionWatcher(sessionPath string) {
activatePath := path.Join(sessionPath, sessionActivateFile) activatePath := path.Join(sessionPath, sessionActivateFile)
if _, err := os.Stat(activatePath); err == nil { if _, err := os.Stat(activatePath); err == nil {
os.Remove(path.Join(sessionPath, sessionActivateFile)) os.Remove(path.Join(sessionPath, sessionActivateFile))
if a.OnReactivate != nil { a.callOnReactivate()
a.OnReactivate()
}
} }
} }
} }
@@ -148,6 +148,12 @@ func (a *App) startSessionWatcher(sessionPath string) {
} }
} }
func (a *App) callOnReactivate() {
if a.OnReactivate != nil {
a.OnReactivate()
}
}
func (a *App) initMPV() error { func (a *App) initMPV() error {
p := player.NewWithClientName(a.appName) p := player.NewWithClientName(a.appName)
c := a.Config.LocalPlayback c := a.Config.LocalPlayback
@@ -206,6 +212,23 @@ func (a *App) setupMPV() error {
return nil return nil
} }
func (a *App) setupMPRIS(mprisAppName string) {
a.MPRISHandler = NewMPRISHandler(mprisAppName, a.Player, a.PlaybackManager)
a.MPRISHandler.ArtURLLookup = a.ImageManager.GetCoverArtUrl
a.MPRISHandler.OnRaise = func() error { a.callOnReactivate(); return nil }
a.MPRISHandler.OnQuit = func() error {
if a.OnExit == nil {
return errors.New("no quit handler registered")
}
go func() {
time.Sleep(10 * time.Millisecond)
a.OnExit()
}()
return nil
}
a.MPRISHandler.Start()
}
func (a *App) LoginToDefaultServer(string) error { func (a *App) LoginToDefaultServer(string) error {
serverCfg := a.ServerManager.GetDefaultServer() serverCfg := a.ServerManager.GetDefaultServer()
if serverCfg == nil { if serverCfg == nil {
+10
View File
@@ -88,6 +88,16 @@ func (i *ImageManager) GetFullSizeCoverArt(coverID string) (image.Image, error)
return im, nil return im, nil
} }
func (i *ImageManager) GetCoverArtUrl(coverID string) (string, error) {
path := i.filePathForCover(coverID)
if _, err := os.Stat(path); err == nil {
// this is probably broken for Windows but it's currently only used
// for MPRIS, so we are OK for now
return fmt.Sprintf("file://%s", path), nil
}
return "", errors.New("cover not found")
}
func (i *ImageManager) GetCachedArtistImage(artistID string) (image.Image, bool) { func (i *ImageManager) GetCachedArtistImage(artistID string) (image.Image, bool) {
return i.loadLocalImage(i.filePathForArtistImage(artistID)) return i.loadLocalImage(i.filePathForArtistImage(artistID))
} }
+11 -5
View File
@@ -31,7 +31,7 @@ type MPRISHandler struct {
OnRaise func() error OnRaise func() error
// Function to look up the artwork URL for a given track ID // Function to look up the artwork URL for a given track ID
ArtURLLookup func(trackID string) string ArtURLLookup func(trackID string) (string, error)
playerName string playerName string
p *player.Player p *player.Player
@@ -44,6 +44,10 @@ func NewMPRISHandler(playerName string, p *player.Player, pm *PlaybackManager) *
m := &MPRISHandler{playerName: playerName, p: p, pm: pm} m := &MPRISHandler{playerName: playerName, p: p, pm: pm}
m.s = server.NewServer(playerName, m, m) m.s = server.NewServer(playerName, m, m)
m.evt = events.NewEventHandler(m.s) m.evt = events.NewEventHandler(m.s)
m.p.OnSeek(func() {
pos := secondsToMicroseconds(m.p.GetStatus().TimePos)
m.evt.Player.OnSeek(pos)
})
return m return m
} }
@@ -176,7 +180,9 @@ func (m *MPRISHandler) Metadata() (types.Metadata, error) {
} }
var artURL string var artURL string
if tr.ID != "" && m.ArtURLLookup != nil { if tr.ID != "" && m.ArtURLLookup != nil {
artURL = m.ArtURLLookup(tr.ID) if u, err := m.ArtURLLookup(tr.ID); err == nil {
artURL = u
}
} }
return types.Metadata{ return types.Metadata{
TrackId: dbus.ObjectPath(trackID), TrackId: dbus.ObjectPath(trackID),
@@ -205,11 +211,11 @@ func (m *MPRISHandler) Position() (int64, error) {
} }
func (m *MPRISHandler) MinimumRate() (float64, error) { func (m *MPRISHandler) MinimumRate() (float64, error) {
return 0, notImplemented return 1, nil
} }
func (m *MPRISHandler) MaximumRate() (float64, error) { func (m *MPRISHandler) MaximumRate() (float64, error) {
return 0, notImplemented return 1, nil
} }
func (m *MPRISHandler) CanGoNext() (bool, error) { func (m *MPRISHandler) CanGoNext() (bool, error) {
@@ -229,7 +235,7 @@ func (m *MPRISHandler) CanPause() (bool, error) {
} }
func (m *MPRISHandler) CanSeek() (bool, error) { func (m *MPRISHandler) CanSeek() (bool, error) {
return false, notImplemented return true, nil
} }
func (m *MPRISHandler) CanControl() (bool, error) { func (m *MPRISHandler) CanControl() (bool, error) {
+10 -2
View File
@@ -41,6 +41,10 @@ func main() {
} }
mainWindow := ui.NewMainWindow(fyneApp, appname, displayName, appVersion, myApp, fyne.NewSize(w, h)) mainWindow := ui.NewMainWindow(fyneApp, appname, displayName, appVersion, myApp, fyne.NewSize(w, h))
myApp.OnReactivate = mainWindow.Show myApp.OnReactivate = mainWindow.Show
myApp.OnExit = func() {
saveWindowPosition(myApp.Config, mainWindow.Window)
fyneApp.Quit()
}
go func() { go func() {
// TODO: There is a race condition with laying out the window before the // TODO: There is a race condition with laying out the window before the
@@ -61,8 +65,7 @@ func main() {
mainWindow.Show() mainWindow.Show()
mainWindow.Window.SetCloseIntercept(func() { mainWindow.Window.SetCloseIntercept(func() {
myApp.Config.Application.WindowHeight = int(mainWindow.Canvas().Size().Height) saveWindowPosition(myApp.Config, mainWindow.Window)
myApp.Config.Application.WindowWidth = int(mainWindow.Canvas().Size().Width)
if myApp.Config.Application.CloseToSystemTray && if myApp.Config.Application.CloseToSystemTray &&
mainWindow.HaveSystemTray() { mainWindow.HaveSystemTray() {
mainWindow.Window.Hide() mainWindow.Window.Hide()
@@ -75,3 +78,8 @@ func main() {
log.Println("Running shutdown tasks...") log.Println("Running shutdown tasks...")
myApp.Shutdown() myApp.Shutdown()
} }
func saveWindowPosition(config *backend.Config, window fyne.Window) {
config.Application.WindowHeight = int(window.Canvas().Size().Height)
config.Application.WindowWidth = int(window.Canvas().Size().Width)
}