feat: add support for multi-disc albums
This commit is contained in:
@@ -61,9 +61,13 @@ export async function POST(request: Request) {
|
||||
// Calculate total size
|
||||
const totalSize = tracks.reduce((acc, track) => acc + (track.size || 0), 0);
|
||||
|
||||
// Sort tracks by track number if available, else by filename
|
||||
// Sort tracks by disc number first, then track number, else by filename
|
||||
tracks.sort((a, b) => {
|
||||
if ('error' in a || 'error' in b) return 0; // Keep order if error
|
||||
const discA = a.common?.disk?.no ?? 1;
|
||||
const discB = b.common?.disk?.no ?? 1;
|
||||
if (discA !== discB) return discA - discB;
|
||||
|
||||
const trackA = a.common?.track?.no ?? 0;
|
||||
const trackB = b.common?.track?.no ?? 0;
|
||||
if (trackA && trackB) return trackA - trackB;
|
||||
@@ -95,6 +99,11 @@ export async function POST(request: Request) {
|
||||
}
|
||||
});
|
||||
|
||||
const discNumbers = new Set(
|
||||
tracks.map(t => ('error' in t ? 1 : (t.common?.disk?.no || 1)))
|
||||
);
|
||||
const isMultiDisc = discNumbers.size > 1 || Array.from(discNumbers).some(d => d > 1);
|
||||
|
||||
if (sampleRates.size > 1 || bitDepths.size > 1) {
|
||||
mixed = true;
|
||||
qualityDetails = `NOTE: Mixed formats. Sample Rates: ${Array.from(sampleRates).join(', ')} Hz. Bit Depths: ${Array.from(bitDepths).join(', ')} bit.`;
|
||||
@@ -102,7 +111,13 @@ export async function POST(request: Request) {
|
||||
// Generate detailed message for mixed content
|
||||
const mixedDetails = tracks.map(t => {
|
||||
if ('error' in t) return `${t.filename}: Error`;
|
||||
return `Track ${t.common?.track?.no || '?'}: ${t.format?.bitsPerSample}bit / ${t.format?.sampleRate}Hz`;
|
||||
const discNo = t.common?.disk?.no || 1;
|
||||
const trackNo = t.common?.track?.no;
|
||||
let trackStr = trackNo !== undefined && trackNo !== null ? String(trackNo).padStart(2, '0') : '?';
|
||||
if (isMultiDisc) {
|
||||
trackStr = `${discNo}-${trackStr}`;
|
||||
}
|
||||
return `Track ${trackStr}: ${t.format?.bitsPerSample}bit / ${t.format?.sampleRate}Hz`;
|
||||
}).join('\n');
|
||||
|
||||
qualityDetails += '\n' + mixedDetails;
|
||||
|
||||
@@ -34,6 +34,10 @@ export async function POST(request: Request) {
|
||||
// Sort tracks
|
||||
tracks.sort((a, b) => {
|
||||
if ('error' in a || 'error' in b) return 0;
|
||||
const discA = a.common?.disk?.no ?? 1;
|
||||
const discB = b.common?.disk?.no ?? 1;
|
||||
if (discA !== discB) return discA - discB;
|
||||
|
||||
const trackA = a.common?.track?.no ?? 0;
|
||||
const trackB = b.common?.track?.no ?? 0;
|
||||
if (trackA && trackB) return trackA - trackB;
|
||||
@@ -58,13 +62,24 @@ export async function POST(request: Request) {
|
||||
if (!sr || sr < 48000 || !bd || bd < 24) isHiRes = false;
|
||||
});
|
||||
|
||||
const discNumbers = new Set(
|
||||
tracks.map(t => ('error' in t ? 1 : (t.common?.disk?.no || 1)))
|
||||
);
|
||||
const isMultiDisc = discNumbers.size > 1 || Array.from(discNumbers).some(d => d > 1);
|
||||
|
||||
if (sampleRates.size > 1 || bitDepths.size > 1) {
|
||||
mixed = true;
|
||||
qualityDetails = `\n\nNOTE: Mixed formats. Sample Rates: ${Array.from(sampleRates).join(', ')} Hz. Bit Depths: ${Array.from(bitDepths).join(', ')} bit.`;
|
||||
|
||||
const mixedDetails = tracks.map(t => {
|
||||
if ('error' in t) return `${t.filename}: Error`;
|
||||
return `Track ${t.common?.track?.no || '?'}: ${t.format?.bitsPerSample}bit / ${t.format?.sampleRate}Hz`;
|
||||
const discNo = t.common?.disk?.no || 1;
|
||||
const trackNo = t.common?.track?.no;
|
||||
let trackStr = trackNo !== undefined && trackNo !== null ? String(trackNo).padStart(2, '0') : '?';
|
||||
if (isMultiDisc) {
|
||||
trackStr = `${discNo}-${trackStr}`;
|
||||
}
|
||||
return `Track ${trackStr}: ${t.format?.bitsPerSample}bit / ${t.format?.sampleRate}Hz`;
|
||||
}).join('\n');
|
||||
|
||||
qualityDetails += '\n' + mixedDetails;
|
||||
@@ -155,10 +170,32 @@ export async function POST(request: Request) {
|
||||
}
|
||||
|
||||
// Tracklist
|
||||
const tracklist = tracks.map(t => {
|
||||
if ('error' in t) return `${t.filename} (Error)`;
|
||||
return `${t.common?.track?.no || '00'}. ${t.common?.title || t.filename}`;
|
||||
}).join('\n');
|
||||
|
||||
let currentDisc: number | null = null;
|
||||
const tracklistLines: string[] = [];
|
||||
|
||||
tracks.forEach(t => {
|
||||
if ('error' in t) {
|
||||
tracklistLines.push(`${t.filename} (Error)`);
|
||||
return;
|
||||
}
|
||||
|
||||
const discNo = t.common?.disk?.no || 1;
|
||||
const trackNo = t.common?.track?.no
|
||||
? String(t.common.track.no).padStart(2, '0')
|
||||
: '00';
|
||||
|
||||
if (isMultiDisc && discNo !== currentDisc) {
|
||||
if (currentDisc !== null) tracklistLines.push('');
|
||||
tracklistLines.push(`[b]Disc ${discNo}[/b]`);
|
||||
currentDisc = discNo;
|
||||
}
|
||||
|
||||
const trackLabel = isMultiDisc ? `${discNo}-${trackNo}` : trackNo;
|
||||
tracklistLines.push(`${trackLabel}. ${t.common?.title || t.filename}`);
|
||||
});
|
||||
|
||||
const tracklist = tracklistLines.join('\n');
|
||||
|
||||
// Description
|
||||
let description = "Sourced from TIDAL";
|
||||
|
||||
@@ -32,9 +32,14 @@ export async function POST(request: Request) {
|
||||
if ('error' in track) return;
|
||||
|
||||
const trackNo = track.common?.track?.no;
|
||||
const discNo = track.common?.disk?.no;
|
||||
if (trackNo === undefined || trackNo === null) return;
|
||||
|
||||
const outputFilename = `${trackNo}.png`;
|
||||
const discPrefix = (discNo && discNo > 1) || tracks.some(t => !('error' in t) && (t.common?.disk?.no ?? 1) > 1)
|
||||
? `${discNo ?? 1}-`
|
||||
: '';
|
||||
|
||||
const outputFilename = `${discPrefix}${trackNo}.png`;
|
||||
const outputPath = path.join(albumSpecDir, outputFilename);
|
||||
const relativePath = path.join(albumId, outputFilename);
|
||||
const publicUrl = `/api/spectrogram?path=${encodeURIComponent(relativePath)}`;
|
||||
@@ -43,7 +48,7 @@ export async function POST(request: Request) {
|
||||
|
||||
if (!exists) {
|
||||
// Generate
|
||||
const title = `${trackNo} - ${track.common?.title || track.filename}`;
|
||||
const title = `${discPrefix}${trackNo} - ${track.common?.title || track.filename}`;
|
||||
|
||||
const args = [
|
||||
track.path,
|
||||
|
||||
Reference in New Issue
Block a user