diff --git a/README.md b/README.md index bb84615..2cd9278 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,15 @@ random-songs = 50 spinner = '▁▂▃▄▅▆▇█▇▆▅▄▃▂▁' ``` +The song info panel on the queue takes up space, and memory for album art. You can disable this panel with: + +```toml +[ui] +hide-info-panel = true +``` + +If the panel is hidden, no album art will be fetched from the server. + ## Usage ### General Navigation diff --git a/gui_handlers.go b/gui_handlers.go index e0294d2..1c998d6 100644 --- a/gui_handlers.go +++ b/gui_handlers.go @@ -9,6 +9,7 @@ import ( "github.com/gdamore/tcell/v2" "github.com/spezifisch/stmps/mpvplayer" "github.com/spezifisch/stmps/subsonic" + "github.com/spf13/viper" ) func (ui *Ui) handlePageInput(event *tcell.EventKey) *tcell.EventKey { @@ -136,6 +137,9 @@ func (ui *Ui) Quit() { // bad data. Therefore, we ignore errors. _ = ui.connection.SavePlayQueue([]string{"XXX"}, "XXX", 0) } + if !viper.GetBool("ui.hide-song-info") { + ui.queuePage.coverArtCache.Close() + } ui.player.Quit() ui.app.Stop() } diff --git a/page_queue.go b/page_queue.go index d466760..aefbf80 100644 --- a/page_queue.go +++ b/page_queue.go @@ -19,6 +19,7 @@ import ( "github.com/spezifisch/stmps/logger" "github.com/spezifisch/stmps/mpvplayer" "github.com/spezifisch/stmps/subsonic" + "github.com/spf13/viper" ) // TODO show total # of entries somewhere (top?) @@ -70,15 +71,21 @@ func init() { } func (ui *Ui) createQueuePage() *QueuePage { - tmpl := template.New("song info").Funcs(template.FuncMap{ - "formatTime": func(i int) string { - return (time.Duration(i) * time.Second).String() - }, - }) - songInfoTemplate, err := tmpl.Parse(songInfoTemplateString) - if err != nil { - ui.logger.PrintError("createQueuePage", err) + addSongInfo := !viper.GetBool("ui.hide-song-info") + + var songInfoTemplate *template.Template + if addSongInfo { + tmpl := template.New("song info").Funcs(template.FuncMap{ + "formatTime": func(i int) string { + return (time.Duration(i) * time.Second).String() + }, + }) + var err error + if songInfoTemplate, err = tmpl.Parse(songInfoTemplateString); err != nil { + ui.logger.PrintError("createQueuePage", err) + } } + queuePage := QueuePage{ ui: ui, logger: ui.logger, @@ -153,71 +160,81 @@ func (ui *Ui) createQueuePage() *QueuePage { queuePage.queueList.SetSelectionChangedFunc(queuePage.changeSelection) - queuePage.coverArt = tview.NewImage() - queuePage.coverArt.SetImage(STMPS_LOGO) - - infoFlex := tview.NewFlex().SetDirection(tview.FlexRow). - AddItem(queuePage.songInfo, 0, 1, false). - AddItem(queuePage.coverArt, 0, 1, false) - infoFlex.SetBorder(true) - infoFlex.SetTitle(" song info ") - - // flex wrapper - queuePage.Root = tview.NewFlex().SetDirection(tview.FlexColumn). - AddItem(queuePage.queueList, 0, 2, true). - AddItem(infoFlex, 0, 1, false) - // private data queuePage.queueData = queueData{ starIdList: ui.starIdList, } - queuePage.coverArtCache = NewCache( - // zero value - STMPS_LOGO, - // function that loads assets; can be slow - ui.connection.GetCoverArt, - // function that gets called when the actual asset is loaded - func(imgId string, img image.Image) { - row, _ := queuePage.queueList.GetSelection() - // If nothing is selected, set the image to the logo - if row >= len(queuePage.queueData.playerQueue) || row < 0 { + // flex wrapper + queuePage.Root = tview.NewFlex().SetDirection(tview.FlexColumn). + AddItem(queuePage.queueList, 0, 2, true) + + if addSongInfo { + // Song info + queuePage.songInfo = tview.NewTextView() + queuePage.songInfo.SetDynamicColors(true).SetScrollable(true) + + queuePage.coverArt = tview.NewImage() + queuePage.coverArt.SetImage(STMPS_LOGO) + + infoFlex := tview.NewFlex().SetDirection(tview.FlexRow). + AddItem(queuePage.songInfo, 0, 1, false). + AddItem(queuePage.coverArt, 0, 1, false) + infoFlex.SetBorder(true) + infoFlex.SetTitle(" song info ") + queuePage.Root.AddItem(infoFlex, 0, 1, false) + + queuePage.coverArtCache = NewCache( + // zero value + STMPS_LOGO, + // function that loads assets; can be slow + ui.connection.GetCoverArt, + // function that gets called when the actual asset is loaded + func(imgId string, img image.Image) { + row, _ := queuePage.queueList.GetSelection() + // If nothing is selected, set the image to the logo + if row >= len(queuePage.queueData.playerQueue) || row < 0 { + ui.app.QueueUpdate(func() { + queuePage.coverArt.SetImage(STMPS_LOGO) + }) + return + } + // If the fetched asset isn't the asset for the current song, + // just skip it. + currentSong := queuePage.queueData.playerQueue[row] + if currentSong.CoverArtId != imgId { + return + } + // Otherwise, the asset is for the current song, so update it ui.app.QueueUpdate(func() { - queuePage.coverArt.SetImage(STMPS_LOGO) + queuePage.coverArt.SetImage(img) }) - return - } - // If the fetched asset isn't the asset for the current song, - // just skip it. - currentSong := queuePage.queueData.playerQueue[row] - if currentSong.CoverArtId != imgId { - return - } - // Otherwise, the asset is for the current song, so update it - ui.app.QueueUpdate(func() { - queuePage.coverArt.SetImage(img) - }) - }, - // function called to check if asset is invalid: - // true if it can be purged from the cache, false if it's still needed - func(assetId string) bool { - for _, song := range queuePage.queueData.playerQueue { - if song.CoverArtId == assetId { - return false + }, + // function called to check if asset is invalid: + // true if it can be purged from the cache, false if it's still needed + func(assetId string) bool { + for _, song := range queuePage.queueData.playerQueue { + if song.CoverArtId == assetId { + return false + } } - } - // Didn't find a song that needs the asset; purge it. - return true - }, - // How frequently we check for invalid assets - time.Minute, - ui.logger, - ) + // Didn't find a song that needs the asset; purge it. + return true + }, + // How frequently we check for invalid assets + time.Minute, + ui.logger, + ) + } return &queuePage } func (q *QueuePage) changeSelection(row, column int) { + // If the user disabled song info, there's nothing to do + if q.songInfo == nil { + return + } q.songInfo.Clear() if row >= len(q.queueData.playerQueue) || row < 0 || column < 0 { q.coverArt.SetImage(STMPS_LOGO)