diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 4e981fa3e5..eef6f0f2f4 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Weather; +using System.Collections.Generic; +using MediaBrowser.Model.Weather; using System; namespace MediaBrowser.Model.Configuration @@ -228,7 +229,8 @@ namespace MediaBrowser.Model.Configuration public LiveTvOptions LiveTvOptions { get; set; } public bool EnableRealtimeMonitor { get; set; } - + public PathSubstitution[] PathSubstitutions { get; set; } + /// /// Initializes a new instance of the class. /// @@ -259,6 +261,7 @@ namespace MediaBrowser.Model.Configuration EnableInternetProviders = true; //initial installs will need these ManualLoginClients = new ManualLoginCategory[] { }; + PathSubstitutions = new PathSubstitution[] { }; MetadataRefreshDays = 30; PreferredMetadataLanguage = "en"; @@ -352,4 +355,10 @@ namespace MediaBrowser.Model.Configuration SeasonZeroFolderName = "Season 0"; } } + + public class PathSubstitution + { + public string From { get; set; } + public string To { get; set; } + } } diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 1a90e75d9e..4d409ff7d4 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -134,6 +134,12 @@ namespace MediaBrowser.Model.Dto /// The genres. public List Genres { get; set; } + /// + /// Gets or sets the mapped paths. + /// + /// The mapped paths. + public List MappedPaths { get; set; } + /// /// Gets or sets the community rating. /// diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index b427b0c457..84033f9ad8 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -8,6 +9,7 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -31,8 +33,9 @@ namespace MediaBrowser.Server.Implementations.Dto private readonly IItemRepository _itemRepo; private readonly IImageProcessor _imageProcessor; + private readonly IServerConfigurationManager _config; - public DtoService(ILogger logger, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor) + public DtoService(ILogger logger, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config) { _logger = logger; _libraryManager = libraryManager; @@ -40,6 +43,7 @@ namespace MediaBrowser.Server.Implementations.Dto _userDataRepository = userDataRepository; _itemRepo = itemRepo; _imageProcessor = imageProcessor; + _config = config; } /// @@ -891,6 +895,7 @@ namespace MediaBrowser.Server.Implementations.Dto if (fields.Contains(ItemFields.Path)) { dto.Path = item.Path; + dto.MappedPaths = GetMappedPaths(item); } dto.PremiereDate = item.PremiereDate; @@ -1142,6 +1147,44 @@ namespace MediaBrowser.Server.Implementations.Dto } } + private List GetMappedPaths(BaseItem item) + { + var list = new List(); + + var locationType = item.LocationType; + + if (locationType == LocationType.FileSystem || locationType == LocationType.Offline) + { + var path = item.Path; + var mappedPaths = _config.Configuration.PathSubstitutions + .Select(p => GetMappedPath(path, p)) + .Where(p => !string.Equals(p, path, StringComparison.OrdinalIgnoreCase)) + .Distinct(StringComparer.OrdinalIgnoreCase); + + list.AddRange(mappedPaths); + } + + return list; + } + + private string GetMappedPath(string path, PathSubstitution map) + { + var toValue = map.To ?? string.Empty; + + path = path.Replace(map.From, toValue, StringComparison.OrdinalIgnoreCase); + + if (toValue.IndexOf('/') != -1) + { + path = path.Replace('\\', '/'); + } + else + { + path = path.Replace('/', '\\'); + } + + return path; + } + private void SetProductionLocations(BaseItem item, BaseItemDto dto) { var hasProductionLocations = item as IHasProductionLocations; diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 0609e80ef9..4fa345829b 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -309,7 +309,7 @@ namespace MediaBrowser.ServerApplication ImageProcessor = new ImageProcessor(Logger, ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer); RegisterSingleInstance(ImageProcessor); - DtoService = new DtoService(Logger, LibraryManager, UserManager, UserDataManager, ItemRepository, ImageProcessor); + DtoService = new DtoService(Logger, LibraryManager, UserManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager); RegisterSingleInstance(DtoService); var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer);