From c180c327d4b63298cb60f2280cab03a292908655 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sat, 10 Dec 2022 09:59:54 -0800 Subject: [PATCH] New: Quality Preferred Size Setting Co-authored-by: Qstick (cherry picked from commit d08f33ae213bb5a94b6b6aa8f6f1e780a7a9835f) Fixed: Include preferred size in quality definition reset (cherry picked from commit 8e925ac76d2f46cf5fef1ea62a20ae5e85d3000e) --- .../Quality/Definition/QualityDefinition.css | 4 +- .../Quality/Definition/QualityDefinition.js | 95 +++++++++++++++---- .../Definition/QualityDefinitionConnector.js | 10 +- .../Qualities/QualityDefinitionResource.cs | 7 +- .../PrioritizeDownloadDecisionFixture.cs | 56 +++++++++++ .../075_quality_definition_preferred_size.cs | 16 ++++ .../DownloadDecisionComparer.cs | 27 +++++- .../DownloadDecisionPriorizationService.cs | 7 +- .../AcceptableSizeSpecification.cs | 4 +- src/NzbDrone.Core/Localization/Core/en.json | 6 +- src/NzbDrone.Core/Qualities/Quality.cs | 76 +++++++-------- .../Qualities/QualityDefinition.cs | 1 + .../Qualities/QualityDefinitionService.cs | 1 + 13 files changed, 239 insertions(+), 71 deletions(-) create mode 100644 src/NzbDrone.Core/Datastore/Migration/075_quality_definition_preferred_size.cs diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinition.css b/frontend/src/Settings/Quality/Definition/QualityDefinition.css index f9d303498..e090428a1 100644 --- a/frontend/src/Settings/Quality/Definition/QualityDefinition.css +++ b/frontend/src/Settings/Quality/Definition/QualityDefinition.css @@ -31,7 +31,7 @@ background-color: var(--sliderAccentColor); box-shadow: 0 0 0 #000; - &:nth-child(odd) { + &:nth-child(3n+1) { background-color: #ddd; } } @@ -56,7 +56,7 @@ .kilobitsPerSecond { display: flex; justify-content: space-between; - flex: 0 0 250px; + flex: 0 0 400px; } .sizeInput { diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinition.js b/frontend/src/Settings/Quality/Definition/QualityDefinition.js index a289631bc..7d8a78737 100644 --- a/frontend/src/Settings/Quality/Definition/QualityDefinition.js +++ b/frontend/src/Settings/Quality/Definition/QualityDefinition.js @@ -50,21 +50,24 @@ class QualityDefinition extends Component { this.state = { sliderMinSize: getSliderValue(props.minSize, slider.min), - sliderMaxSize: getSliderValue(props.maxSize, slider.max) + sliderMaxSize: getSliderValue(props.maxSize, slider.max), + sliderPreferredSize: getSliderValue(props.preferredSize, (slider.max - 3)) }; } // // Listeners - onSliderChange = ([sliderMinSize, sliderMaxSize]) => { + onSliderChange = ([sliderMinSize, sliderPreferredSize, sliderMaxSize]) => { this.setState({ sliderMinSize, - sliderMaxSize + sliderMaxSize, + sliderPreferredSize }); this.props.onSizeChange({ minSize: roundNumber(Math.pow(sliderMinSize, 1.1)), + preferredSize: sliderPreferredSize === (slider.max - 3) ? null : roundNumber(Math.pow(sliderPreferredSize, 1.1)), maxSize: sliderMaxSize === slider.max ? null : roundNumber(Math.pow(sliderMaxSize, 1.1)) }); }; @@ -72,12 +75,14 @@ class QualityDefinition extends Component { onAfterSliderChange = () => { const { minSize, - maxSize + maxSize, + preferredSize } = this.props; this.setState({ sliderMiSize: getSliderValue(minSize, slider.min), - sliderMaxSize: getSliderValue(maxSize, slider.max) + sliderMaxSize: getSliderValue(maxSize, slider.max), + sliderPreferredSize: getSliderValue(preferredSize, (slider.max - 3)) // fix }); }; @@ -90,7 +95,22 @@ class QualityDefinition extends Component { this.props.onSizeChange({ minSize, - maxSize: this.props.maxSize + maxSize: this.props.maxSize, + preferredSize: this.props.preferredSize + }); + }; + + onPreferredSizeChange = ({ value }) => { + const preferredSize = value === (MAX - 3) ? null : getValue(value); + + this.setState({ + sliderPreferredSize: getSliderValue(preferredSize, slider.preferred) + }); + + this.props.onSizeChange({ + minSize: this.props.minSize, + maxSize: this.props.maxSize, + preferredSize }); }; @@ -103,7 +123,8 @@ class QualityDefinition extends Component { this.props.onSizeChange({ minSize: this.props.minSize, - maxSize + maxSize, + preferredSize: this.props.preferredSize }); }; @@ -117,20 +138,25 @@ class QualityDefinition extends Component { title, minSize, maxSize, + preferredSize, advancedSettings, onTitleChange } = this.props; const { sliderMinSize, - sliderMaxSize + sliderMaxSize, + sliderPreferredSize } = this.state; const minBytes = minSize * 128; - const maxBytes = maxSize && maxSize * 128; - const minRate = `${formatBytes(minBytes, true)}/s`; - const maxRate = maxBytes ? `${formatBytes(maxBytes, true)}/s` : 'Unlimited'; + + const preferredBytes = preferredSize * 128; + const preferredRate = preferredBytes ? `${formatBytes(preferredBytes, true)}/s` : translate('Unlimited'); + + const maxBytes = maxSize && maxSize * 128; + const maxRate = maxBytes ? `${formatBytes(maxBytes, true)}/s` : translate('Unlimited'); return (
@@ -151,9 +177,10 @@ class QualityDefinition extends Component { min={slider.min} max={slider.max} step={slider.step} - minDistance={MIN_DISTANCE * 5} - value={[sliderMinSize, sliderMaxSize]} + minDistance={3} + value={[sliderMinSize, sliderPreferredSize, sliderMaxSize]} withTracks={true} + allowCross={false} snapDragDisabled={true} className={styles.slider} trackClassName={styles.bar} @@ -172,7 +199,23 @@ class QualityDefinition extends Component { body={ + } + position={tooltipPositions.BOTTOM} + /> +
+ +
+ {preferredRate} + } + title={translate('PreferredSize')} + body={ + } position={tooltipPositions.BOTTOM} @@ -188,7 +231,7 @@ class QualityDefinition extends Component { body={ } position={tooltipPositions.BOTTOM} @@ -201,14 +244,14 @@ class QualityDefinition extends Component { advancedSettings &&
- Min + {translate('Min')}
- Max + {translate('Preferred')} + + +
+ +
+ {translate('Max')} { + onSizeChange = ({ minSize, maxSize, preferredSize }) => { const { id, minSize: currentMinSize, - maxSize: currentMaxSize + maxSize: currentMaxSize, + preferredSize: currentPreferredSize } = this.props; if (minSize !== currentMinSize) { @@ -37,6 +38,10 @@ class QualityDefinitionConnector extends Component { if (maxSize !== currentMaxSize) { this.props.setQualityDefinitionValue({ id, name: 'maxSize', value: maxSize }); } + + if (preferredSize !== currentPreferredSize) { + this.props.setQualityDefinitionValue({ id, name: 'preferredSize', value: preferredSize }); + } }; // @@ -57,6 +62,7 @@ QualityDefinitionConnector.propTypes = { id: PropTypes.number.isRequired, minSize: PropTypes.number, maxSize: PropTypes.number, + preferredSize: PropTypes.number, setQualityDefinitionValue: PropTypes.func.isRequired, clearPendingChanges: PropTypes.func.isRequired }; diff --git a/src/Lidarr.Api.V1/Qualities/QualityDefinitionResource.cs b/src/Lidarr.Api.V1/Qualities/QualityDefinitionResource.cs index daedc62c3..854e91b65 100644 --- a/src/Lidarr.Api.V1/Qualities/QualityDefinitionResource.cs +++ b/src/Lidarr.Api.V1/Qualities/QualityDefinitionResource.cs @@ -15,6 +15,7 @@ namespace Lidarr.Api.V1.Qualities public double? MinSize { get; set; } public double? MaxSize { get; set; } + public double? PreferredSize { get; set; } } public static class QualityDefinitionResourceMapper @@ -33,7 +34,8 @@ namespace Lidarr.Api.V1.Qualities Title = model.Title, Weight = model.Weight, MinSize = model.MinSize, - MaxSize = model.MaxSize + MaxSize = model.MaxSize, + PreferredSize = model.PreferredSize }; } @@ -51,7 +53,8 @@ namespace Lidarr.Api.V1.Qualities Title = resource.Title, Weight = resource.Weight, MinSize = resource.MinSize, - MaxSize = resource.MaxSize + MaxSize = resource.MaxSize, + PreferredSize = resource.PreferredSize }; } diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs index 4a2b062fb..7a6b7e479 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs @@ -25,12 +25,30 @@ namespace NzbDrone.Core.Test.DecisionEngineTests public void Setup() { GivenPreferredDownloadProtocol(DownloadProtocol.Usenet); + + Mocker.GetMock() + .Setup(s => s.Get(It.IsAny())) + .Returns(new QualityDefinition { PreferredSize = null }); + } + + private void GivenPreferredSize(double? size) + { + Mocker.GetMock() + .Setup(s => s.Get(It.IsAny())) + .Returns(new QualityDefinition { PreferredSize = size }); } private Album GivenAlbum(int id) { + var release = Builder.CreateNew() + .With(e => e.AlbumId = id) + .With(e => e.Monitored = true) + .With(e => e.Duration = 3600000) + .Build(); + return Builder.CreateNew() .With(e => e.Id = id) + .With(e => e.AlbumReleases = new List { release }) .Build(); } @@ -130,6 +148,44 @@ namespace NzbDrone.Core.Test.DecisionEngineTests qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbumHdLargeYoung); } + [Test] + public void should_order_by_closest_to_preferred_size_if_both_under() + { + // 1000 Kibit/Sec * 60 Min Duration = 439.5 MiB + GivenPreferredSize(1000); + + var remoteAlbumSmall = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 120.Megabytes(), age: 1); + var remoteAlbumLarge = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 400.Megabytes(), age: 1); + + var decisions = new List(); + decisions.Add(new DownloadDecision(remoteAlbumSmall)); + decisions.Add(new DownloadDecision(remoteAlbumLarge)); + + var qualifiedReports = Subject.PrioritizeDecisions(decisions); + qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbumLarge); + } + + [Test] + public void should_order_by_closest_to_preferred_size_if_preferred_is_in_between() + { + // 700 Kibit/Sec * 60 Min Duration = 307.6 MiB + GivenPreferredSize(700); + + var remoteAlbum1 = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 100.Megabytes(), age: 1); + var remoteAlbum2 = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 200.Megabytes(), age: 1); + var remoteAlbum3 = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 300.Megabytes(), age: 1); + var remoteAlbum4 = GivenRemoteAlbum(new List { GivenAlbum(1) }, new QualityModel(Quality.MP3_256), size: 500.Megabytes(), age: 1); + + var decisions = new List(); + decisions.Add(new DownloadDecision(remoteAlbum1)); + decisions.Add(new DownloadDecision(remoteAlbum2)); + decisions.Add(new DownloadDecision(remoteAlbum3)); + decisions.Add(new DownloadDecision(remoteAlbum4)); + + var qualifiedReports = Subject.PrioritizeDecisions(decisions); + qualifiedReports.First().RemoteAlbum.Should().Be(remoteAlbum3); + } + [Test] public void should_order_by_youngest() { diff --git a/src/NzbDrone.Core/Datastore/Migration/075_quality_definition_preferred_size.cs b/src/NzbDrone.Core/Datastore/Migration/075_quality_definition_preferred_size.cs new file mode 100644 index 000000000..fceae48fb --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/075_quality_definition_preferred_size.cs @@ -0,0 +1,16 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(075)] + public class quality_definition_preferred_size : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Alter.Table("QualityDefinitions").AddColumn("PreferredSize").AsDouble().Nullable(); + + Execute.Sql("UPDATE \"QualityDefinitions\" SET \"PreferredSize\" = \"MaxSize\" - 5 WHERE \"MaxSize\" > 5"); + } + } +} diff --git a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs index 40bf551ce..97e8eb889 100644 --- a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs +++ b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs @@ -13,14 +13,16 @@ namespace NzbDrone.Core.DecisionEngine { private readonly IConfigService _configService; private readonly IDelayProfileService _delayProfileService; + private readonly IQualityDefinitionService _qualityDefinitionService; public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y); public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y); - public DownloadDecisionComparer(IConfigService configService, IDelayProfileService delayProfileService) + public DownloadDecisionComparer(IConfigService configService, IDelayProfileService delayProfileService, IQualityDefinitionService qualityDefinitionService) { _configService = configService; _delayProfileService = delayProfileService; + _qualityDefinitionService = qualityDefinitionService; } public int Compare(DownloadDecision x, DownloadDecision y) @@ -166,8 +168,27 @@ namespace NzbDrone.Core.DecisionEngine private int CompareSize(DownloadDecision x, DownloadDecision y) { - // TODO: Is smaller better? Smaller for usenet could mean no par2 files. - return CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => remoteAlbum.Release.Size.Round(200.Megabytes())); + var sizeCompare = CompareBy(x.RemoteAlbum, y.RemoteAlbum, remoteAlbum => + { + var preferredSize = _qualityDefinitionService.Get(remoteAlbum.ParsedAlbumInfo.Quality.Quality).PreferredSize; + + var releaseDuration = remoteAlbum.Albums.Select(a => a.AlbumReleases.Value.Where(r => r.Monitored || a.AnyReleaseOk).Select(r => r.Duration).MaxOrDefault()).Sum() / 1000; + + // If no value for preferred it means unlimited so fallback to sort largest is best + if (preferredSize.HasValue && releaseDuration > 0) + { + var preferredAlbumSize = releaseDuration * preferredSize.Value.Kilobits(); + + // Calculate closest to the preferred size + return Math.Abs((remoteAlbum.Release.Size - preferredAlbumSize).Round(100.Megabytes())) * (-1); + } + else + { + return remoteAlbum.Release.Size.Round(100.Megabytes()); + } + }); + + return sizeCompare; } } } diff --git a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionPriorizationService.cs b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionPriorizationService.cs index f7b55535b..af1914814 100644 --- a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionPriorizationService.cs +++ b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionPriorizationService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NzbDrone.Core.Configuration; using NzbDrone.Core.Profiles.Delay; +using NzbDrone.Core.Qualities; namespace NzbDrone.Core.DecisionEngine { @@ -14,11 +15,13 @@ namespace NzbDrone.Core.DecisionEngine { private readonly IConfigService _configService; private readonly IDelayProfileService _delayProfileService; + private readonly IQualityDefinitionService _qualityDefinitionService; - public DownloadDecisionPriorizationService(IConfigService configService, IDelayProfileService delayProfileService) + public DownloadDecisionPriorizationService(IConfigService configService, IDelayProfileService delayProfileService, IQualityDefinitionService qualityDefinitionService) { _configService = configService; _delayProfileService = delayProfileService; + _qualityDefinitionService = qualityDefinitionService; } public List PrioritizeDecisions(List decisions) @@ -26,7 +29,7 @@ namespace NzbDrone.Core.DecisionEngine return decisions.Where(c => c.RemoteAlbum.DownloadAllowed) .GroupBy(c => c.RemoteAlbum.Artist.Id, (artistId, downloadDecisions) => { - return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_configService, _delayProfileService)); + return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_configService, _delayProfileService, _qualityDefinitionService)); }) .SelectMany(c => c) .Union(decisions.Where(c => !c.RemoteAlbum.DownloadAllowed)) diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs index 1cfc12c6d..92b29adbb 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs @@ -49,7 +49,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications var minSize = qualityDefinition.MinSize.Value.Kilobits(); // Multiply minSize by smallest release duration - minSize = minSize * minReleaseDuration; + minSize *= minReleaseDuration; // If the parsed size is smaller than minSize we don't want it if (subject.Release.Size < minSize) @@ -75,7 +75,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications var maxSize = qualityDefinition.MaxSize.Value.Kilobits(); // Multiply maxSize by Album.Duration - maxSize = maxSize * maxReleaseDuration; + maxSize *= maxReleaseDuration; // If the parsed size is greater than maxSize we don't want it if (subject.Release.Size > maxSize) diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 8876a9396..d1cde31b2 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -680,9 +680,9 @@ "NoImportListsFound": "No import lists found", "NoIndexersFound": "No indexers found", "NoLeaveIt": "No, Leave It", - "NoLimitForAnyRuntime": "No limit for any runtime", + "NoLimitForAnyDuration": "No limit for any duration", "NoLogFiles": "No log files", - "NoMinimumForAnyRuntime": "No minimum for any runtime", + "NoMinimumForAnyDuration": "No minimum for any duration", "NoMissingItems": "No missing items", "NoResultsFound": "No results found", "NoTagsHaveBeenAddedYet": "No tags have been added yet", @@ -754,6 +754,7 @@ "PreferTorrent": "Prefer Torrent", "PreferUsenet": "Prefer Usenet", "PreferredProtocol": "Preferred Protocol", + "PreferredSize": "Preferred Size", "Presets": "Presets", "PreviewRename": "Preview Rename", "PreviewRetag": "Preview Retag", @@ -1116,6 +1117,7 @@ "UnableToLoadTheCalendar": "Unable to load the calendar", "UnableToLoadUISettings": "Unable to load UI settings", "Ungroup": "Ungroup", + "Unlimited": "Unlimited", "UnmappedFiles": "Unmapped Files", "UnmappedFilesOnly": "Unmapped Files Only", "Unmonitored": "Unmonitored", diff --git a/src/NzbDrone.Core/Qualities/Quality.cs b/src/NzbDrone.Core/Qualities/Quality.cs index 0e30964ca..cac866b14 100644 --- a/src/NzbDrone.Core/Qualities/Quality.cs +++ b/src/NzbDrone.Core/Qualities/Quality.cs @@ -161,44 +161,44 @@ namespace NzbDrone.Core.Qualities DefaultQualityDefinitions = new HashSet { - new QualityDefinition(Quality.Unknown) { Weight = 1, MinSize = 0, MaxSize = 350, GroupWeight = 1 }, - new QualityDefinition(Quality.MP3_008) { Weight = 2, MinSize = 0, MaxSize = 10, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_016) { Weight = 3, MinSize = 0, MaxSize = 20, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_024) { Weight = 4, MinSize = 0, MaxSize = 30, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_032) { Weight = 5, MinSize = 0, MaxSize = 40, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_040) { Weight = 6, MinSize = 0, MaxSize = 45, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_048) { Weight = 7, MinSize = 0, MaxSize = 55, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_056) { Weight = 8, MinSize = 0, MaxSize = 65, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_064) { Weight = 9, MinSize = 0, MaxSize = 75, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_080) { Weight = 10, MinSize = 0, MaxSize = 95, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, - new QualityDefinition(Quality.MP3_096) { Weight = 11, MinSize = 0, MaxSize = 110, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.MP3_112) { Weight = 12, MinSize = 0, MaxSize = 125, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.MP3_128) { Weight = 13, MinSize = 0, MaxSize = 140, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.VORBIS_Q5) { Weight = 14, MinSize = 0, MaxSize = 175, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.MP3_160) { Weight = 14, MinSize = 0, MaxSize = 175, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, - new QualityDefinition(Quality.MP3_192) { Weight = 15, MinSize = 0, MaxSize = 210, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.VORBIS_Q6) { Weight = 15, MinSize = 0, MaxSize = 210, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.AAC_192) { Weight = 15, MinSize = 0, MaxSize = 210, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.WMA) { Weight = 15, MinSize = 0, MaxSize = 350, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.MP3_224) { Weight = 16, MinSize = 0, MaxSize = 245, GroupName = "Low Quality Lossy", GroupWeight = 4 }, - new QualityDefinition(Quality.VORBIS_Q7) { Weight = 17, MinSize = 0, MaxSize = 245, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.MP3_VBR_V2) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.MP3_256) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.VORBIS_Q8) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.AAC_256) { Weight = 18, MinSize = 0, MaxSize = 280, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, - new QualityDefinition(Quality.MP3_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.AAC_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.MP3_320) { Weight = 20, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.VORBIS_Q9) { Weight = 20, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.AAC_320) { Weight = 20, MinSize = 0, MaxSize = 350, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.VORBIS_Q10) { Weight = 21, MinSize = 0, MaxSize = 550, GroupName = "High Quality Lossy", GroupWeight = 6 }, - new QualityDefinition(Quality.FLAC) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.ALAC) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.APE) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.WAVPACK) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.FLAC_24) { Weight = 23, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.ALAC_24) { Weight = 23, MinSize = 0, MaxSize = null, GroupName = "Lossless", GroupWeight = 7 }, - new QualityDefinition(Quality.WAV) { Weight = 24, MinSize = 0, MaxSize = null, GroupWeight = 8 } + new QualityDefinition(Quality.Unknown) { Weight = 1, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupWeight = 1 }, + new QualityDefinition(Quality.MP3_008) { Weight = 2, MinSize = 0, MaxSize = 10, PreferredSize = 5, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_016) { Weight = 3, MinSize = 0, MaxSize = 20, PreferredSize = 15, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_024) { Weight = 4, MinSize = 0, MaxSize = 30, PreferredSize = 25, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_032) { Weight = 5, MinSize = 0, MaxSize = 40, PreferredSize = 35, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_040) { Weight = 6, MinSize = 0, MaxSize = 45, PreferredSize = 40, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_048) { Weight = 7, MinSize = 0, MaxSize = 55, PreferredSize = 50, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_056) { Weight = 8, MinSize = 0, MaxSize = 65, PreferredSize = 60, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_064) { Weight = 9, MinSize = 0, MaxSize = 75, PreferredSize = 70, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_080) { Weight = 10, MinSize = 0, MaxSize = 95, PreferredSize = 90, GroupName = "Trash Quality Lossy", GroupWeight = 2 }, + new QualityDefinition(Quality.MP3_096) { Weight = 11, MinSize = 0, MaxSize = 110, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.MP3_112) { Weight = 12, MinSize = 0, MaxSize = 125, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.MP3_128) { Weight = 13, MinSize = 0, MaxSize = 140, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.VORBIS_Q5) { Weight = 14, MinSize = 0, MaxSize = 175, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.MP3_160) { Weight = 14, MinSize = 0, MaxSize = 175, PreferredSize = 95, GroupName = "Poor Quality Lossy", GroupWeight = 3 }, + new QualityDefinition(Quality.MP3_192) { Weight = 15, MinSize = 0, MaxSize = 210, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.VORBIS_Q6) { Weight = 15, MinSize = 0, MaxSize = 210, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.AAC_192) { Weight = 15, MinSize = 0, MaxSize = 210, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.WMA) { Weight = 15, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.MP3_224) { Weight = 16, MinSize = 0, MaxSize = 245, PreferredSize = 95, GroupName = "Low Quality Lossy", GroupWeight = 4 }, + new QualityDefinition(Quality.VORBIS_Q7) { Weight = 17, MinSize = 0, MaxSize = 245, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.MP3_VBR_V2) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.MP3_256) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.VORBIS_Q8) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.AAC_256) { Weight = 18, MinSize = 0, MaxSize = 280, PreferredSize = 95, GroupName = "Mid Quality Lossy", GroupWeight = 5 }, + new QualityDefinition(Quality.MP3_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.AAC_VBR) { Weight = 19, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.MP3_320) { Weight = 20, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.VORBIS_Q9) { Weight = 20, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.AAC_320) { Weight = 20, MinSize = 0, MaxSize = 350, PreferredSize = 195, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.VORBIS_Q10) { Weight = 21, MinSize = 0, MaxSize = 550, PreferredSize = 295, GroupName = "High Quality Lossy", GroupWeight = 6 }, + new QualityDefinition(Quality.FLAC) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.ALAC) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.APE) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.WAVPACK) { Weight = 22, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.FLAC_24) { Weight = 23, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.ALAC_24) { Weight = 23, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupName = "Lossless", GroupWeight = 7 }, + new QualityDefinition(Quality.WAV) { Weight = 24, MinSize = 0, MaxSize = null, PreferredSize = 895, GroupWeight = 8 } }; } diff --git a/src/NzbDrone.Core/Qualities/QualityDefinition.cs b/src/NzbDrone.Core/Qualities/QualityDefinition.cs index 6adb1bf41..5c60df7a5 100644 --- a/src/NzbDrone.Core/Qualities/QualityDefinition.cs +++ b/src/NzbDrone.Core/Qualities/QualityDefinition.cs @@ -14,6 +14,7 @@ namespace NzbDrone.Core.Qualities public double? MinSize { get; set; } public double? MaxSize { get; set; } + public double? PreferredSize { get; set; } public QualityDefinition() { diff --git a/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs b/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs index 0aea96a75..2dde9d4e6 100644 --- a/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs +++ b/src/NzbDrone.Core/Qualities/QualityDefinitionService.cs @@ -121,6 +121,7 @@ namespace NzbDrone.Core.Qualities existing.MinSize = definition.MinSize; existing.MaxSize = definition.MaxSize; + existing.PreferredSize = definition.PreferredSize; existing.Title = message.ResetTitles ? definition.Title : existing.Title; updateList.Add(existing);