more mpris features
This commit is contained in:
+29
-6
@@ -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 {
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user