v5.7-patch1
This commit is contained in:
+13
-6
@@ -172,7 +172,7 @@ func sanitizeFilename(name string) string {
|
||||
return sanitized
|
||||
}
|
||||
|
||||
func buildFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool) string {
|
||||
func buildFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool, position int) string {
|
||||
var filename string
|
||||
|
||||
// Build base filename based on format
|
||||
@@ -186,14 +186,15 @@ func buildFilename(title, artist string, trackNumber int, format string, include
|
||||
}
|
||||
|
||||
// Add track number prefix if enabled
|
||||
if includeTrackNumber && trackNumber > 0 {
|
||||
filename = fmt.Sprintf("%02d. %s", trackNumber, filename)
|
||||
// Only use track number for bulk downloads (when position > 0)
|
||||
if includeTrackNumber && position > 0 {
|
||||
filename = fmt.Sprintf("%02d. %s", position, filename)
|
||||
}
|
||||
|
||||
return filename + ".flac"
|
||||
}
|
||||
|
||||
func (d *DeezerDownloader) DownloadByISRC(isrc, outputDir, filenameFormat string, includeTrackNumber bool, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) error {
|
||||
func (d *DeezerDownloader) DownloadByISRC(isrc, outputDir, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) error {
|
||||
fmt.Printf("Fetching track info for ISRC: %s\n", isrc)
|
||||
|
||||
track, err := d.GetTrackByISRC(isrc)
|
||||
@@ -241,7 +242,7 @@ func (d *DeezerDownloader) DownloadByISRC(isrc, outputDir, filenameFormat string
|
||||
safeTitle := sanitizeFilename(trackTitle)
|
||||
|
||||
// Build filename based on format settings
|
||||
filename := buildFilename(safeTitle, safeArtist, track.TrackPos, filenameFormat, includeTrackNumber)
|
||||
filename := buildFilename(safeTitle, safeArtist, track.TrackPos, filenameFormat, includeTrackNumber, position)
|
||||
filepath := filepath.Join(outputDir, filename)
|
||||
|
||||
fmt.Println("Downloading FLAC file...")
|
||||
@@ -263,12 +264,18 @@ func (d *DeezerDownloader) DownloadByISRC(isrc, outputDir, filenameFormat string
|
||||
}
|
||||
|
||||
fmt.Println("Embedding metadata and cover art...")
|
||||
// Only use track number for bulk downloads (when position > 0)
|
||||
trackNumberToEmbed := 0
|
||||
if position > 0 {
|
||||
trackNumberToEmbed = position
|
||||
}
|
||||
|
||||
metadata := Metadata{
|
||||
Title: trackTitle,
|
||||
Artist: artists,
|
||||
Album: albumTitle,
|
||||
Date: track.ReleaseDate,
|
||||
TrackNumber: track.TrackPos,
|
||||
TrackNumber: trackNumberToEmbed,
|
||||
DiscNumber: track.DiskNumber,
|
||||
ISRC: track.ISRC,
|
||||
}
|
||||
|
||||
+43
-1
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Global progress tracker
|
||||
@@ -12,12 +13,15 @@ var (
|
||||
currentProgressLock sync.RWMutex
|
||||
isDownloading bool
|
||||
downloadingLock sync.RWMutex
|
||||
currentSpeed float64
|
||||
speedLock sync.RWMutex
|
||||
)
|
||||
|
||||
// ProgressInfo represents download progress information
|
||||
type ProgressInfo struct {
|
||||
IsDownloading bool `json:"is_downloading"`
|
||||
MBDownloaded float64 `json:"mb_downloaded"`
|
||||
SpeedMBps float64 `json:"speed_mbps"`
|
||||
}
|
||||
|
||||
// GetDownloadProgress returns current download progress
|
||||
@@ -30,12 +34,24 @@ func GetDownloadProgress() ProgressInfo {
|
||||
progress := currentProgress
|
||||
currentProgressLock.RUnlock()
|
||||
|
||||
speedLock.RLock()
|
||||
speed := currentSpeed
|
||||
speedLock.RUnlock()
|
||||
|
||||
return ProgressInfo{
|
||||
IsDownloading: downloading,
|
||||
MBDownloaded: progress,
|
||||
SpeedMBps: speed,
|
||||
}
|
||||
}
|
||||
|
||||
// SetDownloadSpeed updates the current download speed
|
||||
func SetDownloadSpeed(mbps float64) {
|
||||
speedLock.Lock()
|
||||
currentSpeed = mbps
|
||||
speedLock.Unlock()
|
||||
}
|
||||
|
||||
// SetDownloadProgress updates the current download progress
|
||||
func SetDownloadProgress(mbDownloaded float64) {
|
||||
currentProgressLock.Lock()
|
||||
@@ -52,6 +68,7 @@ func SetDownloading(downloading bool) {
|
||||
if !downloading {
|
||||
// Reset progress when download completes
|
||||
SetDownloadProgress(0)
|
||||
SetDownloadSpeed(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,16 +77,27 @@ type ProgressWriter struct {
|
||||
writer io.Writer
|
||||
total int64
|
||||
lastPrinted int64
|
||||
startTime int64
|
||||
lastTime int64
|
||||
lastBytes int64
|
||||
}
|
||||
|
||||
func NewProgressWriter(writer io.Writer) *ProgressWriter {
|
||||
now := getCurrentTimeMillis()
|
||||
return &ProgressWriter{
|
||||
writer: writer,
|
||||
total: 0,
|
||||
lastPrinted: 0,
|
||||
startTime: now,
|
||||
lastTime: now,
|
||||
lastBytes: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func getCurrentTimeMillis() int64 {
|
||||
return time.Now().UnixMilli()
|
||||
}
|
||||
|
||||
func (pw *ProgressWriter) Write(p []byte) (int, error) {
|
||||
n, err := pw.writer.Write(p)
|
||||
pw.total += int64(n)
|
||||
@@ -77,12 +105,26 @@ func (pw *ProgressWriter) Write(p []byte) (int, error) {
|
||||
// Report progress every 256KB for smoother updates
|
||||
if pw.total-pw.lastPrinted >= 256*1024 {
|
||||
mbDownloaded := float64(pw.total) / (1024 * 1024)
|
||||
fmt.Printf("\rDownloaded: %.2f MB", mbDownloaded)
|
||||
|
||||
// Calculate speed (MB/s)
|
||||
now := getCurrentTimeMillis()
|
||||
timeDiff := float64(now-pw.lastTime) / 1000.0 // seconds
|
||||
bytesDiff := float64(pw.total - pw.lastBytes)
|
||||
|
||||
if timeDiff > 0 {
|
||||
speedMBps := (bytesDiff / (1024 * 1024)) / timeDiff
|
||||
SetDownloadSpeed(speedMBps)
|
||||
fmt.Printf("\rDownloaded: %.2f MB (%.2f MB/s)", mbDownloaded, speedMBps)
|
||||
} else {
|
||||
fmt.Printf("\rDownloaded: %.2f MB", mbDownloaded)
|
||||
}
|
||||
|
||||
// Update global progress
|
||||
SetDownloadProgress(mbDownloaded)
|
||||
|
||||
pw.lastPrinted = pw.total
|
||||
pw.lastTime = now
|
||||
pw.lastBytes = pw.total
|
||||
}
|
||||
|
||||
return n, err
|
||||
|
||||
+13
-6
@@ -222,7 +222,7 @@ func (q *QobuzDownloader) DownloadCoverArt(coverURL, filepath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func buildQobuzFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool) string {
|
||||
func buildQobuzFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool, position int) string {
|
||||
var filename string
|
||||
|
||||
// Build base filename based on format
|
||||
@@ -236,14 +236,15 @@ func buildQobuzFilename(title, artist string, trackNumber int, format string, in
|
||||
}
|
||||
|
||||
// Add track number prefix if enabled
|
||||
if includeTrackNumber && trackNumber > 0 {
|
||||
filename = fmt.Sprintf("%02d. %s", trackNumber, filename)
|
||||
// Only use track number for bulk downloads (when position > 0)
|
||||
if includeTrackNumber && position > 0 {
|
||||
filename = fmt.Sprintf("%02d. %s", position, filename)
|
||||
}
|
||||
|
||||
return filename + ".flac"
|
||||
}
|
||||
|
||||
func (q *QobuzDownloader) DownloadByISRC(isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) error {
|
||||
func (q *QobuzDownloader) DownloadByISRC(isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) error {
|
||||
fmt.Printf("Fetching track info for ISRC: %s\n", isrc)
|
||||
|
||||
// Create output directory if it doesn't exist
|
||||
@@ -311,7 +312,7 @@ func (q *QobuzDownloader) DownloadByISRC(isrc, outputDir, quality, filenameForma
|
||||
safeTitle := sanitizeFilename(trackTitle)
|
||||
|
||||
// Build filename based on format settings
|
||||
filename := buildQobuzFilename(safeTitle, safeArtist, track.TrackNumber, filenameFormat, includeTrackNumber)
|
||||
filename := buildQobuzFilename(safeTitle, safeArtist, track.TrackNumber, filenameFormat, includeTrackNumber, position)
|
||||
filepath := filepath.Join(outputDir, filename)
|
||||
|
||||
fmt.Printf("Downloading FLAC file to: %s\n", filepath)
|
||||
@@ -339,12 +340,18 @@ func (q *QobuzDownloader) DownloadByISRC(isrc, outputDir, quality, filenameForma
|
||||
releaseYear = track.ReleaseDateOriginal[:4]
|
||||
}
|
||||
|
||||
// Only use track number for bulk downloads (when position > 0)
|
||||
trackNumberToEmbed := 0
|
||||
if position > 0 {
|
||||
trackNumberToEmbed = position
|
||||
}
|
||||
|
||||
metadata := Metadata{
|
||||
Title: trackTitle,
|
||||
Artist: artists,
|
||||
Album: albumTitle,
|
||||
Date: releaseYear,
|
||||
TrackNumber: track.TrackNumber,
|
||||
TrackNumber: trackNumberToEmbed,
|
||||
DiscNumber: track.MediaNumber,
|
||||
ISRC: track.ISRC,
|
||||
}
|
||||
|
||||
+15
-8
@@ -333,7 +333,7 @@ func (t *TidalDownloader) DownloadFile(url, filepath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) (string, error) {
|
||||
func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) (string, error) {
|
||||
if outputDir != "." {
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
return "", fmt.Errorf("directory error: %w", err)
|
||||
@@ -386,7 +386,7 @@ func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameForm
|
||||
}
|
||||
|
||||
// Build filename based on format settings
|
||||
filename := buildTidalFilename(trackTitle, artistName, trackInfo.TrackNumber, filenameFormat, includeTrackNumber)
|
||||
filename := buildTidalFilename(trackTitle, artistName, trackInfo.TrackNumber, filenameFormat, includeTrackNumber, position)
|
||||
outputFilename := filepath.Join(outputDir, filename)
|
||||
|
||||
if fileInfo, err := os.Stat(outputFilename); err == nil && fileInfo.Size() > 0 {
|
||||
@@ -427,12 +427,18 @@ func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameForm
|
||||
releaseYear = trackInfo.Album.ReleaseDate[:4]
|
||||
}
|
||||
|
||||
// Only use track number for bulk downloads (when position > 0)
|
||||
trackNumberToEmbed := 0
|
||||
if position > 0 {
|
||||
trackNumberToEmbed = position
|
||||
}
|
||||
|
||||
metadata := Metadata{
|
||||
Title: trackTitle,
|
||||
Artist: artistName,
|
||||
Album: albumTitle,
|
||||
Date: releaseYear,
|
||||
TrackNumber: trackInfo.TrackNumber,
|
||||
TrackNumber: trackNumberToEmbed,
|
||||
DiscNumber: trackInfo.VolumeNumber,
|
||||
ISRC: trackInfo.ISRC,
|
||||
}
|
||||
@@ -447,7 +453,7 @@ func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameForm
|
||||
return outputFilename, nil
|
||||
}
|
||||
|
||||
func (t *TidalDownloader) DownloadWithFallback(query, isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) (string, error) {
|
||||
func (t *TidalDownloader) DownloadWithFallback(query, isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) (string, error) {
|
||||
apis, err := t.GetAvailableAPIs()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("no APIs available for fallback: %w", err)
|
||||
@@ -459,7 +465,7 @@ func (t *TidalDownloader) DownloadWithFallback(query, isrc, outputDir, quality,
|
||||
|
||||
fallbackDownloader := NewTidalDownloader(apiURL)
|
||||
|
||||
result, err := fallbackDownloader.Download(query, isrc, outputDir, quality, filenameFormat, includeTrackNumber, spotifyTrackName, spotifyArtistName, spotifyAlbumName)
|
||||
result, err := fallbackDownloader.Download(query, isrc, outputDir, quality, filenameFormat, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName)
|
||||
if err == nil {
|
||||
fmt.Printf("✓ Success with: %s\n", apiURL)
|
||||
return result, nil
|
||||
@@ -476,7 +482,7 @@ func (t *TidalDownloader) DownloadWithFallback(query, isrc, outputDir, quality,
|
||||
return "", fmt.Errorf("all %d APIs failed. Last error: %v", len(apis), lastError)
|
||||
}
|
||||
|
||||
func buildTidalFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool) string {
|
||||
func buildTidalFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool, position int) string {
|
||||
var filename string
|
||||
|
||||
// Build base filename based on format
|
||||
@@ -490,8 +496,9 @@ func buildTidalFilename(title, artist string, trackNumber int, format string, in
|
||||
}
|
||||
|
||||
// Add track number prefix if enabled
|
||||
if includeTrackNumber && trackNumber > 0 {
|
||||
filename = fmt.Sprintf("%02d. %s", trackNumber, filename)
|
||||
// Only use track number for bulk downloads (when position > 0)
|
||||
if includeTrackNumber && position > 0 {
|
||||
filename = fmt.Sprintf("%02d. %s", position, filename)
|
||||
}
|
||||
|
||||
return filename + ".flac"
|
||||
|
||||
Reference in New Issue
Block a user