Files
gspt/ui/progress.go
aditya-k2 3cacc62196 Change some config and flag options
Earlier the flags couldn't override with false values, that has been
changed. Also change how errors are handled while the config is been
read.
2024-01-22 11:01:11 +05:30

237 lines
5.6 KiB
Go

package ui
import (
"fmt"
"strings"
"time"
"github.com/gdamore/tcell/v2"
"github.com/zmb3/spotify/v2"
"github.com/aditya-K2/gspt/config"
"github.com/aditya-K2/gspt/spt"
"github.com/aditya-K2/tview"
"github.com/aditya-K2/utils"
)
var (
state *spotify.PlayerState
ctrackId spotify.ID
devices map[string]string
playIcons map[bool]string
shuffleIcons map[bool]string
repeatIcons map[string]string
)
// ProgressBar is a two-lined Box. First line is the BarTitle
// Second being the actual progress done.
// Use SetProgressFunc to provide the callback which provides the Fields each time the ProgressBar will be Drawn.
// The progressFunc must return (BarTitle, BarTopTitle, BarText, percentage) respectively
type ProgressBar struct {
*tview.Box
BarTitle string
BarText string
BarTopTitle string
progressFunc func() (BarTitle string,
BarTopTitle string,
BarText string,
percentage float64)
}
func (self *ProgressBar) SetProgressFunc(pfunc func() (string, string, string, float64)) *ProgressBar {
self.progressFunc = pfunc
return self
}
func NewProgressBar() *ProgressBar {
return &ProgressBar{
Box: tview.NewBox(),
}
}
func getProgressGlyph(width, percentage float64, btext string) string {
q := "[black:white:b]"
var a string
a += strings.Repeat(" ", int(width)-len(btext))
a = utils.InsertAt(a, btext, int(width/2)-10)
a = utils.InsertAt(a, "[-:-:-]", int(width*percentage/100))
q += a
return q
}
func (self *ProgressBar) Draw(screen tcell.Screen) {
var (
OFFSET int = 1
)
self.Box.SetBorder(true)
self.Box.SetBackgroundColor(tcell.ColorDefault)
var percentage float64
self.BarTitle, self.BarTopTitle, self.BarText, percentage = self.progressFunc()
self.DrawForSubclass(screen, self.Box)
self.Box.SetTitle(self.BarTopTitle)
self.Box.SetTitleAlign(tview.AlignRight)
x, y, _width, _ := self.Box.GetInnerRect()
tview.Print(screen, self.BarTitle, x+OFFSET, y, _width, tview.AlignLeft, tcell.ColorWhite)
tview.Print(screen,
getProgressGlyph(float64(_width-OFFSET-1),
percentage,
self.BarText),
x, y+2, _width-OFFSET, tview.AlignRight, tcell.ColorWhite)
}
func (self *ProgressBar) RefreshState() {
RefreshProgress(false)
}
func RefreshProgress(force bool) {
s, err := spt.GetPlayerState()
if err != nil {
SendNotification(err.Error())
return
}
state = s
// Reset the "cached" if nothing is playing (TODO: better name)[
if s.Item == nil {
ctrackId = ""
}
if coverArt != nil {
// If No Item is playing
if (state.Item == nil) ||
// An Item is Playing but doesn't match the cached Track ID
(state.Item != nil && state.Item.ID != ctrackId) ||
// Forced Redrawing
force {
if state.Item != nil {
ctrackId = state.Item.ID
}
if cfg.Image == config.ImageShow {
coverArt.RefreshState()
}
}
}
}
func refreshProgressLocal() {
if state != nil {
if state.Item != nil && state.Playing {
if state.Item.Duration-state.Progress >= 1000 {
state.Progress += 1000
} else {
state.Progress += state.Item.Duration - state.Progress
go func() {
RefreshProgress(false)
}()
}
}
}
}
func progressRoutine() {
RefreshProgress(false)
go func() {
localTicker := time.NewTicker(time.Second)
spotifyTicker := time.NewTicker(time.Second * 5)
for {
select {
case <-spotifyTicker.C:
{
RefreshProgress(false)
}
case <-localTicker.C:
{
refreshProgressLocal()
}
}
}
}()
}
func deviceIcon(d spotify.PlayerDevice) string {
if val, ok := devices[strings.ToLower(d.Type)]; cfg.UseIcons && ok {
return val
}
return "Device:"
}
func topTitle(playing, shuffle bool, repeat string, device spotify.PlayerDevice) (
playState, deviceIcn, deviceName, shuffleState, repeatState string) {
icon := ""
playState = "Paused"
shuffleState = fmt.Sprintf("%t", shuffle)
if playing {
playState = "Playing"
}
if cfg.UseIcons {
icon = playIcons[playing]
icon += " "
repeat = repeatIcons[repeat]
shuffleState = shuffleIcons[shuffle]
}
playState = icon + playState
deviceIcn = deviceIcon(device)
deviceName = device.Name
repeatState = repeat
return
}
func setIcons() {
devices = map[string]string{
"computer": cfg.Icons.Computer,
"tablet": cfg.Icons.Tablet,
"smartphone": cfg.Icons.Smartphone,
"speaker": cfg.Icons.Speaker,
"tv": cfg.Icons.Tv,
"avr": cfg.Icons.Avr,
"stb": cfg.Icons.Stb,
"audio_dongle": cfg.Icons.AudioDongle,
"game_console": cfg.Icons.GameConsole,
"cast_video": cfg.Icons.CastVideo,
"cast_audio": cfg.Icons.CastAudio,
"automobile": cfg.Icons.Automobile,
}
playIcons = map[bool]string{
true: cfg.Icons.Playing,
false: cfg.Icons.Paused,
}
shuffleIcons = map[bool]string{
true: cfg.Icons.ShuffleOn,
false: cfg.Icons.ShuffleOff,
}
repeatIcons = map[string]string{
"track": cfg.Icons.RepeatOne,
"off": cfg.Icons.RepeatAll,
"context": cfg.Icons.RepeatOff,
}
}
func progressFunc() (barTitle, barTopTitle, barText string, percentage float64) {
percentage = 0
barTitle = " - "
barText = "---:---"
barTopTitle = "[]"
if state != nil {
barTopTitle = fmt.Sprintf("[ %s %s %s Shuffle: %s Repeat: %s ]",
wrap(
topTitle(
state.Playing,
state.ShuffleState,
state.RepeatState,
state.Device))...)
if state.Item != nil {
barTitle = fmt.Sprintf("%s%s[-:-:-] - %s%s",
cfg.Colors.PBarTrack.String(), state.Item.Name,
cfg.Colors.PBarArtist.String(), artistName(state.Item.Artists))
barText = utils.StrTime(float64(state.Progress/1000)) +
"/" +
utils.StrTime(float64(state.Item.Duration/1000))
percentage = (float64(state.Progress) / float64(state.Item.Duration)) * 100
}
}
return
}