From 83619ef25a64c9a82d8af992a6a02811b70ddadf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 27 Feb 2014 23:49:02 -0500 Subject: [PATCH] added app theme classes and service --- MediaBrowser.Api/AppThemeService.cs | 102 +++++++++++ MediaBrowser.Api/MediaBrowser.Api.csproj | 1 + .../Security/MBRegistration.cs | 22 ++- .../Security/PluginSecurityManager.cs | 2 +- .../Entities/TV/Episode.cs | 1 + MediaBrowser.Controller/Entities/TV/Season.cs | 1 + MediaBrowser.Controller/Entities/TV/Series.cs | 8 +- .../MediaBrowser.Controller.csproj | 2 + .../Providers/ItemLookupInfo.cs | 4 +- .../Themes/IAppThemeManager.cs | 38 ++++ .../Themes/InternalThemeImage.cs | 31 ++++ .../MediaBrowser.Model.Portable.csproj | 6 + .../MediaBrowser.Model.net35.csproj | 6 + MediaBrowser.Model/MediaBrowser.Model.csproj | 2 + MediaBrowser.Model/Themes/AppTheme.cs | 30 ++++ MediaBrowser.Model/Themes/ThemeImage.cs | 18 ++ .../ServerConfigurationManager.cs | 1 + ...MediaBrowser.Server.Implementations.csproj | 1 + .../Themes/AppThemeManager.cs | 163 ++++++++++++++++++ .../ApplicationHost.cs | 9 +- 20 files changed, 438 insertions(+), 10 deletions(-) create mode 100644 MediaBrowser.Api/AppThemeService.cs create mode 100644 MediaBrowser.Controller/Themes/IAppThemeManager.cs create mode 100644 MediaBrowser.Controller/Themes/InternalThemeImage.cs create mode 100644 MediaBrowser.Model/Themes/AppTheme.cs create mode 100644 MediaBrowser.Model/Themes/ThemeImage.cs create mode 100644 MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs diff --git a/MediaBrowser.Api/AppThemeService.cs b/MediaBrowser.Api/AppThemeService.cs new file mode 100644 index 0000000000..3115fbb366 --- /dev/null +++ b/MediaBrowser.Api/AppThemeService.cs @@ -0,0 +1,102 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Themes; +using MediaBrowser.Model.Themes; +using ServiceStack; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace MediaBrowser.Api +{ + [Route("/Themes", "GET")] + [Api(Description = "Gets a list of available themes for an app")] + public class GetAppThemes : IReturn> + { + [ApiMember(Name = "ApplicationName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string ApplicationName { get; set; } + } + + [Route("/Themes/Info", "GET")] + [Api(Description = "Gets an app theme")] + public class GetAppTheme : IReturn + { + [ApiMember(Name = "ApplicationName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string ApplicationName { get; set; } + + [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string Name { get; set; } + } + + [Route("/Themes/Images", "GET")] + [Api(Description = "Gets an app theme")] + public class GetAppThemeImage + { + [ApiMember(Name = "ApplicationName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string ApplicationName { get; set; } + + [ApiMember(Name = "ThemeName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string ThemeName { get; set; } + + [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string Name { get; set; } + + [ApiMember(Name = "Tag", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string Tag { get; set; } + } + + [Route("/Themes", "POST")] + [Api(Description = "Saves a theme")] + public class SaveTheme : AppTheme, IReturnVoid + { + } + + public class AppThemeService : BaseApiService + { + private readonly IAppThemeManager _themeManager; + private readonly IFileSystem _fileSystem; + + public AppThemeService(IAppThemeManager themeManager, IFileSystem fileSystem) + { + _themeManager = themeManager; + _fileSystem = fileSystem; + } + + public object Get(GetAppThemes request) + { + var result = _themeManager.GetThemes(request.ApplicationName).ToList(); + + return ToOptimizedResult(result); + } + + public object Get(GetAppTheme request) + { + var result = _themeManager.GetTheme(request.ApplicationName, request.Name); + + return ToOptimizedResult(result); + } + + public void Post(SaveTheme request) + { + _themeManager.SaveTheme(request); + } + + public object Get(GetAppThemeImage request) + { + var info = _themeManager.GetImageImageInfo(request.ApplicationName, request.ThemeName, request.Name); + + var cacheGuid = new Guid(info.CacheTag); + + TimeSpan? cacheDuration = null; + + if (!string.IsNullOrEmpty(request.Tag) && cacheGuid == new Guid(request.Tag)) + { + cacheDuration = TimeSpan.FromDays(365); + } + + var contentType = MimeTypes.GetMimeType(info.Path); + + return ToCachedResult(cacheGuid, info.DateModified, cacheDuration, () => _fileSystem.GetFileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read), contentType); + } + } +} diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 6e214f960c..ee2a7eafcf 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -67,6 +67,7 @@ Properties\SharedVersion.cs + diff --git a/MediaBrowser.Common.Implementations/Security/MBRegistration.cs b/MediaBrowser.Common.Implementations/Security/MBRegistration.cs index cbb6bda94f..1d64b5ea15 100644 --- a/MediaBrowser.Common.Implementations/Security/MBRegistration.cs +++ b/MediaBrowser.Common.Implementations/Security/MBRegistration.cs @@ -14,11 +14,12 @@ namespace MediaBrowser.Common.Implementations.Security { private static MBLicenseFile _licenseFile; - private const string MBValidateUrl = Constants.Constants.MbAdminUrl+"service/registration/validate"; + private const string MBValidateUrl = Constants.Constants.MbAdminUrl + "service/registration/validate"; private static IApplicationPaths _appPaths; private static INetworkManager _networkManager; private static ILogger _logger; + private static IApplicationHost _applicationHost; private static MBLicenseFile LicenseFile { @@ -37,24 +38,35 @@ namespace MediaBrowser.Common.Implementations.Security set { LicenseFile.LegacyKey = value; LicenseFile.Save(); } } - public static void Init(IApplicationPaths appPaths, INetworkManager networkManager, ILogManager logManager) + public static void Init(IApplicationPaths appPaths, INetworkManager networkManager, ILogManager logManager, IApplicationHost appHost) { // Ugly alert (static init) _appPaths = appPaths; _networkManager = networkManager; _logger = logManager.GetLogger("SecurityManager"); + _applicationHost = appHost; } public static async Task GetRegistrationStatus(IHttpClient httpClient, IJsonSerializer jsonSerializer, string feature, string mb2Equivalent = null, string version = null) { //check the reg file first to alleviate strain on the MB admin server - must actually check in every 30 days tho - var reg = new RegRecord {registered = LicenseFile.LastChecked(feature) > DateTime.UtcNow.AddDays(-30)}; + var reg = new RegRecord { registered = LicenseFile.LastChecked(feature) > DateTime.UtcNow.AddDays(-30) }; if (!reg.registered) { var mac = _networkManager.GetMacAddress(); - var data = new Dictionary { { "feature", feature }, { "key", SupporterKey }, { "mac", mac }, { "mb2equiv", mb2Equivalent }, { "legacykey", LegacyKey }, { "ver", version }, { "platform", Environment.OSVersion.VersionString } }; + var data = new Dictionary + { + { "feature", feature }, + { "key", SupporterKey }, + { "mac", mac }, + { "mb2equiv", mb2Equivalent }, + { "legacykey", LegacyKey }, + { "ver", version }, + { "platform", Environment.OSVersion.VersionString }, + { "isservice", _applicationHost.IsRunningAsService.ToString().ToLower() } + }; try { @@ -79,7 +91,7 @@ namespace MediaBrowser.Common.Implementations.Security } } - return new MBRegistrationRecord {IsRegistered = reg.registered, ExpirationDate = reg.expDate, RegChecked = true}; + return new MBRegistrationRecord { IsRegistered = reg.registered, ExpirationDate = reg.expDate, RegChecked = true }; } } diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs index 3cfdc8053b..d0b108c7da 100644 --- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs +++ b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs @@ -74,7 +74,7 @@ namespace MediaBrowser.Common.Implementations.Security _appHost = appHost; _httpClient = httpClient; _jsonSerializer = jsonSerializer; - MBRegistration.Init(_applciationPaths, _networkManager, logManager); + MBRegistration.Init(_applciationPaths, _networkManager, logManager, _appHost); } /// diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 8784a7187f..4a3c82b461 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -256,6 +256,7 @@ namespace MediaBrowser.Controller.Entities.TV if (series != null) { id.SeriesProviderIds = series.ProviderIds; + id.AnimeSeriesIndex = series.AnimeSeriesIndex; } id.IndexNumberEnd = IndexNumberEnd; diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 4fadd8f6e1..d371cbb922 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -257,6 +257,7 @@ namespace MediaBrowser.Controller.Entities.TV if (series != null) { id.SeriesProviderIds = series.ProviderIds; + id.AnimeSeriesIndex = series.AnimeSeriesIndex; } return id; diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index be6c92864c..ce0ea4458f 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -20,6 +20,8 @@ namespace MediaBrowser.Controller.Entities.TV public int SeasonCount { get; set; } + public int? AnimeSeriesIndex { get; set; } + /// /// Gets or sets the preferred metadata country code. /// @@ -224,7 +226,11 @@ namespace MediaBrowser.Controller.Entities.TV public SeriesInfo GetLookupInfo() { - return GetItemLookupInfo(); + var info = GetItemLookupInfo(); + + info.AnimeSeriesIndex = AnimeSeriesIndex; + + return info; } public override bool BeforeMetadataRefresh() diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 30174982f9..c07693b36b 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -239,6 +239,8 @@ + + diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs index c2409715ad..65ee945564 100644 --- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs @@ -101,6 +101,7 @@ namespace MediaBrowser.Controller.Providers public Dictionary SeriesProviderIds { get; set; } public int? IndexNumberEnd { get; set; } + public int? AnimeSeriesIndex { get; set; } public EpisodeInfo() { @@ -117,7 +118,7 @@ namespace MediaBrowser.Controller.Providers public class SeriesInfo : ItemLookupInfo { - + public int? AnimeSeriesIndex { get; set; } } public class PersonLookupInfo : ItemLookupInfo @@ -153,6 +154,7 @@ namespace MediaBrowser.Controller.Providers public class SeasonInfo : ItemLookupInfo { public Dictionary SeriesProviderIds { get; set; } + public int? AnimeSeriesIndex { get; set; } public SeasonInfo() { diff --git a/MediaBrowser.Controller/Themes/IAppThemeManager.cs b/MediaBrowser.Controller/Themes/IAppThemeManager.cs new file mode 100644 index 0000000000..1a7c2aaabc --- /dev/null +++ b/MediaBrowser.Controller/Themes/IAppThemeManager.cs @@ -0,0 +1,38 @@ +using MediaBrowser.Model.Themes; +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Themes +{ + public interface IAppThemeManager + { + /// + /// Gets the themes. + /// + /// Name of the application. + /// IEnumerable{AppThemeInfo}. + IEnumerable GetThemes(string applicationName); + + /// + /// Gets the theme. + /// + /// Name of the application. + /// The name. + /// AppTheme. + AppTheme GetTheme(string applicationName, string name); + + /// + /// Saves the theme. + /// + /// The theme. + void SaveTheme(AppTheme theme); + + /// + /// Gets the image image information. + /// + /// Name of the application. + /// Name of the theme. + /// Name of the image. + /// InternalThemeImage. + InternalThemeImage GetImageImageInfo(string applicationName, string themeName, string imageName); + } +} diff --git a/MediaBrowser.Controller/Themes/InternalThemeImage.cs b/MediaBrowser.Controller/Themes/InternalThemeImage.cs new file mode 100644 index 0000000000..2b676c25b7 --- /dev/null +++ b/MediaBrowser.Controller/Themes/InternalThemeImage.cs @@ -0,0 +1,31 @@ +using System; + +namespace MediaBrowser.Controller.Themes +{ + public class InternalThemeImage + { + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; set; } + + /// + /// Gets or sets the cache tag. + /// + /// The cache tag. + public string CacheTag { get; set; } + + /// + /// Gets or sets the path. + /// + /// The path. + public string Path { get; set; } + + /// + /// Gets or sets the date modified. + /// + /// The date modified. + public DateTime DateModified { get; set; } + } +} diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index e9ac46e50a..04296de355 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -452,6 +452,12 @@ Tasks\TaskTriggerInfo.cs + + Themes\AppTheme.cs + + + Themes\ThemeImage.cs + Updates\CheckForUpdateResult.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 16e3f27674..56f7fb99d2 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -439,6 +439,12 @@ Tasks\TaskTriggerInfo.cs + + Themes\AppTheme.cs + + + Themes\ThemeImage.cs + Updates\CheckForUpdateResult.cs diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index d9c7cbffe3..10aedb3baf 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -165,6 +165,8 @@ + + diff --git a/MediaBrowser.Model/Themes/AppTheme.cs b/MediaBrowser.Model/Themes/AppTheme.cs new file mode 100644 index 0000000000..a0532854dc --- /dev/null +++ b/MediaBrowser.Model/Themes/AppTheme.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Model.Themes +{ + public class AppTheme + { + public string ApplicationName { get; set; } + + public string Name { get; set; } + + public Dictionary Options { get; set; } + + public List Images { get; set; } + + public AppTheme() + { + Options = new Dictionary(StringComparer.Ordinal); + + Images = new List(); + } + } + + public class AppThemeInfo + { + public string ApplicationName { get; set; } + + public string Name { get; set; } + } +} diff --git a/MediaBrowser.Model/Themes/ThemeImage.cs b/MediaBrowser.Model/Themes/ThemeImage.cs new file mode 100644 index 0000000000..2fe0820ae1 --- /dev/null +++ b/MediaBrowser.Model/Themes/ThemeImage.cs @@ -0,0 +1,18 @@ + +namespace MediaBrowser.Model.Themes +{ + public class ThemeImage + { + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; set; } + + /// + /// Gets or sets the cache tag. + /// + /// The cache tag. + public string CacheTag { get; set; } + } +} diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index db839a66e9..415205cb11 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -25,6 +25,7 @@ namespace MediaBrowser.Server.Implementations.Configuration : base(applicationPaths, logManager, xmlSerializer) { UpdateItemsByNamePath(); + UpdateTranscodingTempPath(); } /// diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 01fd82b19c..f0b08b9233 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -248,6 +248,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs b/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs new file mode 100644 index 0000000000..ca792bcd34 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs @@ -0,0 +1,163 @@ +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Themes; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.Themes; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace MediaBrowser.Server.Implementations.Themes +{ + public class AppThemeManager : IAppThemeManager + { + private readonly IServerApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; + private readonly IJsonSerializer _json; + private readonly ILogger _logger; + + private readonly string[] _supportedImageExtensions = { ".png", ".jpg", ".jpeg" }; + + public AppThemeManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer json, ILogger logger) + { + _appPaths = appPaths; + _fileSystem = fileSystem; + _json = json; + _logger = logger; + } + + private string ThemePath + { + get + { + return Path.Combine(_appPaths.ItemsByNamePath, "appthemes"); + } + } + + private string GetThemesPath(string applicationName) + { + if (string.IsNullOrWhiteSpace(applicationName)) + { + throw new ArgumentNullException("applicationName"); + } + + // Force everything lowercase for consistency and maximum compatibility with case-sensitive file systems + var name = _fileSystem.GetValidFilename(applicationName.ToLower()); + + return Path.Combine(ThemePath, name); + } + + private string GetThemePath(string applicationName, string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentNullException("name"); + } + + // Force everything lowercase for consistency and maximum compatibility with case-sensitive file systems + name = _fileSystem.GetValidFilename(name.ToLower()); + + return Path.Combine(GetThemesPath(applicationName), name); + } + + public IEnumerable GetThemes(string applicationName) + { + var path = GetThemesPath(applicationName); + + try + { + return Directory + .EnumerateFiles(path, "*", SearchOption.AllDirectories) + .Where(i => string.Equals(Path.GetExtension(i), ".json", StringComparison.OrdinalIgnoreCase)) + .Select(i => + { + try + { + return _json.DeserializeFromFile(i); + } + catch (Exception ex) + { + _logger.ErrorException("Error deserializing {0}", ex, i); + return null; + } + + }).Where(i => i != null); + } + catch (DirectoryNotFoundException) + { + return new List(); + } + } + + public AppTheme GetTheme(string applicationName, string name) + { + var themePath = GetThemePath(applicationName, name); + var file = Path.Combine(themePath, "theme.json"); + + var theme = _json.DeserializeFromFile(file); + + theme.Images = new DirectoryInfo(themePath) + .EnumerateFiles("*", SearchOption.TopDirectoryOnly) + .Where(i => _supportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase)) + .Select(GetThemeImage) + .ToList(); + + return theme; + } + + private ThemeImage GetThemeImage(FileInfo file) + { + var dateModified = _fileSystem.GetLastWriteTimeUtc(file); + + var cacheTag = (file.FullName + dateModified.Ticks).GetMD5().ToString("N"); + + return new ThemeImage + { + CacheTag = cacheTag, + Name = file.Name + }; + } + + public void SaveTheme(AppTheme theme) + { + var themePath = GetThemePath(theme.ApplicationName, theme.Name); + var file = Path.Combine(themePath, "theme.json"); + + Directory.CreateDirectory(themePath); + + // Clone it so that we don't serialize all the images - they're always dynamic + var clone = new AppTheme + { + ApplicationName = theme.ApplicationName, + Name = theme.Name, + Options = theme.Options, + Images = null + }; + + _json.SerializeToFile(clone, file); + } + + public InternalThemeImage GetImageImageInfo(string applicationName, string themeName, string imageName) + { + var themePath = GetThemePath(applicationName, themeName); + + var fullPath = Path.Combine(themePath, imageName); + + var file = new DirectoryInfo(themePath).EnumerateFiles("*", SearchOption.TopDirectoryOnly) + .First(i => string.Equals(i.FullName, fullPath, StringComparison.OrdinalIgnoreCase)); + + var themeImage = GetThemeImage(file); + + return new InternalThemeImage + { + CacheTag = themeImage.CacheTag, + Name = themeImage.Name, + Path = file.FullName, + DateModified = _fileSystem.GetLastWriteTimeUtc(file) + }; + } + } +} diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index f199dc048d..73f99cda1d 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -27,6 +27,7 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Sorting; +using MediaBrowser.Controller.Themes; using MediaBrowser.Dlna.PlayTo; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; @@ -49,6 +50,7 @@ using MediaBrowser.Server.Implementations.MediaEncoder; using MediaBrowser.Server.Implementations.Persistence; using MediaBrowser.Server.Implementations.ServerManager; using MediaBrowser.Server.Implementations.Session; +using MediaBrowser.Server.Implementations.Themes; using MediaBrowser.Server.Implementations.WebSocket; using MediaBrowser.ServerApplication.EntryPoints; using MediaBrowser.ServerApplication.FFMpeg; @@ -163,7 +165,7 @@ namespace MediaBrowser.ServerApplication private ILocalizationManager LocalizationManager { get; set; } private IEncodingManager EncodingManager { get; set; } - + /// /// Gets or sets the user data repository. /// @@ -438,6 +440,9 @@ namespace MediaBrowser.ServerApplication MediaEncoder); RegisterSingleInstance(EncodingManager); + var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger); + RegisterSingleInstance(appThemeManager); + LiveTvManager = new LiveTvManager(ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager); RegisterSingleInstance(LiveTvManager); @@ -747,7 +752,7 @@ namespace MediaBrowser.ServerApplication // Dlna implementations list.Add(typeof(PlayToServerEntryPoint).Assembly); - + list.AddRange(Assemblies.GetAssembliesWithParts()); // Include composable parts in the running assembly