diff --git a/gui_handlers.go b/gui_handlers.go index 14ff0cb..2fab0bb 100644 --- a/gui_handlers.go +++ b/gui_handlers.go @@ -173,6 +173,7 @@ func (ui *Ui) addSongToQueue(entity *subsonic.SubsonicEntity) { TrackNumber: entity.Track, CoverArtId: entity.CoverArtId, DiscNumber: entity.DiscNumber, + Year: entity.Year, } ui.player.AddToQueue(queueItem) } @@ -188,6 +189,7 @@ func makeSongHandler(entity *subsonic.SubsonicEntity, ui *Ui, fallbackArtist str track := entity.Track coverArtId := entity.CoverArtId disc := entity.DiscNumber + year := entity.Year response, err := ui.connection.GetAlbum(entity.Parent) album := "" @@ -205,7 +207,7 @@ func makeSongHandler(entity *subsonic.SubsonicEntity, ui *Ui, fallbackArtist str } return func() { - if err := ui.player.PlayUri(id, uri, title, artist, album, duration, track, disc, coverArtId); err != nil { + if err := ui.player.PlayUri(id, uri, title, artist, album, duration, track, disc, coverArtId, year); err != nil { ui.logger.PrintError("SongHandler Play", err) return } diff --git a/help_text.go b/help_text.go index 663a464..e736094 100644 --- a/help_text.go +++ b/help_text.go @@ -51,13 +51,12 @@ artist, album/genre, or song tab Left previous column Right next column / start search + a recursively add item to quue g toggle genre search In album tab - Enter/a recursively add item to quue + Enter recursively add item to quue In genre tab Enter shows songs with genre -In song tab - Enter/a adds song to queue search field Enter search for text ` diff --git a/mpvplayer/player.go b/mpvplayer/player.go index fb13811..8ae9983 100644 --- a/mpvplayer/player.go +++ b/mpvplayer/player.go @@ -125,8 +125,8 @@ func (p *Player) PlayNextTrack() error { return nil } -func (p *Player) PlayUri(id, uri, title, artist, album string, duration, track, disc int, coverArtId string) error { - p.queue = []QueueItem{{id, uri, title, artist, duration, album, track, coverArtId, disc}} +func (p *Player) PlayUri(id, uri, title, artist, album string, duration, track, disc int, coverArtId string, year int) error { + p.queue = []QueueItem{{id, uri, title, artist, duration, album, track, coverArtId, disc, year}} p.replaceInProgress = true if ip, e := p.IsPaused(); ip && e == nil { if err := p.Pause(); err != nil { diff --git a/mpvplayer/queue_item.go b/mpvplayer/queue_item.go index 2b147e4..04fb54c 100644 --- a/mpvplayer/queue_item.go +++ b/mpvplayer/queue_item.go @@ -17,6 +17,7 @@ type QueueItem struct { TrackNumber int CoverArtId string DiscNumber int + Year int } var _ remote.TrackInterface = (*QueueItem)(nil) @@ -60,3 +61,7 @@ func (q QueueItem) GetTrackNumber() int { func (q QueueItem) GetDiscNumber() int { return q.DiscNumber } + +func (q QueueItem) GetYear() int { + return q.Year +} diff --git a/page_queue.go b/page_queue.go index a7b12e7..f306f3d 100644 --- a/page_queue.go +++ b/page_queue.go @@ -241,6 +241,7 @@ func (q *QueuePage) updateQueue() { q.queueList.ScrollToBeginning() } + q.queueList.Box.SetTitle(fmt.Sprintf(" queue (%d) ", q.queueList.GetRowCount())) r, c := q.queueList.GetSelection() q.changeSelection(r, c) } @@ -443,6 +444,7 @@ var songInfoTemplateString = `[blue::b]Title:[-:-:-:-] [green::i]{{.Title}}[-:-: [blue::b]Artist:[-:-:-:-] [::i]{{.Artist}}[-:-:-:-] [blue::b]Album:[-:-:-:-] [::i]{{.GetAlbum}}[-:-:-:-] [blue::b]Disc:[-:-:-:-] [::i]{{.GetDiscNumber}}[-:-:-:-] +[blue::b]Year:[-:-:-:-] [::i]{{.GetYear}}[-:-:-:-] [blue::b]Track:[-:-:-:-] [::i]{{.GetTrackNumber}}[-:-:-:-] [blue::b]Duration:[-:-:-:-] [::i]{{formatTime .Duration}}[-:-:-:-] ` diff --git a/page_search.go b/page_search.go index c0d6012..f2cf4b6 100644 --- a/page_search.go +++ b/page_search.go @@ -108,8 +108,8 @@ func (ui *Ui) createSearchPage() *SearchPage { if searchPage.queryGenre { searchPage.albumList.SetTitle(" album matches ") } else { - searchPage.albumList.SetTitle(" genres ") searchPage.populateGenres() + searchPage.albumList.SetTitle(fmt.Sprintf(" genres (%d) ", searchPage.albumList.GetItemCount())) searchPage.ui.app.SetFocus(searchPage.albumList) } searchPage.queryGenre = !searchPage.queryGenre @@ -150,7 +150,12 @@ func (ui *Ui) createSearchPage() *SearchPage { switch event.Rune() { case 'a': if searchPage.queryGenre { - return event + idx := searchPage.albumList.GetCurrentItem() + if idx < searchPage.albumList.GetItemCount() { + genre, _ := searchPage.albumList.GetItemText(idx) + searchPage.addGenreToQueue(genre) + } + return nil } idx := searchPage.albumList.GetCurrentItem() searchPage.logger.Printf("albumList adding (%d) %s", idx, searchPage.albums[idx].Name) @@ -163,8 +168,8 @@ func (ui *Ui) createSearchPage() *SearchPage { if searchPage.queryGenre { searchPage.albumList.SetTitle(" album matches ") } else { - searchPage.albumList.SetTitle(" genres ") searchPage.populateGenres() + searchPage.albumList.SetTitle(fmt.Sprintf(" genres (%d) ", searchPage.albumList.GetItemCount())) searchPage.ui.app.SetFocus(searchPage.albumList) } searchPage.queryGenre = !searchPage.queryGenre @@ -201,8 +206,8 @@ func (ui *Ui) createSearchPage() *SearchPage { if searchPage.queryGenre { searchPage.albumList.SetTitle(" album matches ") } else { - searchPage.albumList.SetTitle(" genres ") searchPage.populateGenres() + searchPage.albumList.SetTitle(fmt.Sprintf(" genres (%d) ", searchPage.albumList.GetItemCount())) searchPage.ui.app.SetFocus(searchPage.albumList) } searchPage.queryGenre = !searchPage.queryGenre @@ -250,6 +255,8 @@ func (s *SearchPage) search(search chan string) { var query string var artOff, albOff, songOff int more := make(chan bool, 5) + var res *subsonic.SubsonicResponse + var err error for { // quit searching if we receive an interrupt select { @@ -265,11 +272,11 @@ func (s *SearchPage) search(search chan string) { } case <-more: } - var res *subsonic.SubsonicResponse - var err error if s.queryGenre { + s.logger.Printf("genre %q %d", query, songOff) res, err = s.ui.connection.GetSongsByGenre(query, songOff, "") if len(res.SongsByGenre.Song) == 0 { + s.logger.Printf("found a total of %d songs", songOff) continue } } else { @@ -286,19 +293,19 @@ func (s *SearchPage) search(search chan string) { return } - query = strings.ToLower(query) s.ui.app.QueueUpdate(func() { if s.queryGenre { if songOff == 0 { s.artistList.Box.SetTitle(" artist matches ") - s.albumList.Box.SetTitle(" genres ") } for _, song := range res.SongsByGenre.Song { s.songList.AddItem(tview.Escape(song.Title), "", 0, nil) s.songs = append(s.songs, &song) } s.songList.Box.SetTitle(fmt.Sprintf(" genre song matches (%d) ", len(s.songs))) + songOff += len(res.SongsByGenre.Song) } else { + query = strings.ToLower(query) for _, artist := range res.SearchResults.Artist { if strings.Contains(strings.ToLower(artist.Name), query) { s.artistList.AddItem(tview.Escape(artist.Name), "", 0, nil) @@ -320,21 +327,37 @@ func (s *SearchPage) search(search chan string) { } } s.songList.Box.SetTitle(fmt.Sprintf(" song matches (%d) ", len(s.songs))) + artOff += len(res.SearchResults.Artist) + albOff += len(res.SearchResults.Album) + songOff += len(res.SearchResults.Song) } + more <- true }) - if !s.queryGenre { - artOff += len(res.SearchResults.Artist) - albOff += len(res.SearchResults.Album) - songOff += len(res.SearchResults.Song) - } else { - songOff += len(res.SongsByGenre.Song) - } s.ui.app.Draw() - more <- true } } +func (s *SearchPage) addGenreToQueue(query string) { + var songOff int + for { + res, err := s.ui.connection.GetSongsByGenre(query, songOff, "") + if err != nil { + s.logger.PrintError("SearchPage.addGenreToQueue", err) + return + } + if len(res.SongsByGenre.Song) == 0 { + break + } + for _, song := range res.SongsByGenre.Song { + s.ui.addSongToQueue(&song) + } + songOff += len(res.SongsByGenre.Song) + } + s.logger.Printf("added a total of %d songs to the queue for %q", songOff, query) + s.ui.queuePage.UpdateQueue() +} + func (s *SearchPage) addArtistToQueue(entity subsonic.Ider) { response, err := s.ui.connection.GetArtist(entity.ID()) if err != nil { diff --git a/subsonic/api.go b/subsonic/api.go index 20d5482..edbf235 100644 --- a/subsonic/api.go +++ b/subsonic/api.go @@ -187,6 +187,7 @@ type SubsonicEntity struct { DiscNumber int `json:"discNumber"` Path string `json:"path"` CoverArtId string `json:"coverArt"` + Year int `json:"year"` } func (s SubsonicEntity) ID() string {