mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-03-31 17:10:29 +02:00
223 lines
5.6 KiB
Go
223 lines
5.6 KiB
Go
package gobackend
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sync"
|
|
)
|
|
|
|
// DownloadProgress represents current download progress
|
|
// Now unified - returns data from multi-progress system
|
|
type DownloadProgress struct {
|
|
CurrentFile string `json:"current_file"`
|
|
Progress float64 `json:"progress"`
|
|
Speed float64 `json:"speed_mbps"`
|
|
BytesTotal int64 `json:"bytes_total"`
|
|
BytesReceived int64 `json:"bytes_received"`
|
|
IsDownloading bool `json:"is_downloading"`
|
|
Status string `json:"status"` // "downloading", "finalizing", "completed"
|
|
}
|
|
|
|
// ItemProgress represents progress for a single download item
|
|
type ItemProgress struct {
|
|
ItemID string `json:"item_id"`
|
|
BytesTotal int64 `json:"bytes_total"`
|
|
BytesReceived int64 `json:"bytes_received"`
|
|
Progress float64 `json:"progress"` // 0.0 to 1.0
|
|
IsDownloading bool `json:"is_downloading"`
|
|
Status string `json:"status"` // "downloading", "finalizing", "completed"
|
|
}
|
|
|
|
// MultiProgress holds progress for multiple concurrent downloads
|
|
type MultiProgress struct {
|
|
Items map[string]*ItemProgress `json:"items"`
|
|
}
|
|
|
|
var (
|
|
downloadDir string
|
|
downloadDirMu sync.RWMutex
|
|
|
|
// Multi-download progress tracking (unified system)
|
|
multiProgress = MultiProgress{Items: make(map[string]*ItemProgress)}
|
|
multiMu sync.RWMutex
|
|
)
|
|
|
|
// getProgress returns current download progress from multi-progress system
|
|
// Returns first active item's progress for backward compatibility
|
|
func getProgress() DownloadProgress {
|
|
multiMu.RLock()
|
|
defer multiMu.RUnlock()
|
|
|
|
// Find first active item
|
|
for _, item := range multiProgress.Items {
|
|
return DownloadProgress{
|
|
CurrentFile: item.ItemID,
|
|
Progress: item.Progress * 100, // Convert to percentage
|
|
BytesTotal: item.BytesTotal,
|
|
BytesReceived: item.BytesReceived,
|
|
IsDownloading: item.IsDownloading,
|
|
Status: item.Status,
|
|
}
|
|
}
|
|
|
|
return DownloadProgress{}
|
|
}
|
|
|
|
// GetMultiProgress returns progress for all active downloads as JSON
|
|
func GetMultiProgress() string {
|
|
multiMu.RLock()
|
|
defer multiMu.RUnlock()
|
|
|
|
jsonBytes, err := json.Marshal(multiProgress)
|
|
if err != nil {
|
|
return "{\"items\":{}}"
|
|
}
|
|
return string(jsonBytes)
|
|
}
|
|
|
|
// GetItemProgress returns progress for a specific item as JSON
|
|
func GetItemProgress(itemID string) string {
|
|
multiMu.RLock()
|
|
defer multiMu.RUnlock()
|
|
|
|
if item, ok := multiProgress.Items[itemID]; ok {
|
|
jsonBytes, _ := json.Marshal(item)
|
|
return string(jsonBytes)
|
|
}
|
|
return "{}"
|
|
}
|
|
|
|
// StartItemProgress initializes progress tracking for an item
|
|
func StartItemProgress(itemID string) {
|
|
multiMu.Lock()
|
|
defer multiMu.Unlock()
|
|
|
|
multiProgress.Items[itemID] = &ItemProgress{
|
|
ItemID: itemID,
|
|
BytesTotal: 0,
|
|
BytesReceived: 0,
|
|
Progress: 0,
|
|
IsDownloading: true,
|
|
Status: "downloading",
|
|
}
|
|
}
|
|
|
|
// SetItemBytesTotal sets total bytes for an item
|
|
func SetItemBytesTotal(itemID string, total int64) {
|
|
multiMu.Lock()
|
|
defer multiMu.Unlock()
|
|
|
|
if item, ok := multiProgress.Items[itemID]; ok {
|
|
item.BytesTotal = total
|
|
}
|
|
}
|
|
|
|
// SetItemBytesReceived sets bytes received for an item
|
|
func SetItemBytesReceived(itemID string, received int64) {
|
|
multiMu.Lock()
|
|
defer multiMu.Unlock()
|
|
|
|
if item, ok := multiProgress.Items[itemID]; ok {
|
|
item.BytesReceived = received
|
|
if item.BytesTotal > 0 {
|
|
item.Progress = float64(received) / float64(item.BytesTotal)
|
|
}
|
|
}
|
|
}
|
|
|
|
// CompleteItemProgress marks an item as complete
|
|
func CompleteItemProgress(itemID string) {
|
|
multiMu.Lock()
|
|
defer multiMu.Unlock()
|
|
|
|
if item, ok := multiProgress.Items[itemID]; ok {
|
|
item.Progress = 1.0
|
|
item.IsDownloading = false
|
|
item.Status = "completed"
|
|
}
|
|
}
|
|
|
|
// SetItemProgress sets progress for an item directly
|
|
func SetItemProgress(itemID string, progress float64, bytesReceived, bytesTotal int64) {
|
|
multiMu.Lock()
|
|
defer multiMu.Unlock()
|
|
|
|
if item, ok := multiProgress.Items[itemID]; ok {
|
|
item.Progress = progress
|
|
if bytesReceived > 0 {
|
|
item.BytesReceived = bytesReceived
|
|
}
|
|
if bytesTotal > 0 {
|
|
item.BytesTotal = bytesTotal
|
|
}
|
|
}
|
|
}
|
|
|
|
// SetItemFinalizing marks an item as finalizing (embedding metadata)
|
|
func SetItemFinalizing(itemID string) {
|
|
multiMu.Lock()
|
|
defer multiMu.Unlock()
|
|
|
|
if item, ok := multiProgress.Items[itemID]; ok {
|
|
item.Progress = 1.0
|
|
item.Status = "finalizing"
|
|
}
|
|
}
|
|
|
|
// RemoveItemProgress removes progress tracking for an item
|
|
func RemoveItemProgress(itemID string) {
|
|
multiMu.Lock()
|
|
defer multiMu.Unlock()
|
|
|
|
delete(multiProgress.Items, itemID)
|
|
}
|
|
|
|
// ClearAllItemProgress clears all item progress
|
|
func ClearAllItemProgress() {
|
|
multiMu.Lock()
|
|
defer multiMu.Unlock()
|
|
|
|
multiProgress.Items = make(map[string]*ItemProgress)
|
|
}
|
|
|
|
// setDownloadDir sets the default download directory
|
|
func setDownloadDir(path string) error {
|
|
downloadDirMu.Lock()
|
|
defer downloadDirMu.Unlock()
|
|
downloadDir = path
|
|
return nil
|
|
}
|
|
|
|
// getDownloadDir returns the default download directory
|
|
func getDownloadDir() string {
|
|
downloadDirMu.RLock()
|
|
defer downloadDirMu.RUnlock()
|
|
return downloadDir
|
|
}
|
|
|
|
// ItemProgressWriter wraps io.Writer to track download progress for a specific item
|
|
type ItemProgressWriter struct {
|
|
writer interface{ Write([]byte) (int, error) }
|
|
itemID string
|
|
current int64
|
|
}
|
|
|
|
// NewItemProgressWriter creates a new progress writer for a specific item
|
|
func NewItemProgressWriter(w interface{ Write([]byte) (int, error) }, itemID string) *ItemProgressWriter {
|
|
return &ItemProgressWriter{
|
|
writer: w,
|
|
itemID: itemID,
|
|
current: 0,
|
|
}
|
|
}
|
|
|
|
// Write implements io.Writer
|
|
func (pw *ItemProgressWriter) Write(p []byte) (int, error) {
|
|
n, err := pw.writer.Write(p)
|
|
if err != nil {
|
|
return n, err
|
|
}
|
|
pw.current += int64(n)
|
|
SetItemBytesReceived(pw.itemID, pw.current)
|
|
return n, nil
|
|
}
|