Add the support to copy .cue files to the media library folder.

(cherry picked from commit 57ae74b49afea29100882edbe6e49fa24210bbbf)
pull/4200/head
zhangdoa 7 months ago
parent 31016bca8a
commit 16a3fbe25b

@ -58,6 +58,11 @@ const columns = [
label: () => 'Is Single File Release',
isVisible: true
},
{
name: 'cuesheetPath',
label: () => 'Cuesheet Path',
isVisible: true
},
{
name: 'releaseGroup',
label: () => translate('ReleaseGroup'),
@ -441,6 +446,7 @@ class InteractiveImportModalContent extends Component {
onSelectedChange={this.onSelectedChange}
onValidRowChange={this.onValidRowChange}
isSingleFileRelease={item.isSingleFileRelease}
cuesheetPath={item.cuesheetPath}
/>
);
})

@ -135,6 +135,7 @@ class InteractiveImportModalContentConnector extends Component {
albumReleaseId,
tracks,
isSingleFileRelease,
cuesheetPath,
quality,
disableReleaseSwitching
} = item;
@ -149,7 +150,7 @@ class InteractiveImportModalContentConnector extends Component {
return false;
}
if (!isSingleFileRelease && (!tracks || !tracks.length)) {
if (!(isSingleFileRelease && cuesheetPath) && (!tracks || !tracks.length)) {
this.setState({ interactiveImportErrorMessage: 'One or more tracks must be chosen for each selected file' });
return false;
}
@ -166,6 +167,7 @@ class InteractiveImportModalContentConnector extends Component {
albumReleaseId,
trackIds: _.map(tracks, 'id'),
isSingleFileRelease: item.isSingleFileRelease,
cuesheetPath: item.cuesheetPath,
quality,
downloadId: this.props.downloadId,
disableReleaseSwitching

@ -65,6 +65,7 @@ class InteractiveImportRow extends Component {
album,
tracks,
isSingleFileRelease,
cuesheetPath,
quality,
isSelected,
onValidRowChange
@ -83,7 +84,7 @@ class InteractiveImportRow extends Component {
const isValid = !!(
artist &&
album &&
(isSingleFileRelease || tracks.length) &&
((isSingleFileRelease && cuesheetPath) || tracks.length) &&
quality
);
@ -169,6 +170,7 @@ class InteractiveImportRow extends Component {
albumReleaseId,
tracks,
isSingleFileRelease,
cuesheetPath,
quality,
releaseGroup,
size,
@ -281,6 +283,15 @@ class InteractiveImportRow extends Component {
}
</TableRowCell>
<TableRowCell
id={id}
title={'Cuesheet Path'}
>
{
cuesheetPath
}
</TableRowCell>
<TableRowCellButton
title={translate('ClickToChangeReleaseGroup')}
onPress={this.onSelectReleaseGroupPress}
@ -422,6 +433,7 @@ InteractiveImportRow.propTypes = {
albumReleaseId: PropTypes.number,
tracks: PropTypes.arrayOf(PropTypes.object),
isSingleFileRelease: PropTypes.bool.isRequired,
cuesheetPath: PropTypes.string.isRequired,
releaseGroup: PropTypes.string,
quality: PropTypes.object,
size: PropTypes.number.isRequired,

@ -207,6 +207,7 @@ export const actionHandlers = handleThunks({
albumReleaseId: item.albumReleaseId ? item.albumReleaseId : undefined,
trackIds: (item.tracks || []).map((e) => e.id),
isSingleFileRelease: item.isSingleFileRelease,
cuesheetPath: item.cuesheetPath,
quality: item.quality,
releaseGroup: item.releaseGroup,
downloadId: item.downloadId,

@ -85,6 +85,7 @@ namespace Lidarr.Api.V1.ManualImport
ReplaceExistingFiles = resource.ReplaceExistingFiles,
DisableReleaseSwitching = resource.DisableReleaseSwitching,
IsSingleFileRelease = resource.IsSingleFileRelease,
CuesheetPath = resource.CuesheetPath,
});
}

@ -30,6 +30,7 @@ namespace Lidarr.Api.V1.ManualImport
public bool ReplaceExistingFiles { get; set; }
public bool DisableReleaseSwitching { get; set; }
public bool IsSingleFileRelease { get; set; }
public string CuesheetPath { get; set; }
}
public static class ManualImportResourceMapper
@ -54,6 +55,7 @@ namespace Lidarr.Api.V1.ManualImport
Quality = model.Quality,
ReleaseGroup = model.ReleaseGroup,
IsSingleFileRelease = model.IsSingleFileRelease,
CuesheetPath = model.CuesheetPath,
// QualityWeight
DownloadId = model.DownloadId,

@ -22,7 +22,7 @@ namespace Lidarr.Api.V1.ManualImport
public bool ReplaceExistingFiles { get; set; }
public bool DisableReleaseSwitching { get; set; }
public bool IsSingleFileRelease { get; set; }
public string CuesheetPath { get; set; }
public IEnumerable<Rejection> Rejections { get; set; }
}
}

@ -140,6 +140,7 @@ namespace NzbDrone.Core.MediaFiles
CleanMediaFiles(folder, files.Select(x => x.FullName).ToList());
mediaFileList.AddRange(files);
mediaFileList.RemoveAll(x => x.Extension == ".cue");
}
musicFilesStopwatch.Stop();

@ -4,6 +4,7 @@ using System.IO;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.MediaFiles.TrackImport;
@ -90,6 +91,21 @@ namespace NzbDrone.Core.MediaFiles
EnsureTrackFolder(trackFile, localTrack, filePath);
if (!localTrack.CuesheetPath.Empty())
{
var directory = Path.GetDirectoryName(filePath);
var fileName = Path.GetFileNameWithoutExtension(filePath);
var cuesheetPath = Path.Combine(directory, fileName + ".cue");
_diskTransferService.TransferFile(localTrack.CuesheetPath, cuesheetPath, TransferMode.Copy);
var lines = new List<string>(File.ReadAllLines(cuesheetPath));
var fileLineIndex = lines.FindIndex(line => line.Contains("FILE"));
if (fileLineIndex != -1)
{
lines[fileLineIndex] = "FILE \"" + Path.GetFileName(filePath) + "\" WAVE";
File.WriteAllLines(cuesheetPath, lines);
}
}
if (_configService.CopyUsingHardlinks)
{
_logger.Debug("Attempting to hardlink track file: {0} to {1}", trackFile.Path, filePath);

@ -16,6 +16,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
public string DownloadId { get; set; }
public bool DisableReleaseSwitching { get; set; }
public bool IsSingleFileRelease { get; set; }
public string CuesheetPath { get; set; }
public bool Equals(ManualImportFile other)
{

@ -33,5 +33,6 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
public bool ReplaceExistingFiles { get; set; }
public bool DisableReleaseSwitching { get; set; }
public bool IsSingleFileRelease { get; set; }
public string CuesheetPath { get; set; }
}
}

@ -186,6 +186,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
audioFiles.RemoveAll(l => cueFiles.Contains(l));
foreach (var cueFile in cueFiles)
{
// TODO move this to the disk service
using (var fs = cueFile.OpenRead())
{
var bytes = new byte[cueFile.Length];
@ -239,19 +240,19 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
audioFile
};
results.AddRange(ProcessFolder(downloadId, artistFromCue, albumsFromCue[0], filter, replaceExistingFiles, downloadClientItem, albumTitle, tempAudioFiles, true));
results.AddRange(ProcessFolder(downloadId, artistFromCue, albumsFromCue[0], filter, replaceExistingFiles, downloadClientItem, albumTitle, tempAudioFiles, cueFile.FullName));
audioFiles.Remove(audioFile);
}
}
}
}
results.AddRange(ProcessFolder(downloadId, artist, null, filter, replaceExistingFiles, downloadClientItem, directoryInfo.Name, audioFiles, false));
results.AddRange(ProcessFolder(downloadId, artist, null, filter, replaceExistingFiles, downloadClientItem, directoryInfo.Name, audioFiles, string.Empty));
return results;
}
private List<ManualImportItem> ProcessFolder(string downloadId, Artist overrideArtist, Album overrideAlbum, FilterFilesType filter, bool replaceExistingFiles, DownloadClientItem downloadClientItem, string albumTitle, List<IFileInfo> audioFiles, bool isSingleFileRelease)
private List<ManualImportItem> ProcessFolder(string downloadId, Artist overrideArtist, Album overrideAlbum, FilterFilesType filter, bool replaceExistingFiles, DownloadClientItem downloadClientItem, string albumTitle, List<IFileInfo> audioFiles, string cuesheetPath)
{
var idOverrides = new IdentificationOverrides
{
@ -262,7 +263,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
{
DownloadClientItem = downloadClientItem,
ParsedAlbumInfo = Parser.Parser.ParseAlbumTitle(albumTitle),
IsSingleFileRelease = isSingleFileRelease
IsSingleFileRelease = !cuesheetPath.Empty()
};
var config = new ImportDecisionMakerConfig
{
@ -286,7 +287,10 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
var existingDecisions = decisions.Except(newFiles.Select(x => x.Decision));
var existingItems = existingDecisions.Select(x => MapItem(x, null, replaceExistingFiles, false));
return newItems.Concat(existingItems).ToList();
var itemsList = newItems.Concat(existingItems).ToList();
itemsList.ForEach(item => { item.CuesheetPath = cuesheetPath; });
return itemsList;
}
public List<ManualImportItem> UpdateItems(List<ManualImportItem> items)
@ -405,6 +409,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
item.ReplaceExistingFiles = replaceExistingFiles;
item.DisableReleaseSwitching = disableReleaseSwitching;
item.IsSingleFileRelease = decision.Item.IsSingleFileRelease;
item.CuesheetPath = decision.Item.CuesheetPath;
return item;
}
@ -454,6 +459,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
Album = album,
Release = release,
IsSingleFileRelease = file.IsSingleFileRelease,
CuesheetPath = file.CuesheetPath,
};
if (file.IsSingleFileRelease)

@ -32,6 +32,7 @@ namespace NzbDrone.Core.Parser.Model
public string ReleaseGroup { get; set; }
public string SceneName { get; set; }
public bool IsSingleFileRelease { get; set; }
public string CuesheetPath { get; set; }
public override string ToString()
{
return Path;

Loading…
Cancel
Save