add SearchTracksIterator

This commit is contained in:
Drew Weymouth
2023-04-20 19:24:44 -07:00
parent 5e8c450d76
commit 6d8fd75767
3 changed files with 133 additions and 25 deletions
+8 -18
View File
@@ -142,12 +142,9 @@ func (r *baseIter) Next() *subsonic.AlbumID3 {
}
type searchIter struct {
query string
artistOffset int
albumOffset int
songOffset int
searchIterBase
l *LibraryManager
s *subsonic.Client
filter func(*subsonic.AlbumID3) bool
prefetched []*subsonic.AlbumID3
prefetchedPos int
@@ -157,9 +154,11 @@ type searchIter struct {
func (l *LibraryManager) newSearchIter(query string, filter func(*subsonic.AlbumID3) bool) *searchIter {
return &searchIter{
query: query,
searchIterBase: searchIterBase{
query: query,
s: l.s.Server,
},
l: l,
s: l.s.Server,
filter: filter,
albumIDset: make(map[string]bool),
}
@@ -172,17 +171,8 @@ func (s *searchIter) Next() *subsonic.AlbumID3 {
// prefetch more search results from server
if s.prefetched == nil {
searchOpts := map[string]string{
"artistOffset": strconv.Itoa(s.artistOffset),
"albumOffset": strconv.Itoa(s.albumOffset),
"songOffset": strconv.Itoa(s.songOffset),
}
results, err := s.s.Search3(s.query, searchOpts)
if err != nil {
log.Println(err)
results = nil
}
if results == nil || len(results.Album)+len(results.Artist)+len(results.Song) == 0 {
results := s.searchIterBase.fetchResults()
if results == nil {
s.done = true
s.albumIDset = nil
return nil
+33
View File
@@ -0,0 +1,33 @@
package backend
import (
"log"
"strconv"
"github.com/dweymouth/go-subsonic/subsonic"
)
type searchIterBase struct {
query string
artistOffset int
albumOffset int
songOffset int
s *subsonic.Client
}
func (s *searchIterBase) fetchResults() *subsonic.SearchResult3 {
searchOpts := map[string]string{
"artistOffset": strconv.Itoa(s.artistOffset),
"albumOffset": strconv.Itoa(s.albumOffset),
"songOffset": strconv.Itoa(s.songOffset),
}
results, err := s.s.Search3(s.query, searchOpts)
if err != nil {
log.Println(err)
results = nil
}
if results == nil || len(results.Album)+len(results.Artist)+len(results.Song) == 0 {
return nil
}
return results
}
+92 -7
View File
@@ -6,6 +6,20 @@ import (
"github.com/dweymouth/go-subsonic/subsonic"
)
func (l *LibraryManager) AllTracksIterator() TrackIterator {
return &allTracksIterator{
l: l,
albumIter: l.AlbumsIter(AlbumSortArtistAZ),
}
}
func (l *LibraryManager) SearchTracksIterator(query string) TrackIterator {
return &searchTracksIterator{searchIterBase: searchIterBase{
s: l.s.Server,
query: query,
}}
}
type allTracksIterator struct {
l *LibraryManager
albumIter AlbumIterator
@@ -14,13 +28,6 @@ type allTracksIterator struct {
done bool
}
func (l *LibraryManager) AllTracksIterator() TrackIterator {
return &allTracksIterator{
l: l,
albumIter: l.AlbumsIter(AlbumSortArtistAZ),
}
}
func (a *allTracksIterator) Next() *subsonic.Child {
if a.done {
return nil
@@ -50,3 +57,81 @@ func (a *allTracksIterator) Next() *subsonic.Child {
a.curTrackIdx += 1
return tr
}
type searchTracksIterator struct {
searchIterBase
prefetched []*subsonic.Child
prefetchedPos int
trackIDset map[string]bool
done bool
}
func (s *searchTracksIterator) Next() *subsonic.Child {
if s.done {
return nil
}
// prefetch more search results from server
if s.prefetched == nil {
results := s.searchIterBase.fetchResults()
if results == nil || len(results.Album)+len(results.Artist)+len(results.Song) == 0 {
s.done = true
s.trackIDset = nil
return nil
}
// add results from songs search
s.addNewTracks(results.Song)
s.songOffset += len(results.Song)
// add results from artists search
for _, artist := range results.Artist {
artist, err := s.s.GetArtist(artist.ID)
if err != nil {
log.Printf("error fetching artist: %s", err.Error())
} else {
s.addNewTracksFromAlbums(artist.Album)
}
}
s.artistOffset += len(results.Artist)
// add results from albums search
s.addNewTracksFromAlbums(results.Album)
s.albumOffset += len(results.Album)
}
// return from prefetched results
if len(s.prefetched) > 0 {
tr := s.prefetched[s.prefetchedPos]
s.prefetchedPos++
if s.prefetchedPos == len(s.prefetched) {
s.prefetched = nil
s.prefetchedPos = 0
}
return tr
}
return nil
}
func (s *searchTracksIterator) addNewTracks(tracks []*subsonic.Child) {
for _, tr := range tracks {
if _, have := s.trackIDset[tr.ID]; have {
continue
}
s.prefetched = append(s.prefetched, tr)
s.trackIDset[tr.ID] = true
}
}
func (s *searchTracksIterator) addNewTracksFromAlbums(albums []*subsonic.AlbumID3) {
for _, al := range albums {
if album, err := s.s.GetAlbum(al.ID); err != nil {
log.Printf("error fetching album: %s", err.Error())
} else {
s.addNewTracks(album.Song)
}
}
}