diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js
index d90ba63b9..f57dcbe3a 100644
--- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js
+++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js
@@ -59,8 +59,8 @@ const columns = [
isVisible: true
},
{
- name: 'cuesheetPath',
- label: () => 'Cuesheet Path',
+ name: 'cueSheetPath',
+ label: () => 'Cue Sheet Path',
isVisible: true
},
{
@@ -446,7 +446,7 @@ class InteractiveImportModalContent extends Component {
onSelectedChange={this.onSelectedChange}
onValidRowChange={this.onValidRowChange}
isSingleFileRelease={item.isSingleFileRelease}
- cuesheetPath={item.cuesheetPath}
+ cueSheetPath={item.cueSheetPath}
/>
);
})
diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js
index f7d094733..019d7c212 100644
--- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js
+++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js
@@ -135,7 +135,7 @@ class InteractiveImportModalContentConnector extends Component {
albumReleaseId,
tracks,
isSingleFileRelease,
- cuesheetPath,
+ cueSheetPath,
quality,
disableReleaseSwitching
} = item;
@@ -150,7 +150,7 @@ class InteractiveImportModalContentConnector extends Component {
return false;
}
- if (!(isSingleFileRelease && cuesheetPath) && (!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;
}
@@ -167,7 +167,7 @@ class InteractiveImportModalContentConnector extends Component {
albumReleaseId,
trackIds: _.map(tracks, 'id'),
isSingleFileRelease: item.isSingleFileRelease,
- cuesheetPath: item.cuesheetPath,
+ 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 470553638..a2c05de62 100644
--- a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js
+++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js
@@ -169,7 +169,7 @@ class InteractiveImportRow extends Component {
albumReleaseId,
tracks,
isSingleFileRelease,
- cuesheetPath,
+ cueSheetPath,
quality,
releaseGroup,
size,
@@ -284,10 +284,10 @@ class InteractiveImportRow extends Component {
{
- cuesheetPath
+ cueSheetPath
}
@@ -432,7 +432,7 @@ InteractiveImportRow.propTypes = {
albumReleaseId: PropTypes.number,
tracks: PropTypes.arrayOf(PropTypes.object),
isSingleFileRelease: PropTypes.bool.isRequired,
- cuesheetPath: PropTypes.string.isRequired,
+ cueSheetPath: PropTypes.string.isRequired,
releaseGroup: PropTypes.string,
quality: PropTypes.object,
size: PropTypes.number.isRequired,
diff --git a/frontend/src/Store/Actions/interactiveImportActions.js b/frontend/src/Store/Actions/interactiveImportActions.js
index 2dc63b6d2..037a56c3a 100644
--- a/frontend/src/Store/Actions/interactiveImportActions.js
+++ b/frontend/src/Store/Actions/interactiveImportActions.js
@@ -207,7 +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,
+ 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 baafd6468..6b27dbd38 100644
--- a/src/Lidarr.Api.V1/ManualImport/ManualImportController.cs
+++ b/src/Lidarr.Api.V1/ManualImport/ManualImportController.cs
@@ -85,7 +85,7 @@ namespace Lidarr.Api.V1.ManualImport
ReplaceExistingFiles = resource.ReplaceExistingFiles,
DisableReleaseSwitching = resource.DisableReleaseSwitching,
IsSingleFileRelease = resource.IsSingleFileRelease,
- CuesheetPath = resource.CuesheetPath,
+ CueSheetPath = resource.CueSheetPath,
});
}
diff --git a/src/Lidarr.Api.V1/ManualImport/ManualImportResource.cs b/src/Lidarr.Api.V1/ManualImport/ManualImportResource.cs
index 4f132d3f9..a410d2537 100644
--- a/src/Lidarr.Api.V1/ManualImport/ManualImportResource.cs
+++ b/src/Lidarr.Api.V1/ManualImport/ManualImportResource.cs
@@ -30,7 +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 string CueSheetPath { get; set; }
}
public static class ManualImportResourceMapper
@@ -55,7 +55,7 @@ namespace Lidarr.Api.V1.ManualImport
Quality = model.Quality,
ReleaseGroup = model.ReleaseGroup,
IsSingleFileRelease = model.IsSingleFileRelease,
- CuesheetPath = model.CuesheetPath,
+ 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 0a443f715..4e9ec7c03 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 string CueSheetPath { get; set; }
public IEnumerable Rejections { get; set; }
}
}
diff --git a/src/NzbDrone.Core/MediaFiles/CueSheet.cs b/src/NzbDrone.Core/MediaFiles/CueSheet.cs
index bcf330f58..a22cb6c0a 100644
--- a/src/NzbDrone.Core/MediaFiles/CueSheet.cs
+++ b/src/NzbDrone.Core/MediaFiles/CueSheet.cs
@@ -12,6 +12,8 @@ namespace NzbDrone.Core.MediaFiles
{
public CueSheet(IFileInfo fileInfo)
{
+ Path = fileInfo.FullName;
+
using (var fs = fileInfo.OpenRead())
{
var bytes = new byte[fileInfo.Length];
@@ -23,58 +25,66 @@ namespace NzbDrone.Core.MediaFiles
var lines = content.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
// Single-file cue means it's an unsplit image
- var fileNames = ReadFieldFromCuesheet(lines, "FILE");
- IsSingleFileRelease = fileNames.Count == 1;
- FileName = fileNames[0];
+ FileNames = ReadField(lines, "FILE");
+ IsSingleFileRelease = FileNames.Count == 1;
- var performers = ReadFieldFromCuesheet(lines, "PERFORMER");
+ var performers = ReadField(lines, "PERFORMER");
if (performers.Count > 0)
{
Performer = performers[0];
}
- var titles = ReadFieldFromCuesheet(lines, "TITLE");
+ var titles = ReadField(lines, "TITLE");
if (titles.Count > 0)
{
Title = titles[0];
}
- Date = ReadOptionalFieldFromCuesheet(lines, "REM DATE");
+ var dates = ReadField(lines, "REM DATE");
+ if (dates.Count > 0)
+ {
+ Date = dates[0];
+ }
}
}
}
+ public string Path { get; set; }
public bool IsSingleFileRelease { get; set; }
- public string FileName { get; set; }
+ public List FileNames { get; set; }
public string Title { get; set; }
public string Performer { get; set; }
public string Date { get; set; }
- private static List ReadFieldFromCuesheet(string[] lines, string fieldName)
+ private static List ReadField(string[] lines, string fieldName)
{
+ var inQuotePattern = "\"(.*?)\"";
+ var flatPattern = fieldName + " (.+)";
+
var results = new List();
var candidates = lines.Where(l => l.StartsWith(fieldName)).ToList();
foreach (var candidate in candidates)
{
- var matches = Regex.Matches(candidate, "\"(.*?)\"");
- var result = matches.ToList()[0].Groups[1].Value;
- results.Add(result);
+ var matches = Regex.Matches(candidate, inQuotePattern).ToList();
+ if (matches.Count == 0)
+ {
+ matches = Regex.Matches(candidate, flatPattern).ToList();
+ }
+
+ if (matches.Count == 0)
+ {
+ continue;
+ }
+
+ var groups = matches[0].Groups;
+ if (groups.Count > 0)
+ {
+ var result = groups[1].Value;
+ results.Add(result);
+ }
}
return results;
}
-
- private static string ReadOptionalFieldFromCuesheet(string[] lines, string fieldName)
- {
- var results = lines.Where(l => l.StartsWith(fieldName));
- if (results.Any())
- {
- var matches = Regex.Matches(results.ToList()[0], fieldName + " (.+)");
- var result = matches.ToList()[0].Groups[1].Value;
- return result;
- }
-
- return "";
- }
}
}
diff --git a/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs b/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs
index 9abcf26de..5872047ba 100644
--- a/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs
+++ b/src/NzbDrone.Core/MediaFiles/TrackFileMovingService.cs
@@ -91,18 +91,18 @@ namespace NzbDrone.Core.MediaFiles
EnsureTrackFolder(trackFile, localTrack, filePath);
- if (!localTrack.CuesheetPath.Empty())
+ if (localTrack.IsSingleFileRelease && !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 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);
+ File.WriteAllLines(cueSheetPath, lines);
}
}
diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/ImportDecisionMaker.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/ImportDecisionMaker.cs
index b047d3770..b1bbc4ec6 100644
--- a/src/NzbDrone.Core/MediaFiles/TrackImport/ImportDecisionMaker.cs
+++ b/src/NzbDrone.Core/MediaFiles/TrackImport/ImportDecisionMaker.cs
@@ -34,6 +34,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
public DownloadClientItem DownloadClientItem { get; set; }
public ParsedAlbumInfo ParsedAlbumInfo { get; set; }
public bool IsSingleFileRelease { get; set; }
+ public CueSheet CueSheet { get; set; }
}
public class ImportDecisionMakerConfig
diff --git a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportFile.cs b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportFile.cs
index f3d6cd830..598ae785c 100644
--- a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportFile.cs
+++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportFile.cs
@@ -16,7 +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 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 6102d8ad2..8456dfa5f 100644
--- a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportItem.cs
+++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportItem.cs
@@ -33,6 +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; }
+ 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 ae3ccc650..3adf9cd4f 100644
--- a/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportService.cs
+++ b/src/NzbDrone.Core/MediaFiles/TrackImport/Manual/ManualImportService.cs
@@ -165,7 +165,18 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
artistFromCue = _parsingService.GetArtist(cueSheet.Performer);
}
- var audioFile = audioFiles.Find(x => x.Name == cueSheet.FileName && x.DirectoryName == cueFile.DirectoryName);
+ if (artistFromCue == null)
+ {
+ continue;
+ }
+
+ // TODO use the audio files from the cue sheet
+ var validAudioFiles = audioFiles.FindAll(x => cueSheet.FileNames.Contains(x.Name));
+ if (validAudioFiles.Count == 0)
+ {
+ continue;
+ }
+
var parsedAlbumInfo = new ParsedAlbumInfo
{
AlbumTitle = cueSheet.Title,
@@ -178,18 +189,16 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
continue;
}
- var tempAudioFiles = new List { audioFile };
-
- results.AddRange(ProcessFolder(downloadId, artistFromCue, albumsFromCue[0], filter, replaceExistingFiles, downloadClientItem, cueSheet.Title, tempAudioFiles, cueFile.FullName));
- audioFiles.Remove(audioFile);
+ results.AddRange(ProcessFolder(downloadId, artistFromCue, albumsFromCue[0], filter, replaceExistingFiles, downloadClientItem, cueSheet.Title, validAudioFiles, cueSheet));
+ audioFiles.RemoveAll(x => validAudioFiles.Contains(x));
}
- results.AddRange(ProcessFolder(downloadId, artist, null, filter, replaceExistingFiles, downloadClientItem, directoryInfo.Name, audioFiles, string.Empty));
+ results.AddRange(ProcessFolder(downloadId, artist, null, filter, replaceExistingFiles, downloadClientItem, directoryInfo.Name, audioFiles, null));
return results;
}
- private List ProcessFolder(string downloadId, Artist overrideArtist, Album overrideAlbum, FilterFilesType filter, bool replaceExistingFiles, DownloadClientItem downloadClientItem, string albumTitle, List audioFiles, string cuesheetPath)
+ private List ProcessFolder(string downloadId, Artist overrideArtist, Album overrideAlbum, FilterFilesType filter, bool replaceExistingFiles, DownloadClientItem downloadClientItem, string albumTitle, List audioFiles, CueSheet cueSheet)
{
var idOverrides = new IdentificationOverrides
{
@@ -200,7 +209,8 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
{
DownloadClientItem = downloadClientItem,
ParsedAlbumInfo = Parser.Parser.ParseAlbumTitle(albumTitle),
- IsSingleFileRelease = !cuesheetPath.Empty()
+ CueSheet = cueSheet,
+ IsSingleFileRelease = cueSheet != null ? cueSheet.IsSingleFileRelease : false,
};
var config = new ImportDecisionMakerConfig
{
@@ -225,7 +235,10 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
var existingItems = existingDecisions.Select(x => MapItem(x, null, replaceExistingFiles, false));
var itemsList = newItems.Concat(existingItems).ToList();
- itemsList.ForEach(item => { item.CuesheetPath = cuesheetPath; });
+ if (cueSheet != null)
+ {
+ itemsList.ForEach(item => { item.CueSheetPath = cueSheet.Path; });
+ }
return itemsList;
}
@@ -265,7 +278,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
IsSingleFileRelease = group.All(x => x.IsSingleFileRelease == true)
};
- // TODO support with the cuesheet
+ // TODO support with the cue sheet
var decisions = _importDecisionMaker.GetImportDecisions(files, idOverride, itemInfo, config);
var existingItems = group.Join(decisions,
@@ -353,7 +366,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
item.ReplaceExistingFiles = replaceExistingFiles;
item.DisableReleaseSwitching = disableReleaseSwitching;
item.IsSingleFileRelease = decision.Item.IsSingleFileRelease;
- item.CuesheetPath = decision.Item.CuesheetPath;
+ item.CueSheetPath = decision.Item.CueSheetPath;
return item;
}
@@ -403,7 +416,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
Album = album,
Release = release,
IsSingleFileRelease = file.IsSingleFileRelease,
- CuesheetPath = file.CuesheetPath,
+ 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 ee929c588..422ac2b87 100644
--- a/src/NzbDrone.Core/Parser/Model/LocalTrack.cs
+++ b/src/NzbDrone.Core/Parser/Model/LocalTrack.cs
@@ -32,7 +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 string CueSheetPath { get; set; }
public override string ToString()
{
return Path;