diff --git a/frontend/src/Settings/MediaManagement/Naming/Naming.js b/frontend/src/Settings/MediaManagement/Naming/Naming.js
index ef22d320a..81367c831 100644
--- a/frontend/src/Settings/MediaManagement/Naming/Naming.js
+++ b/frontend/src/Settings/MediaManagement/Naming/Naming.js
@@ -40,6 +40,18 @@ class Naming extends Component {
});
}
+ onMultiDiscNamingModalOpenClick = () => {
+ this.setState({
+ isNamingModalOpen: true,
+ namingModalOptions: {
+ name: 'multiDiscTrackFormat',
+ album: true,
+ track: true,
+ additional: true
+ }
+ });
+ }
+
onArtistFolderNamingModalOpenClick = () => {
this.setState({
isNamingModalOpen: true,
@@ -87,6 +99,8 @@ class Naming extends Component {
const standardTrackFormatHelpTexts = [];
const standardTrackFormatErrors = [];
+ const multiDiscTrackFormatHelpTexts = [];
+ const multiDiscTrackFormatErrors = [];
const artistFolderFormatHelpTexts = [];
const artistFolderFormatErrors = [];
const albumFolderFormatHelpTexts = [];
@@ -99,6 +113,12 @@ class Naming extends Component {
standardTrackFormatErrors.push({ message: 'Single Track: Invalid Format' });
}
+ if (examples.multiDiscTrackExample) {
+ multiDiscTrackFormatHelpTexts.push(`Multi Disc Track: ${examples.multiDiscTrackExample}`);
+ } else {
+ multiDiscTrackFormatErrors.push({ message: 'Single Track: Invalid Format' });
+ }
+
if (examples.artistFolderExample) {
artistFolderFormatHelpTexts.push(`Example: ${examples.artistFolderExample}`);
} else {
@@ -169,6 +189,21 @@ class Naming extends Component {
/>
+
+ Multi Disc Track Format
+
+ ?}
+ onChange={onInputChange}
+ {...settings.multiDiscTrackFormat}
+ helpTexts={multiDiscTrackFormatHelpTexts}
+ errors={[...multiDiscTrackFormatErrors, ...settings.multiDiscTrackFormat.errors]}
+ />
+
+
}
diff --git a/src/Lidarr.Api.V1/Config/NamingConfigModule.cs b/src/Lidarr.Api.V1/Config/NamingConfigModule.cs
index 4af476d20..c2ba93c5c 100644
--- a/src/Lidarr.Api.V1/Config/NamingConfigModule.cs
+++ b/src/Lidarr.Api.V1/Config/NamingConfigModule.cs
@@ -37,6 +37,7 @@ public NamingConfigModule(INamingConfigService namingConfigService,
SharedValidator.RuleFor(c => c.StandardTrackFormat).ValidTrackFormat();
+ SharedValidator.RuleFor(c => c.MultiDiscTrackFormat).ValidTrackFormat();
SharedValidator.RuleFor(c => c.ArtistFolderFormat).ValidArtistFolderFormat();
SharedValidator.RuleFor(c => c.AlbumFolderFormat).ValidAlbumFolderFormat();
}
@@ -60,6 +61,12 @@ private NamingConfigResource GetNamingConfig()
basicConfig.AddToResource(resource);
}
+ if (resource.MultiDiscTrackFormat.IsNotNullOrWhiteSpace())
+ {
+ var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec);
+ basicConfig.AddToResource(resource);
+ }
+
return resource;
}
@@ -79,11 +86,16 @@ private JsonResponse GetExamples(NamingConfigResource con
var sampleResource = new NamingExampleResource();
var singleTrackSampleResult = _filenameSampleService.GetStandardTrackSample(nameSpec);
+ var multiDiscTrackSampleResult = _filenameSampleService.GetMultiDiscTrackSample(nameSpec);
sampleResource.SingleTrackExample = _filenameValidationService.ValidateTrackFilename(singleTrackSampleResult) != null
? null
: singleTrackSampleResult.FileName;
+ sampleResource.MultiDiscTrackExample = _filenameValidationService.ValidateTrackFilename(multiDiscTrackSampleResult) != null
+ ? null
+ : multiDiscTrackSampleResult.FileName;
+
sampleResource.ArtistFolderExample = nameSpec.ArtistFolderFormat.IsNullOrWhiteSpace()
? null
: _filenameSampleService.GetArtistFolderSample(nameSpec);
diff --git a/src/Lidarr.Api.V1/Config/NamingConfigResource.cs b/src/Lidarr.Api.V1/Config/NamingConfigResource.cs
index fce16aa99..ee39b9040 100644
--- a/src/Lidarr.Api.V1/Config/NamingConfigResource.cs
+++ b/src/Lidarr.Api.V1/Config/NamingConfigResource.cs
@@ -7,6 +7,7 @@ public class NamingConfigResource : RestResource
public bool RenameTracks { get; set; }
public bool ReplaceIllegalCharacters { get; set; }
public string StandardTrackFormat { get; set; }
+ public string MultiDiscTrackFormat { get; set; }
public string ArtistFolderFormat { get; set; }
public string AlbumFolderFormat { get; set; }
public bool IncludeArtistName { get; set; }
diff --git a/src/Lidarr.Api.V1/Config/NamingExampleResource.cs b/src/Lidarr.Api.V1/Config/NamingExampleResource.cs
index 19c281e8a..7a12db6ea 100644
--- a/src/Lidarr.Api.V1/Config/NamingExampleResource.cs
+++ b/src/Lidarr.Api.V1/Config/NamingExampleResource.cs
@@ -5,6 +5,7 @@ namespace Lidarr.Api.V1.Config
public class NamingExampleResource
{
public string SingleTrackExample { get; set; }
+ public string MultiDiscTrackExample { get; set; }
public string ArtistFolderExample { get; set; }
public string AlbumFolderExample { get; set; }
}
@@ -20,6 +21,7 @@ public static NamingConfigResource ToResource(this NamingConfig model)
RenameTracks = model.RenameTracks,
ReplaceIllegalCharacters = model.ReplaceIllegalCharacters,
StandardTrackFormat = model.StandardTrackFormat,
+ MultiDiscTrackFormat = model.MultiDiscTrackFormat,
ArtistFolderFormat = model.ArtistFolderFormat,
AlbumFolderFormat = model.AlbumFolderFormat
};
@@ -44,6 +46,7 @@ public static NamingConfig ToModel(this NamingConfigResource resource)
RenameTracks = resource.RenameTracks,
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
StandardTrackFormat = resource.StandardTrackFormat,
+ MultiDiscTrackFormat = resource.MultiDiscTrackFormat,
ArtistFolderFormat = resource.ArtistFolderFormat,
AlbumFolderFormat = resource.AlbumFolderFormat
diff --git a/src/NzbDrone.Core/Datastore/Migration/035_multi_disc_naming_format.cs b/src/NzbDrone.Core/Datastore/Migration/035_multi_disc_naming_format.cs
new file mode 100644
index 000000000..e1f9b915b
--- /dev/null
+++ b/src/NzbDrone.Core/Datastore/Migration/035_multi_disc_naming_format.cs
@@ -0,0 +1,17 @@
+using FluentMigrator;
+using NzbDrone.Core.Datastore.Migration.Framework;
+using System.Data;
+using System.IO;
+
+namespace NzbDrone.Core.Datastore.Migration
+{
+ [Migration(35)]
+ public class multi_disc_naming_format : NzbDroneMigrationBase
+ {
+ protected override void MainDbUpgrade()
+ {
+ Alter.Table("NamingConfig").AddColumn("MultiDiscTrackFormat").AsString().Nullable();
+ Execute.Sql("UPDATE NamingConfig SET MultiDiscTrackFormat = '{Medium Format} {medium:00}/{Artist Name} - {Album Title} - {track:00} - {Track Title}'");
+ }
+ }
+}
diff --git a/src/NzbDrone.Core/Organizer/EpisodeSortingType.cs b/src/NzbDrone.Core/Organizer/EpisodeSortingType.cs
deleted file mode 100644
index d68549f07..000000000
--- a/src/NzbDrone.Core/Organizer/EpisodeSortingType.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace NzbDrone.Core.Organizer
-{
- public class EpisodeSortingType
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public string Pattern { get; set; }
- public string EpisodeSeparator { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
index 15d1966ed..4bdb6b2d6 100644
--- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
+++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
@@ -66,7 +66,7 @@ public class FileNameBuilder : IBuildFileNames
//TODO: Support Written numbers (One, Two, etc) and Roman Numerals (I, II, III etc)
private static readonly Regex MultiPartCleanupRegex = new Regex(@"(?:\(\d+\)|(Part|Pt\.?)\s?\d+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
- private static readonly char[] EpisodeTitleTrimCharacters = new[] { ' ', '.', '?' };
+ private static readonly char[] TrackTitleTrimCharacters = new[] { ' ', '.', '?' };
private static readonly Regex TitlePrefixRegex = new Regex(@"^(The|An|A) (.*?)((?: *\([^)]+\))*)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
@@ -96,18 +96,27 @@ public string BuildTrackFileName(List