From e754b40a0982f0eeae48d568655415f8ebb178f8 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Thu, 13 Jul 2023 14:41:11 -0700 Subject: [PATCH] implement MPRIS SetVolume --- backend/mpris.go | 9 +++++++-- backend/playbackmanager.go | 21 +++++++++++++++++++++ ui/bottompanel.go | 9 ++++----- ui/mainwindow.go | 8 ++++---- ui/widgets/auxcontrols.go | 32 +++++++++++++++++++++++--------- 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/backend/mpris.go b/backend/mpris.go index 1b89376..83243d9 100644 --- a/backend/mpris.go +++ b/backend/mpris.go @@ -59,6 +59,11 @@ func NewMPRISHandler(playerName string, p *player.Player, pm *PlaybackManager) * m.evt.Player.OnTitle() } }) + m.pm.OnVolumeChange(func(vol int) { + if m.connErr == nil { + m.evt.Player.OnVolume() + } + }) emitPlayStatus := func() { if m.connErr == nil { m.evt.Player.OnPlayPause() @@ -253,8 +258,8 @@ func (m *MPRISHandler) Volume() (float64, error) { return float64(m.p.GetVolume()) / 100, nil } -func (m *MPRISHandler) SetVolume(float64) error { - return errNotImplemented +func (m *MPRISHandler) SetVolume(v float64) error { + return m.pm.SetVolume(int(v * 100)) } func (m *MPRISHandler) Position() (int64, error) { diff --git a/backend/playbackmanager.go b/backend/playbackmanager.go index 8622db8..97de5af 100644 --- a/backend/playbackmanager.go +++ b/backend/playbackmanager.go @@ -49,6 +49,7 @@ type PlaybackManager struct { onSongChange []func(nowPlaying, justScrobbledIfAny *mediaprovider.Track) onPlayTimeUpdate []func(float64, float64) onLoopModeChange []func(LoopMode) + onVolumeChange []func(int) } func NewPlaybackManager( @@ -142,6 +143,11 @@ func (p *PlaybackManager) OnLoopModeChange(cb func(LoopMode)) { p.onLoopModeChange = append(p.onLoopModeChange, cb) } +// Registers a callback that is notified whenever the volume changes. +func (p *PlaybackManager) OnVolumeChange(cb func(int)) { + p.onVolumeChange = append(p.onVolumeChange, cb) +} + // Loads the specified album into the play queue. func (p *PlaybackManager) LoadAlbum(albumID string, appendToQueue bool, shuffle bool) error { album, err := p.sm.Server.GetAlbum(albumID) @@ -335,6 +341,21 @@ func (p *PlaybackManager) LoopMode() LoopMode { return LoopMode(p.player.GetLoopMode()) } +func (p *PlaybackManager) SetVolume(vol int) error { + vol = clamp(vol, 0, 100) + if err := p.player.SetVolume(vol); err != nil { + return err + } + for _, cb := range p.onVolumeChange { + cb(vol) + } + return nil +} + +func (p *PlaybackManager) Volume() int { + return p.player.GetVolume() +} + // call BEFORE updating p.nowPlayingIdx func (p *PlaybackManager) checkScrobble() { if !p.scrobbleCfg.Enabled || len(p.playQueue) == 0 || p.nowPlayingIdx < 0 { diff --git a/ui/bottompanel.go b/ui/bottompanel.go index f451667..85162d9 100644 --- a/ui/bottompanel.go +++ b/ui/bottompanel.go @@ -54,9 +54,7 @@ func NewBottomPanel(p *player.Player, pm *backend.PlaybackManager, contr *contro p.OnStopped(func() { bp.Controls.SetPlaying(false) }) - pm.OnLoopModeChange(func(mode backend.LoopMode) { - bp.AuxControls.SetLoopMode(mode) - }) + pm.OnLoopModeChange(bp.AuxControls.SetLoopMode) bp.NowPlaying = widgets.NewNowPlayingCard() bp.NowPlaying.OnShowCoverImage = func() { @@ -100,8 +98,9 @@ func NewBottomPanel(p *player.Player, pm *backend.PlaybackManager, contr *contro }) bp.AuxControls = widgets.NewAuxControls(p.GetVolume()) - bp.AuxControls.VolumeControl.OnVolumeChanged = func(v int) { - _ = p.SetVolume(v) + pm.OnVolumeChange(bp.AuxControls.VolumeControl.SetVolume) + bp.AuxControls.VolumeControl.OnSetVolume = func(v int) { + _ = bp.playbackManager.SetVolume(v) } bp.AuxControls.OnChangeLoopMode(func() { bp.playbackManager.SetNextLoopMode() diff --git a/ui/mainwindow.go b/ui/mainwindow.go index be0d54e..0baec49 100644 --- a/ui/mainwindow.go +++ b/ui/mainwindow.go @@ -163,15 +163,15 @@ func (m *MainWindow) SetupSystemTrayMenu(appName string, fyneApp fyne.App) { }), fyne.NewMenuItemSeparator(), fyne.NewMenuItem("Volume +10%", func() { - vol := m.App.Player.GetVolume() + vol := m.App.PlaybackManager.Volume() vol = vol + int(float64(vol)*0.1) // will clamp to range for us - m.BottomPanel.AuxControls.VolumeControl.SetVolume(vol) + m.App.PlaybackManager.SetVolume(vol) }), fyne.NewMenuItem("Volume -10%", func() { - vol := m.App.Player.GetVolume() + vol := m.App.PlaybackManager.Volume() vol = vol - int(float64(vol)*0.1) - m.BottomPanel.AuxControls.VolumeControl.SetVolume(vol) + m.App.PlaybackManager.SetVolume(vol) }), fyne.NewMenuItemSeparator(), fyne.NewMenuItem("Show", m.Window.Show), diff --git a/ui/widgets/auxcontrols.go b/ui/widgets/auxcontrols.go index 0589438..e426157 100644 --- a/ui/widgets/auxcontrols.go +++ b/ui/widgets/auxcontrols.go @@ -162,7 +162,7 @@ type VolumeControl struct { icon *TappableIcon slider *volumeSlider - OnVolumeChanged func(int) + OnSetVolume func(int) muted bool lastVol int @@ -185,24 +185,35 @@ func NewVolumeControl(initialVol int) *VolumeControl { return v } +// Sets the volume that is displayed in the slider. +// Does not invoke OnSetVolume callback. +func (v *VolumeControl) SetVolume(vol int) { + if (vol == v.lastVol && !v.muted) || (v.muted && vol == 0) { + return + } + v.lastVol = vol + v.muted = false + v.setDisplayedVolume(vol) +} + func (v *VolumeControl) onChanged(volume float64) { vol := int(volume) v.lastVol = vol v.muted = false v.updateIconForVolume(vol) - if v.OnVolumeChanged != nil { - v.OnVolumeChanged(vol) - } + v.invokeOnVolumeChange(vol) } func (v *VolumeControl) toggleMute() { if !v.muted { v.muted = true v.lastVol = int(v.slider.Value) - v.SetVolume(0) + v.setDisplayedVolume(0) + v.invokeOnVolumeChange(0) } else { v.muted = false - v.SetVolume(v.lastVol) + v.setDisplayedVolume(v.lastVol) + v.invokeOnVolumeChange(v.lastVol) } } @@ -211,12 +222,15 @@ func (v *VolumeControl) CreateRenderer() fyne.WidgetRenderer { return widget.NewSimpleRenderer(v.container) } -func (v *VolumeControl) SetVolume(vol int) { +func (v *VolumeControl) setDisplayedVolume(vol int) { v.slider.Value = float64(vol) v.slider.Refresh() v.updateIconForVolume(vol) - if v.OnVolumeChanged != nil { - v.OnVolumeChanged(vol) +} + +func (v *VolumeControl) invokeOnVolumeChange(vol int) { + if v.OnSetVolume != nil { + v.OnSetVolume(vol) } }