Skip to content

Commit

Permalink
Fixes #21; playlists are loaded in the background, with a spinner to …
Browse files Browse the repository at this point in the history
…show the user the ongoing operation.
  • Loading branch information
xxxserxxx committed Aug 15, 2024
1 parent d3b9934 commit b18dfe9
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 25 deletions.
5 changes: 3 additions & 2 deletions gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ const (
)

func InitGui(indexes *[]subsonic.SubsonicIndex,
playlists *[]subsonic.SubsonicPlaylist,
connection *subsonic.SubsonicConnection,
player *mpvplayer.Player,
logger *logger.Logger,
Expand All @@ -82,7 +81,7 @@ func InitGui(indexes *[]subsonic.SubsonicIndex,
eventLoop: nil, // initialized by initEventLoops()
mpvEvents: make(chan mpvplayer.UiEvent, 5),

playlists: *playlists,
playlists: []subsonic.SubsonicPlaylist{},
connection: connection,
player: player,
logger: logger,
Expand Down Expand Up @@ -176,6 +175,8 @@ func InitGui(indexes *[]subsonic.SubsonicIndex,
SetFocus(rootFlex).
EnableMouse(true)

ui.playlistPage.UpdatePlaylists()

return ui
}

Expand Down
92 changes: 79 additions & 13 deletions page_playlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
package main

import (
"fmt"
"sync"
"time"

"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"github.com/spezifisch/stmps/logger"
Expand All @@ -22,12 +26,16 @@ type PlaylistPage struct {
// external refs
ui *Ui
logger logger.LoggerInterface

updatingMutex sync.Locker
isUpdating bool
}

func (ui *Ui) createPlaylistPage() *PlaylistPage {
playlistPage := PlaylistPage{
ui: ui,
logger: ui.logger,
ui: ui,
logger: ui.logger,
updatingMutex: &sync.Mutex{},
}

// left half: playlists
Expand Down Expand Up @@ -180,19 +188,77 @@ func (p *PlaylistPage) GetCount() int {
}

func (p *PlaylistPage) UpdatePlaylists() {
response, err := p.ui.connection.GetPlaylists()
if err != nil {
p.logger.PrintError("GetPlaylists", err)
// There's a potential race condition here and, albeit highly unlikely to ever get hit,
// we'll put in some protection
p.updatingMutex.Lock()
defer p.updatingMutex.Unlock()
if p.isUpdating {
return
}
p.ui.playlists = response.Playlists.Playlists

p.playlistList.Clear()
p.ui.addToPlaylistList.Clear()
p.isUpdating = true

var spinnerText []rune = []rune("⠁⠂⠄⡀⢀⠠⠐⠈")
playlistsButton := buttonOrder[2]
stop := make(chan bool)
go func() {
var idx int
timer := time.NewTicker(500 * time.Millisecond)
defer timer.Stop()
for {
select {
case <-timer.C:
p.ui.app.QueueUpdateDraw(func() {
var format string
if playlistsButton == p.ui.menuWidget.activeButton {
format = "%d: [::b][red]%c[white]%s[::-]"
} else {
format = "%d: [red]%c[white]%s"
}
label := fmt.Sprintf(format, 3, spinnerText[idx], playlistsButton)
p.ui.menuWidget.buttons[playlistsButton].SetLabel(label)
idx++
if idx > 7 {
idx = 0
}
})
case <-stop:
p.ui.app.QueueUpdateDraw(func() {
var format string
if playlistsButton == p.ui.menuWidget.activeButton {
format = "%d: [::b]%s[::-]"
} else {
format = "%d: %s"
}
label := fmt.Sprintf(format, 3, playlistsButton)
p.ui.menuWidget.buttons[playlistsButton].SetLabel(label)
})
close(stop)
return
}
}
}()

for _, playlist := range p.ui.playlists {
p.playlistList.AddItem(tview.Escape(playlist.Name), "", 0, nil)
p.ui.addToPlaylistList.AddItem(tview.Escape(playlist.Name), "", 0, nil)
}
go func() {
response, err := p.ui.connection.GetPlaylists()
if err != nil {
p.logger.PrintError("GetPlaylists", err)
}
p.updatingMutex.Lock()
defer p.updatingMutex.Unlock()
p.ui.playlists = response.Playlists.Playlists
p.ui.app.QueueUpdateDraw(func() {
p.playlistList.Clear()
p.ui.addToPlaylistList.Clear()

for _, playlist := range p.ui.playlists {
p.playlistList.AddItem(tview.Escape(playlist.Name), "", 0, nil)
p.ui.addToPlaylistList.AddItem(tview.Escape(playlist.Name), "", 0, nil)
}

p.isUpdating = false
})
stop <- true
}()
}

func (p *PlaylistPage) handleAddPlaylistSongToQueue() {
Expand Down
15 changes: 6 additions & 9 deletions stmps.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,6 @@ func main() {
os.Exit(1)
}

// TODO (B) loading playlists can take a long time on e.g. gonic if there are a lot of them; can it be done in the background?
playlistResponse, err := connection.GetPlaylists()
if err != nil {
fmt.Printf("Error fetching indexes from server: %s\n", err)
os.Exit(1)
}

if *list {
fmt.Printf("Index response:\n")
fmt.Printf(" Directory: %s\n", indexResponse.Directory.Name)
Expand All @@ -134,7 +127,12 @@ func main() {
for _, pl := range indexResponse.Indexes.Index {
fmt.Printf(" %s\n", pl.Name)
}
fmt.Printf("Playlist response:\n")
fmt.Printf("Playlist response: (this can take a while)\n")
playlistResponse, err := connection.GetPlaylists()
if err != nil {
fmt.Printf("Error fetching indexes from server: %s\n", err)
os.Exit(1)
}
fmt.Printf(" Directory: %s\n", playlistResponse.Directory.Name)
fmt.Printf(" Status: %s\n", playlistResponse.Status)
fmt.Printf(" Error: %s\n", playlistResponse.Error.Message)
Expand Down Expand Up @@ -181,7 +179,6 @@ func main() {
}

ui := InitGui(&indexResponse.Indexes.Index,
&playlistResponse.Playlists.Playlists,
connection,
player,
logger,
Expand Down
1 change: 0 additions & 1 deletion widget_help.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/rivo/tview"
)

// FIXME (A) invoking help and the dismissing it ('q') dismisses it forever (it can't be called back up)
type HelpWidget struct {
Root *tview.Flex

Expand Down

0 comments on commit b18dfe9

Please sign in to comment.