WIP - pre-download audio files for queued tracks
This commit is contained in:
+10
-1
@@ -44,6 +44,7 @@ type App struct {
|
|||||||
Config *Config
|
Config *Config
|
||||||
ServerManager *ServerManager
|
ServerManager *ServerManager
|
||||||
ImageManager *ImageManager
|
ImageManager *ImageManager
|
||||||
|
AudioCache *AudioCache
|
||||||
PlaybackManager *PlaybackManager
|
PlaybackManager *PlaybackManager
|
||||||
LocalPlayer *mpv.Player
|
LocalPlayer *mpv.Player
|
||||||
UpdateChecker UpdateChecker
|
UpdateChecker UpdateChecker
|
||||||
@@ -142,8 +143,13 @@ func StartupApp(appName, displayAppName, appVersion, appVersionTag, latestReleas
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.ServerManager = NewServerManager(appName, appVersion, a.Config, !portableMode && a.Config.Application.EnablePasswordStorage)
|
a.ServerManager = NewServerManager(appName, appVersion, a.Config, !portableMode && a.Config.Application.EnablePasswordStorage)
|
||||||
a.PlaybackManager = NewPlaybackManager(a.bgrndCtx, a.ServerManager, a.LocalPlayer, &a.Config.Playback, &a.Config.Scrobbling, &a.Config.Transcoding, &a.Config.Application)
|
|
||||||
a.ImageManager = NewImageManager(a.bgrndCtx, a.ServerManager, cacheDir)
|
a.ImageManager = NewImageManager(a.bgrndCtx, a.ServerManager, cacheDir)
|
||||||
|
ac, err := NewAudioCache(a.bgrndCtx, a.ServerManager, filepath.Join(cacheDir, "audio"))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to create audio cache: %s", err.Error())
|
||||||
|
}
|
||||||
|
a.AudioCache = ac
|
||||||
|
a.PlaybackManager = NewPlaybackManager(a.bgrndCtx, a.ServerManager, a.LocalPlayer, &a.Config.Playback, &a.Config.Scrobbling, &a.Config.Transcoding, &a.Config.Application)
|
||||||
a.Config.Application.MaxImageCacheSizeMB = clamp(a.Config.Application.MaxImageCacheSizeMB, 1, 500)
|
a.Config.Application.MaxImageCacheSizeMB = clamp(a.Config.Application.MaxImageCacheSizeMB, 1, 500)
|
||||||
a.ImageManager.SetMaxOnDiskCacheSizeBytes(int64(a.Config.Application.MaxImageCacheSizeMB) * 1_048_576)
|
a.ImageManager.SetMaxOnDiskCacheSizeBytes(int64(a.Config.Application.MaxImageCacheSizeMB) * 1_048_576)
|
||||||
a.ServerManager.SetPrefetchAlbumCoverCallback(func(coverID string) {
|
a.ServerManager.SetPrefetchAlbumCoverCallback(func(coverID string) {
|
||||||
@@ -475,6 +481,9 @@ func (a *App) Shutdown() {
|
|||||||
}
|
}
|
||||||
a.PlaybackManager.DisableCallbacks()
|
a.PlaybackManager.DisableCallbacks()
|
||||||
a.PlaybackManager.Shutdown() // will trigger scrobble check
|
a.PlaybackManager.Shutdown() // will trigger scrobble check
|
||||||
|
if a.AudioCache != nil {
|
||||||
|
a.AudioCache.Shutdown()
|
||||||
|
}
|
||||||
a.cancel()
|
a.cancel()
|
||||||
a.LocalPlayer.Destroy()
|
a.LocalPlayer.Destroy()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
package sharedutil
|
package sharedutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -133,3 +139,50 @@ func ReorderItems[T any](items []T, idxToMove []int, insertIdx int) []T {
|
|||||||
|
|
||||||
return newItems
|
return newItems
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DownloadFileWithContext downloads a file from the specified URL and saves it to destPath.
|
||||||
|
// It respects the provided context and will cancel the request and cleanup if context is done.
|
||||||
|
// Returns an error if an error other than cancellation occurs, and returns true IFF the file was completely downloaded.
|
||||||
|
func DownloadFileWithContext(ctx context.Context, url string, destPath string) (bool, error) {
|
||||||
|
// Create HTTP request with context
|
||||||
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("creating request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the request
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("performing request: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// Check for non-200 status codes
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return false, fmt.Errorf("bad status: %s", resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the destination file
|
||||||
|
out, err := os.Create(destPath)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("creating file: %w", err)
|
||||||
|
}
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(out, resp.Body)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
// Cancelled, delete partial file
|
||||||
|
out.Close()
|
||||||
|
os.Remove(destPath)
|
||||||
|
return false, nil
|
||||||
|
default:
|
||||||
|
if err != nil {
|
||||||
|
os.Remove(destPath)
|
||||||
|
return false, fmt.Errorf("error copying data: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user