Merge pull request #793 from Tim-Kaiser/ISSUE/787
Fixes #787 : StopAfterCurrent shouldn't clear the queue
This commit is contained in:
+2
-2
@@ -598,8 +598,8 @@ func (a *App) checkFlagsAndSendIPCMsg(cli *ipc.Client) error {
|
|||||||
return cli.SeekNext()
|
return cli.SeekNext()
|
||||||
case *FlagStop:
|
case *FlagStop:
|
||||||
return cli.Stop()
|
return cli.Stop()
|
||||||
case *FlagStopAfterCurrent:
|
case *FlagPauseAfterCurrent:
|
||||||
return cli.StopAfterCurrent()
|
return cli.PauseAfterCurrent()
|
||||||
case *FlagShow:
|
case *FlagShow:
|
||||||
return cli.Show()
|
return cli.Show()
|
||||||
case VolumeCLIArg >= 0:
|
case VolumeCLIArg >= 0:
|
||||||
|
|||||||
+12
-12
@@ -22,18 +22,18 @@ var (
|
|||||||
SearchPlaylistCLIArg string = ""
|
SearchPlaylistCLIArg string = ""
|
||||||
SearchTrackCLIArg string = ""
|
SearchTrackCLIArg string = ""
|
||||||
|
|
||||||
FlagPlay = flag.Bool("play", false, "unpause or begin playback")
|
FlagPlay = flag.Bool("play", false, "unpause or begin playback")
|
||||||
FlagPause = flag.Bool("pause", false, "pause playback")
|
FlagPause = flag.Bool("pause", false, "pause playback")
|
||||||
FlagPlayPause = flag.Bool("play-pause", false, "toggle play/pause state")
|
FlagPlayPause = flag.Bool("play-pause", false, "toggle play/pause state")
|
||||||
FlagPrevious = flag.Bool("previous", false, "seek to previous track or beginning of current")
|
FlagPrevious = flag.Bool("previous", false, "seek to previous track or beginning of current")
|
||||||
FlagNext = flag.Bool("next", false, "seek to next track")
|
FlagNext = flag.Bool("next", false, "seek to next track")
|
||||||
FlagStop = flag.Bool("stop", false, "stop playback")
|
FlagStop = flag.Bool("stop", false, "stop playback")
|
||||||
FlagStopAfterCurrent = flag.Bool("stop-after-current", false, "stop playback after current track")
|
FlagPauseAfterCurrent = flag.Bool("pause-after-current", false, "pause playback after current track")
|
||||||
FlagStartMinimized = flag.Bool("start-minimized", false, "start app minimized")
|
FlagStartMinimized = flag.Bool("start-minimized", false, "start app minimized")
|
||||||
FlagShow = flag.Bool("show", false, "show minimized app")
|
FlagShow = flag.Bool("show", false, "show minimized app")
|
||||||
FlagShuffle = flag.Bool("shuffle", false, "shuffle the tracklist (to be used with either -play-album-by-id or -play-playlist-by-id)")
|
FlagShuffle = flag.Bool("shuffle", false, "shuffle the tracklist (to be used with either -play-album-by-id or -play-playlist-by-id)")
|
||||||
FlagVersion = flag.Bool("version", false, "print app version and exit")
|
FlagVersion = flag.Bool("version", false, "print app version and exit")
|
||||||
FlagHelp = flag.Bool("help", false, "print command line options and exit")
|
FlagHelp = flag.Bool("help", false, "print command line options and exit")
|
||||||
|
|
||||||
FlagPlayAlbum *bool
|
FlagPlayAlbum *bool
|
||||||
FlagPlayPlaylist *bool
|
FlagPlayPlaylist *bool
|
||||||
|
|||||||
+20
-20
@@ -7,26 +7,26 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PingPath = "/ping"
|
PingPath = "/ping"
|
||||||
PlayPath = "/transport/play"
|
PlayPath = "/transport/play"
|
||||||
PlayAlbumPath = "/transport/play-album" // ?id=<album ID>&t=<firstTrack>&s=<shuffle>
|
PlayAlbumPath = "/transport/play-album" // ?id=<album ID>&t=<firstTrack>&s=<shuffle>
|
||||||
PlayPlaylistPath = "/transport/play-playlist" // ?id=<playlist ID>&t=<firstTrack>&s=<shuffle>
|
PlayPlaylistPath = "/transport/play-playlist" // ?id=<playlist ID>&t=<firstTrack>&s=<shuffle>
|
||||||
PlayTrackPath = "/transport/play-track" // ?id=<track ID>
|
PlayTrackPath = "/transport/play-track" // ?id=<track ID>
|
||||||
SearchAlbumPath = "/transport/search-album" // ?s=<searchQuery>
|
SearchAlbumPath = "/transport/search-album" // ?s=<searchQuery>
|
||||||
SearchPlaylistPath = "/transport/search-playlist" // ?s=<searchQuery>
|
SearchPlaylistPath = "/transport/search-playlist" // ?s=<searchQuery>
|
||||||
SearchTrackPath = "/transport/search-track" // ?s=<searchQuery>
|
SearchTrackPath = "/transport/search-track" // ?s=<searchQuery>
|
||||||
PlayPausePath = "/transport/playpause"
|
PlayPausePath = "/transport/playpause"
|
||||||
PausePath = "/transport/pause"
|
PausePath = "/transport/pause"
|
||||||
StopPath = "/transport/stop"
|
StopPath = "/transport/stop"
|
||||||
StopAfterCurrentPath = "/transport/stop-after-current"
|
PauseAfterCurrentPath = "/transport/pause-after-current"
|
||||||
PreviousPath = "/transport/previous"
|
PreviousPath = "/transport/previous"
|
||||||
NextPath = "/transport/next"
|
NextPath = "/transport/next"
|
||||||
TimePosPath = "/transport/timepos" // ?s=<seconds>
|
TimePosPath = "/transport/timepos" // ?s=<seconds>
|
||||||
SeekByPath = "/transport/seek-by" // ?s=<+/- seconds>
|
SeekByPath = "/transport/seek-by" // ?s=<+/- seconds>
|
||||||
VolumePath = "/volume" // ?v=<vol>
|
VolumePath = "/volume" // ?v=<vol>
|
||||||
VolumeAdjustPath = "/volume/adjust" // ?pct=<+/- percentage>
|
VolumeAdjustPath = "/volume/adjust" // ?pct=<+/- percentage>
|
||||||
ShowPath = "/window/show"
|
ShowPath = "/window/show"
|
||||||
QuitPath = "/window/quit"
|
QuitPath = "/window/quit"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Response struct {
|
type Response struct {
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ func (c *Client) Stop() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) StopAfterCurrent() error {
|
func (c *Client) PauseAfterCurrent() error {
|
||||||
_, err := c.sendRequest(StopAfterCurrentPath)
|
_, err := c.sendRequest(PauseAfterCurrentPath)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type PlaybackHandler interface {
|
|||||||
Continue()
|
Continue()
|
||||||
SeekBackOrPrevious()
|
SeekBackOrPrevious()
|
||||||
SeekNext()
|
SeekNext()
|
||||||
SetStopAfterCurrent(bool)
|
SetPauseAfterCurrent(bool)
|
||||||
SeekSeconds(float64)
|
SeekSeconds(float64)
|
||||||
SeekBySeconds(float64)
|
SeekBySeconds(float64)
|
||||||
Volume() int
|
Volume() int
|
||||||
@@ -83,8 +83,8 @@ func (s *serverImpl) createHandler() http.Handler {
|
|||||||
m.HandleFunc(PausePath, s.makeSimpleEndpointHandler(s.pbHandler.Pause))
|
m.HandleFunc(PausePath, s.makeSimpleEndpointHandler(s.pbHandler.Pause))
|
||||||
m.HandleFunc(PlayPausePath, s.makeSimpleEndpointHandler(s.pbHandler.PlayPause))
|
m.HandleFunc(PlayPausePath, s.makeSimpleEndpointHandler(s.pbHandler.PlayPause))
|
||||||
m.HandleFunc(StopPath, s.makeSimpleEndpointHandler(s.pbHandler.Stop))
|
m.HandleFunc(StopPath, s.makeSimpleEndpointHandler(s.pbHandler.Stop))
|
||||||
m.HandleFunc(StopAfterCurrentPath, s.makeSimpleEndpointHandler(func() {
|
m.HandleFunc(PauseAfterCurrentPath, s.makeSimpleEndpointHandler(func() {
|
||||||
s.pbHandler.SetStopAfterCurrent(true)
|
s.pbHandler.SetPauseAfterCurrent(true)
|
||||||
}))
|
}))
|
||||||
m.HandleFunc(PreviousPath, s.makeSimpleEndpointHandler(s.pbHandler.SeekBackOrPrevious))
|
m.HandleFunc(PreviousPath, s.makeSimpleEndpointHandler(s.pbHandler.SeekBackOrPrevious))
|
||||||
m.HandleFunc(NextPath, s.makeSimpleEndpointHandler(s.pbHandler.SeekNext))
|
m.HandleFunc(NextPath, s.makeSimpleEndpointHandler(s.pbHandler.SeekNext))
|
||||||
|
|||||||
+11
-10
@@ -66,7 +66,7 @@ type playbackEngine struct {
|
|||||||
isRadio bool
|
isRadio bool
|
||||||
loopMode LoopMode
|
loopMode LoopMode
|
||||||
|
|
||||||
stopAfterCurrent bool // flag to stop playback after current track ends
|
pauseAfterCurrent bool // flag to pause playback after current track ends
|
||||||
|
|
||||||
// flags for handleOnTrackChange / handleOnStopped callbacks - reset to false in the callbacks
|
// flags for handleOnTrackChange / handleOnStopped callbacks - reset to false in the callbacks
|
||||||
wasStopped bool // true iff player was stopped before handleOnTrackChange invocation
|
wasStopped bool // true iff player was stopped before handleOnTrackChange invocation
|
||||||
@@ -337,13 +337,8 @@ func (p *playbackEngine) Stop() error {
|
|||||||
return p.player.Stop(false)
|
return p.player.Stop(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *playbackEngine) SetStopAfterCurrent(stopAfterCurrent bool) {
|
func (p *playbackEngine) SetPauseAfterCurrent(pauseAfterCurrent bool) {
|
||||||
p.stopAfterCurrent = stopAfterCurrent
|
p.pauseAfterCurrent = pauseAfterCurrent
|
||||||
if p.stopAfterCurrent {
|
|
||||||
p.setNextTrack(-1) // clear next playing track from internal player, if any
|
|
||||||
} else if p.loopMode != LoopNone || p.nowPlayingIdx < len(p.playQueue)-1 {
|
|
||||||
p.needToSetNextTrack = true // need to restore next track to internal player queue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *playbackEngine) Pause() error {
|
func (p *playbackEngine) Pause() error {
|
||||||
@@ -632,6 +627,12 @@ func (p *playbackEngine) handleOnTrackChange() {
|
|||||||
p.invokeOnSongChangeCallbacks()
|
p.invokeOnSongChangeCallbacks()
|
||||||
p.handleTimePosUpdate(false)
|
p.handleTimePosUpdate(false)
|
||||||
p.handleNextTrackUpdated()
|
p.handleNextTrackUpdated()
|
||||||
|
|
||||||
|
if p.pauseAfterCurrent {
|
||||||
|
p.Pause()
|
||||||
|
p.SetPauseAfterCurrent(false)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *playbackEngine) handleOnStopped() {
|
func (p *playbackEngine) handleOnStopped() {
|
||||||
@@ -646,7 +647,7 @@ func (p *playbackEngine) handleOnStopped() {
|
|||||||
p.alreadyScrobbled = false
|
p.alreadyScrobbled = false
|
||||||
p.wasStopped = true
|
p.wasStopped = true
|
||||||
p.nowPlayingIdx = -1
|
p.nowPlayingIdx = -1
|
||||||
p.stopAfterCurrent = false
|
p.pauseAfterCurrent = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be invoked as soon as the next item in the queue that should play changes
|
// to be invoked as soon as the next item in the queue that should play changes
|
||||||
@@ -868,7 +869,7 @@ func (p *playbackEngine) handleTimePosUpdate(seeked bool) {
|
|||||||
meta = np.Metadata()
|
meta = np.Metadata()
|
||||||
}
|
}
|
||||||
isNearEnd := meta.Type != mediaprovider.MediaItemTypeRadioStation && s.TimePos > meta.Duration.Seconds()-10
|
isNearEnd := meta.Type != mediaprovider.MediaItemTypeRadioStation && s.TimePos > meta.Duration.Seconds()-10
|
||||||
if p.needToSetNextTrack && !p.stopAfterCurrent && isNearEnd {
|
if p.needToSetNextTrack && isNearEnd {
|
||||||
p.needToSetNextTrack = false
|
p.needToSetNextTrack = false
|
||||||
p.setNextTrack(p.nextPlayingIndex())
|
p.setNextTrack(p.nextPlayingIndex())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -687,12 +687,12 @@ func (p *PlaybackManager) PlayPause() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PlaybackManager) SetStopAfterCurrent(stopAfterCurrent bool) {
|
func (p *PlaybackManager) SetPauseAfterCurrent(pauseAfterCurrent bool) {
|
||||||
p.engine.SetStopAfterCurrent(stopAfterCurrent)
|
p.engine.SetPauseAfterCurrent(pauseAfterCurrent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PlaybackManager) IsStopAfterCurrent() bool {
|
func (p *PlaybackManager) IsPauseAfterCurrent() bool {
|
||||||
return p.engine.stopAfterCurrent
|
return p.engine.pauseAfterCurrent
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PlaybackManager) enqueueAutoplayTracks() {
|
func (p *PlaybackManager) enqueueAutoplayTracks() {
|
||||||
@@ -827,7 +827,14 @@ func (p *PlaybackManager) runCmdQueue(ctx context.Context) {
|
|||||||
case cmdForceRestartPlayback:
|
case cmdForceRestartPlayback:
|
||||||
if mpv, ok := p.engine.CurrentPlayer().(*mpv.Player); ok {
|
if mpv, ok := p.engine.CurrentPlayer().(*mpv.Player); ok {
|
||||||
log.Println("Force-restarting MPV playback")
|
log.Println("Force-restarting MPV playback")
|
||||||
mpv.ForceRestartPlayback()
|
|
||||||
|
// restart player, but perserve the state
|
||||||
|
isPaused := false
|
||||||
|
stat := p.engine.CurrentPlayer().GetStatus()
|
||||||
|
if stat.State == player.Paused {
|
||||||
|
isPaused = true
|
||||||
|
}
|
||||||
|
mpv.ForceRestartPlayback(isPaused)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.OnDone != nil {
|
if c.OnDone != nil {
|
||||||
|
|||||||
@@ -349,9 +349,10 @@ func (p *Player) Continue() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) ForceRestartPlayback() error {
|
func (p *Player) ForceRestartPlayback(isPaused bool) error {
|
||||||
p.mpv.SetProperty("pause", mpv.FORMAT_FLAG, true)
|
p.mpv.SetProperty("pause", mpv.FORMAT_FLAG, true)
|
||||||
return p.mpv.SetProperty("pause", mpv.FORMAT_FLAG, false)
|
p.mpv.SetProperty("pause", mpv.FORMAT_FLAG, false)
|
||||||
|
return p.mpv.SetProperty("pause", mpv.FORMAT_FLAG, isPaused)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current status of the player.
|
// Get the current status of the player.
|
||||||
|
|||||||
@@ -229,6 +229,7 @@
|
|||||||
"Unset favorite": "Von Favoriten entfernen",
|
"Unset favorite": "Von Favoriten entfernen",
|
||||||
"Remove from queue": "Aus Wiedergabeliste entfernen",
|
"Remove from queue": "Aus Wiedergabeliste entfernen",
|
||||||
"Play song radio": "Liedradio abspielen",
|
"Play song radio": "Liedradio abspielen",
|
||||||
|
"Pause after current track": "Nach dem aktuellen Lied pausieren",
|
||||||
"to": "bis",
|
"to": "bis",
|
||||||
"by": "von",
|
"by": "von",
|
||||||
"Jan": "Jan",
|
"Jan": "Jan",
|
||||||
|
|||||||
@@ -228,7 +228,7 @@
|
|||||||
"Soundtrack": "Soundtrack",
|
"Soundtrack": "Soundtrack",
|
||||||
"Spoken Word": "Spoken Word",
|
"Spoken Word": "Spoken Word",
|
||||||
"Startup page": "Startup page",
|
"Startup page": "Startup page",
|
||||||
"Stop after current track": "Stop after current track",
|
"Pause after current track": "Pause after current track",
|
||||||
"Stopped": "Stopped",
|
"Stopped": "Stopped",
|
||||||
"Success": "Success",
|
"Success": "Success",
|
||||||
"Successfully created playlist": "Successfully created playlist",
|
"Successfully created playlist": "Successfully created playlist",
|
||||||
|
|||||||
@@ -219,7 +219,7 @@
|
|||||||
"Soundtrack": "Bande originale",
|
"Soundtrack": "Bande originale",
|
||||||
"Spoken Word": "Spoken Word",
|
"Spoken Word": "Spoken Word",
|
||||||
"Startup page": "Page de démarrage",
|
"Startup page": "Page de démarrage",
|
||||||
"Stop after current track": "Arrêter après la piste en cours",
|
"Pause after current track": "Arrêter après la piste en cours",
|
||||||
"Stopped": "Arrêté",
|
"Stopped": "Arrêté",
|
||||||
"Success": "Succès",
|
"Success": "Succès",
|
||||||
"Support the project": "Soutenir le projet",
|
"Support the project": "Soutenir le projet",
|
||||||
@@ -283,9 +283,8 @@
|
|||||||
"Oct": "Oct",
|
"Oct": "Oct",
|
||||||
"Nov": "Nov",
|
"Nov": "Nov",
|
||||||
"Dec": "Déc",
|
"Dec": "Déc",
|
||||||
|
|
||||||
"playlist.addedtracks": {
|
"playlist.addedtracks": {
|
||||||
"one": "Une piste ajoutée à la liste de lecture",
|
"one": "Une piste ajoutée à la liste de lecture",
|
||||||
"other": "{{.trackCount}} pistes ajoutées à la liste de lecture"
|
"other": "{{.trackCount}} pistes ajoutées à la liste de lecture"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ type Controller struct {
|
|||||||
|
|
||||||
popUpQueue *widget.PopUp
|
popUpQueue *widget.PopUp
|
||||||
popUpQueueList *widgets.PlayQueueList
|
popUpQueueList *widgets.PlayQueueList
|
||||||
stopAfterCurrent *widget.Check
|
pauseAfterCurrent *widget.Check
|
||||||
popUpQueueLastUsed int64
|
popUpQueueLastUsed int64
|
||||||
escapablePopUp fyne.CanvasObject
|
escapablePopUp fyne.CanvasObject
|
||||||
haveModal bool
|
haveModal bool
|
||||||
@@ -198,10 +198,10 @@ func (m *Controller) ShowPopUpPlayQueue() {
|
|||||||
title := widget.NewRichTextWithText(lang.L("Play Queue"))
|
title := widget.NewRichTextWithText(lang.L("Play Queue"))
|
||||||
title.Segments[0].(*widget.TextSegment).Style.Alignment = fyne.TextAlignCenter
|
title.Segments[0].(*widget.TextSegment).Style.Alignment = fyne.TextAlignCenter
|
||||||
title.Segments[0].(*widget.TextSegment).Style.TextStyle.Bold = true
|
title.Segments[0].(*widget.TextSegment).Style.TextStyle.Bold = true
|
||||||
m.stopAfterCurrent = widget.NewCheck(lang.L("Stop after current track"), func(b bool) {
|
m.pauseAfterCurrent = widget.NewCheck(lang.L("Pause after current track"), func(b bool) {
|
||||||
m.App.PlaybackManager.SetStopAfterCurrent(b)
|
m.App.PlaybackManager.SetPauseAfterCurrent(b)
|
||||||
})
|
})
|
||||||
bottomRow := container.NewHBox(layout.NewSpacer(), m.stopAfterCurrent)
|
bottomRow := container.NewHBox(layout.NewSpacer(), m.pauseAfterCurrent)
|
||||||
ctr := container.NewBorder(title, bottomRow, nil, nil,
|
ctr := container.NewBorder(title, bottomRow, nil, nil,
|
||||||
container.NewPadded(m.popUpQueueList),
|
container.NewPadded(m.popUpQueueList),
|
||||||
)
|
)
|
||||||
@@ -231,7 +231,7 @@ func (m *Controller) ShowPopUpPlayQueue() {
|
|||||||
fynetooltip.DestroyPopUpToolTipLayer(m.popUpQueue)
|
fynetooltip.DestroyPopUpToolTipLayer(m.popUpQueue)
|
||||||
m.popUpQueue = nil
|
m.popUpQueue = nil
|
||||||
m.popUpQueueList = nil
|
m.popUpQueueList = nil
|
||||||
m.stopAfterCurrent = nil
|
m.pauseAfterCurrent = nil
|
||||||
m.popUpQueueLastUsed = 0
|
m.popUpQueueLastUsed = 0
|
||||||
t.Stop()
|
t.Stop()
|
||||||
return
|
return
|
||||||
@@ -260,7 +260,7 @@ func (m *Controller) ShowPopUpPlayQueue() {
|
|||||||
))
|
))
|
||||||
pop.Resize(size)
|
pop.Resize(size)
|
||||||
popUpQueueList.ScrollToNowPlaying() // must come after resize
|
popUpQueueList.ScrollToNowPlaying() // must come after resize
|
||||||
m.stopAfterCurrent.SetChecked(m.App.PlaybackManager.IsStopAfterCurrent())
|
m.pauseAfterCurrent.SetChecked(m.App.PlaybackManager.IsPauseAfterCurrent())
|
||||||
pop.ShowAtPosition(fyne.NewPos(
|
pop.ShowAtPosition(fyne.NewPos(
|
||||||
canvasSize.Width-size.Width-10,
|
canvasSize.Width-size.Width-10,
|
||||||
canvasSize.Height-size.Height-100,
|
canvasSize.Height-size.Height-100,
|
||||||
|
|||||||
Reference in New Issue
Block a user