add AlbumFilter to backend album iterators

This commit is contained in:
Drew Weymouth
2023-05-11 08:54:18 -07:00
parent 5634dfcfc1
commit 882f951aa1
6 changed files with 68 additions and 21 deletions
+51 -13
View File
@@ -3,8 +3,10 @@ package backend
import (
"log"
"strconv"
"strings"
"github.com/dweymouth/go-subsonic/subsonic"
"github.com/dweymouth/supersonic/sharedutil"
)
type AlbumSortOrder string
@@ -33,36 +35,69 @@ var (
}
)
func (l *LibraryManager) AlbumsIter(sort AlbumSortOrder) AlbumIterator {
type AlbumFilter struct {
MinYear int
MaxYear int // 0 == unset/match any
Genres []string // len(0) == unset/match any
ExcludeFavorited bool // mut. exc. with ExcludeUnfavorited
ExcludeUnfavorited bool // mut. exc. with ExcludeFavorited
}
func (f *AlbumFilter) Matches(album *subsonic.AlbumID3) bool {
if album == nil {
return false
}
if f.ExcludeFavorited && !album.Starred.IsZero() {
return false
}
if f.ExcludeUnfavorited && album.Starred.IsZero() {
return false
}
if y := album.Year; y < f.MinYear || (f.MaxYear > 0 && y > f.MaxYear) {
return false
}
if len(f.Genres) == 0 {
return true
}
for _, g := range f.Genres {
if strings.EqualFold(g, album.Genre) {
return true
}
}
return false
}
func (l *LibraryManager) AlbumsIter(sort AlbumSortOrder, filter AlbumFilter) AlbumIterator {
switch sort {
case AlbumSortRecentlyAdded:
return l.newBaseIter("newest", make(map[string]string))
return l.newBaseIter("newest", filter, make(map[string]string))
case AlbumSortRecentlyPlayed:
return l.newBaseIter("recent", make(map[string]string))
return l.newBaseIter("recent", filter, make(map[string]string))
case AlbumSortFrequentlyPlayed:
return l.newBaseIter("frequent", make(map[string]string))
return l.newBaseIter("frequent", filter, make(map[string]string))
case AlbumSortRandom:
return l.newRandomIter()
case AlbumSortTitleAZ:
return l.newBaseIter("alphabeticalByName", make(map[string]string))
return l.newBaseIter("alphabeticalByName", filter, make(map[string]string))
case AlbumSortArtistAZ:
return l.newBaseIter("alphabeticalByArtist", make(map[string]string))
return l.newBaseIter("alphabeticalByArtist", filter, make(map[string]string))
case AlbumSortYearAscending:
return l.newBaseIter("byYear", map[string]string{"fromYear": "0", "toYear": "3000"})
return l.newBaseIter("byYear", filter, map[string]string{"fromYear": "0", "toYear": "3000"})
case AlbumSortYearDescending:
return l.newBaseIter("byYear", map[string]string{"fromYear": "3000", "toYear": "0"})
return l.newBaseIter("byYear", filter, map[string]string{"fromYear": "3000", "toYear": "0"})
default:
log.Printf("Undefined album sort order: %s", sort)
return nil
}
}
func (l *LibraryManager) StarredIter() AlbumIterator {
return l.newBaseIter("starred", make(map[string]string))
func (l *LibraryManager) StarredIter(filter AlbumFilter) AlbumIterator {
return l.newBaseIter("starred", filter, make(map[string]string))
}
func (l *LibraryManager) GenreIter(genre string) AlbumIterator {
return l.newBaseIter("byGenre", map[string]string{"genre": genre})
func (l *LibraryManager) GenreIter(genre string, filter AlbumFilter) AlbumIterator {
return l.newBaseIter("byGenre", filter, map[string]string{"genre": genre})
}
func (l *LibraryManager) SearchIter(query string) AlbumIterator {
@@ -83,6 +118,7 @@ func (l *LibraryManager) GetAlbum(id string) (*subsonic.AlbumID3, error) {
type baseIter struct {
listType string
filter AlbumFilter
pos int
l *LibraryManager
s *subsonic.Client
@@ -92,9 +128,10 @@ type baseIter struct {
done bool
}
func (l *LibraryManager) newBaseIter(listType string, opts map[string]string) *baseIter {
func (l *LibraryManager) newBaseIter(listType string, filter AlbumFilter, opts map[string]string) *baseIter {
return &baseIter{
listType: listType,
filter: filter,
l: l,
s: l.s.Server,
opts: opts,
@@ -123,6 +160,7 @@ func (r *baseIter) Next() *subsonic.AlbumID3 {
log.Println(err)
albums = nil
}
albums = sharedutil.FilterSlice(albums, r.filter.Matches)
if len(albums) == 0 {
r.done = true
return nil
+1 -1
View File
@@ -9,7 +9,7 @@ import (
func (l *LibraryManager) AllTracksIterator() TrackIterator {
return &allTracksIterator{
l: l,
albumIter: l.AlbumsIter(AlbumSortArtistAZ),
albumIter: l.AlbumsIter(AlbumSortArtistAZ, AlbumFilter{}),
}
}
+6
View File
@@ -17,6 +17,9 @@ func SliceContains[T comparable](ts []T, t T) bool {
}
func FilterSlice[T any](ss []T, test func(T) bool) []T {
if ss == nil {
return nil
}
result := make([]T, 0)
for _, s := range ss {
if test(s) {
@@ -27,6 +30,9 @@ func FilterSlice[T any](ss []T, test func(T) bool) []T {
}
func MapSlice[T any, U any](ts []T, f func(T) U) []U {
if ts == nil {
return nil
}
result := make([]U, len(ts))
for i, t := range ts {
result[i] = f(t)
+3 -3
View File
@@ -71,7 +71,7 @@ func NewAlbumsPage(cfg *backend.AlbumsPageConfig, contr *controller.Controller,
cfg.SortOrder = string(backend.AlbumSortRecentlyAdded)
}
a.sortOrder.Selected = cfg.SortOrder
iter := lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected))
iter := lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), backend.AlbumFilter{})
a.grid = widgets.NewGridView(widgets.NewGridViewAlbumIterator(iter), im)
contr.ConnectAlbumGridActions(a.grid)
a.searcher = widgets.NewSearchEntry()
@@ -154,7 +154,7 @@ func (a *AlbumsPage) Reload() {
if a.searchText != "" {
a.doSearch(a.searchText)
} else {
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected))
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), backend.AlbumFilter{})
a.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
a.grid.Refresh()
}
@@ -190,7 +190,7 @@ func (a *AlbumsPage) doSearch(query string) {
func (a *AlbumsPage) onSortOrderChanged(order string) {
a.cfg.SortOrder = a.sortOrder.Selected
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(order))
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(order), backend.AlbumFilter{})
a.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
if a.searchText == "" {
a.container.Objects[0] = a.grid
+4 -2
View File
@@ -55,7 +55,8 @@ func NewFavoritesPage(cfg *backend.FavoritesPageConfig, contr *controller.Contro
}
a.ExtendBaseWidget(a)
a.createHeader(0, "")
a.grid = widgets.NewGridView(widgets.NewGridViewAlbumIterator(lm.StarredIter()), a.im)
iter := lm.StarredIter(backend.AlbumFilter{})
a.grid = widgets.NewGridView(widgets.NewGridViewAlbumIterator(iter), a.im)
a.contr.ConnectAlbumGridActions(a.grid)
if cfg.InitialView == "Artists" {
a.toggleBtns.SetActivatedButton(1)
@@ -129,7 +130,8 @@ func (a *FavoritesPage) Reload() {
if a.searchText != "" {
a.doSearchAlbums(a.searchText)
} else {
a.grid.Reset(widgets.NewGridViewAlbumIterator(a.lm.StarredIter()))
iter := a.lm.StarredIter(backend.AlbumFilter{})
a.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
}
if a.tracklistCtr != nil || a.artistListCtr != nil {
go func() {
+3 -2
View File
@@ -52,7 +52,7 @@ func NewGenrePage(genre string, contr *controller.Controller, pm *backend.Playba
SizeName: theme.SizeNameHeadingText,
}
g.playRandom = widget.NewButtonWithIcon(" Play random", myTheme.ShuffleIcon, g.playRandomSongs)
iter := g.lm.GenreIter(g.genre)
iter := g.lm.GenreIter(g.genre, backend.AlbumFilter{})
g.grid = widgets.NewGridView(widgets.NewGridViewAlbumIterator(iter), g.im)
g.contr.ConnectAlbumGridActions(g.grid)
g.searcher = widgets.NewSearchEntry()
@@ -118,7 +118,8 @@ func (g *GenrePage) Reload() {
if g.searchText != "" {
g.doSearch(g.searchText)
} else {
g.grid.Reset(widgets.NewGridViewAlbumIterator(g.lm.GenreIter(g.genre)))
iter := g.lm.GenreIter(g.genre, backend.AlbumFilter{})
g.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
g.grid.Refresh()
}
}