add searchiterator
This commit is contained in:
+110
-2
@@ -42,6 +42,10 @@ func (l *LibraryManager) FrequentlyPlayedIter() AlbumIterator {
|
|||||||
return l.newBaseIter("frequent")
|
return l.newBaseIter("frequent")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *LibraryManager) SearchIter(query string) AlbumIterator {
|
||||||
|
return l.newSearchIter(query)
|
||||||
|
}
|
||||||
|
|
||||||
func (l *LibraryManager) CacheAlbum(a *subsonic.AlbumID3) {
|
func (l *LibraryManager) CacheAlbum(a *subsonic.AlbumID3) {
|
||||||
l.albumCache.Set(a.ID, a)
|
l.albumCache.Set(a.ID, a)
|
||||||
}
|
}
|
||||||
@@ -78,8 +82,6 @@ func (l *LibraryManager) newBaseIter(listType string) *baseIter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: figure out why the iterator sometimes returns an album twice
|
|
||||||
|
|
||||||
func (r *baseIter) Next() *subsonic.AlbumID3 {
|
func (r *baseIter) Next() *subsonic.AlbumID3 {
|
||||||
if r.done {
|
if r.done {
|
||||||
return nil
|
return nil
|
||||||
@@ -128,3 +130,109 @@ func (r *baseIter) NextN(n int, cb func(*subsonic.AlbumID3)) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type searchIter struct {
|
||||||
|
query string
|
||||||
|
artistOffset int
|
||||||
|
albumOffset int
|
||||||
|
songOffset int
|
||||||
|
l *LibraryManager
|
||||||
|
s *subsonic.Client
|
||||||
|
prefetched []*subsonic.AlbumID3
|
||||||
|
prefetchedPos int
|
||||||
|
albumIDset map[string]bool
|
||||||
|
done bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LibraryManager) newSearchIter(query string) *searchIter {
|
||||||
|
return &searchIter{
|
||||||
|
query: query,
|
||||||
|
l: l,
|
||||||
|
s: l.s.Server,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *searchIter) Next() *subsonic.AlbumID3 {
|
||||||
|
if s.done {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
s.done = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// add results from albums search
|
||||||
|
s.addNewAlbums(results.Album)
|
||||||
|
s.albumOffset += len(results.Album)
|
||||||
|
|
||||||
|
// 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())
|
||||||
|
}
|
||||||
|
s.addNewAlbums(artist.Album)
|
||||||
|
}
|
||||||
|
s.artistOffset += len(results.Artist)
|
||||||
|
|
||||||
|
// add results from songs search
|
||||||
|
for _, song := range results.Song {
|
||||||
|
album, err := s.s.GetAlbum(song.Parent)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("error fetching album: %s", err.Error())
|
||||||
|
}
|
||||||
|
s.addNewAlbums([]*subsonic.AlbumID3{album})
|
||||||
|
}
|
||||||
|
s.songOffset += len(results.Song)
|
||||||
|
}
|
||||||
|
|
||||||
|
// return from prefetched results
|
||||||
|
if len(s.prefetched) > 0 {
|
||||||
|
a := s.prefetched[s.prefetchedPos]
|
||||||
|
s.prefetchedPos++
|
||||||
|
if s.prefetchedPos == len(s.prefetched) {
|
||||||
|
s.prefetched = nil
|
||||||
|
s.prefetchedPos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
s.l.CacheAlbum(a)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *searchIter) NextN(n int, cb func(*subsonic.AlbumID3)) {
|
||||||
|
go func() {
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
a := s.Next()
|
||||||
|
cb(a)
|
||||||
|
if a == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *searchIter) addNewAlbums(al []*subsonic.AlbumID3) {
|
||||||
|
for _, album := range al {
|
||||||
|
if _, have := s.albumIDset[album.ID]; have {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.prefetched = append(s.prefetched, album)
|
||||||
|
s.albumIDset[album.ID] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user