fix behavior of switching players while paused
This commit is contained in:
+1
-1
@@ -404,7 +404,7 @@ func (a *App) SetupWindowsSMTC(hwnd uintptr) {
|
|||||||
})
|
})
|
||||||
a.PlaybackManager.OnSeek(func() {
|
a.PlaybackManager.OnSeek(func() {
|
||||||
dur := a.PlaybackManager.NowPlaying().Metadata().Duration
|
dur := a.PlaybackManager.NowPlaying().Metadata().Duration
|
||||||
smtc.UpdatePosition(int(a.PlaybackManager.PlayerStatus().TimePos*1000), dur*1000)
|
smtc.UpdatePosition(int(a.PlaybackManager.PlaybackStatus().TimePos*1000), dur*1000)
|
||||||
})
|
})
|
||||||
a.PlaybackManager.OnPlaying(func() {
|
a.PlaybackManager.OnPlaying(func() {
|
||||||
smtc.SetEnabled(true)
|
smtc.SetEnabled(true)
|
||||||
|
|||||||
@@ -84,17 +84,17 @@ func InitMPMediaHandler(playbackManager *PlaybackManager, artURLLookup func(trac
|
|||||||
})
|
})
|
||||||
|
|
||||||
mp.playbackManager.OnSeek(func() {
|
mp.playbackManager.OnSeek(func() {
|
||||||
C.update_os_now_playing_info_position(C.double(mp.playbackManager.PlayerStatus().TimePos))
|
C.update_os_now_playing_info_position(C.double(mp.playbackManager.PlaybackStatus().TimePos))
|
||||||
})
|
})
|
||||||
|
|
||||||
mp.playbackManager.OnPlaying(func() {
|
mp.playbackManager.OnPlaying(func() {
|
||||||
C.set_os_playback_state_playing()
|
C.set_os_playback_state_playing()
|
||||||
C.update_os_now_playing_info_position(C.double(mp.playbackManager.PlayerStatus().TimePos))
|
C.update_os_now_playing_info_position(C.double(mp.playbackManager.PlaybackStatus().TimePos))
|
||||||
})
|
})
|
||||||
|
|
||||||
mp.playbackManager.OnPaused(func() {
|
mp.playbackManager.OnPaused(func() {
|
||||||
C.set_os_playback_state_paused()
|
C.set_os_playback_state_paused()
|
||||||
C.update_os_now_playing_info_position(C.double(mp.playbackManager.PlayerStatus().TimePos))
|
C.update_os_now_playing_info_position(C.double(mp.playbackManager.PlaybackStatus().TimePos))
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+6
-6
@@ -54,7 +54,7 @@ func NewMPRISHandler(playerName string, pm *PlaybackManager) *MPRISHandler {
|
|||||||
|
|
||||||
pm.OnSeek(func() {
|
pm.OnSeek(func() {
|
||||||
if m.connErr == nil {
|
if m.connErr == nil {
|
||||||
pos := secondsToMicroseconds(pm.PlayerStatus().TimePos)
|
pos := secondsToMicroseconds(pm.PlaybackStatus().TimePos)
|
||||||
m.evt.Player.OnSeek(pos)
|
m.evt.Player.OnSeek(pos)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -160,7 +160,7 @@ func (m *MPRISHandler) Previous() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MPRISHandler) Pause() error {
|
func (m *MPRISHandler) Pause() error {
|
||||||
if m.pm.PlayerStatus().State == player.Playing {
|
if m.pm.PlaybackStatus().State == player.Playing {
|
||||||
m.pm.PlayPause()
|
m.pm.PlayPause()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -177,7 +177,7 @@ func (m *MPRISHandler) Stop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MPRISHandler) Play() error {
|
func (m *MPRISHandler) Play() error {
|
||||||
switch m.pm.PlayerStatus().State {
|
switch m.pm.PlaybackStatus().State {
|
||||||
case player.Paused:
|
case player.Paused:
|
||||||
m.pm.PlayPause()
|
m.pm.PlayPause()
|
||||||
case player.Stopped:
|
case player.Stopped:
|
||||||
@@ -204,7 +204,7 @@ func (m *MPRISHandler) OpenUri(uri string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MPRISHandler) PlaybackStatus() (types.PlaybackStatus, error) {
|
func (m *MPRISHandler) PlaybackStatus() (types.PlaybackStatus, error) {
|
||||||
switch m.pm.PlayerStatus().State {
|
switch m.pm.PlaybackStatus().State {
|
||||||
case player.Playing:
|
case player.Playing:
|
||||||
return types.PlaybackStatusPlaying, nil
|
return types.PlaybackStatusPlaying, nil
|
||||||
case player.Paused:
|
case player.Paused:
|
||||||
@@ -254,7 +254,7 @@ func (m *MPRISHandler) Metadata() (types.Metadata, error) {
|
|||||||
if m.curTrackPath != "" {
|
if m.curTrackPath != "" {
|
||||||
trackObjPath = m.curTrackPath
|
trackObjPath = m.curTrackPath
|
||||||
}
|
}
|
||||||
status := m.pm.PlayerStatus()
|
status := m.pm.PlaybackStatus()
|
||||||
|
|
||||||
var meta mediaprovider.MediaItemMetadata
|
var meta mediaprovider.MediaItemMetadata
|
||||||
// metadata that can come only from tracks
|
// metadata that can come only from tracks
|
||||||
@@ -307,7 +307,7 @@ func (m *MPRISHandler) SetVolume(v float64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MPRISHandler) Position() (int64, error) {
|
func (m *MPRISHandler) Position() (int64, error) {
|
||||||
return int64(secondsToMicroseconds(m.pm.PlayerStatus().TimePos)), nil
|
return int64(secondsToMicroseconds(m.pm.PlaybackStatus().TimePos)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MPRISHandler) MinimumRate() (float64, error) {
|
func (m *MPRISHandler) MinimumRate() (float64, error) {
|
||||||
|
|||||||
+31
-18
@@ -40,6 +40,14 @@ const (
|
|||||||
LoopOne
|
LoopOne
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PlaybackState = player.State
|
||||||
|
|
||||||
|
type PlaybackStatus struct {
|
||||||
|
State PlaybackState
|
||||||
|
TimePos float64
|
||||||
|
Duration float64
|
||||||
|
}
|
||||||
|
|
||||||
type playbackEngine struct {
|
type playbackEngine struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancelPollPos context.CancelFunc
|
cancelPollPos context.CancelFunc
|
||||||
@@ -65,8 +73,8 @@ type playbackEngine struct {
|
|||||||
// and reset this to -1
|
// and reset this to -1
|
||||||
pendingTrackChangeNum int
|
pendingTrackChangeNum int
|
||||||
|
|
||||||
pendingPlayerChange bool
|
pendingPlayerChange bool
|
||||||
pendingPlayerChangeTimePos float64
|
pendingPlayerChangeStatus player.Status
|
||||||
|
|
||||||
// to pass to onSongChange listeners; clear once listeners have been called
|
// to pass to onSongChange listeners; clear once listeners have been called
|
||||||
lastScrobbled *mediaprovider.Track
|
lastScrobbled *mediaprovider.Track
|
||||||
@@ -155,7 +163,7 @@ func (p *playbackEngine) SetPlayer(pl player.BasePlayer) error {
|
|||||||
|
|
||||||
needToUnpause := false
|
needToUnpause := false
|
||||||
|
|
||||||
stat := p.PlayerStatus()
|
stat := p.CurrentPlayer().GetStatus()
|
||||||
if p.pendingPlayerChange {
|
if p.pendingPlayerChange {
|
||||||
stat.State = player.Paused
|
stat.State = player.Paused
|
||||||
}
|
}
|
||||||
@@ -165,9 +173,10 @@ func (p *playbackEngine) SetPlayer(pl player.BasePlayer) error {
|
|||||||
// nothing
|
// nothing
|
||||||
case player.Playing:
|
case player.Playing:
|
||||||
needToUnpause = true
|
needToUnpause = true
|
||||||
|
p.stopPollTimePos()
|
||||||
fallthrough
|
fallthrough
|
||||||
case player.Paused:
|
case player.Paused:
|
||||||
p.pendingPlayerChangeTimePos = stat.TimePos
|
p.pendingPlayerChangeStatus = stat
|
||||||
p.pendingPlayerChange = true
|
p.pendingPlayerChange = true
|
||||||
}
|
}
|
||||||
p.unregisterPlayerCallbacks(p.player)
|
p.unregisterPlayerCallbacks(p.player)
|
||||||
@@ -183,7 +192,7 @@ func (p *playbackEngine) SetPlayer(pl player.BasePlayer) error {
|
|||||||
p.registerPlayerCallbacks(pl)
|
p.registerPlayerCallbacks(pl)
|
||||||
|
|
||||||
if needToUnpause {
|
if needToUnpause {
|
||||||
p.playTrackAt(p.nowPlayingIdx, p.pendingPlayerChangeTimePos)
|
p.playTrackAt(p.nowPlayingIdx, p.pendingPlayerChangeStatus.TimePos)
|
||||||
p.pendingPlayerChange = false
|
p.pendingPlayerChange = false
|
||||||
}
|
}
|
||||||
p.invokeNoArgCallbacks(p.onPlayerChange)
|
p.invokeNoArgCallbacks(p.onPlayerChange)
|
||||||
@@ -239,8 +248,16 @@ func (p *playbackEngine) GetLoopMode() LoopMode {
|
|||||||
return p.loopMode
|
return p.loopMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *playbackEngine) PlayerStatus() player.Status {
|
func (p *playbackEngine) PlaybackStatus() PlaybackStatus {
|
||||||
return p.player.GetStatus()
|
stat := p.pendingPlayerChangeStatus
|
||||||
|
if !p.pendingPlayerChange {
|
||||||
|
stat = p.CurrentPlayer().GetStatus()
|
||||||
|
}
|
||||||
|
return PlaybackStatus{
|
||||||
|
State: stat.State,
|
||||||
|
TimePos: stat.TimePos,
|
||||||
|
Duration: stat.Duration,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *playbackEngine) SetVolume(vol int) error {
|
func (p *playbackEngine) SetVolume(vol int) error {
|
||||||
@@ -259,14 +276,14 @@ func (p *playbackEngine) CurrentPlayer() player.BasePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *playbackEngine) SeekNext() error {
|
func (p *playbackEngine) SeekNext() error {
|
||||||
if p.PlayerStatus().State == player.Stopped {
|
if p.PlaybackStatus().State == player.Stopped {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return p.PlayTrackAt(p.nowPlayingIdx + 1)
|
return p.PlayTrackAt(p.nowPlayingIdx + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *playbackEngine) SeekBackOrPrevious() error {
|
func (p *playbackEngine) SeekBackOrPrevious() error {
|
||||||
if p.nowPlayingIdx == 0 || p.PlayerStatus().TimePos > 3 {
|
if p.nowPlayingIdx == 0 || p.PlaybackStatus().TimePos > 3 {
|
||||||
return p.player.SeekSeconds(0)
|
return p.player.SeekSeconds(0)
|
||||||
}
|
}
|
||||||
return p.PlayTrackAt(p.nowPlayingIdx - 1)
|
return p.PlayTrackAt(p.nowPlayingIdx - 1)
|
||||||
@@ -274,7 +291,7 @@ func (p *playbackEngine) SeekBackOrPrevious() error {
|
|||||||
|
|
||||||
func (p *playbackEngine) SeekFwdBackN(n int) error {
|
func (p *playbackEngine) SeekFwdBackN(n int) error {
|
||||||
idx := p.nowPlayingIdx
|
idx := p.nowPlayingIdx
|
||||||
if n < 0 && p.PlayerStatus().TimePos > 3 {
|
if n < 0 && p.PlaybackStatus().TimePos > 3 {
|
||||||
n += 1 // first seek back is just seek to beginning of current
|
n += 1 // first seek back is just seek to beginning of current
|
||||||
}
|
}
|
||||||
if n == 0 || (idx == 0 && n < 0) {
|
if n == 0 || (idx == 0 && n < 0) {
|
||||||
@@ -310,15 +327,11 @@ func (p *playbackEngine) Pause() error {
|
|||||||
|
|
||||||
func (p *playbackEngine) Continue() error {
|
func (p *playbackEngine) Continue() error {
|
||||||
if p.pendingPlayerChange {
|
if p.pendingPlayerChange {
|
||||||
err := p.PlayTrackAt(p.nowPlayingIdx)
|
|
||||||
if p.pendingPlayerChangeTimePos != 0 {
|
|
||||||
p.SeekSeconds(p.pendingPlayerChangeTimePos)
|
|
||||||
}
|
|
||||||
p.pendingPlayerChange = false
|
p.pendingPlayerChange = false
|
||||||
return err
|
return p.playTrackAt(p.nowPlayingIdx, p.pendingPlayerChangeStatus.TimePos)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.PlayerStatus().State == player.Stopped {
|
if p.PlaybackStatus().State == player.Stopped {
|
||||||
return p.PlayTrackAt(0)
|
return p.PlayTrackAt(0)
|
||||||
}
|
}
|
||||||
return p.player.Continue()
|
return p.player.Continue()
|
||||||
@@ -548,7 +561,7 @@ func (p *playbackEngine) handleOnTrackChange() {
|
|||||||
p.checkScrobble()
|
p.checkScrobble()
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.PlayerStatus().State == player.Playing {
|
if p.PlaybackStatus().State == player.Playing {
|
||||||
p.playTimeStopwatch.Start()
|
p.playTimeStopwatch.Start()
|
||||||
}
|
}
|
||||||
if p.pendingTrackChangeNum < 0 && (p.wasStopped || p.loopMode != LoopOne) {
|
if p.pendingTrackChangeNum < 0 && (p.wasStopped || p.loopMode != LoopOne) {
|
||||||
@@ -785,7 +798,7 @@ func (p *playbackEngine) doUpdateTimePos(seeked bool) {
|
|||||||
if p.callbacksDisabled {
|
if p.callbacksDisabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s := p.PlayerStatus()
|
s := p.PlaybackStatus()
|
||||||
if s.TimePos > p.latestTrackPosition {
|
if s.TimePos > p.latestTrackPosition {
|
||||||
p.latestTrackPosition = s.TimePos
|
p.latestTrackPosition = s.TimePos
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func (p *PlaybackManager) addOnTrackChangeHook() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// workaround for https://github.com/dweymouth/supersonic/issues/483 (see above comment)
|
// workaround for https://github.com/dweymouth/supersonic/issues/483 (see above comment)
|
||||||
if p.NowPlayingIndex() != len(p.engine.playQueue) && p.PlayerStatus().State == player.Playing {
|
if p.NowPlayingIndex() != len(p.engine.playQueue) && p.PlaybackStatus().State == player.Playing {
|
||||||
p.lastPlayTime = 0
|
p.lastPlayTime = 0
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(300 * time.Millisecond)
|
time.Sleep(300 * time.Millisecond)
|
||||||
@@ -476,8 +476,8 @@ func (p *PlaybackManager) IsAutoplay() bool {
|
|||||||
return p.autoplay
|
return p.autoplay
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PlaybackManager) PlayerStatus() player.Status {
|
func (p *PlaybackManager) PlaybackStatus() PlaybackStatus {
|
||||||
return p.engine.PlayerStatus()
|
return p.engine.PlaybackStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PlaybackManager) SetVolume(vol int) {
|
func (p *PlaybackManager) SetVolume(vol int) {
|
||||||
@@ -510,7 +510,7 @@ func (p *PlaybackManager) SeekSeconds(sec float64) {
|
|||||||
|
|
||||||
// Seek by given relative position in the current track by seconds.
|
// Seek by given relative position in the current track by seconds.
|
||||||
func (p *PlaybackManager) SeekBySeconds(sec float64) {
|
func (p *PlaybackManager) SeekBySeconds(sec float64) {
|
||||||
status := p.engine.PlayerStatus()
|
status := p.engine.PlaybackStatus()
|
||||||
target := status.TimePos + sec
|
target := status.TimePos + sec
|
||||||
if target < 0 {
|
if target < 0 {
|
||||||
target = 0
|
target = 0
|
||||||
@@ -548,7 +548,7 @@ func (p *PlaybackManager) Continue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PlaybackManager) PlayPause() {
|
func (p *PlaybackManager) PlayPause() {
|
||||||
switch p.engine.PlayerStatus().State {
|
switch p.engine.PlaybackStatus().State {
|
||||||
case player.Playing:
|
case player.Playing:
|
||||||
p.Pause()
|
p.Pause()
|
||||||
case player.Paused:
|
case player.Paused:
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type serializedSavedPlayQueue struct {
|
|||||||
// If the provided CanSavePlayQueue server is non-nil, it will also save to the server.
|
// If the provided CanSavePlayQueue server is non-nil, it will also save to the server.
|
||||||
func SavePlayQueue(serverID string, pm *PlaybackManager, filepath string, server mediaprovider.CanSavePlayQueue) error {
|
func SavePlayQueue(serverID string, pm *PlaybackManager, filepath string, server mediaprovider.CanSavePlayQueue) error {
|
||||||
queue := pm.GetPlayQueue()
|
queue := pm.GetPlayQueue()
|
||||||
stats := pm.PlayerStatus()
|
stats := pm.PlaybackStatus()
|
||||||
trackIdx := pm.NowPlayingIndex()
|
trackIdx := pm.NowPlayingIndex()
|
||||||
|
|
||||||
trackIDs := make([]string, 0, len(queue))
|
trackIDs := make([]string, 0, len(queue))
|
||||||
|
|||||||
@@ -443,7 +443,7 @@ func (a *NowPlayingPage) Reload() {
|
|||||||
}
|
}
|
||||||
switch a.tabs.SelectedIndex() {
|
switch a.tabs.SelectedIndex() {
|
||||||
case 1: /*lyrics*/
|
case 1: /*lyrics*/
|
||||||
a.lastPlayPos = a.pm.PlayerStatus().TimePos
|
a.lastPlayPos = a.pm.PlaybackStatus().TimePos
|
||||||
a.updateLyrics()
|
a.updateLyrics()
|
||||||
case 2: /*related*/
|
case 2: /*related*/
|
||||||
a.updateRelatedList()
|
a.updateRelatedList()
|
||||||
@@ -527,7 +527,7 @@ func (a *NowPlayingPage) saveSelectedTab(tabNum int) {
|
|||||||
|
|
||||||
func (a *NowPlayingPage) formatStatusLine() {
|
func (a *NowPlayingPage) formatStatusLine() {
|
||||||
curPlayer := a.pm.CurrentPlayer()
|
curPlayer := a.pm.CurrentPlayer()
|
||||||
playerStats := a.pm.PlayerStatus()
|
playerStats := a.pm.PlaybackStatus()
|
||||||
lastStatus := a.statusLabel.Text
|
lastStatus := a.statusLabel.Text
|
||||||
stopped := lang.L("Stopped")
|
stopped := lang.L("Stopped")
|
||||||
state := stopped
|
state := stopped
|
||||||
|
|||||||
@@ -155,6 +155,9 @@ func (m *Controller) ShowCastMenu(onPendingPlayerChange func()) {
|
|||||||
rp := m.App.PlaybackManager.CurrentRemotePlayer()
|
rp := m.App.PlaybackManager.CurrentRemotePlayer()
|
||||||
devices := m.App.PlaybackManager.RemotePlayers()
|
devices := m.App.PlaybackManager.RemotePlayers()
|
||||||
local := fyne.NewMenuItem(lang.L("This computer"), func() {
|
local := fyne.NewMenuItem(lang.L("This computer"), func() {
|
||||||
|
if rp == nil {
|
||||||
|
return // no-op. already not casting
|
||||||
|
}
|
||||||
onPendingPlayerChange()
|
onPendingPlayerChange()
|
||||||
go func() {
|
go func() {
|
||||||
if err := m.App.PlaybackManager.SetRemotePlayer(nil); err != nil {
|
if err := m.App.PlaybackManager.SetRemotePlayer(nil); err != nil {
|
||||||
@@ -168,7 +171,11 @@ func (m *Controller) ShowCastMenu(onPendingPlayerChange func()) {
|
|||||||
menu := fyne.NewMenu("", local)
|
menu := fyne.NewMenu("", local)
|
||||||
for _, d := range devices {
|
for _, d := range devices {
|
||||||
_d := d
|
_d := d
|
||||||
|
isCurrent := rp != nil && _d.URL == rp.URL
|
||||||
item := fyne.NewMenuItem(d.Name, func() {
|
item := fyne.NewMenuItem(d.Name, func() {
|
||||||
|
if isCurrent {
|
||||||
|
return // no-op.
|
||||||
|
}
|
||||||
onPendingPlayerChange()
|
onPendingPlayerChange()
|
||||||
go func() {
|
go func() {
|
||||||
if err := m.App.PlaybackManager.SetRemotePlayer(&_d); err != nil {
|
if err := m.App.PlaybackManager.SetRemotePlayer(&_d); err != nil {
|
||||||
@@ -177,7 +184,7 @@ func (m *Controller) ShowCastMenu(onPendingPlayerChange func()) {
|
|||||||
}()
|
}()
|
||||||
})
|
})
|
||||||
item.Icon = myTheme.CastIcon
|
item.Icon = myTheme.CastIcon
|
||||||
item.Checked = rp != nil && _d.URL == rp.URL
|
item.Checked = isCurrent
|
||||||
menu.Items = append(menu.Items, item)
|
menu.Items = append(menu.Items, item)
|
||||||
}
|
}
|
||||||
pop := widget.NewPopUpMenu(menu, m.MainWindow.Canvas())
|
pop := widget.NewPopUpMenu(menu, m.MainWindow.Canvas())
|
||||||
|
|||||||
Reference in New Issue
Block a user