diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js
index 220b13a4b..d90ba63b9 100644
--- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js
+++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js
@@ -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}
/>
);
})
diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js
index d05b38e06..f7d094733 100644
--- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js
+++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js
@@ -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
diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js
index 797ad389e..f8d797d53 100644
--- a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js
+++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js
@@ -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 {
}
+
+ {
+ cuesheetPath
+ }
+
+
e.id),
isSingleFileRelease: item.isSingleFileRelease,
+ cuesheetPath: item.cuesheetPath,
quality: item.quality,
releaseGroup: item.releaseGroup,
downloadId: item.downloadId,
diff --git a/src/Lidarr.Api.V1/ManualImport/ManualImportController.cs b/src/Lidarr.Api.V1/ManualImport/ManualImportController.cs
index 071fbe05f..baafd6468 100644
--- a/src/Lidarr.Api.V1/ManualImport/ManualImportController.cs
+++ b/src/Lidarr.Api.V1/ManualImport/ManualImportController.cs
@@ -85,6 +85,7 @@ namespace Lidarr.Api.V1.ManualImport
ReplaceExistingFiles = resource.ReplaceExistingFiles,
DisableReleaseSwitching = resource.DisableReleaseSwitching,
IsSingleFileRelease = resource.IsSingleFileRelease,
+ CuesheetPath = resource.CuesheetPath,
});
}
diff --git a/src/Lidarr.Api.V1/ManualImport/ManualImportResource.cs b/src/Lidarr.Api.V1/ManualImport/ManualImportResource.cs
index 5d4f29815..4f132d3f9 100644
--- a/src/Lidarr.Api.V1/ManualImport/ManualImportResource.cs
+++ b/src/Lidarr.Api.V1/ManualImport/ManualImportResource.cs
@@ -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,
diff --git a/src/Lidarr.Api.V1/ManualImport/ManualImportUpdateResource.cs b/src/Lidarr.Api.V1/ManualImport/ManualImportUpdateResource.cs
index bf19a2b1b..0a443f715 100644
--- a/src/Lidarr.Api.V1/ManualImport/ManualImportUpdateResource.cs
+++ b/src/Lidarr.Api.V1/ManualImport/ManualImportUpdateResource.cs
@@ -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 Rejections { get; set; }
}
}
diff --git a/src/NzbDrone.Core/MediaFiles/DiskScanService.cs b/src/NzbDrone.Core/MediaFiles/DiskScanService.cs
index 0c5c4ca05..f5e6bb5cc 100644
--- a/src/NzbDrone.Core/MediaFiles/DiskScanService.cs
+++ b/src/NzbDrone.Core/MediaFiles/DiskScanService.cs
@@ -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();
diff --git a/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs b/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs
index fe48b4d6d..9abcf26de 100644
--- a/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs
+++ b/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs
@@ -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(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);
diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportFile.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportFile.cs
index 631318c89..f3d6cd830 100644
--- a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportFile.cs
+++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportFile.cs
@@ -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)
{
diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportItem.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportItem.cs
index 879eff917..6102d8ad2 100644
--- a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportItem.cs
+++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportItem.cs
@@ -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; }
}
}
diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportService.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportService.cs
index 9e6308323..4ec9e6012 100644
--- a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportService.cs
+++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportService.cs
@@ -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 ProcessFolder(string downloadId, Artist overrideArtist, Album overrideAlbum, FilterFilesType filter, bool replaceExistingFiles, DownloadClientItem downloadClientItem, string albumTitle, List audioFiles, bool isSingleFileRelease)
+ private List ProcessFolder(string downloadId, Artist overrideArtist, Album overrideAlbum, FilterFilesType filter, bool replaceExistingFiles, DownloadClientItem downloadClientItem, string albumTitle, List 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 UpdateItems(List 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)
diff --git a/src/NzbDrone.Core/Parser/Model/LocalTrack.cs b/src/NzbDrone.Core/Parser/Model/LocalTrack.cs
index e5b48152e..ee929c588 100644
--- a/src/NzbDrone.Core/Parser/Model/LocalTrack.cs
+++ b/src/NzbDrone.Core/Parser/Model/LocalTrack.cs
@@ -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;