mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-21 22:13:29 -07:00
Centralize most of the cue sheet-related features to a service.
(cherry picked from commit 5636735ae645280132d94e64d2e45f1a4b5f6323)
This commit is contained in:
parent
14bf91360a
commit
2d5b6a1def
6 changed files with 358 additions and 374 deletions
|
@ -1,35 +1,10 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO.Abstractions;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles
|
namespace NzbDrone.Core.MediaFiles
|
||||||
{
|
{
|
||||||
public class CueSheet : ModelBase
|
public class CueSheet : ModelBase
|
||||||
{
|
{
|
||||||
public CueSheet(IFileInfo fileInfo)
|
|
||||||
{
|
|
||||||
Path = fileInfo.FullName;
|
|
||||||
|
|
||||||
using (var fs = fileInfo.OpenRead())
|
|
||||||
{
|
|
||||||
var bytes = new byte[fileInfo.Length];
|
|
||||||
var encoding = new UTF8Encoding(true);
|
|
||||||
string content;
|
|
||||||
while (fs.Read(bytes, 0, bytes.Length) > 0)
|
|
||||||
{
|
|
||||||
content = encoding.GetString(bytes);
|
|
||||||
var lines = content.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
|
|
||||||
ParseCueSheet(lines);
|
|
||||||
|
|
||||||
// Single-file cue means it's an unsplit image, which should be specially treated in the pipeline
|
|
||||||
IsSingleFileRelease = Files.Count == 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class IndexEntry
|
public class IndexEntry
|
||||||
{
|
{
|
||||||
public int Key { get; set; }
|
public int Key { get; set; }
|
||||||
|
@ -59,143 +34,5 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
public string DiscID { get; set; }
|
public string DiscID { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string Performer { get; set; }
|
public string Performer { get; set; }
|
||||||
private static string _FileKey = "FILE";
|
|
||||||
private static string _TrackKey = "TRACK";
|
|
||||||
private static string _IndexKey = "INDEX";
|
|
||||||
private static string _GenreKey = "REM GENRE";
|
|
||||||
private static string _DateKey = "REM DATE";
|
|
||||||
private static string _DiscIdKey = "REM DISCID";
|
|
||||||
private static string _PerformerKey = "PERFORMER";
|
|
||||||
private static string _TitleKey = "TITLE";
|
|
||||||
|
|
||||||
private string ExtractValue(string line, string keyword)
|
|
||||||
{
|
|
||||||
var pattern = keyword + @"\s+(?:(?:\""(.*?)\"")|(.+))";
|
|
||||||
var match = Regex.Match(line, pattern);
|
|
||||||
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
var value = match.Groups[1].Success ? match.Groups[1].Value : match.Groups[2].Value;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ParseCueSheet(string[] lines)
|
|
||||||
{
|
|
||||||
var i = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
var line = lines[i];
|
|
||||||
if (line.StartsWith(_FileKey))
|
|
||||||
{
|
|
||||||
line = line.Trim();
|
|
||||||
line = line.Substring(_FileKey.Length).Trim();
|
|
||||||
var filename = line.Split('"')[1];
|
|
||||||
var fileDetails = new FileEntry { Name = filename };
|
|
||||||
|
|
||||||
i++;
|
|
||||||
line = lines[i];
|
|
||||||
while (line.StartsWith(" "))
|
|
||||||
{
|
|
||||||
line = line.Trim();
|
|
||||||
if (line.StartsWith(_TrackKey))
|
|
||||||
{
|
|
||||||
line = line.Substring(_TrackKey.Length).Trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
var trackDetails = new TrackEntry();
|
|
||||||
var trackInfo = line.Split(' ');
|
|
||||||
if (trackInfo.Length > 0)
|
|
||||||
{
|
|
||||||
if (int.TryParse(trackInfo[0], out var number))
|
|
||||||
{
|
|
||||||
trackDetails.Number = number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
line = lines[i];
|
|
||||||
while (line.StartsWith(" "))
|
|
||||||
{
|
|
||||||
line = line.Trim();
|
|
||||||
if (line.StartsWith(_IndexKey))
|
|
||||||
{
|
|
||||||
line = line.Substring(_IndexKey.Length).Trim();
|
|
||||||
var parts = line.Split(' ');
|
|
||||||
if (parts.Length > 1)
|
|
||||||
{
|
|
||||||
if (int.TryParse(parts[0], out var key))
|
|
||||||
{
|
|
||||||
var value = parts[1].Trim('"');
|
|
||||||
trackDetails.Indices.Add(new IndexEntry { Key = key, Time = value });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
line = lines[i];
|
|
||||||
}
|
|
||||||
else if (line.StartsWith(_TitleKey))
|
|
||||||
{
|
|
||||||
trackDetails.Title = ExtractValue(line, _TitleKey);
|
|
||||||
i++;
|
|
||||||
line = lines[i];
|
|
||||||
}
|
|
||||||
else if (line.StartsWith(_PerformerKey))
|
|
||||||
{
|
|
||||||
trackDetails.Performer = ExtractValue(line, _PerformerKey);
|
|
||||||
i++;
|
|
||||||
line = lines[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
line = lines[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fileDetails.Tracks.Add(trackDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
Files.Add(fileDetails);
|
|
||||||
}
|
|
||||||
else if (line.StartsWith(_GenreKey))
|
|
||||||
{
|
|
||||||
Genre = ExtractValue(line, _GenreKey);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if (line.StartsWith(_DateKey))
|
|
||||||
{
|
|
||||||
Date = ExtractValue(line, _DateKey);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if (line.StartsWith(_DiscIdKey))
|
|
||||||
{
|
|
||||||
DiscID = ExtractValue(line, _DiscIdKey);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if (line.StartsWith(_PerformerKey))
|
|
||||||
{
|
|
||||||
Performer = ExtractValue(line, _PerformerKey);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if (line.StartsWith(_TitleKey))
|
|
||||||
{
|
|
||||||
Title = ExtractValue(line, _TitleKey);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IndexOutOfRangeException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
332
src/NzbDrone.Core/MediaFiles/CueSheetService.cs
Normal file
332
src/NzbDrone.Core/MediaFiles/CueSheetService.cs
Normal file
|
@ -0,0 +1,332 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Abstractions;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.MediaFiles.TrackImport;
|
||||||
|
using NzbDrone.Core.Music;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles
|
||||||
|
{
|
||||||
|
public class CueSheetInfo
|
||||||
|
{
|
||||||
|
public List<IFileInfo> MusicFiles { get; set; } = new List<IFileInfo>();
|
||||||
|
public IdentificationOverrides IdOverrides { get; set; }
|
||||||
|
public CueSheet CueSheet { get; set; }
|
||||||
|
public bool IsForMediaFile(string path) => CueSheet != null && CueSheet.Files.Count > 0 && CueSheet.Files.Any(x => Path.GetFileName(path) == x.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ICueSheetService
|
||||||
|
{
|
||||||
|
List<ImportDecision<LocalTrack>> GetImportDecisions(ref List<IFileInfo> mediaFileList, ImportDecisionMakerInfo itemInfo, ImportDecisionMakerConfig config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CueSheetService : ICueSheetService
|
||||||
|
{
|
||||||
|
private readonly IParsingService _parsingService;
|
||||||
|
private readonly IMakeImportDecision _importDecisionMaker;
|
||||||
|
|
||||||
|
private static string _FileKey = "FILE";
|
||||||
|
private static string _TrackKey = "TRACK";
|
||||||
|
private static string _IndexKey = "INDEX";
|
||||||
|
private static string _GenreKey = "REM GENRE";
|
||||||
|
private static string _DateKey = "REM DATE";
|
||||||
|
private static string _DiscIdKey = "REM DISCID";
|
||||||
|
private static string _PerformerKey = "PERFORMER";
|
||||||
|
private static string _TitleKey = "TITLE";
|
||||||
|
|
||||||
|
public CueSheetService(IParsingService parsingService,
|
||||||
|
IMakeImportDecision importDecisionMaker)
|
||||||
|
{
|
||||||
|
_parsingService = parsingService;
|
||||||
|
_importDecisionMaker = importDecisionMaker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ImportDecision<LocalTrack>> GetImportDecisions(ref List<IFileInfo> mediaFileList, ImportDecisionMakerInfo itemInfo, ImportDecisionMakerConfig config)
|
||||||
|
{
|
||||||
|
var decisions = new List<ImportDecision<LocalTrack>>();
|
||||||
|
var cueFiles = mediaFileList.Where(x => x.Extension.Equals(".cue")).ToList();
|
||||||
|
if (cueFiles.Count == 0)
|
||||||
|
{
|
||||||
|
return decisions;
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaFileList.RemoveAll(l => cueFiles.Contains(l));
|
||||||
|
var cueSheetInfos = new List<CueSheetInfo>();
|
||||||
|
foreach (var cueFile in cueFiles)
|
||||||
|
{
|
||||||
|
var cueSheetInfo = GetCueSheetInfo(cueFile, mediaFileList);
|
||||||
|
cueSheetInfos.Add(cueSheetInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cueSheetInfosGroupedByDiscId = cueSheetInfos.GroupBy(x => x.CueSheet.DiscID).ToList();
|
||||||
|
foreach (var cueSheetInfoGroup in cueSheetInfosGroupedByDiscId)
|
||||||
|
{
|
||||||
|
var audioFilesForCues = new List<IFileInfo>();
|
||||||
|
foreach (var cueSheetInfo in cueSheetInfoGroup)
|
||||||
|
{
|
||||||
|
audioFilesForCues.AddRange(cueSheetInfo.MusicFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
decisions.AddRange(_importDecisionMaker.GetImportDecisions(audioFilesForCues, cueSheetInfoGroup.First().IdOverrides, itemInfo, config, cueSheetInfos));
|
||||||
|
|
||||||
|
foreach (var cueSheetInfo in cueSheetInfos)
|
||||||
|
{
|
||||||
|
if (cueSheetInfo.CueSheet != null)
|
||||||
|
{
|
||||||
|
decisions.ForEach(item =>
|
||||||
|
{
|
||||||
|
if (cueSheetInfo.IsForMediaFile(item.Item.Path))
|
||||||
|
{
|
||||||
|
item.Item.CueSheetPath = cueSheetInfo.CueSheet.Path;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaFileList.RemoveAll(x => cueSheetInfo.MusicFiles.Contains(x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var addedTracks = new List<Track>();
|
||||||
|
decisions.ForEach(decision =>
|
||||||
|
{
|
||||||
|
if (!decision.Item.IsSingleFileRelease)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cueSheetFindResult = cueSheetInfos.Find(x => x.IsForMediaFile(decision.Item.Path));
|
||||||
|
var cueSheet = cueSheetFindResult?.CueSheet;
|
||||||
|
if (cueSheet == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cueSheet.Files.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tracksFromCueSheet = cueSheet.Files.SelectMany(x => x.Tracks).ToList();
|
||||||
|
if (tracksFromCueSheet.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tracksFromRelease = decision.Item.Release.Tracks.Value;
|
||||||
|
if (tracksFromRelease.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decision.Item.Tracks = tracksFromRelease.Where(trackFromRelease => !addedTracks.Contains(trackFromRelease) && tracksFromCueSheet.Any(trackFromCueSheet => string.Equals(trackFromCueSheet.Title, trackFromRelease.Title, StringComparison.InvariantCultureIgnoreCase))).ToList();
|
||||||
|
addedTracks.AddRange(decision.Item.Tracks);
|
||||||
|
});
|
||||||
|
|
||||||
|
return decisions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CueSheet LoadCueSheet(IFileInfo fileInfo)
|
||||||
|
{
|
||||||
|
using (var fs = fileInfo.OpenRead())
|
||||||
|
{
|
||||||
|
var bytes = new byte[fileInfo.Length];
|
||||||
|
var encoding = new UTF8Encoding(true);
|
||||||
|
string content;
|
||||||
|
while (fs.Read(bytes, 0, bytes.Length) > 0)
|
||||||
|
{
|
||||||
|
content = encoding.GetString(bytes);
|
||||||
|
var lines = content.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
|
||||||
|
var cueSheet = ParseLines(lines);
|
||||||
|
|
||||||
|
// Single-file cue means it's an unsplit image, which should be specially treated in the pipeline
|
||||||
|
cueSheet.IsSingleFileRelease = cueSheet.Files.Count == 1;
|
||||||
|
cueSheet.Path = fileInfo.FullName;
|
||||||
|
|
||||||
|
return cueSheet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CueSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ExtractValue(string line, string keyword)
|
||||||
|
{
|
||||||
|
var pattern = keyword + @"\s+(?:(?:\""(.*?)\"")|(.+))";
|
||||||
|
var match = Regex.Match(line, pattern);
|
||||||
|
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
var value = match.Groups[1].Success ? match.Groups[1].Value : match.Groups[2].Value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private CueSheet ParseLines(string[] lines)
|
||||||
|
{
|
||||||
|
var cueSheet = new CueSheet();
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var line = lines[i];
|
||||||
|
if (line.StartsWith(_FileKey))
|
||||||
|
{
|
||||||
|
line = line.Trim();
|
||||||
|
line = line.Substring(_FileKey.Length).Trim();
|
||||||
|
var filename = line.Split('"')[1];
|
||||||
|
var fileDetails = new CueSheet.FileEntry { Name = filename };
|
||||||
|
|
||||||
|
i++;
|
||||||
|
line = lines[i];
|
||||||
|
while (line.StartsWith(" "))
|
||||||
|
{
|
||||||
|
line = line.Trim();
|
||||||
|
if (line.StartsWith(_TrackKey))
|
||||||
|
{
|
||||||
|
line = line.Substring(_TrackKey.Length).Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
var trackDetails = new CueSheet.TrackEntry();
|
||||||
|
var trackInfo = line.Split(' ');
|
||||||
|
if (trackInfo.Length > 0)
|
||||||
|
{
|
||||||
|
if (int.TryParse(trackInfo[0], out var number))
|
||||||
|
{
|
||||||
|
trackDetails.Number = number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
line = lines[i];
|
||||||
|
while (line.StartsWith(" "))
|
||||||
|
{
|
||||||
|
line = line.Trim();
|
||||||
|
if (line.StartsWith(_IndexKey))
|
||||||
|
{
|
||||||
|
line = line.Substring(_IndexKey.Length).Trim();
|
||||||
|
var parts = line.Split(' ');
|
||||||
|
if (parts.Length > 1)
|
||||||
|
{
|
||||||
|
if (int.TryParse(parts[0], out var key))
|
||||||
|
{
|
||||||
|
var value = parts[1].Trim('"');
|
||||||
|
trackDetails.Indices.Add(new CueSheet.IndexEntry { Key = key, Time = value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
line = lines[i];
|
||||||
|
}
|
||||||
|
else if (line.StartsWith(_TitleKey))
|
||||||
|
{
|
||||||
|
trackDetails.Title = ExtractValue(line, _TitleKey);
|
||||||
|
i++;
|
||||||
|
line = lines[i];
|
||||||
|
}
|
||||||
|
else if (line.StartsWith(_PerformerKey))
|
||||||
|
{
|
||||||
|
trackDetails.Performer = ExtractValue(line, _PerformerKey);
|
||||||
|
i++;
|
||||||
|
line = lines[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
line = lines[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileDetails.Tracks.Add(trackDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
cueSheet.Files.Add(fileDetails);
|
||||||
|
}
|
||||||
|
else if (line.StartsWith(_GenreKey))
|
||||||
|
{
|
||||||
|
cueSheet.Genre = ExtractValue(line, _GenreKey);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (line.StartsWith(_DateKey))
|
||||||
|
{
|
||||||
|
cueSheet.Date = ExtractValue(line, _DateKey);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (line.StartsWith(_DiscIdKey))
|
||||||
|
{
|
||||||
|
cueSheet.DiscID = ExtractValue(line, _DiscIdKey);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (line.StartsWith(_PerformerKey))
|
||||||
|
{
|
||||||
|
cueSheet.Performer = ExtractValue(line, _PerformerKey);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (line.StartsWith(_TitleKey))
|
||||||
|
{
|
||||||
|
cueSheet.Title = ExtractValue(line, _TitleKey);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IndexOutOfRangeException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return cueSheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CueSheetInfo GetCueSheetInfo(IFileInfo cueFile, List<IFileInfo> musicFiles)
|
||||||
|
{
|
||||||
|
var cueSheetInfo = new CueSheetInfo();
|
||||||
|
var cueSheet = LoadCueSheet(cueFile);
|
||||||
|
if (cueSheet == null)
|
||||||
|
{
|
||||||
|
return cueSheetInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
cueSheetInfo.CueSheet = cueSheet;
|
||||||
|
cueSheetInfo.IdOverrides = new IdentificationOverrides();
|
||||||
|
|
||||||
|
Artist artistFromCue = null;
|
||||||
|
if (!cueSheet.Performer.Empty())
|
||||||
|
{
|
||||||
|
artistFromCue = _parsingService.GetArtist(cueSheet.Performer);
|
||||||
|
if (artistFromCue != null)
|
||||||
|
{
|
||||||
|
cueSheetInfo.IdOverrides.Artist = artistFromCue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedAlbumInfo = new ParsedAlbumInfo
|
||||||
|
{
|
||||||
|
AlbumTitle = cueSheet.Title,
|
||||||
|
ArtistName = artistFromCue.Name,
|
||||||
|
ReleaseDate = cueSheet.Date,
|
||||||
|
};
|
||||||
|
|
||||||
|
var albumsFromCue = _parsingService.GetAlbums(parsedAlbumInfo, artistFromCue);
|
||||||
|
if (albumsFromCue != null && albumsFromCue.Count > 0)
|
||||||
|
{
|
||||||
|
cueSheetInfo.IdOverrides.Album = albumsFromCue[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
cueSheetInfo.MusicFiles = musicFiles.Where(musicFile => cueSheet.Files.Any(musicFileFromCue => musicFileFromCue.Name == musicFile.Name)).ToList();
|
||||||
|
|
||||||
|
return cueSheetInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,6 +43,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
private readonly IMediaFileService _mediaFileService;
|
private readonly IMediaFileService _mediaFileService;
|
||||||
private readonly IMakeImportDecision _importDecisionMaker;
|
private readonly IMakeImportDecision _importDecisionMaker;
|
||||||
|
private readonly ICueSheetService _cueSheetService;
|
||||||
private readonly IImportApprovedTracks _importApprovedTracks;
|
private readonly IImportApprovedTracks _importApprovedTracks;
|
||||||
private readonly IArtistService _artistService;
|
private readonly IArtistService _artistService;
|
||||||
private readonly IMediaFileTableCleanupService _mediaFileTableCleanupService;
|
private readonly IMediaFileTableCleanupService _mediaFileTableCleanupService;
|
||||||
|
@ -54,6 +55,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
IMediaFileService mediaFileService,
|
IMediaFileService mediaFileService,
|
||||||
IMakeImportDecision importDecisionMaker,
|
IMakeImportDecision importDecisionMaker,
|
||||||
|
ICueSheetService cueSheetService,
|
||||||
IImportApprovedTracks importApprovedTracks,
|
IImportApprovedTracks importApprovedTracks,
|
||||||
IArtistService artistService,
|
IArtistService artistService,
|
||||||
IRootFolderService rootFolderService,
|
IRootFolderService rootFolderService,
|
||||||
|
@ -65,6 +67,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
_mediaFileService = mediaFileService;
|
_mediaFileService = mediaFileService;
|
||||||
_importDecisionMaker = importDecisionMaker;
|
_importDecisionMaker = importDecisionMaker;
|
||||||
|
_cueSheetService = cueSheetService;
|
||||||
_importApprovedTracks = importApprovedTracks;
|
_importApprovedTracks = importApprovedTracks;
|
||||||
_artistService = artistService;
|
_artistService = artistService;
|
||||||
_mediaFileTableCleanupService = mediaFileTableCleanupService;
|
_mediaFileTableCleanupService = mediaFileTableCleanupService;
|
||||||
|
@ -98,46 +101,8 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
};
|
};
|
||||||
|
|
||||||
var decisions = new List<ImportDecision<LocalTrack>>();
|
var decisions = new List<ImportDecision<LocalTrack>>();
|
||||||
var cueFiles = mediaFileList.Where(x => x.Extension.Equals(".cue")).ToList();
|
|
||||||
if (cueFiles.Count > 0)
|
|
||||||
{
|
|
||||||
mediaFileList.RemoveAll(l => cueFiles.Contains(l));
|
|
||||||
var cueSheetInfos = new List<CueSheetInfo>();
|
|
||||||
foreach (var cueFile in cueFiles)
|
|
||||||
{
|
|
||||||
var cueSheetInfo = _importDecisionMaker.GetCueSheetInfo(cueFile, mediaFileList);
|
|
||||||
cueSheetInfos.Add(cueSheetInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cueSheetInfosGroupedByDiscId = cueSheetInfos.GroupBy(x => x.CueSheet.DiscID).ToList();
|
|
||||||
foreach (var cueSheetInfoGroup in cueSheetInfosGroupedByDiscId)
|
|
||||||
{
|
|
||||||
var audioFilesForCues = new List<IFileInfo>();
|
|
||||||
foreach (var cueSheetInfo in cueSheetInfoGroup)
|
|
||||||
{
|
|
||||||
audioFilesForCues.AddRange(cueSheetInfo.MusicFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
decisions.AddRange(_importDecisionMaker.GetImportDecisions(audioFilesForCues, cueSheetInfoGroup.First().IdOverrides, itemInfo, config, cueSheetInfos));
|
|
||||||
|
|
||||||
foreach (var cueSheetInfo in cueSheetInfos)
|
|
||||||
{
|
|
||||||
if (cueSheetInfo.CueSheet != null)
|
|
||||||
{
|
|
||||||
decisions.ForEach(item =>
|
|
||||||
{
|
|
||||||
if (cueSheetInfo.IsForMediaFile(item.Item.Path))
|
|
||||||
{
|
|
||||||
item.Item.CueSheetPath = cueSheetInfo.CueSheet.Path;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaFileList.RemoveAll(x => cueSheetInfo.MusicFiles.Contains(x));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
decisions.AddRange(_cueSheetService.GetImportDecisions(ref mediaFileList, itemInfo, config));
|
||||||
decisions.AddRange(_importDecisionMaker.GetImportDecisions(mediaFileList, null, itemInfo, config));
|
decisions.AddRange(_importDecisionMaker.GetImportDecisions(mediaFileList, null, itemInfo, config));
|
||||||
|
|
||||||
decisionsStopwatch.Stop();
|
decisionsStopwatch.Stop();
|
||||||
|
|
|
@ -132,41 +132,6 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Identification
|
||||||
i++;
|
i++;
|
||||||
_logger.ProgressInfo($"Identifying album {i}/{releases.Count}");
|
_logger.ProgressInfo($"Identifying album {i}/{releases.Count}");
|
||||||
IdentifyRelease(localRelease, idOverrides, config);
|
IdentifyRelease(localRelease, idOverrides, config);
|
||||||
|
|
||||||
if (cueSheetInfos != null && localRelease.IsSingleFileRelease)
|
|
||||||
{
|
|
||||||
var addedMbTracks = new List<Track>();
|
|
||||||
localRelease.LocalTracks.ForEach(localTrack =>
|
|
||||||
{
|
|
||||||
var cueSheetFindResult = cueSheetInfos.Find(x => x.IsForMediaFile(localTrack.Path));
|
|
||||||
var cueSheet = cueSheetFindResult?.CueSheet;
|
|
||||||
if (cueSheet == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
localTrack.Tracks.Clear();
|
|
||||||
localRelease.AlbumRelease.Tracks.Value.ForEach(mbTrack =>
|
|
||||||
{
|
|
||||||
cueSheet.Files[0].Tracks.ForEach(cueTrack =>
|
|
||||||
{
|
|
||||||
if (!string.Equals(cueTrack.Title, mbTrack.Title, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addedMbTracks.Contains(mbTrack))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mbTrack.IsSingleFileRelease = true;
|
|
||||||
localTrack.Tracks.Add(mbTrack);
|
|
||||||
addedMbTracks.Add(mbTrack);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
watch.Stop();
|
watch.Stop();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.IO.Abstractions;
|
using System.IO.Abstractions;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DryIoc.ImTools;
|
using DryIoc.ImTools;
|
||||||
|
@ -22,8 +21,6 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
||||||
public interface IMakeImportDecision
|
public interface IMakeImportDecision
|
||||||
{
|
{
|
||||||
List<ImportDecision<LocalTrack>> GetImportDecisions(List<IFileInfo> musicFiles, IdentificationOverrides idOverrides, ImportDecisionMakerInfo itemInfo, ImportDecisionMakerConfig config, List<CueSheetInfo> cueSheetInfos = null);
|
List<ImportDecision<LocalTrack>> GetImportDecisions(List<IFileInfo> musicFiles, IdentificationOverrides idOverrides, ImportDecisionMakerInfo itemInfo, ImportDecisionMakerConfig config, List<CueSheetInfo> cueSheetInfos = null);
|
||||||
List<ImportDecision<LocalTrack>> GetImportDecisions(List<CueSheetInfo> cueSheetInfos, ImportDecisionMakerInfo itemInfo, ImportDecisionMakerConfig config);
|
|
||||||
CueSheetInfo GetCueSheetInfo(IFileInfo cueFile, List<IFileInfo> musicFiles);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class IdentificationOverrides
|
public class IdentificationOverrides
|
||||||
|
@ -33,14 +30,6 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
||||||
public AlbumRelease AlbumRelease { get; set; }
|
public AlbumRelease AlbumRelease { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CueSheetInfo
|
|
||||||
{
|
|
||||||
public List<IFileInfo> MusicFiles { get; set; } = new List<IFileInfo>();
|
|
||||||
public IdentificationOverrides IdOverrides { get; set; }
|
|
||||||
public CueSheet CueSheet { get; set; }
|
|
||||||
public bool IsForMediaFile(string path) => CueSheet != null && CueSheet.Files.Count > 0 && CueSheet.Files.Any(x => Path.GetFileName(path) == x.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ImportDecisionMakerInfo
|
public class ImportDecisionMakerInfo
|
||||||
{
|
{
|
||||||
public DownloadClientItem DownloadClientItem { get; set; }
|
public DownloadClientItem DownloadClientItem { get; set; }
|
||||||
|
@ -92,46 +81,6 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CueSheetInfo GetCueSheetInfo(IFileInfo cueFile, List<IFileInfo> musicFiles)
|
|
||||||
{
|
|
||||||
var cueSheetInfo = new CueSheetInfo();
|
|
||||||
var cueSheet = new CueSheet(cueFile);
|
|
||||||
if (cueSheet == null)
|
|
||||||
{
|
|
||||||
return cueSheetInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
cueSheetInfo.CueSheet = cueSheet;
|
|
||||||
cueSheetInfo.IdOverrides = new IdentificationOverrides();
|
|
||||||
|
|
||||||
Artist artistFromCue = null;
|
|
||||||
if (!cueSheet.Performer.Empty())
|
|
||||||
{
|
|
||||||
artistFromCue = _parsingService.GetArtist(cueSheet.Performer);
|
|
||||||
if (artistFromCue != null)
|
|
||||||
{
|
|
||||||
cueSheetInfo.IdOverrides.Artist = artistFromCue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var parsedAlbumInfo = new ParsedAlbumInfo
|
|
||||||
{
|
|
||||||
AlbumTitle = cueSheet.Title,
|
|
||||||
ArtistName = artistFromCue.Name,
|
|
||||||
ReleaseDate = cueSheet.Date,
|
|
||||||
};
|
|
||||||
|
|
||||||
var albumsFromCue = _parsingService.GetAlbums(parsedAlbumInfo, artistFromCue);
|
|
||||||
if (albumsFromCue != null && albumsFromCue.Count > 0)
|
|
||||||
{
|
|
||||||
cueSheetInfo.IdOverrides.Album = albumsFromCue[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
cueSheetInfo.MusicFiles = musicFiles.Where(musicFile => cueSheet.Files.Any(musicFileFromCue => musicFileFromCue.Name == musicFile.Name)).ToList();
|
|
||||||
|
|
||||||
return cueSheetInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Tuple<List<LocalTrack>, List<ImportDecision<LocalTrack>>> GetLocalTracks(List<IFileInfo> musicFiles, DownloadClientItem downloadClientItem, ParsedAlbumInfo folderInfo, FilterFilesType filter)
|
public Tuple<List<LocalTrack>, List<ImportDecision<LocalTrack>>> GetLocalTracks(List<IFileInfo> musicFiles, DownloadClientItem downloadClientItem, ParsedAlbumInfo folderInfo, FilterFilesType filter)
|
||||||
{
|
{
|
||||||
var watch = new System.Diagnostics.Stopwatch();
|
var watch = new System.Diagnostics.Stopwatch();
|
||||||
|
@ -284,17 +233,6 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
|
||||||
return decisions;
|
return decisions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ImportDecision<LocalTrack>> GetImportDecisions(List<CueSheetInfo> cueSheetInfos, ImportDecisionMakerInfo itemInfo, ImportDecisionMakerConfig config)
|
|
||||||
{
|
|
||||||
var decisions = new List<ImportDecision<LocalTrack>>();
|
|
||||||
foreach (var cueSheetInfo in cueSheetInfos)
|
|
||||||
{
|
|
||||||
decisions.AddRange(GetImportDecisions(cueSheetInfo.MusicFiles, cueSheetInfo.IdOverrides, itemInfo, config, cueSheetInfos));
|
|
||||||
}
|
|
||||||
|
|
||||||
return decisions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EnsureData(LocalAlbumRelease release)
|
private void EnsureData(LocalAlbumRelease release)
|
||||||
{
|
{
|
||||||
if (release.AlbumRelease != null && release.AlbumRelease.Album.Value.Artist.Value.QualityProfileId == 0)
|
if (release.AlbumRelease != null && release.AlbumRelease.Album.Value.Artist.Value.QualityProfileId == 0)
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
private readonly IRootFolderService _rootFolderService;
|
private readonly IRootFolderService _rootFolderService;
|
||||||
private readonly IDiskScanService _diskScanService;
|
private readonly IDiskScanService _diskScanService;
|
||||||
private readonly IMakeImportDecision _importDecisionMaker;
|
private readonly IMakeImportDecision _importDecisionMaker;
|
||||||
|
private readonly ICueSheetService _cueSheetService;
|
||||||
private readonly ICustomFormatCalculationService _formatCalculator;
|
private readonly ICustomFormatCalculationService _formatCalculator;
|
||||||
private readonly IArtistService _artistService;
|
private readonly IArtistService _artistService;
|
||||||
private readonly IAlbumService _albumService;
|
private readonly IAlbumService _albumService;
|
||||||
|
@ -55,6 +56,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
IRootFolderService rootFolderService,
|
IRootFolderService rootFolderService,
|
||||||
IDiskScanService diskScanService,
|
IDiskScanService diskScanService,
|
||||||
IMakeImportDecision importDecisionMaker,
|
IMakeImportDecision importDecisionMaker,
|
||||||
|
ICueSheetService cueSheetService,
|
||||||
ICustomFormatCalculationService formatCalculator,
|
ICustomFormatCalculationService formatCalculator,
|
||||||
IArtistService artistService,
|
IArtistService artistService,
|
||||||
IAlbumService albumService,
|
IAlbumService albumService,
|
||||||
|
@ -73,6 +75,7 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
_rootFolderService = rootFolderService;
|
_rootFolderService = rootFolderService;
|
||||||
_diskScanService = diskScanService;
|
_diskScanService = diskScanService;
|
||||||
_importDecisionMaker = importDecisionMaker;
|
_importDecisionMaker = importDecisionMaker;
|
||||||
|
_cueSheetService = cueSheetService;
|
||||||
_formatCalculator = formatCalculator;
|
_formatCalculator = formatCalculator;
|
||||||
_artistService = artistService;
|
_artistService = artistService;
|
||||||
_albumService = albumService;
|
_albumService = albumService;
|
||||||
|
@ -153,28 +156,6 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
var audioFiles = _diskScanService.GetAudioFiles(folder).ToList();
|
var audioFiles = _diskScanService.GetAudioFiles(folder).ToList();
|
||||||
var results = new List<ManualImportItem>();
|
var results = new List<ManualImportItem>();
|
||||||
|
|
||||||
// Split cue and non-cue files
|
|
||||||
var cueFiles = audioFiles.Where(x => x.Extension.Equals(".cue")).ToList();
|
|
||||||
if (cueFiles.Count > 0)
|
|
||||||
{
|
|
||||||
audioFiles.RemoveAll(l => cueFiles.Contains(l));
|
|
||||||
var cueSheetInfos = new List<CueSheetInfo>();
|
|
||||||
foreach (var cueFile in cueFiles)
|
|
||||||
{
|
|
||||||
var cueSheetInfo = _importDecisionMaker.GetCueSheetInfo(cueFile, audioFiles);
|
|
||||||
cueSheetInfos.Add(cueSheetInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cueSheetInfosGroupedByDiscId = cueSheetInfos.GroupBy(x => x.CueSheet.DiscID).ToList();
|
|
||||||
foreach (var cueSheetInfoGroup in cueSheetInfosGroupedByDiscId)
|
|
||||||
{
|
|
||||||
var manualImportItems = ProcessFolder(downloadId, filter, replaceExistingFiles, downloadClientItem, cueSheetInfoGroup.ToList());
|
|
||||||
results.AddRange(manualImportItems);
|
|
||||||
|
|
||||||
RemoveProcessedAudioFiles(audioFiles, cueSheetInfos, manualImportItems);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var idOverrides = new IdentificationOverrides
|
var idOverrides = new IdentificationOverrides
|
||||||
{
|
{
|
||||||
Artist = artist,
|
Artist = artist,
|
||||||
|
@ -186,36 +167,6 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveProcessedAudioFiles(List<IFileInfo> audioFiles, List<CueSheetInfo> cueSheetInfos, List<ManualImportItem> manualImportItems)
|
|
||||||
{
|
|
||||||
foreach (var cueSheetInfo in cueSheetInfos)
|
|
||||||
{
|
|
||||||
if (cueSheetInfo.CueSheet != null)
|
|
||||||
{
|
|
||||||
manualImportItems.ForEach(item =>
|
|
||||||
{
|
|
||||||
if (cueSheetInfo.IsForMediaFile(item.Path))
|
|
||||||
{
|
|
||||||
item.CueSheetPath = cueSheetInfo.CueSheet.Path;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
audioFiles.RemoveAll(x => cueSheetInfo.MusicFiles.Contains(x));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ManualImportItem> ProcessFolder(string downloadId, FilterFilesType filter, bool replaceExistingFiles, DownloadClientItem downloadClientItem, List<CueSheetInfo> cueSheetInfos)
|
|
||||||
{
|
|
||||||
var audioFilesForCues = new List<IFileInfo>();
|
|
||||||
foreach (var cueSheetInfo in cueSheetInfos)
|
|
||||||
{
|
|
||||||
audioFilesForCues.AddRange(cueSheetInfo.MusicFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ProcessFolder(downloadId, cueSheetInfos[0].IdOverrides, filter, replaceExistingFiles, downloadClientItem, cueSheetInfos[0].CueSheet.Title, audioFilesForCues, cueSheetInfos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ManualImportItem> ProcessFolder(string downloadId, IdentificationOverrides idOverrides, FilterFilesType filter, bool replaceExistingFiles, DownloadClientItem downloadClientItem, string albumTitle, List<IFileInfo> audioFiles, List<CueSheetInfo> cueSheetInfos = null)
|
private List<ManualImportItem> ProcessFolder(string downloadId, IdentificationOverrides idOverrides, FilterFilesType filter, bool replaceExistingFiles, DownloadClientItem downloadClientItem, string albumTitle, List<IFileInfo> audioFiles, List<CueSheetInfo> cueSheetInfos = null)
|
||||||
{
|
{
|
||||||
idOverrides ??= new IdentificationOverrides();
|
idOverrides ??= new IdentificationOverrides();
|
||||||
|
@ -234,7 +185,11 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
AddNewArtists = false
|
AddNewArtists = false
|
||||||
};
|
};
|
||||||
|
|
||||||
var decisions = _importDecisionMaker.GetImportDecisions(audioFiles, idOverrides, itemInfo, config, cueSheetInfos);
|
var decisions = _cueSheetService.GetImportDecisions(ref audioFiles, itemInfo, config);
|
||||||
|
if (audioFiles.Count > 0)
|
||||||
|
{
|
||||||
|
decisions.AddRange(_importDecisionMaker.GetImportDecisions(audioFiles, idOverrides, itemInfo, config, cueSheetInfos));
|
||||||
|
}
|
||||||
|
|
||||||
// paths will be different for new and old files which is why we need to map separately
|
// paths will be different for new and old files which is why we need to map separately
|
||||||
var newFiles = audioFiles.Join(decisions,
|
var newFiles = audioFiles.Join(decisions,
|
||||||
|
@ -280,40 +235,32 @@ namespace NzbDrone.Core.MediaFiles.TrackImport.Manual
|
||||||
{
|
{
|
||||||
var file = _diskProvider.GetFileInfo(item.Path);
|
var file = _diskProvider.GetFileInfo(item.Path);
|
||||||
audioFiles.Add(file);
|
audioFiles.Add(file);
|
||||||
}
|
|
||||||
|
|
||||||
var cueSheetInfos = new List<CueSheetInfo>();
|
if (item.CueSheetPath != null)
|
||||||
var audioFilesForCues = new List<IFileInfo>();
|
|
||||||
var itemInfo = new ImportDecisionMakerInfo();
|
|
||||||
foreach (var item in group)
|
|
||||||
{
|
|
||||||
if (item.IsSingleFileRelease)
|
|
||||||
{
|
{
|
||||||
var cueFile = _diskProvider.GetFileInfo(item.CueSheetPath);
|
var cueFile = _diskProvider.GetFileInfo(item.CueSheetPath);
|
||||||
var cueSheetInfo = _importDecisionMaker.GetCueSheetInfo(cueFile, audioFiles);
|
audioFiles.Add(cueFile);
|
||||||
cueSheetInfos.Add(cueSheetInfo);
|
|
||||||
audioFilesForCues.AddRange(cueSheetInfo.MusicFiles);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioFilesForCues.Count > 0)
|
var itemInfo = new ImportDecisionMakerInfo();
|
||||||
{
|
|
||||||
var idOverrides = cueSheetInfos.Count > 0 ? cueSheetInfos[0].IdOverrides : null;
|
|
||||||
var singleFileReleaseDecisions = _importDecisionMaker.GetImportDecisions(audioFilesForCues, idOverrides, itemInfo, config, cueSheetInfos);
|
|
||||||
var manualImportItems = UpdateItems(group, singleFileReleaseDecisions, replaceExistingFiles, disableReleaseSwitching);
|
|
||||||
result.AddRange(manualImportItems);
|
|
||||||
|
|
||||||
RemoveProcessedAudioFiles(audioFiles, cueSheetInfos, manualImportItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
var idOverride = new IdentificationOverrides
|
var idOverride = new IdentificationOverrides
|
||||||
{
|
{
|
||||||
Artist = group.First().Artist,
|
Artist = group.First().Artist,
|
||||||
Album = group.First().Album,
|
Album = group.First().Album,
|
||||||
AlbumRelease = group.First().Release
|
AlbumRelease = group.First().Release
|
||||||
};
|
};
|
||||||
var decisions = _importDecisionMaker.GetImportDecisions(audioFiles, idOverride, itemInfo, config);
|
|
||||||
result.AddRange(UpdateItems(group, decisions, replaceExistingFiles, disableReleaseSwitching));
|
var decisions = _cueSheetService.GetImportDecisions(ref audioFiles, itemInfo, config);
|
||||||
|
if (audioFiles.Count > 0)
|
||||||
|
{
|
||||||
|
decisions.AddRange(_importDecisionMaker.GetImportDecisions(audioFiles, idOverride, itemInfo, config));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decisions.Count > 0)
|
||||||
|
{
|
||||||
|
result.AddRange(UpdateItems(group, decisions, replaceExistingFiles, disableReleaseSwitching));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue