more mpris features
This commit is contained in:
+29
-6
@@ -38,7 +38,10 @@ type App struct {
|
||||
Player *player.Player
|
||||
UpdateChecker UpdateChecker
|
||||
MPRISHandler *MPRISHandler
|
||||
OnReactivate func()
|
||||
|
||||
// UI callbacks to be set in main
|
||||
OnReactivate func()
|
||||
OnExit func()
|
||||
|
||||
appName string
|
||||
appVersionTag string
|
||||
@@ -104,8 +107,7 @@ func StartupApp(appName, displayAppName, appVersionTag, configFile, latestReleas
|
||||
_, _ = a.ImageManager.GetCoverThumbnail(coverID)
|
||||
})
|
||||
|
||||
a.MPRISHandler = NewMPRISHandler(displayAppName, a.Player, a.PlaybackManager)
|
||||
a.MPRISHandler.Start()
|
||||
a.setupMPRIS(displayAppName)
|
||||
|
||||
return a, nil
|
||||
}
|
||||
@@ -138,9 +140,7 @@ func (a *App) startSessionWatcher(sessionPath string) {
|
||||
activatePath := path.Join(sessionPath, sessionActivateFile)
|
||||
if _, err := os.Stat(activatePath); err == nil {
|
||||
os.Remove(path.Join(sessionPath, sessionActivateFile))
|
||||
if a.OnReactivate != nil {
|
||||
a.OnReactivate()
|
||||
}
|
||||
a.callOnReactivate()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
p := player.NewWithClientName(a.appName)
|
||||
c := a.Config.LocalPlayback
|
||||
@@ -206,6 +212,23 @@ func (a *App) setupMPV() error {
|
||||
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 {
|
||||
serverCfg := a.ServerManager.GetDefaultServer()
|
||||
if serverCfg == nil {
|
||||
|
||||
@@ -88,6 +88,16 @@ func (i *ImageManager) GetFullSizeCoverArt(coverID string) (image.Image, error)
|
||||
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) {
|
||||
return i.loadLocalImage(i.filePathForArtistImage(artistID))
|
||||
}
|
||||
|
||||
+11
-5
@@ -31,7 +31,7 @@ type MPRISHandler struct {
|
||||
OnRaise func() error
|
||||
|
||||
// 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
|
||||
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.s = server.NewServer(playerName, m, m)
|
||||
m.evt = events.NewEventHandler(m.s)
|
||||
m.p.OnSeek(func() {
|
||||
pos := secondsToMicroseconds(m.p.GetStatus().TimePos)
|
||||
m.evt.Player.OnSeek(pos)
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -176,7 +180,9 @@ func (m *MPRISHandler) Metadata() (types.Metadata, error) {
|
||||
}
|
||||
var artURL string
|
||||
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{
|
||||
TrackId: dbus.ObjectPath(trackID),
|
||||
@@ -205,11 +211,11 @@ func (m *MPRISHandler) Position() (int64, error) {
|
||||
}
|
||||
|
||||
func (m *MPRISHandler) MinimumRate() (float64, error) {
|
||||
return 0, notImplemented
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
func (m *MPRISHandler) MaximumRate() (float64, error) {
|
||||
return 0, notImplemented
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
func (m *MPRISHandler) CanGoNext() (bool, error) {
|
||||
@@ -229,7 +235,7 @@ func (m *MPRISHandler) CanPause() (bool, error) {
|
||||
}
|
||||
|
||||
func (m *MPRISHandler) CanSeek() (bool, error) {
|
||||
return false, notImplemented
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (m *MPRISHandler) CanControl() (bool, error) {
|
||||
|
||||
@@ -41,6 +41,10 @@ func main() {
|
||||
}
|
||||
mainWindow := ui.NewMainWindow(fyneApp, appname, displayName, appVersion, myApp, fyne.NewSize(w, h))
|
||||
myApp.OnReactivate = mainWindow.Show
|
||||
myApp.OnExit = func() {
|
||||
saveWindowPosition(myApp.Config, mainWindow.Window)
|
||||
fyneApp.Quit()
|
||||
}
|
||||
|
||||
go func() {
|
||||
// TODO: There is a race condition with laying out the window before the
|
||||
@@ -61,8 +65,7 @@ func main() {
|
||||
|
||||
mainWindow.Show()
|
||||
mainWindow.Window.SetCloseIntercept(func() {
|
||||
myApp.Config.Application.WindowHeight = int(mainWindow.Canvas().Size().Height)
|
||||
myApp.Config.Application.WindowWidth = int(mainWindow.Canvas().Size().Width)
|
||||
saveWindowPosition(myApp.Config, mainWindow.Window)
|
||||
if myApp.Config.Application.CloseToSystemTray &&
|
||||
mainWindow.HaveSystemTray() {
|
||||
mainWindow.Window.Hide()
|
||||
@@ -75,3 +78,8 @@ func main() {
|
||||
log.Println("Running shutdown tasks...")
|
||||
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user