diff --git a/backend/app.go b/backend/app.go index 39461148..06f1fc96 100644 --- a/backend/app.go +++ b/backend/app.go @@ -361,6 +361,7 @@ func (a *App) Shutdown() { repeatMode = "All" } a.Config.Playback.RepeatMode = repeatMode + a.Config.Playback.Autoplay = a.PlaybackManager.IsAutoplay() a.Config.LocalPlayback.Volume = a.LocalPlayer.GetVolume() a.SavePlayQueueIfEnabled() a.SaveConfigFile() diff --git a/backend/config.go b/backend/config.go index 41626fcb..6b88f42b 100644 --- a/backend/config.go +++ b/backend/config.go @@ -99,6 +99,7 @@ type NowPlayingPageConfig struct { } type PlaybackConfig struct { + Autoplay bool RepeatMode string } @@ -215,6 +216,7 @@ func DefaultConfig(appVersionTag string) *Config { TracklistColumns: []string{"Album", "Time", "Plays"}, }, Playback: PlaybackConfig{ + Autoplay: false, RepeatMode: "None", }, LocalPlayback: LocalPlaybackConfig{ diff --git a/backend/playbackmanager.go b/backend/playbackmanager.go index a175064d..6d985044 100644 --- a/backend/playbackmanager.go +++ b/backend/playbackmanager.go @@ -42,7 +42,7 @@ func NewPlaybackManager( engine: e, cmdQueue: q, cfg: appCfg, - autoplay: true, // TODO + autoplay: playbackCfg.Autoplay, } pm.addOnTrackChangeHook() go pm.runCmdQueue(ctx) @@ -364,6 +364,10 @@ func (p *PlaybackManager) GetLoopMode() LoopMode { return p.engine.loopMode } +func (p *PlaybackManager) IsAutoplay() bool { + return p.autoplay +} + func (p *PlaybackManager) PlayerStatus() player.Status { return p.engine.PlayerStatus() } @@ -372,6 +376,13 @@ func (p *PlaybackManager) SetVolume(vol int) { p.cmdQueue.SetVolume(vol) } +func (p *PlaybackManager) SetAutoplay(autoplay bool) { + p.autoplay = autoplay + if autoplay && p.NowPlayingIndex() == len(p.engine.playQueue)-1 { + p.enqueueAutoplayTracks() + } +} + func (p *PlaybackManager) Volume() int { return p.engine.CurrentPlayer().GetVolume() } diff --git a/res/bundled.go b/res/bundled.go index b0806e45..dfb3f955 100644 --- a/res/bundled.go +++ b/res/bundled.go @@ -40,6 +40,11 @@ var ResHeartOutlineSvg = &fyne.StaticResource{ StaticContent: []byte( ""), } +var ResInfinitySvg = &fyne.StaticResource{ + StaticName: "infinity.svg", + StaticContent: []byte( + "\n\n \n"), +} var ResMusicnotesSvg = &fyne.StaticResource{ StaticName: "musicnotes.svg", StaticContent: []byte( diff --git a/res/bundled_gen.sh b/res/bundled_gen.sh index aa21d2ea..a963c502 100755 --- a/res/bundled_gen.sh +++ b/res/bundled_gen.sh @@ -7,6 +7,7 @@ fyne bundle -append -prefix Res icons/publicdomain/disc.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/headphones.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/heart-filled.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/heart-outline.svg >> bundled.go +fyne bundle -append -prefix Res icons/publicdomain/infinity.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/musicnotes.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/people.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/playlist.svg >> bundled.go diff --git a/res/translations/en.json b/res/translations/en.json index bf7b4380..f5f8a853 100644 --- a/res/translations/en.json +++ b/res/translations/en.json @@ -28,6 +28,7 @@ "Audiobook": "Audiobook", "Authentication failed": "Authentication failed", "Auto": "Auto", + "Autoplay": "Autoplay", "Autoselect device": "Autoselect device", "Back": "Back", "Bit rate": "Bit rate", diff --git a/ui/bottompanel.go b/ui/bottompanel.go index 5851ffc9..09255710 100644 --- a/ui/bottompanel.go +++ b/ui/bottompanel.go @@ -102,7 +102,7 @@ func NewBottomPanel(pm *backend.PlaybackManager, im *backend.ImageManager, contr pm.SeekFraction(f) }) - bp.AuxControls = widgets.NewAuxControls(pm.Volume(), pm.GetLoopMode()) + bp.AuxControls = widgets.NewAuxControls(pm.Volume(), pm.GetLoopMode(), pm.IsAutoplay()) pm.OnLoopModeChange(bp.AuxControls.SetLoopMode) pm.OnVolumeChange(bp.AuxControls.VolumeControl.SetVolume) bp.AuxControls.VolumeControl.OnSetVolume = func(v int) { @@ -111,6 +111,9 @@ func NewBottomPanel(pm *backend.PlaybackManager, im *backend.ImageManager, contr bp.AuxControls.OnChangeLoopMode(func() { pm.SetNextLoopMode() }) + bp.AuxControls.OnChangeAutoplay = func(autoplay bool) { + pm.SetAutoplay(autoplay) + } bp.AuxControls.OnShowPlayQueue(contr.ShowPopUpPlayQueue) bp.imageLoader = util.NewThumbnailLoader(im, bp.NowPlaying.SetImage) diff --git a/ui/mainwindow.go b/ui/mainwindow.go index c8f1f89a..f6fbaa98 100644 --- a/ui/mainwindow.go +++ b/ui/mainwindow.go @@ -160,6 +160,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string, repeatMode = "All" } app.Config.Playback.RepeatMode = repeatMode + app.Config.Playback.Autoplay = app.PlaybackManager.IsAutoplay() app.SavePlayQueueIfEnabled() app.SaveConfigFile() diff --git a/ui/theme/theme.go b/ui/theme/theme.go index 5f92cbce..a9a1bcc0 100644 --- a/ui/theme/theme.go +++ b/ui/theme/theme.go @@ -38,6 +38,7 @@ var ( AlbumIcon fyne.Resource = theme.NewThemedResource(res.ResDiscSvg) ArtistIcon fyne.Resource = theme.NewThemedResource(res.ResPeopleSvg) + AutoplayIcon fyne.Resource = theme.NewThemedResource(res.ResInfinitySvg) RadioIcon fyne.Resource = theme.NewThemedResource(res.ResBroadcastSvg) FavoriteIcon fyne.Resource = theme.NewThemedResource(res.ResHeartFilledSvg) NotFavoriteIcon fyne.Resource = theme.NewThemedResource(res.ResHeartOutlineSvg) diff --git a/ui/widgets/auxcontrols.go b/ui/widgets/auxcontrols.go index 582657d2..b5f7a1d7 100644 --- a/ui/widgets/auxcontrols.go +++ b/ui/widgets/auxcontrols.go @@ -18,21 +18,34 @@ import ( type AuxControls struct { widget.BaseWidget + OnChangeAutoplay func(autoplay bool) + VolumeControl *VolumeControl + autoplay *IconButton loop *IconButton showQueue *IconButton container *fyne.Container } -func NewAuxControls(initialVolume int, initialLoopMode backend.LoopMode) *AuxControls { +func NewAuxControls(initialVolume int, initialLoopMode backend.LoopMode, initialAutoplay bool) *AuxControls { a := &AuxControls{ VolumeControl: NewVolumeControl(initialVolume), + autoplay: NewIconButton(myTheme.AutoplayIcon, nil), loop: NewIconButton(myTheme.RepeatIcon, nil), showQueue: NewIconButton(myTheme.PlayQueueIcon, nil), } a.loop.IconSize = IconButtonSizeSmaller a.loop.SetToolTip(lang.L("Repeat")) + a.loop.Highlighted = initialAutoplay + //a.autoplay.IconSize = IconButtonSizeSmaller + a.autoplay.SetToolTip(lang.L("Autoplay")) + a.autoplay.OnTapped = func() { + a.SetAutoplay(!a.autoplay.Highlighted) + if a.OnChangeAutoplay != nil { + a.OnChangeAutoplay(a.autoplay.Highlighted) + } + } a.SetLoopMode(initialLoopMode) a.showQueue.IconSize = IconButtonSizeSmaller a.showQueue.SetToolTip(lang.L("Show play queue")) @@ -43,7 +56,7 @@ func NewAuxControls(initialVolume int, initialLoopMode backend.LoopMode) *AuxCon a.VolumeControl, container.New( layout.NewCustomPaddedHBoxLayout(theme.Padding()*1.5), - layout.NewSpacer(), a.loop, a.showQueue, util.NewHSpace(5)), + layout.NewSpacer(), a.autoplay, a.loop, a.showQueue, util.NewHSpace(5)), layout.NewSpacer(), ), ) @@ -73,6 +86,14 @@ func (a *AuxControls) SetLoopMode(mode backend.LoopMode) { } } +func (a *AuxControls) SetAutoplay(autoplay bool) { + if autoplay == a.autoplay.Highlighted { + return + } + a.autoplay.Highlighted = autoplay + a.autoplay.Refresh() +} + func (a *AuxControls) OnShowPlayQueue(f func()) { a.showQueue.OnTapped = f }