feat(cms): replace track audio in edit form, gate last-track delete
Swap a track's audio by EntryKey (metadata/release/position preserved, waveform regenerated); hide per-track remove on a release's sole persisted track so it can only be replaced or release-deleted.
This commit is contained in:
@@ -100,6 +100,54 @@ public class TrackContentService
|
||||
string? originalFileName = null) =>
|
||||
AddTrackAsync(wavFilePath, trackName, artist, album, genre, releaseDate, originalFileName);
|
||||
|
||||
/// <summary>
|
||||
/// Swaps the audio bytes for an existing track in place: processes a new audio file and
|
||||
/// re-registers it under the SAME <paramref name="entryKey"/> in the tracks vault. The track's
|
||||
/// vault key — and therefore its SQL link, release membership, position, and metadata — is
|
||||
/// untouched; only the binary changes. The prior entry is removed first so a replacement whose
|
||||
/// extension differs from the original (e.g. .wav → .flac) does not strand the old file on disk
|
||||
/// under its former filename. Returns the freshly stored <see cref="AudioBinary"/> on success
|
||||
/// (so the caller can regenerate waveform data from the same bytes), or null on processing or
|
||||
/// vault failure — matching the FileDatabase swallow-and-return-null contract.
|
||||
/// </summary>
|
||||
public async Task<AudioBinary?> ReplaceTrackAudioAsync(string entryKey, string audioFilePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var audioBinary = await _audioProcessorRouter.ProcessAudioFileAsync(audioFilePath);
|
||||
if (audioBinary == null)
|
||||
{
|
||||
Console.WriteLine($"TrackContentService.ReplaceTrackAudioAsync: processing returned null for {entryKey}");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!_fileDatabase.HasVault(VaultConstants.Tracks))
|
||||
{
|
||||
await _fileDatabase.CreateVaultAsync(VaultConstants.Tracks, MediaVaultType.Audio);
|
||||
}
|
||||
|
||||
// Drop the old entry first. The backing file is keyed by entryKey + its *stored*
|
||||
// extension, so a register alone would leave a stale file when the new format differs.
|
||||
// A null/false removal is non-fatal (the entry may already be absent); the register
|
||||
// below is the authoritative write.
|
||||
await _fileDatabase.RemoveResourceAsync(VaultConstants.Tracks, entryKey);
|
||||
|
||||
var success = await _fileDatabase.RegisterResourceAsync(VaultConstants.Tracks, entryKey, audioBinary);
|
||||
if (!success)
|
||||
{
|
||||
Console.WriteLine($"TrackContentService.ReplaceTrackAudioAsync: vault write failed for {entryKey}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return audioBinary;
|
||||
}
|
||||
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||
{
|
||||
Console.WriteLine($"TrackContentService.ReplaceTrackAudioAsync failed: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves audio binary from FileDatabase
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user