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);