New: Readarr 0.1

This commit is contained in:
ta264
2020-05-06 21:14:11 +01:00
parent 476f2d6047
commit 08496c82af
911 changed files with 14837 additions and 24442 deletions
@@ -31,29 +31,20 @@ namespace NzbDrone.Core.Parser.Model
public List<LocalTrack> LocalTracks { get; set; }
public int TrackCount => LocalTracks.Count;
public TrackMapping TrackMapping { get; set; }
public Distance Distance { get; set; }
public AlbumRelease AlbumRelease { get; set; }
public Book Book { get; set; }
public List<LocalTrack> ExistingTracks { get; set; }
public bool NewDownload { get; set; }
public void PopulateMatch()
{
if (AlbumRelease != null)
if (Book != null)
{
LocalTracks = LocalTracks.Concat(ExistingTracks).DistinctBy(x => x.Path).ToList();
foreach (var localTrack in LocalTracks)
{
localTrack.Release = AlbumRelease;
localTrack.Album = AlbumRelease.Album.Value;
localTrack.Artist = localTrack.Album.Artist.Value;
if (TrackMapping.Mapping.ContainsKey(localTrack))
{
var track = TrackMapping.Mapping[localTrack].Item1;
localTrack.Tracks = new List<Track> { track };
localTrack.Distance = TrackMapping.Mapping[localTrack].Item2;
}
localTrack.Album = Book;
localTrack.Artist = Book.Author.Value;
}
}
}
@@ -63,16 +54,4 @@ namespace NzbDrone.Core.Parser.Model
return "[" + string.Join(", ", LocalTracks.Select(x => Path.GetDirectoryName(x.Path)).Distinct()) + "]";
}
}
public class TrackMapping
{
public TrackMapping()
{
Mapping = new Dictionary<LocalTrack, Tuple<Track, Distance>>();
}
public Dictionary<LocalTrack, Tuple<Track, Distance>> Mapping { get; set; }
public List<LocalTrack> LocalExtra { get; set; }
public List<Track> MBExtra { get; set; }
}
}
+2 -9
View File
@@ -8,11 +8,6 @@ namespace NzbDrone.Core.Parser.Model
{
public class LocalTrack
{
public LocalTrack()
{
Tracks = new List<Track>();
}
public string Path { get; set; }
public long Size { get; set; }
public DateTime Modified { get; set; }
@@ -20,10 +15,8 @@ namespace NzbDrone.Core.Parser.Model
public ParsedTrackInfo FolderTrackInfo { get; set; }
public ParsedAlbumInfo DownloadClientAlbumInfo { get; set; }
public List<string> AcoustIdResults { get; set; }
public Artist Artist { get; set; }
public Album Album { get; set; }
public AlbumRelease Release { get; set; }
public List<Track> Tracks { get; set; }
public Author Artist { get; set; }
public Book Album { get; set; }
public Distance Distance { get; set; }
public QualityModel Quality { get; set; }
public bool ExistingFile { get; set; }
@@ -11,7 +11,11 @@ namespace NzbDrone.Core.Parser.Model
public string CleanTitle { get; set; }
public string ArtistTitle { get; set; }
public string AlbumTitle { get; set; }
public ArtistTitleInfo ArtistTitleInfo { get; set; }
public string SeriesTitle { get; set; }
public string SeriesIndex { get; set; }
public string Isbn { get; set; }
public string Asin { get; set; }
public string GoodreadsId { get; set; }
public string ArtistMBId { get; set; }
public string AlbumMBId { get; set; }
public string ReleaseMBId { get; set; }
@@ -21,13 +25,16 @@ namespace NzbDrone.Core.Parser.Model
public int DiscCount { get; set; }
public IsoCountry Country { get; set; }
public uint Year { get; set; }
public string Publisher { get; set; }
public string Label { get; set; }
public string Source { get; set; }
public string CatalogNumber { get; set; }
public string Disambiguation { get; set; }
public TimeSpan Duration { get; set; }
public QualityModel Quality { get; set; }
public MediaInfoModel MediaInfo { get; set; }
public int[] TrackNumbers { get; set; }
public string Language { get; set; }
public string ReleaseGroup { get; set; }
public string ReleaseHash { get; set; }
@@ -10,15 +10,15 @@ namespace NzbDrone.Core.Parser.Model
{
public ReleaseInfo Release { get; set; }
public ParsedAlbumInfo ParsedAlbumInfo { get; set; }
public Artist Artist { get; set; }
public List<Album> Albums { get; set; }
public Author Artist { get; set; }
public List<Book> Albums { get; set; }
public bool DownloadAllowed { get; set; }
public TorrentSeedConfiguration SeedConfiguration { get; set; }
public int PreferredWordScore { get; set; }
public RemoteAlbum()
{
Albums = new List<Album>();
Albums = new List<Book>();
}
public bool IsRecentAlbum()
+111 -38
View File
@@ -195,7 +195,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex YearInTitleRegex = new Regex(@"^(?<title>.+?)(?:\W|_)?(?<year>\d{4})",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex WordDelimiterRegex = new Regex(@"(\s|\.|,|_|-|=|\|)+", RegexOptions.Compiled);
private static readonly Regex WordDelimiterRegex = new Regex(@"(\s|\.|,|_|-|=|\(|\)|\[|\]|\|)+", RegexOptions.Compiled);
private static readonly Regex PunctuationRegex = new Regex(@"[^\w\s]", RegexOptions.Compiled);
private static readonly Regex CommonWordRegex = new Regex(@"\b(a|an|the|and|or|of)\b\s?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex SpecialEpisodeWordRegex = new Regex(@"\b(part|special|edition|christmas)\b\s?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
@@ -219,6 +219,8 @@ namespace NzbDrone.Core.Parser
private static readonly Regex AfterDashRegex = new Regex(@"[-:].*", RegexOptions.Compiled);
private static readonly Regex CalibreIdRegex = new Regex(@"\((?<id>\d+)\)", RegexOptions.Compiled);
public static ParsedTrackInfo ParseMusicPath(string path)
{
var fileInfo = new FileInfo(path);
@@ -291,7 +293,7 @@ namespace NzbDrone.Core.Parser
if (result != null)
{
result.Quality = QualityParser.ParseQuality(title, null, 0);
result.Quality = QualityParser.ParseQuality(title);
Logger.Debug("Quality parsed: {0}", result.Quality);
return result;
@@ -317,7 +319,7 @@ namespace NzbDrone.Core.Parser
return null;
}
public static ParsedAlbumInfo ParseAlbumTitleWithSearchCriteria(string title, Artist artist, List<Album> album)
public static ParsedAlbumInfo ParseAlbumTitleWithSearchCriteria(string title, Author artist, List<Book> album)
{
try
{
@@ -341,47 +343,39 @@ namespace NzbDrone.Core.Parser
simpleTitle = CleanTorrentSuffixRegex.Replace(simpleTitle);
var escapedArtist = Regex.Escape(artistName.RemoveAccent()).Replace(@"\ ", @"[\W_]");
var escapedAlbums = string.Join("|", album.Select(s => Regex.Escape(s.Title.RemoveAccent())).ToList()).Replace(@"\ ", @"[\W_]");
var bestAlbum = album.OrderByDescending(x => simpleTitle.FuzzyContains(x.Title)).First();
var releaseRegex = new Regex(@"^(\W*|\b)(?<artist>" + escapedArtist + @")(\W*|\b).*(\W*|\b)(?<album>" + escapedAlbums + @")(\W*|\b)", RegexOptions.IgnoreCase);
var foundArtist = GetTitleFuzzy(simpleTitle, artistName, out var remainder);
var foundAlbum = GetTitleFuzzy(remainder, bestAlbum.Title, out _);
var match = releaseRegex.Matches(simpleTitle);
Logger.Trace($"Found {foundArtist} - {foundAlbum} with fuzzy parser");
if (match.Count != 0)
if (foundArtist == null || foundAlbum == null)
{
try
{
var result = ParseAlbumMatchCollection(match);
return null;
}
if (result != null)
{
result.Quality = QualityParser.ParseQuality(title, null, 0);
Logger.Debug("Quality parsed: {0}", result.Quality);
var result = new ParsedAlbumInfo
{
ArtistName = foundArtist,
ArtistTitleInfo = GetArtistTitleInfo(foundArtist),
AlbumTitle = foundAlbum
};
result.ReleaseGroup = ParseReleaseGroup(releaseTitle);
try
{
result.Quality = QualityParser.ParseQuality(title);
Logger.Debug("Quality parsed: {0}", result.Quality);
var subGroup = GetSubGroup(match);
if (!subGroup.IsNullOrWhiteSpace())
{
result.ReleaseGroup = subGroup;
}
result.ReleaseGroup = ParseReleaseGroup(releaseTitle);
Logger.Debug("Release Group parsed: {0}", result.ReleaseGroup);
Logger.Debug("Release Group parsed: {0}", result.ReleaseGroup);
result.ReleaseHash = GetReleaseHash(match);
if (!result.ReleaseHash.IsNullOrWhiteSpace())
{
Logger.Debug("Release Hash parsed: {0}", result.ReleaseHash);
}
return result;
}
}
catch (InvalidDateException ex)
{
Logger.Debug(ex, ex.Message);
}
return result;
}
catch (InvalidDateException ex)
{
Logger.Debug(ex, ex.Message);
}
}
catch (Exception e)
@@ -396,6 +390,86 @@ namespace NzbDrone.Core.Parser
return null;
}
private static string GetTitleFuzzy(string report, string name, out string remainder)
{
remainder = report;
Logger.Trace($"Finding '{name}' in '{report}'");
var loc = report.ToLowerInvariant().FuzzyFind(name.ToLowerInvariant(), 0.6);
if (loc == -1)
{
return null;
}
Logger.Trace($"start '{loc}'");
var boundaries = WordDelimiterRegex.Matches(report);
if (boundaries.Count == 0)
{
return null;
}
var starts = new List<int>();
var finishes = new List<int>();
if (boundaries[0].Index == 0)
{
starts.Add(boundaries[0].Length);
}
else
{
starts.Add(0);
}
foreach (Match match in boundaries)
{
var start = match.Index + match.Length;
if (start < report.Length)
{
starts.Add(start);
}
var finish = match.Index - 1;
if (finish >= 0)
{
finishes.Add(finish);
}
}
var lastMatch = boundaries[boundaries.Count - 1];
if (lastMatch.Index + lastMatch.Length < report.Length)
{
finishes.Add(report.Length - 1);
}
Logger.Trace(starts.ConcatToString(x => x.ToString()));
Logger.Trace(finishes.ConcatToString(x => x.ToString()));
var wordStart = starts.OrderBy(x => Math.Abs(x - loc)).First();
var wordEnd = finishes.OrderBy(x => Math.Abs(x - (loc + name.Length))).First();
var found = report.Substring(wordStart, wordEnd - wordStart + 1);
if (found.ToLowerInvariant().FuzzyMatch(name.ToLowerInvariant()) >= 0.8)
{
remainder = report.Remove(wordStart, wordEnd - wordStart + 1);
return found.Replace('.', ' ').Replace('_', ' ');
}
return null;
}
public static int ParseCalibreId(this string path)
{
var bookFolder = path.GetParentPath();
var match = CalibreIdRegex.Match(bookFolder);
return match.Success ? int.Parse(match.Groups["id"].Value) : 0;
}
public static ParsedAlbumInfo ParseAlbumTitle(string title)
{
try
@@ -450,7 +524,7 @@ namespace NzbDrone.Core.Parser
if (result != null)
{
result.Quality = QualityParser.ParseQuality(title, null, 0);
result.Quality = QualityParser.ParseQuality(title);
Logger.Debug("Quality parsed: {0}", result.Quality);
result.ReleaseGroup = ParseReleaseGroup(releaseTitle);
@@ -562,7 +636,7 @@ namespace NzbDrone.Core.Parser
title = FileExtensionRegex.Replace(title, m =>
{
var extension = m.Value.ToLower();
if (MediaFiles.MediaFileExtensions.Extensions.Contains(extension) || new[] { ".par2", ".nzb" }.Contains(extension))
if (MediaFiles.MediaFileExtensions.AllExtensions.Contains(extension) || new[] { ".par2", ".nzb" }.Contains(extension))
{
return string.Empty;
}
@@ -653,7 +727,6 @@ namespace NzbDrone.Core.Parser
ParsedTrackInfo result = new ParsedTrackInfo();
result.ArtistTitle = artistName;
result.ArtistTitleInfo = GetArtistTitleInfo(result.ArtistTitle);
Logger.Debug("Track Parsed. {0}", result);
return result;
+66 -26
View File
@@ -13,38 +13,37 @@ namespace NzbDrone.Core.Parser
{
public interface IParsingService
{
Artist GetArtist(string title);
Artist GetArtistFromTag(string file);
Author GetArtist(string title);
Author GetArtistFromTag(string file);
RemoteAlbum Map(ParsedAlbumInfo parsedAlbumInfo, SearchCriteriaBase searchCriteria = null);
RemoteAlbum Map(ParsedAlbumInfo parsedAlbumInfo, int artistId, IEnumerable<int> albumIds);
List<Album> GetAlbums(ParsedAlbumInfo parsedAlbumInfo, Artist artist, SearchCriteriaBase searchCriteria = null);
RemoteAlbum Map(ParsedAlbumInfo parsedAlbumInfo, int authorId, IEnumerable<int> bookIds);
List<Book> GetAlbums(ParsedAlbumInfo parsedAlbumInfo, Author artist, SearchCriteriaBase searchCriteria = null);
ParsedAlbumInfo ParseAlbumTitleFuzzy(string title);
// Music stuff here
Album GetLocalAlbum(string filename, Artist artist);
Book GetLocalAlbum(string filename, Author artist);
}
public class ParsingService : IParsingService
{
private readonly IArtistService _artistService;
private readonly IAlbumService _albumService;
private readonly ITrackService _trackService;
private readonly IMediaFileService _mediaFileService;
private readonly Logger _logger;
public ParsingService(ITrackService trackService,
IArtistService artistService,
public ParsingService(IArtistService artistService,
IAlbumService albumService,
IMediaFileService mediaFileService,
Logger logger)
{
_albumService = albumService;
_artistService = artistService;
_trackService = trackService;
_mediaFileService = mediaFileService;
_logger = logger;
}
public Artist GetArtist(string title)
public Author GetArtist(string title)
{
var parsedAlbumInfo = Parser.ParseAlbumTitle(title);
@@ -64,11 +63,11 @@ namespace NzbDrone.Core.Parser
return artistInfo;
}
public Artist GetArtistFromTag(string file)
public Author GetArtistFromTag(string file)
{
var parsedTrackInfo = Parser.ParseMusicPath(file);
var artist = new Artist();
var artist = new Author();
if (parsedTrackInfo.ArtistMBId.IsNotNullOrWhiteSpace())
{
@@ -116,17 +115,17 @@ namespace NzbDrone.Core.Parser
return remoteAlbum;
}
public List<Album> GetAlbums(ParsedAlbumInfo parsedAlbumInfo, Artist artist, SearchCriteriaBase searchCriteria = null)
public List<Book> GetAlbums(ParsedAlbumInfo parsedAlbumInfo, Author artist, SearchCriteriaBase searchCriteria = null)
{
var albumTitle = parsedAlbumInfo.AlbumTitle;
var result = new List<Album>();
var result = new List<Book>();
if (parsedAlbumInfo.AlbumTitle == null)
{
return new List<Album>();
return new List<Book>();
}
Album albumInfo = null;
Book albumInfo = null;
if (parsedAlbumInfo.Discography)
{
@@ -157,13 +156,13 @@ namespace NzbDrone.Core.Parser
if (albumInfo == null)
{
// TODO: Search by Title and Year instead of just Title when matching
albumInfo = _albumService.FindByTitle(artist.ArtistMetadataId, parsedAlbumInfo.AlbumTitle);
albumInfo = _albumService.FindByTitle(artist.AuthorMetadataId, parsedAlbumInfo.AlbumTitle);
}
if (albumInfo == null)
{
_logger.Debug("Trying inexact album match for {0}", parsedAlbumInfo.AlbumTitle);
albumInfo = _albumService.FindByTitleInexact(artist.ArtistMetadataId, parsedAlbumInfo.AlbumTitle);
albumInfo = _albumService.FindByTitleInexact(artist.AuthorMetadataId, parsedAlbumInfo.AlbumTitle);
}
if (albumInfo != null)
@@ -178,19 +177,19 @@ namespace NzbDrone.Core.Parser
return result;
}
public RemoteAlbum Map(ParsedAlbumInfo parsedAlbumInfo, int artistId, IEnumerable<int> albumIds)
public RemoteAlbum Map(ParsedAlbumInfo parsedAlbumInfo, int authorId, IEnumerable<int> bookIds)
{
return new RemoteAlbum
{
ParsedAlbumInfo = parsedAlbumInfo,
Artist = _artistService.GetArtist(artistId),
Albums = _albumService.GetAlbums(albumIds)
Artist = _artistService.GetArtist(authorId),
Albums = _albumService.GetAlbums(bookIds)
};
}
private Artist GetArtist(ParsedAlbumInfo parsedAlbumInfo, SearchCriteriaBase searchCriteria)
private Author GetArtist(ParsedAlbumInfo parsedAlbumInfo, SearchCriteriaBase searchCriteria)
{
Artist artist = null;
Author artist = null;
if (searchCriteria != null)
{
@@ -217,7 +216,48 @@ namespace NzbDrone.Core.Parser
return artist;
}
public Album GetLocalAlbum(string filename, Artist artist)
public ParsedAlbumInfo ParseAlbumTitleFuzzy(string title)
{
var bestScore = 0.0;
Author bestAuthor = null;
Book bestBook = null;
var possibleAuthors = _artistService.GetReportCandidates(title);
foreach (var author in possibleAuthors)
{
_logger.Trace($"Trying possible author {author}");
var authorMatch = title.FuzzyMatch(author.Metadata.Value.Name, 0.5);
var possibleBooks = _albumService.GetCandidates(author.AuthorMetadataId, title);
foreach (var book in possibleBooks)
{
var bookMatch = title.FuzzyMatch(book.Title, 0.5);
var score = (authorMatch.Item2 + bookMatch.Item2) / 2;
_logger.Trace($"Book {book} has score {score}");
if (score > bestScore)
{
bestAuthor = author;
bestBook = book;
}
}
}
_logger.Trace($"Best match: {bestAuthor} {bestBook}");
if (bestAuthor != null)
{
return Parser.ParseAlbumTitleWithSearchCriteria(title, bestAuthor, new List<Book> { bestBook });
}
return null;
}
public Book GetLocalAlbum(string filename, Author artist)
{
if (Path.HasExtension(filename))
{
@@ -226,10 +266,10 @@ namespace NzbDrone.Core.Parser
var tracksInAlbum = _mediaFileService.GetFilesByArtist(artist.Id)
.FindAll(s => Path.GetDirectoryName(s.Path) == filename)
.DistinctBy(s => s.AlbumId)
.DistinctBy(s => s.BookId)
.ToList();
return tracksInAlbum.Count == 1 ? _albumService.GetAlbum(tracksInAlbum.First().AlbumId) : null;
return tracksInAlbum.Count == 1 ? _albumService.GetAlbum(tracksInAlbum.First().BookId) : null;
}
}
}
+50 -447
View File
@@ -25,24 +25,10 @@ namespace NzbDrone.Core.Parser
private static readonly Regex RealRegex = new Regex(@"\b(?<real>REAL)\b",
RegexOptions.Compiled);
private static readonly Regex BitRateRegex = new Regex(@"\b(?:(?<B096>96[ ]?kbps|96|[\[\(].*96.*[\]\)])|
(?<B128>128[ ]?kbps|128|[\[\(].*128.*[\]\)])|
(?<B160>160[ ]?kbps|160|[\[\(].*160.*[\]\)]|q5)|
(?<B192>192[ ]?kbps|192|[\[\(].*192.*[\]\)]|q6)|
(?<B224>224[ ]?kbps|224|[\[\(].*224.*[\]\)]|q7)|
(?<B256>256[ ]?kbps|256|itunes\splus|[\[\(].*256.*[\]\)]|q8)|
(?<B320>320[ ]?kbps|320|[\[\(].*320.*[\]\)]|q9)|
(?<B500>500[ ]?kbps|500|[\[\(].*500.*[\]\)]|q10)|
(?<VBRV0>V0[ ]?kbps|V0|[\[\(].*V0.*[\]\)])|
(?<VBRV2>V2[ ]?kbps|V2|[\[\(].*V2.*[\]\)]))\b",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
private static readonly Regex CodecRegex = new Regex(@"\b(?:(?<PDF>PDF)|(?<MOBI>MOBI)|(?<EPUB>EPUB)|(?<AZW3>AZW3?)|(?<MP1>MPEG Version \d(.5)? Audio, Layer 1|MP1)|(?<MP2>MPEG Version \d(.5)? Audio, Layer 2|MP2)|(?<MP3VBR>MP3.*VBR|MPEG Version \d(.5)? Audio, Layer 3 vbr)|(?<MP3CBR>MP3|MPEG Version \d(.5)? Audio, Layer 3)|(?<FLAC>flac)|(?<WAVPACK>wavpack|wv)|(?<ALAC>alac)|(?<WMA>WMA\d?)|(?<WAV>WAV|PCM)|(?<AAC>M4A|M4P|M4B|AAC|mp4a|MPEG-4 Audio(?!.*alac))|(?<OGG>OGG|OGA|Vorbis))\b|(?<APE>monkey's audio|[\[|\(].*\bape\b.*[\]|\)])|(?<OPUS>Opus Version \d(.5)? Audio|[\[|\(].*\bopus\b.*[\]|\)])",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex SampleSizeRegex = new Regex(@"\b(?:(?<S24>24[ ]bit|24bit|[\[\(].*24bit.*[\]\)]))");
private static readonly Regex CodecRegex = new Regex(@"\b(?:(?<MP1>MPEG Version \d(.5)? Audio, Layer 1|MP1)|(?<MP2>MPEG Version \d(.5)? Audio, Layer 2|MP2)|(?<MP3VBR>MP3.*VBR|MPEG Version \d(.5)? Audio, Layer 3 vbr)|(?<MP3CBR>MP3|MPEG Version \d(.5)? Audio, Layer 3)|(?<FLAC>flac)|(?<WAVPACK>wavpack|wv)|(?<ALAC>alac)|(?<WMA>WMA\d?)|(?<WAV>WAV|PCM)|(?<AAC>M4A|M4P|M4B|AAC|mp4a|MPEG-4 Audio(?!.*alac))|(?<OGG>OGG|OGA|Vorbis))\b|(?<APE>monkey's audio|[\[|\(].*\bape\b.*[\]|\)])|(?<OPUS>Opus Version \d(.5)? Audio|[\[|\(].*\bopus\b.*[\]|\)])",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static QualityModel ParseQuality(string name, string desc, int fileBitrate, int fileSampleSize = 0)
public static QualityModel ParseQuality(string name, string desc = null)
{
Logger.Debug("Trying to parse quality for {0}", name);
@@ -54,7 +40,7 @@ namespace NzbDrone.Core.Parser
var descCodec = ParseCodec(desc, "");
Logger.Trace($"Got codec {descCodec}");
result.Quality = FindQuality(descCodec, fileBitrate, fileSampleSize);
result.Quality = FindQuality(descCodec);
if (result.Quality != Quality.Unknown)
{
@@ -64,164 +50,40 @@ namespace NzbDrone.Core.Parser
}
var codec = ParseCodec(normalizedName, name);
var bitrate = ParseBitRate(normalizedName);
var sampleSize = ParseSampleSize(normalizedName);
switch (codec)
{
case Codec.MP1:
case Codec.MP2:
result.Quality = Quality.Unknown;
case Codec.PDF:
result.Quality = Quality.PDF;
break;
case Codec.MP3VBR:
if (bitrate == BitRate.VBRV0)
{
result.Quality = Quality.MP3_VBR;
}
else if (bitrate == BitRate.VBRV2)
{
result.Quality = Quality.MP3_VBR_V2;
}
else
{
result.Quality = Quality.Unknown;
}
case Codec.EPUB:
result.Quality = Quality.EPUB;
break;
case Codec.MP3CBR:
if (bitrate == BitRate.B096)
{
result.Quality = Quality.MP3_096;
}
else if (bitrate == BitRate.B128)
{
result.Quality = Quality.MP3_128;
}
else if (bitrate == BitRate.B160)
{
result.Quality = Quality.MP3_160;
}
else if (bitrate == BitRate.B192)
{
result.Quality = Quality.MP3_192;
}
else if (bitrate == BitRate.B256)
{
result.Quality = Quality.MP3_256;
}
else if (bitrate == BitRate.B320)
{
result.Quality = Quality.MP3_320;
}
else
{
result.Quality = Quality.Unknown;
}
case Codec.MOBI:
result.Quality = Quality.MOBI;
break;
case Codec.AZW3:
result.Quality = Quality.AZW3;
break;
case Codec.FLAC:
if (sampleSize == SampleSize.S24)
{
result.Quality = Quality.FLAC_24;
}
else
{
result.Quality = Quality.FLAC;
}
break;
case Codec.ALAC:
result.Quality = Quality.ALAC;
break;
case Codec.WAVPACK:
result.Quality = Quality.WAVPACK;
result.Quality = Quality.FLAC;
break;
case Codec.MP1:
case Codec.MP2:
case Codec.MP3VBR:
case Codec.MP3CBR:
case Codec.APE:
result.Quality = Quality.APE;
break;
case Codec.WMA:
result.Quality = Quality.WMA;
break;
case Codec.WAV:
result.Quality = Quality.WAV;
break;
case Codec.AAC:
if (bitrate == BitRate.B192)
{
result.Quality = Quality.AAC_192;
}
else if (bitrate == BitRate.B256)
{
result.Quality = Quality.AAC_256;
}
else if (bitrate == BitRate.B320)
{
result.Quality = Quality.AAC_320;
}
else
{
result.Quality = Quality.AAC_VBR;
}
break;
case Codec.AACVBR:
result.Quality = Quality.AAC_VBR;
break;
case Codec.OGG:
case Codec.OPUS:
if (bitrate == BitRate.B160)
{
result.Quality = Quality.VORBIS_Q5;
}
else if (bitrate == BitRate.B192)
{
result.Quality = Quality.VORBIS_Q6;
}
else if (bitrate == BitRate.B224)
{
result.Quality = Quality.VORBIS_Q7;
}
else if (bitrate == BitRate.B256)
{
result.Quality = Quality.VORBIS_Q8;
}
else if (bitrate == BitRate.B320)
{
result.Quality = Quality.VORBIS_Q9;
}
else if (bitrate == BitRate.B500)
{
result.Quality = Quality.VORBIS_Q10;
}
else
{
result.Quality = Quality.Unknown;
}
result.Quality = Quality.MP3_320;
break;
case Codec.Unknown:
if (bitrate == BitRate.B192)
{
result.Quality = Quality.MP3_192;
}
else if (bitrate == BitRate.B256)
{
result.Quality = Quality.MP3_256;
}
else if (bitrate == BitRate.B320)
{
result.Quality = Quality.MP3_320;
}
else if (bitrate == BitRate.VBR)
{
result.Quality = Quality.MP3_VBR_V2;
}
else
{
result.Quality = Quality.Unknown;
}
break;
default:
result.Quality = Quality.Unknown;
break;
@@ -259,6 +121,26 @@ namespace NzbDrone.Core.Parser
return Codec.Unknown;
}
if (match.Groups["PDF"].Success)
{
return Codec.PDF;
}
if (match.Groups["EPUB"].Success)
{
return Codec.EPUB;
}
if (match.Groups["MOBI"].Success)
{
return Codec.MOBI;
}
if (match.Groups["AZW3"].Success)
{
return Codec.AZW3;
}
if (match.Groups["FLAC"].Success)
{
return Codec.FLAC;
@@ -327,287 +209,26 @@ namespace NzbDrone.Core.Parser
return Codec.Unknown;
}
private static BitRate ParseBitRate(string name)
{
//var nameWithNoSpaces = Regex.Replace(name, @"\s+", "");
var match = BitRateRegex.Match(name);
if (!match.Success)
{
return BitRate.Unknown;
}
if (match.Groups["B096"].Success)
{
return BitRate.B096;
}
if (match.Groups["B128"].Success)
{
return BitRate.B128;
}
if (match.Groups["B160"].Success)
{
return BitRate.B160;
}
if (match.Groups["B192"].Success)
{
return BitRate.B192;
}
if (match.Groups["B224"].Success)
{
return BitRate.B224;
}
if (match.Groups["B256"].Success)
{
return BitRate.B256;
}
if (match.Groups["B320"].Success)
{
return BitRate.B320;
}
if (match.Groups["B500"].Success)
{
return BitRate.B500;
}
if (match.Groups["VBR"].Success)
{
return BitRate.VBR;
}
if (match.Groups["VBRV0"].Success)
{
return BitRate.VBRV0;
}
if (match.Groups["VBRV2"].Success)
{
return BitRate.VBRV2;
}
return BitRate.Unknown;
}
private static SampleSize ParseSampleSize(string name)
{
var match = SampleSizeRegex.Match(name);
if (!match.Success)
{
return SampleSize.Unknown;
}
if (match.Groups["S24"].Success)
{
return SampleSize.S24;
}
return SampleSize.Unknown;
}
private static Quality FindQuality(Codec codec, int bitrate, int sampleSize = 0)
private static Quality FindQuality(Codec codec)
{
switch (codec)
{
case Codec.ALAC:
case Codec.FLAC:
case Codec.WAVPACK:
case Codec.WAV:
return Quality.FLAC;
case Codec.MP1:
case Codec.MP2:
return Quality.Unknown;
case Codec.MP3VBR:
return Quality.MP3_VBR;
case Codec.MP3CBR:
if (bitrate == 8)
{
return Quality.MP3_008;
}
if (bitrate == 16)
{
return Quality.MP3_016;
}
if (bitrate == 24)
{
return Quality.MP3_024;
}
if (bitrate == 32)
{
return Quality.MP3_032;
}
if (bitrate == 40)
{
return Quality.MP3_040;
}
if (bitrate == 48)
{
return Quality.MP3_048;
}
if (bitrate == 56)
{
return Quality.MP3_056;
}
if (bitrate == 64)
{
return Quality.MP3_064;
}
if (bitrate == 80)
{
return Quality.MP3_080;
}
if (bitrate == 96)
{
return Quality.MP3_096;
}
if (bitrate == 112)
{
return Quality.MP3_112;
}
if (bitrate == 128)
{
return Quality.MP3_128;
}
if (bitrate == 160)
{
return Quality.MP3_160;
}
if (bitrate == 192)
{
return Quality.MP3_192;
}
if (bitrate == 224)
{
return Quality.MP3_224;
}
if (bitrate == 256)
{
return Quality.MP3_256;
}
if (bitrate == 320)
{
return Quality.MP3_320;
}
return Quality.Unknown;
case Codec.FLAC:
if (sampleSize == 24)
{
return Quality.FLAC_24;
}
return Quality.FLAC;
case Codec.ALAC:
return Quality.ALAC;
case Codec.WAVPACK:
return Quality.WAVPACK;
case Codec.APE:
return Quality.APE;
case Codec.WMA:
return Quality.WMA;
case Codec.WAV:
return Quality.WAV;
case Codec.AAC:
if (bitrate == 192)
{
return Quality.AAC_192;
}
if (bitrate == 256)
{
return Quality.AAC_256;
}
if (bitrate == 320)
{
return Quality.AAC_320;
}
return Quality.AAC_VBR;
case Codec.OGG:
if (bitrate == 160)
{
return Quality.VORBIS_Q5;
}
if (bitrate == 192)
{
return Quality.VORBIS_Q6;
}
if (bitrate == 224)
{
return Quality.VORBIS_Q7;
}
if (bitrate == 256)
{
return Quality.VORBIS_Q8;
}
if (bitrate == 320)
{
return Quality.VORBIS_Q9;
}
if (bitrate == 500)
{
return Quality.VORBIS_Q10;
}
return Quality.Unknown;
case Codec.OPUS:
if (bitrate < 130)
{
return Quality.Unknown;
}
if (bitrate < 180)
{
return Quality.VORBIS_Q5;
}
if (bitrate < 205)
{
return Quality.VORBIS_Q6;
}
if (bitrate < 240)
{
return Quality.VORBIS_Q7;
}
if (bitrate < 290)
{
return Quality.VORBIS_Q8;
}
if (bitrate < 410)
{
return Quality.VORBIS_Q9;
}
return Quality.VORBIS_Q10;
default:
return Quality.Unknown;
return Quality.MP3_320;
}
}
@@ -661,28 +282,10 @@ namespace NzbDrone.Core.Parser
OGG,
OPUS,
WAV,
Unknown
}
public enum BitRate
{
B096,
B128,
B160,
B192,
B224,
B256,
B320,
B500,
VBR,
VBRV0,
VBRV2,
Unknown,
}
public enum SampleSize
{
S24,
PDF,
EPUB,
MOBI,
AZW3,
Unknown
}
}