2024-05-29 22:19:47 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/adrg/xdg"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Stores information about the album covers cache
|
|
|
|
type AlbumCoverInfo struct {
|
|
|
|
Cached bool
|
|
|
|
Error error
|
|
|
|
WaitGroup *sync.WaitGroup
|
|
|
|
}
|
|
|
|
|
|
|
|
// Caches info about the album covers
|
|
|
|
var albumCoverCacheInfo = make(map[string]*AlbumCoverInfo)
|
|
|
|
var cacheMutex = sync.RWMutex{}
|
|
|
|
|
2024-05-29 23:06:34 +00:00
|
|
|
func generateCacheFilename(albumId string) string {
|
|
|
|
albumCacheFile, err := xdg.CacheFile(fmt.Sprintf("%s/%s", appname, albumId))
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprint("error creating cacheFile url: ", err))
|
|
|
|
}
|
|
|
|
return albumCacheFile
|
|
|
|
}
|
|
|
|
|
2024-05-29 22:19:47 +00:00
|
|
|
// Loads a single album cover and caches it in XDG_CACHE_HOME
|
|
|
|
// First it checks if the cover already exists in XDG_CACHE_HOME
|
|
|
|
// If it doesn't, loads it and stores it
|
|
|
|
func loadAlbumCover(albumId string) {
|
|
|
|
// Check cache info
|
|
|
|
cacheMutex.Lock()
|
|
|
|
_, ok := albumCoverCacheInfo[albumId]
|
|
|
|
cacheMutex.Unlock()
|
|
|
|
if ok {
|
|
|
|
log.Print("album cover: cache hit: ", albumId)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-05-29 23:06:34 +00:00
|
|
|
albumCacheFile := generateCacheFilename(albumId)
|
2024-05-29 22:19:47 +00:00
|
|
|
|
|
|
|
// Attempt to read file
|
2024-05-29 23:06:34 +00:00
|
|
|
if _, err := os.Stat(albumCacheFile); err == nil {
|
2024-05-29 22:19:47 +00:00
|
|
|
// File exists
|
|
|
|
log.Print("album cover: cache hit (disk): ", albumId)
|
|
|
|
cacheMutex.Lock()
|
|
|
|
albumCoverCacheInfo[albumId] = &AlbumCoverInfo{
|
|
|
|
Cached: true,
|
|
|
|
WaitGroup: &sync.WaitGroup{},
|
|
|
|
}
|
|
|
|
cacheMutex.Unlock()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load cover from network
|
|
|
|
log.Print("load album cover for ", albumId)
|
|
|
|
coverInfo := AlbumCoverInfo{
|
|
|
|
Cached: false,
|
|
|
|
WaitGroup: &sync.WaitGroup{},
|
|
|
|
}
|
|
|
|
coverInfo.WaitGroup.Add(1)
|
|
|
|
defer coverInfo.WaitGroup.Done()
|
|
|
|
|
|
|
|
cacheMutex.Lock()
|
|
|
|
albumCoverCacheInfo[albumId] = &coverInfo
|
|
|
|
cacheMutex.Unlock()
|
|
|
|
|
|
|
|
response, err := client.R().
|
|
|
|
// TODO: replace `fernando` with the username
|
|
|
|
Get(fmt.Sprintf(
|
|
|
|
"%s/rest/getCoverArt.view?id=%s&u=%s&s=12e7f3&t=%s&v=1.13.0&c=wmusic&size=300",
|
|
|
|
serverUrl,
|
|
|
|
albumId,
|
|
|
|
"fernando",
|
|
|
|
"d7bbe92d7da363aa202ae16136887adc",
|
|
|
|
))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Print("error loadAlbumCover: ", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if !response.IsSuccess() {
|
|
|
|
log.Print("error loadAlbumCover")
|
|
|
|
log.Printf("%s", response.Body())
|
|
|
|
coverInfo.Error = errors.New("error loading")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
imgBytes := response.Body()
|
|
|
|
|
|
|
|
// Write the image to cache
|
|
|
|
err = os.WriteFile(albumCacheFile, imgBytes, 0644)
|
|
|
|
if err != nil {
|
|
|
|
coverInfo.Error = errors.New("error writing album cover to disk")
|
|
|
|
log.Fatalf("Error writing to cache file for album cover: %s", albumCacheFile)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Print("Loading albumCover for ", albumId, " successful")
|
|
|
|
}
|
2024-05-29 23:06:34 +00:00
|
|
|
|
|
|
|
// Tries to load the album cover
|
|
|
|
func (a *App) GetAlbumCover(albumId string) ([]byte, error) {
|
2024-05-30 00:10:05 +00:00
|
|
|
if albumId == "" {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2024-05-29 23:06:34 +00:00
|
|
|
cacheMutex.Lock()
|
|
|
|
coverInfo, ok := albumCoverCacheInfo[albumId]
|
|
|
|
cacheMutex.Unlock()
|
|
|
|
if !ok {
|
|
|
|
panic("Illegal state: Tried to load an album, but it wasn't on memory cache")
|
|
|
|
}
|
|
|
|
|
|
|
|
coverInfo.WaitGroup.Wait()
|
|
|
|
|
|
|
|
if coverInfo.Error != nil {
|
|
|
|
return nil, coverInfo.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the file
|
|
|
|
filename := generateCacheFilename(albumId)
|
|
|
|
log.Print("reading: ", filename)
|
|
|
|
bytes, err := os.ReadFile(filename)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("error getting album cover: ", err)
|
|
|
|
return nil, errors.New("error reading cover file")
|
|
|
|
}
|
|
|
|
|
|
|
|
return bytes, nil
|
|
|
|
}
|