diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index f278e1e296..b286885a55 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -34,7 +34,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.15\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index 3d6cdd03dd..380c56059d 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -63,6 +63,7 @@ namespace Emby.Drawing.ImageMagick { _logger.Info("ImageMagick version: " + Wand.VersionString); TestWebp(); + Wand.SetMagickThreadCount(1); } private bool _webpAvailable = true; diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 55c6f6455e..59c2e95c76 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -51,8 +51,14 @@ namespace Emby.Drawing private readonly IJsonSerializer _jsonSerializer; private readonly IServerApplicationPaths _appPaths; private readonly IImageEncoder _imageEncoder; + private readonly SemaphoreSlim _imageProcessingSemaphore; - public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IImageEncoder imageEncoder) + public ImageProcessor(ILogger logger, + IServerApplicationPaths appPaths, + IFileSystem fileSystem, + IJsonSerializer jsonSerializer, + IImageEncoder imageEncoder, + int maxConcurrentImageProcesses) { _logger = logger; _fileSystem = fileSystem; @@ -88,6 +94,8 @@ namespace Emby.Drawing } _cachedImagedSizes = new ConcurrentDictionary(sizeDictionary); + _logger.Info("ImageProcessor started with {0} max concurrent image processes", maxConcurrentImageProcesses); + _imageProcessingSemaphore = new SemaphoreSlim(maxConcurrentImageProcesses, maxConcurrentImageProcesses); } public string[] SupportedInputFormats @@ -201,6 +209,8 @@ namespace Emby.Drawing await semaphore.WaitAsync().ConfigureAwait(false); + var imageProcessingLockTaken = false; + try { CheckDisposed(); @@ -212,11 +222,20 @@ namespace Emby.Drawing Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + + imageProcessingLockTaken = true; + _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options); } } finally { + if (imageProcessingLockTaken) + { + _imageProcessingSemaphore.Release(); + } + semaphore.Release(); } @@ -254,10 +273,15 @@ namespace Emby.Drawing return GetResult(croppedImagePath); } + var imageProcessingLockTaken = false; + try { Directory.CreateDirectory(Path.GetDirectoryName(croppedImagePath)); + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + imageProcessingLockTaken = true; + _imageEncoder.CropWhiteSpace(originalImagePath, croppedImagePath); } catch (Exception ex) @@ -269,6 +293,11 @@ namespace Emby.Drawing } finally { + if (imageProcessingLockTaken) + { + _imageProcessingSemaphore.Release(); + } + semaphore.Release(); } @@ -592,13 +621,25 @@ namespace Emby.Drawing return enhancedImagePath; } + var imageProcessingLockTaken = false; + try { Directory.CreateDirectory(Path.GetDirectoryName(enhancedImagePath)); + + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + + imageProcessingLockTaken = true; + await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false); } finally { + if (imageProcessingLockTaken) + { + _imageProcessingSemaphore.Release(); + } + semaphore.Release(); } @@ -717,9 +758,18 @@ namespace Emby.Drawing return Path.Combine(path, filename); } - public void CreateImageCollage(ImageCollageOptions options) + public async Task CreateImageCollage(ImageCollageOptions options) { - _imageEncoder.CreateImageCollage(options); + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + + try + { + _imageEncoder.CreateImageCollage(options); + } + finally + { + _imageProcessingSemaphore.Release(); + } } public IEnumerable GetSupportedEnhancers(IHasImages item, ImageType imageType) diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config index 35c98e592f..acbd2ee3ac 100644 --- a/Emby.Drawing/packages.config +++ b/Emby.Drawing/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index 419077f212..f56fd32828 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -1,7 +1,9 @@ -using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using ServiceStack; +using System.Threading; namespace MediaBrowser.Api { @@ -52,7 +54,14 @@ namespace MediaBrowser.Api var options = GetRefreshOptions(request); - _providerManager.QueueRefresh(item.Id, options); + if (item is Folder) + { + _providerManager.QueueRefresh(item.Id, options); + } + else + { + _providerManager.RefreshFullItem(item, options, CancellationToken.None); + } } private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request) diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 4d9afa260e..f89a703406 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -591,7 +591,7 @@ namespace MediaBrowser.Api.Library ThemeSongsResult = themeSongs, ThemeVideosResult = themeVideos, - SoundtrackSongsResult = GetSoundtrackSongs(request, request.Id, request.UserId, request.InheritFromParent) + SoundtrackSongsResult = new ThemeMediaResult() }); } @@ -789,53 +789,5 @@ namespace MediaBrowser.Api.Library return ToOptimizedSerializedResultUsingCache(lookup); } - - public ThemeMediaResult GetSoundtrackSongs(GetThemeMedia request, string id, Guid? userId, bool inheritFromParent) - { - var user = userId.HasValue ? _userManager.GetUserById(userId.Value) : null; - - var item = string.IsNullOrEmpty(id) - ? (userId.HasValue - ? user.RootFolder - : _libraryManager.RootFolder) - : _libraryManager.GetItemById(id); - - var dtoOptions = GetDtoOptions(request); - - var dtos = GetSoundtrackSongIds(item, inheritFromParent) - .Select(_libraryManager.GetItemById) - .OfType() - .SelectMany(i => i.GetRecursiveChildren(a => a is Audio)) - .OrderBy(i => i.SortName) - .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); - - var items = dtos.ToArray(); - - return new ThemeMediaResult - { - Items = items, - TotalRecordCount = items.Length, - OwnerId = _dtoService.GetDtoId(item) - }; - } - - private IEnumerable GetSoundtrackSongIds(BaseItem item, bool inherit) - { - var hasSoundtracks = item as IHasSoundtracks; - - if (hasSoundtracks != null) - { - return hasSoundtracks.SoundtrackIds; - } - - if (!inherit) - { - return new List(); - } - - hasSoundtracks = item.Parents.OfType().FirstOrDefault(); - - return hasSoundtracks != null ? hasSoundtracks.SoundtrackIds : new List(); - } } } diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs index e6277e39a2..ec3265b56b 100644 --- a/MediaBrowser.Api/Movies/CollectionService.cs +++ b/MediaBrowser.Api/Movies/CollectionService.cs @@ -62,12 +62,15 @@ namespace MediaBrowser.Api.Movies public async Task Post(CreateCollection request) { + var userId = AuthorizationContext.GetAuthorizationInfo(Request).UserId; + var item = await _collectionManager.CreateCollection(new CollectionCreationOptions { IsLocked = request.IsLocked, Name = request.Name, ParentId = request.ParentId, - ItemIdList = (request.Ids ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList() + ItemIdList = (request.Ids ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList(), + UserIds = new List { new Guid(userId) } }).ConfigureAwait(false); diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 923af3816a..db94e37f49 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1522,6 +1522,10 @@ namespace MediaBrowser.Api.Playback { request.LiveStreamId = val; } + else if (i == 24) + { + // Duplicating ItemId because of MediaMonkey + } } } @@ -2029,8 +2033,6 @@ namespace MediaBrowser.Api.Playback profile.GetVideoMediaProfile(state.OutputContainer, audioCodec, videoCodec, - state.OutputAudioBitrate, - state.OutputAudioChannels, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, @@ -2117,8 +2119,6 @@ namespace MediaBrowser.Api.Playback state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, - state.OutputAudioBitrate, - state.OutputAudioChannels, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 919fe07733..78dee4c448 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -159,10 +159,12 @@ namespace MediaBrowser.Api.Playback.Hls { var text = reader.ReadToEnd(); - var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(UsCulture) + Environment.NewLine + "#EXT-X-ALLOW-CACHE:NO"; + var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(UsCulture); // ffmpeg pads the reported length by a full second - return text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(UsCulture), newDuration, StringComparison.OrdinalIgnoreCase); + text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(UsCulture), newDuration, StringComparison.OrdinalIgnoreCase); + + return text; } } } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index a55f54d3c8..4f938dc419 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -608,7 +608,6 @@ namespace MediaBrowser.Api.Playback.Hls builder.AppendLine("#EXT-X-VERSION:3"); builder.AppendLine("#EXT-X-TARGETDURATION:" + state.SegmentLength.ToString(UsCulture)); builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0"); - builder.AppendLine("#EXT-X-ALLOW-CACHE:NO"); var queryStringIndex = Request.RawUrl.IndexOf('?'); var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex); diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index c71048b0da..72d4961cd7 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -18,16 +18,6 @@ using System.Threading.Tasks; namespace MediaBrowser.Api.Playback { - [Route("/Items/{Id}/MediaInfo", "GET", Summary = "Gets live playback media info for an item")] - public class GetLiveMediaInfo : IReturn - { - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string UserId { get; set; } - } - [Route("/Items/{Id}/PlaybackInfo", "GET", Summary = "Gets live playback media info for an item")] public class GetPlaybackInfo : IReturn { @@ -55,6 +45,19 @@ namespace MediaBrowser.Api.Playback public string LiveStreamId { get; set; } } + [Route("/Playback/BitrateTest", "GET")] + public class GetBitrateTestBytes : IReturn + { + [ApiMember(Name = "Size", Description = "Size", IsRequired = true, DataType = "int", ParameterType = "query", Verb = "GET")] + public long Size { get; set; } + + public GetBitrateTestBytes() + { + // 100k + Size = 102400; + } + } + [Authenticated] public class MediaInfoService : BaseApiService { @@ -73,13 +76,19 @@ namespace MediaBrowser.Api.Playback _networkManager = networkManager; } - public async Task Get(GetPlaybackInfo request) + public object Get(GetBitrateTestBytes request) { - var result = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }).ConfigureAwait(false); - return ToOptimizedResult(result); + var bytes = new byte[request.Size]; + + for (var i = 0; i < bytes.Length; i++) + { + bytes[i] = 0; + } + + return ResultFactory.GetResult(bytes, "application/octet-stream"); } - public async Task Get(GetLiveMediaInfo request) + public async Task Get(GetPlaybackInfo request) { var result = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }).ConfigureAwait(false); return ToOptimizedResult(result); @@ -325,10 +334,11 @@ namespace MediaBrowser.Api.Playback private int? GetMaxBitrate(int? clientMaxBitrate) { var maxBitrate = clientMaxBitrate; + var remoteClientMaxBitrate = _config.Configuration.RemoteClientBitrateLimit; - if (_config.Configuration.RemoteClientBitrateLimit > 0 && !_networkManager.IsInLocalNetwork(Request.RemoteIp)) + if (remoteClientMaxBitrate > 0 && !_networkManager.IsInLocalNetwork(Request.RemoteIp)) { - maxBitrate = Math.Min(maxBitrate ?? _config.Configuration.RemoteClientBitrateLimit, _config.Configuration.RemoteClientBitrateLimit); + maxBitrate = Math.Min(maxBitrate ?? remoteClientMaxBitrate, remoteClientMaxBitrate); } return maxBitrate; diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 4655f2c6f9..6ee8d36035 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -66,6 +66,7 @@ namespace MediaBrowser.Api _config.Configuration.EnableStandaloneMetadata = true; _config.Configuration.EnableLibraryMetadataSubFolder = true; _config.Configuration.EnableUserSpecificUserViews = true; + _config.Configuration.EnableCustomPathSubFolders = true; _config.SaveConfiguration(); } diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs index a70118d3ce..c9280b6f63 100644 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -100,6 +100,7 @@ namespace MediaBrowser.Api.Subtitles } [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/subtitles.m3u8", "GET", Summary = "Gets an HLS subtitle playlist.")] + [Authenticated] public class GetSubtitlePlaylist { /// diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs index d5f88e6a43..5863e05e3a 100644 --- a/MediaBrowser.Api/Sync/SyncService.cs +++ b/MediaBrowser.Api/Sync/SyncService.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Dto; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Sync; @@ -230,6 +231,11 @@ namespace MediaBrowser.Api.Sync { var jobItem = _syncManager.GetJobItem(request.Id); + if (jobItem == null) + { + throw new ResourceNotFoundException(); + } + if (jobItem.Status < SyncJobItemStatus.ReadyToTransfer) { throw new ArgumentException("The job item is not yet ready for transfer."); diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index a734581f58..51f88d5743 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "StudioIds", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string StudioIds { get; set; } - + /// /// Gets or sets the studios. /// @@ -68,7 +68,7 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "ArtistIds", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string ArtistIds { get; set; } - + [ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string Albums { get; set; } @@ -622,7 +622,7 @@ namespace MediaBrowser.Api.UserLibrary private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, bool isPreFiltered, ILibraryManager libraryManager) { var video = i as Video; - + if (!isPreFiltered) { var mediaTypes = request.GetMediaTypes(); @@ -979,8 +979,8 @@ namespace MediaBrowser.Api.UserLibrary if (years.Length > 0 && !(i.ProductionYear.HasValue && years.Contains(i.ProductionYear.Value))) { return false; - } - + } + // Apply person filter var personIds = request.GetPersonIds(); if (personIds.Length > 0) @@ -1057,7 +1057,7 @@ namespace MediaBrowser.Api.UserLibrary // Artists if (!string.IsNullOrEmpty(request.ArtistIds)) { - var artistIds = request.ArtistIds.Split('|'); + var artistIds = request.ArtistIds.Split(new[] { '|', ',' }); var audio = i as IHasArtist; diff --git a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs index c53947e443..1b9146644a 100644 --- a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs +++ b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs @@ -164,9 +164,22 @@ namespace MediaBrowser.Common.Implementations.Configuration /// private void UpdateCachePath() { - ((BaseApplicationPaths)CommonApplicationPaths).CachePath = string.IsNullOrEmpty(CommonConfiguration.CachePath) ? - null : - CommonConfiguration.CachePath; + string cachePath; + + if (string.IsNullOrWhiteSpace(CommonConfiguration.CachePath)) + { + cachePath = null; + } + else if (CommonConfiguration.EnableCustomPathSubFolders) + { + cachePath = Path.Combine(CommonConfiguration.CachePath, "cache"); + } + else + { + cachePath = CommonConfiguration.CachePath; + } + + ((BaseApplicationPaths)CommonApplicationPaths).CachePath = cachePath; } /// diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index d7e5886d59..967cf54a6d 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -48,9 +48,9 @@ Always - + False - ..\packages\NLog.3.2.0.0\lib\net45\NLog.dll + ..\packages\NLog.3.2.1\lib\net45\NLog.dll False diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config index 825b6662b2..56cb78031a 100644 --- a/MediaBrowser.Common.Implementations/packages.config +++ b/MediaBrowser.Common.Implementations/packages.config @@ -1,5 +1,5 @@  - + diff --git a/MediaBrowser.Controller/Dlna/ISsdpHandler.cs b/MediaBrowser.Controller/Dlna/ISsdpHandler.cs new file mode 100644 index 0000000000..e4126ddcf4 --- /dev/null +++ b/MediaBrowser.Controller/Dlna/ISsdpHandler.cs @@ -0,0 +1,9 @@ +using System; + +namespace MediaBrowser.Controller.Dlna +{ + public interface ISsdpHandler + { + event EventHandler MessageReceived; + } +} diff --git a/MediaBrowser.Dlna/Ssdp/SsdpMessageEventArgs.cs b/MediaBrowser.Controller/Dlna/SsdpMessageEventArgs.cs similarity index 85% rename from MediaBrowser.Dlna/Ssdp/SsdpMessageEventArgs.cs rename to MediaBrowser.Controller/Dlna/SsdpMessageEventArgs.cs index 602a5bfc18..63f3a67aa0 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpMessageEventArgs.cs +++ b/MediaBrowser.Controller/Dlna/SsdpMessageEventArgs.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Net; -namespace MediaBrowser.Dlna.Ssdp +namespace MediaBrowser.Controller.Dlna { public class SsdpMessageEventArgs { @@ -13,6 +13,7 @@ namespace MediaBrowser.Dlna.Ssdp public Dictionary Headers { get; set; } public IPAddress LocalIp { get; set; } + public byte[] Message { get; set; } public SsdpMessageEventArgs() { diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 685d2706da..aeb8173921 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -104,6 +104,6 @@ namespace MediaBrowser.Controller.Drawing /// Creates the image collage. /// /// The options. - void CreateImageCollage(ImageCollageOptions options); + Task CreateImageCollage(ImageCollageOptions options); } } diff --git a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs index 254f90376d..a7c914664e 100644 --- a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs @@ -17,10 +17,6 @@ namespace MediaBrowser.Controller.Entities.Audio public static class HasArtistExtensions { - public static bool HasArtist(this IHasArtist hasArtist, string artist) - { - return NameExtensions.EqualsAny(hasArtist.Artists, artist); - } public static bool HasAnyArtist(this IHasArtist hasArtist, string artist) { return NameExtensions.EqualsAny(hasArtist.AllArtists, artist); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 22efd3fba7..3313f45fd1 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -491,6 +491,17 @@ namespace MediaBrowser.Controller.Entities } } + /// + /// Finds a parent of a given type + /// + /// + /// ``0. + public T FindParent() + where T : Folder + { + return Parents.OfType().FirstOrDefault(); + } + [IgnoreDataMember] public virtual BaseItem DisplayParent { @@ -1457,30 +1468,6 @@ namespace MediaBrowser.Controller.Entities return Task.FromResult(true); } - /// - /// Finds a parent of a given type - /// - /// - /// ``0. - public T FindParent() - where T : Folder - { - var parent = Parent; - - while (parent != null) - { - var result = parent as T; - if (result != null) - { - return result; - } - - parent = parent.Parent; - } - - return null; - } - /// /// Gets an image /// diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index 899e5628f1..15d2d755a8 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -8,10 +8,8 @@ using System.Linq; namespace MediaBrowser.Controller.Entities { - public class Game : BaseItem, IHasSoundtracks, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, ISupportsPlaceHolders, IHasPreferredMetadataLanguage, IHasLookupInfo + public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, ISupportsPlaceHolders, IHasPreferredMetadataLanguage, IHasLookupInfo { - public List SoundtrackIds { get; set; } - public List ThemeSongIds { get; set; } public List ThemeVideoIds { get; set; } @@ -26,7 +24,6 @@ namespace MediaBrowser.Controller.Entities public Game() { MultiPartGameFiles = new List(); - SoundtrackIds = new List(); RemoteTrailers = new List(); LocalTrailerIds = new List(); RemoteTrailerIds = new List(); diff --git a/MediaBrowser.Controller/Entities/IHasSoundtracks.cs b/MediaBrowser.Controller/Entities/IHasSoundtracks.cs deleted file mode 100644 index 3ac2491fbc..0000000000 --- a/MediaBrowser.Controller/Entities/IHasSoundtracks.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Entities -{ - /// - /// Interface IHasSoundtracks - /// - public interface IHasSoundtracks - { - /// - /// Gets or sets the soundtrack ids. - /// - /// The soundtrack ids. - List SoundtrackIds { get; set; } - - /// - /// Gets the name. - /// - /// The name. - string Name { get; } - - /// - /// Gets the identifier. - /// - /// The identifier. - Guid Id { get; } - } -} diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 4110047821..fc07f67788 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -14,12 +14,11 @@ namespace MediaBrowser.Controller.Entities.Movies /// /// Class Movie /// - public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo, ISupportsBoxSetGrouping, IHasOriginalTitle + public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo, ISupportsBoxSetGrouping, IHasOriginalTitle { public List SpecialFeatureIds { get; set; } public string OriginalTitle { get; set; } - public List SoundtrackIds { get; set; } public List ThemeSongIds { get; set; } public List ThemeVideoIds { get; set; } @@ -28,7 +27,6 @@ namespace MediaBrowser.Controller.Entities.Movies public Movie() { SpecialFeatureIds = new List(); - SoundtrackIds = new List(); RemoteTrailers = new List(); LocalTrailerIds = new List(); RemoteTrailerIds = new List(); @@ -102,7 +100,19 @@ namespace MediaBrowser.Controller.Entities.Movies /// System.String. protected override string CreateUserDataKey() { - return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey(); + var key = this.GetProviderId(MetadataProviders.Tmdb); + + if (string.IsNullOrWhiteSpace(key)) + { + key = this.GetProviderId(MetadataProviders.Imdb); + } + + if (string.IsNullOrWhiteSpace(key)) + { + key = base.CreateUserDataKey(); + } + + return key; } protected override async Task RefreshedOwnedItems(MetadataRefreshOptions options, List fileSystemChildren, CancellationToken cancellationToken) diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 91014ccdad..4696afeb62 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -15,10 +15,9 @@ namespace MediaBrowser.Controller.Entities.TV /// /// Class Series /// - public class Series : Folder, IHasSoundtracks, IHasTrailers, IHasDisplayOrder, IHasLookupInfo, IHasSpecialFeatures, IMetadataContainer, IHasOriginalTitle + public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo, IHasSpecialFeatures, IMetadataContainer, IHasOriginalTitle { public List SpecialFeatureIds { get; set; } - public List SoundtrackIds { get; set; } public string OriginalTitle { get; set; } public int SeasonCount { get; set; } @@ -30,7 +29,6 @@ namespace MediaBrowser.Controller.Entities.TV AirDays = new List(); SpecialFeatureIds = new List(); - SoundtrackIds = new List(); RemoteTrailers = new List(); LocalTrailerIds = new List(); RemoteTrailerIds = new List(); @@ -63,7 +61,7 @@ namespace MediaBrowser.Controller.Entities.TV /// airdate, dvd or absolute /// public string DisplayOrder { get; set; } - + /// /// Gets or sets the status. /// @@ -115,7 +113,19 @@ namespace MediaBrowser.Controller.Entities.TV /// System.String. protected override string CreateUserDataKey() { - return this.GetProviderId(MetadataProviders.Tvdb) ?? this.GetProviderId(MetadataProviders.Tvcom) ?? base.CreateUserDataKey(); + var key = this.GetProviderId(MetadataProviders.Tvdb); + + if (string.IsNullOrWhiteSpace(key)) + { + key = this.GetProviderId(MetadataProviders.Imdb); + } + + if (string.IsNullOrWhiteSpace(key)) + { + key = base.CreateUserDataKey(); + } + + return key; } /// @@ -190,7 +200,7 @@ namespace MediaBrowser.Controller.Entities.TV public IEnumerable GetEpisodes(User user) { var config = user.Configuration; - + return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 522e6edf69..f44128e2d6 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -14,17 +14,14 @@ namespace MediaBrowser.Controller.Entities /// Class Trailer /// [Obsolete] - public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo + public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo { - public List SoundtrackIds { get; set; } - public List ProductionLocations { get; set; } public Trailer() { RemoteTrailers = new List(); Taglines = new List(); - SoundtrackIds = new List(); Keywords = new List(); ProductionLocations = new List(); } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 199f5e0d1f..b66e6b9c8c 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -116,7 +116,9 @@ + + @@ -150,7 +152,6 @@ - diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index 13f83c0fc9..a8a3e88abb 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -1426,6 +1426,46 @@ namespace MediaBrowser.Controller.Providers return null; } + protected Share GetShare(XmlReader reader) + { + reader.MoveToContent(); + + var item = new Share(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "UserId": + { + item.UserId = reader.ReadElementContentAsString(); + break; + } + + case "CanEdit": + { + item.CanEdit = string.Equals(reader.ReadElementContentAsString(), "true", StringComparison.OrdinalIgnoreCase); + break; + } + + default: + reader.Skip(); + break; + } + } + } + + // This is valid + if (!string.IsNullOrWhiteSpace(item.UserId)) + { + return item; + } + + return null; + } + /// /// Used to split names of comma or pipe delimeted genres and people diff --git a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs index 78db68f63f..7e896492da 100644 --- a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs +++ b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Providers; using MediaBrowser.Dlna.ContentDirectory; using MediaBrowser.Dlna.PlayTo; diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index 3d7ae8cc4d..246c234625 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -638,6 +638,17 @@ namespace MediaBrowser.Dlna.ContentDirectory Guid itemId; StubType? stubType = null; + // After using PlayTo, MediaMonkey sends a request to the server trying to get item info + const string paramsSrch = "Params="; + var paramsIndex = id.IndexOf(paramsSrch, StringComparison.OrdinalIgnoreCase); + if (paramsIndex != -1) + { + id = id.Substring(paramsIndex + paramsSrch.Length); + + var parts = id.Split(';'); + id = parts[24]; + } + if (id.StartsWith("folder_", StringComparison.OrdinalIgnoreCase)) { stubType = StubType.Folder; diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 52791822bb..08f7707355 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -149,8 +149,6 @@ namespace MediaBrowser.Dlna.Didl targetHeight, streamInfo.TargetVideoBitDepth, streamInfo.TargetVideoBitrate, - streamInfo.TargetAudioChannels, - streamInfo.TargetAudioBitrate, streamInfo.TargetTimestamp, streamInfo.IsDirectStream, streamInfo.RunTimeTicks, @@ -276,11 +274,9 @@ namespace MediaBrowser.Dlna.Didl streamInfo.AudioCodec, streamInfo.VideoCodec, streamInfo.TargetAudioBitrate, - targetChannels, targetWidth, targetHeight, streamInfo.TargetVideoBitDepth, - streamInfo.TargetVideoBitrate, streamInfo.TargetVideoProfile, streamInfo.TargetVideoLevel, streamInfo.TargetFramerate, diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs index f0f295c831..bdc8beb989 100644 --- a/MediaBrowser.Dlna/DlnaManager.cs +++ b/MediaBrowser.Dlna/DlnaManager.cs @@ -8,7 +8,6 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Dlna.Profiles; using MediaBrowser.Dlna.Server; using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dlna.Profiles; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs index 4a8baf0feb..f9f9c3f18b 100644 --- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs +++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs @@ -37,13 +37,26 @@ namespace MediaBrowser.Dlna.Main private readonly ILocalizationManager _localization; private readonly IMediaSourceManager _mediaSourceManager; - private SsdpHandler _ssdpHandler; + private readonly SsdpHandler _ssdpHandler; private DeviceDiscovery _deviceDiscovery; private readonly List _registeredServerIds = new List(); private bool _dlnaServerStarted; - public DlnaEntryPoint(IServerConfigurationManager config, ILogManager logManager, IServerApplicationHost appHost, INetworkManager network, ISessionManager sessionManager, IHttpClient httpClient, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IImageProcessor imageProcessor, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) + public DlnaEntryPoint(IServerConfigurationManager config, + ILogManager logManager, + IServerApplicationHost appHost, + INetworkManager network, + ISessionManager sessionManager, + IHttpClient httpClient, + ILibraryManager libraryManager, + IUserManager userManager, + IDlnaManager dlnaManager, + IImageProcessor imageProcessor, + IUserDataManager userDataManager, + ILocalizationManager localization, + IMediaSourceManager mediaSourceManager, + ISsdpHandler ssdpHandler) { _config = config; _appHost = appHost; @@ -57,6 +70,7 @@ namespace MediaBrowser.Dlna.Main _userDataManager = userDataManager; _localization = localization; _mediaSourceManager = mediaSourceManager; + _ssdpHandler = (SsdpHandler)ssdpHandler; _logger = logManager.GetLogger("Dlna"); } @@ -109,8 +123,6 @@ namespace MediaBrowser.Dlna.Main { try { - _ssdpHandler = new SsdpHandler(_logger, _config, GenerateServerSignature()); - _ssdpHandler.Start(); _deviceDiscovery = new DeviceDiscovery(_logger, _config, _ssdpHandler, _appHost); @@ -123,7 +135,7 @@ namespace MediaBrowser.Dlna.Main } } - private void DisposeSsdpHandler() + private void DisposeDeviceDiscovery() { try { @@ -133,15 +145,6 @@ namespace MediaBrowser.Dlna.Main { _logger.ErrorException("Error disposing device discovery", ex); } - - try - { - _ssdpHandler.Dispose(); - } - catch (Exception ex) - { - _logger.ErrorException("Error disposing ssdp handler", ex); - } } public void StartDlnaServer() @@ -184,29 +187,6 @@ namespace MediaBrowser.Dlna.Main } } - private string GenerateServerSignature() - { - var os = Environment.OSVersion; - var pstring = os.Platform.ToString(); - switch (os.Platform) - { - case PlatformID.Win32NT: - case PlatformID.Win32S: - case PlatformID.Win32Windows: - pstring = "WIN"; - break; - } - - return String.Format( - "{0}{1}/{2}.{3} UPnP/1.0 DLNADOC/1.5 MediaBrowser/{4}", - pstring, - IntPtr.Size * 8, - os.Version.Major, - os.Version.Minor, - _appHost.ApplicationVersion - ); - } - private readonly object _syncLock = new object(); private void StartPlayToManager() { @@ -260,7 +240,7 @@ namespace MediaBrowser.Dlna.Main { DisposeDlnaServer(); DisposePlayToManager(); - DisposeSsdpHandler(); + DisposeDeviceDiscovery(); } public void DisposeDlnaServer() diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index 0cbe363982..b4e93ed681 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -77,6 +77,7 @@ + @@ -134,7 +135,6 @@ - diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index 66cdc51afe..5aa8c1f9ca 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -310,12 +310,12 @@ namespace MediaBrowser.Dlna.PlayTo { if (isFirst && command.StartPositionTicks.HasValue) { - playlist.Add(CreatePlaylistItem(item, user, command.StartPositionTicks.Value)); + playlist.Add(CreatePlaylistItem(item, user, command.StartPositionTicks.Value, null, null, null)); isFirst = false; } else { - playlist.Add(CreatePlaylistItem(item, user, 0)); + playlist.Add(CreatePlaylistItem(item, user, 0, null, null, null)); } } @@ -456,11 +456,6 @@ namespace MediaBrowser.Dlna.PlayTo } } - private PlaylistItem CreatePlaylistItem(BaseItem item, User user, long startPostionTicks) - { - return CreatePlaylistItem(item, user, startPostionTicks, null, null, null); - } - private PlaylistItem CreatePlaylistItem(BaseItem item, User user, long startPostionTicks, string mediaSourceId, int? audioStreamIndex, int? subtitleStreamIndex) { var deviceInfo = _device.Properties; @@ -514,8 +509,6 @@ namespace MediaBrowser.Dlna.PlayTo streamInfo.TargetHeight, streamInfo.TargetVideoBitDepth, streamInfo.TargetVideoBitrate, - streamInfo.TargetAudioChannels, - streamInfo.TargetAudioBitrate, streamInfo.TargetTimestamp, streamInfo.IsDirectStream, streamInfo.RunTimeTicks, diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index 77c98f9b97..3c68af5505 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -13,6 +13,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net; +using System.Threading; namespace MediaBrowser.Dlna.PlayTo { @@ -34,6 +35,9 @@ namespace MediaBrowser.Dlna.PlayTo private readonly DeviceDiscovery _deviceDiscovery; private readonly IMediaSourceManager _mediaSourceManager; + private readonly List _nonRendererUrls = new List(); + private Timer _clearNonRenderersTimer; + public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, DeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) { _logger = logger; @@ -53,9 +57,19 @@ namespace MediaBrowser.Dlna.PlayTo public void Start() { + _clearNonRenderersTimer = new Timer(OnClearUrlTimerCallback, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); + _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; } + private void OnClearUrlTimerCallback(object state) + { + lock (_nonRendererUrls) + { + _nonRendererUrls.Clear(); + } + } + async void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e) { var localIp = e.LocalIp; @@ -68,7 +82,7 @@ namespace MediaBrowser.Dlna.PlayTo string location; if (!e.Headers.TryGetValue("Location", out location)) location = string.Empty; - + // It has to report that it's a media renderer if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 && nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1) @@ -85,61 +99,75 @@ namespace MediaBrowser.Dlna.PlayTo { var uri = new Uri(location); + lock (_nonRendererUrls) + { + if (_nonRendererUrls.Contains(location, StringComparer.OrdinalIgnoreCase)) + { + return; + } + } + var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger).ConfigureAwait(false); - if (device.RendererCommands != null) + if (device.RendererCommands == null) { - var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null) - .ConfigureAwait(false); - - var controller = sessionInfo.SessionController as PlayToController; - - if (controller == null) + lock (_nonRendererUrls) { - var serverAddress = GetServerAddress(localIp); - string accessToken = null; - - sessionInfo.SessionController = controller = new PlayToController(sessionInfo, - _sessionManager, - _libraryManager, - _logger, - _dlnaManager, - _userManager, - _imageProcessor, - serverAddress, - accessToken, - _deviceDiscovery, - _userDataManager, - _localization, - _mediaSourceManager); - - controller.Init(device); - - var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ?? - _dlnaManager.GetDefaultProfile(); - - _sessionManager.ReportCapabilities(sessionInfo.Id, new ClientCapabilities - { - PlayableMediaTypes = profile.GetSupportedMediaTypes(), - - SupportedCommands = new List - { - GeneralCommandType.VolumeDown.ToString(), - GeneralCommandType.VolumeUp.ToString(), - GeneralCommandType.Mute.ToString(), - GeneralCommandType.Unmute.ToString(), - GeneralCommandType.ToggleMute.ToString(), - GeneralCommandType.SetVolume.ToString(), - GeneralCommandType.SetAudioStreamIndex.ToString(), - GeneralCommandType.SetSubtitleStreamIndex.ToString() - }, - - SupportsMediaControl = true - }); - - _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName); + _nonRendererUrls.Add(location); + return; } } + + var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null) + .ConfigureAwait(false); + + var controller = sessionInfo.SessionController as PlayToController; + + if (controller == null) + { + var serverAddress = GetServerAddress(localIp); + string accessToken = null; + + sessionInfo.SessionController = controller = new PlayToController(sessionInfo, + _sessionManager, + _libraryManager, + _logger, + _dlnaManager, + _userManager, + _imageProcessor, + serverAddress, + accessToken, + _deviceDiscovery, + _userDataManager, + _localization, + _mediaSourceManager); + + controller.Init(device); + + var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ?? + _dlnaManager.GetDefaultProfile(); + + _sessionManager.ReportCapabilities(sessionInfo.Id, new ClientCapabilities + { + PlayableMediaTypes = profile.GetSupportedMediaTypes(), + + SupportedCommands = new List + { + GeneralCommandType.VolumeDown.ToString(), + GeneralCommandType.VolumeUp.ToString(), + GeneralCommandType.Mute.ToString(), + GeneralCommandType.Unmute.ToString(), + GeneralCommandType.ToggleMute.ToString(), + GeneralCommandType.SetVolume.ToString(), + GeneralCommandType.SetAudioStreamIndex.ToString(), + GeneralCommandType.SetSubtitleStreamIndex.ToString() + }, + + SupportsMediaControl = true + }); + + _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName); + } } catch (Exception ex) { @@ -155,6 +183,12 @@ namespace MediaBrowser.Dlna.PlayTo public void Dispose() { _deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered; + + if (_clearNonRenderersTimer != null) + { + _clearNonRenderersTimer.Dispose(); + _clearNonRenderersTimer = null; + } } } } diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs index 2af9f8da91..e1f14bfa2c 100644 --- a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs +++ b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs @@ -4,8 +4,6 @@ namespace MediaBrowser.Dlna.PlayTo { public class PlaylistItem { - public int PlayState { get; set; } - public string StreamUrl { get; set; } public string Didl { get; set; } diff --git a/MediaBrowser.Model/Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs similarity index 98% rename from MediaBrowser.Model/Dlna/Profiles/DefaultProfile.cs rename to MediaBrowser.Dlna/Profiles/DefaultProfile.cs index c9db9fbf85..a243fd0118 100644 --- a/MediaBrowser.Model/Dlna/Profiles/DefaultProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs @@ -1,6 +1,7 @@ -using System.Xml.Serialization; +using MediaBrowser.Model.Dlna; +using System.Xml.Serialization; -namespace MediaBrowser.Model.Dlna.Profiles +namespace MediaBrowser.Dlna.Profiles { [XmlRoot("Profile")] public class DefaultProfile : DeviceProfile diff --git a/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs b/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs index 224ae7715a..f8451bdfd8 100644 --- a/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs b/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs index 4c07c2827c..585f8652e6 100644 --- a/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/DishHopperJoeyProfile.cs b/MediaBrowser.Dlna/Profiles/DishHopperJoeyProfile.cs index ab887a3bff..bd7b42d5d2 100644 --- a/MediaBrowser.Dlna/Profiles/DishHopperJoeyProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DishHopperJoeyProfile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs b/MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs index 1d011a2432..45cbbef6cb 100644 --- a/MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs +++ b/MediaBrowser.Dlna/Profiles/Foobar2000Profile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/LgTvProfile.cs b/MediaBrowser.Dlna/Profiles/LgTvProfile.cs index 8b887500e3..4ecfd3c5b9 100644 --- a/MediaBrowser.Dlna/Profiles/LgTvProfile.cs +++ b/MediaBrowser.Dlna/Profiles/LgTvProfile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs b/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs index 0565f6c932..e7542ea9e5 100644 --- a/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs +++ b/MediaBrowser.Dlna/Profiles/LinksysDMA2100Profile.cs @@ -1,7 +1,6 @@ using System.Xml.Serialization; using MediaBrowser.Controller.Dlna; using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/MediaMonkeyProfile.cs b/MediaBrowser.Dlna/Profiles/MediaMonkeyProfile.cs index a73c6ccf4b..7163252db2 100644 --- a/MediaBrowser.Dlna/Profiles/MediaMonkeyProfile.cs +++ b/MediaBrowser.Dlna/Profiles/MediaMonkeyProfile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs b/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs index 99dec2bc6c..9e51c2895c 100644 --- a/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs +++ b/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs b/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs index 883af57d29..c98609393a 100644 --- a/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs +++ b/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dlna.Profiles; using System.Xml.Serialization; namespace MediaBrowser.Dlna.Profiles diff --git a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs index 970995b7d9..396dd64892 100644 --- a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs +++ b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dlna.Profiles; using System.Xml.Serialization; namespace MediaBrowser.Dlna.Profiles diff --git a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs index ed325e3018..baaccba5a7 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayer2013Profile.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dlna.Profiles; using System.Xml.Serialization; namespace MediaBrowser.Dlna.Profiles diff --git a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs index 6802bf6318..d2e6d7c15f 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs index 46549040f3..71f8772325 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs index d9891e87be..0b157ae336 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs index 85643bace6..0d974cbc0e 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs index 0f7151a840..ac4cb21312 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs b/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs index e92b0acfef..a99d7775aa 100644 --- a/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs index 553d77c7f7..a26c439113 100644 --- a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs +++ b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dlna.Profiles; using System.Xml.Serialization; namespace MediaBrowser.Dlna.Profiles diff --git a/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs index e3dd832248..62c06f8f57 100644 --- a/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs +++ b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Dlna; using System.Xml.Serialization; -using MediaBrowser.Model.Dlna.Profiles; namespace MediaBrowser.Dlna.Profiles { diff --git a/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs b/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs index 3427d75f70..4c3b049bdd 100644 --- a/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs +++ b/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dlna.Profiles; using System.Xml.Serialization; namespace MediaBrowser.Dlna.Profiles diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs index a90c6dc01e..3dd482e647 100644 --- a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs +++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; @@ -47,12 +48,13 @@ namespace MediaBrowser.Dlna.Ssdp if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any()) continue; - - var ipV4 = network.GetIPProperties().GetIPv4Properties(); + + var properties = network.GetIPProperties(); + var ipV4 = properties.GetIPv4Properties(); if (null == ipV4) continue; - var localIps = network.GetIPProperties().UnicastAddresses + var localIps = properties.UnicastAddresses .Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork) .Select(i => i.Address) .ToList(); @@ -182,7 +184,6 @@ namespace MediaBrowser.Dlna.Ssdp } }, _tokenSource.Token, TaskCreationOptions.LongRunning); - } private Socket GetMulticastSocket(IPAddress localIpAddress, EndPoint localEndpoint) diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index 73bc4984c8..5b3746aeb4 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -1,6 +1,8 @@ -using MediaBrowser.Common.Configuration; +using MediaBrowser.Common; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; using MediaBrowser.Dlna.Server; using MediaBrowser.Model.Logging; using System; @@ -16,7 +18,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Dlna.Ssdp { - public class SsdpHandler : IDisposable + public class SsdpHandler : IDisposable, ISsdpHandler { private Socket _socket; @@ -39,13 +41,39 @@ namespace MediaBrowser.Dlna.Ssdp private bool _isDisposed; private readonly ConcurrentDictionary> _devices = new ConcurrentDictionary>(); - public SsdpHandler(ILogger logger, IServerConfigurationManager config, string serverSignature) + private readonly IApplicationHost _appHost; + + public SsdpHandler(ILogger logger, IServerConfigurationManager config, IApplicationHost appHost) { _logger = logger; _config = config; - _serverSignature = serverSignature; + _appHost = appHost; _config.NamedConfigurationUpdated += _config_ConfigurationUpdated; + _serverSignature = GenerateServerSignature(); + } + + private string GenerateServerSignature() + { + var os = Environment.OSVersion; + var pstring = os.Platform.ToString(); + switch (os.Platform) + { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + pstring = "WIN"; + break; + } + + return String.Format( + "{0}{1}/{2}.{3} UPnP/1.0 DLNADOC/1.5 MediaBrowser/{4}", + pstring, + IntPtr.Size * 8, + os.Version.Major, + os.Version.Minor, + _appHost.ApplicationVersion + ); } void _config_ConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) @@ -116,13 +144,14 @@ namespace MediaBrowser.Dlna.Ssdp // Seconds to delay response values["MX"] = "3"; - SendDatagram("M-SEARCH * HTTP/1.1", values, localIp); + // UDP is unreliable, so send 3 requests at a time (per Upnp spec, sec 1.1.2) + SendDatagram("M-SEARCH * HTTP/1.1", values, localIp, 2); } public void SendDatagram(string header, Dictionary values, EndPoint localAddress, - int sendCount = 1) + int sendCount) { SendDatagram(header, values, _ssdpEndp, localAddress, false, sendCount); } @@ -132,7 +161,7 @@ namespace MediaBrowser.Dlna.Ssdp EndPoint endpoint, EndPoint localAddress, bool ignoreBindFailure, - int sendCount = 1) + int sendCount) { var msg = new SsdpMessageBuilder().BuildMessage(header, values); var queued = false; @@ -376,11 +405,11 @@ namespace MediaBrowser.Dlna.Ssdp } foreach (var d in RegisteredDevices) { - NotifyDevice(d, "alive"); + NotifyDevice(d, "alive", 1); } } - private void NotifyDevice(UpnpDevice dev, string type, int sendCount = 1) + private void NotifyDevice(UpnpDevice dev, string type, int sendCount) { const string header = "NOTIFY * HTTP/1.1"; diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHelper.cs b/MediaBrowser.Dlna/Ssdp/SsdpHelper.cs index 707f0b8777..d196e98518 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHelper.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHelper.cs @@ -1,4 +1,5 @@ -using System; +using MediaBrowser.Controller.Dlna; +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -34,7 +35,8 @@ namespace MediaBrowser.Dlna.Ssdp return new SsdpMessageEventArgs { Method = method, - Headers = headers + Headers = headers, + Message = data }; } } diff --git a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs index a12724ff72..02457ee73c 100644 --- a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs @@ -50,6 +50,14 @@ namespace MediaBrowser.LocalMetadata.Parsers } break; + case "Shares": + + using (var subReader = reader.ReadSubtree()) + { + FetchFromSharesNode(subReader, item); + } + break; + default: base.FetchDataFromXmlNode(reader, item); break; @@ -92,5 +100,42 @@ namespace MediaBrowser.LocalMetadata.Parsers item.LinkedChildren = list; } + + private void FetchFromSharesNode(XmlReader reader, Playlist item) + { + reader.MoveToContent(); + + var list = new List(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Share": + { + using (var subReader = reader.ReadSubtree()) + { + var child = GetShare(subReader); + + if (child != null) + { + list.Add(child); + } + } + + break; + } + + default: + reader.Skip(); + break; + } + } + } + + item.Shares = list; + } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index ea3cc6d898..44b85a77df 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -716,8 +716,6 @@ namespace MediaBrowser.MediaEncoding.Encoder profile.GetVideoMediaProfile(outputContainer, audioCodec, videoCodec, - state.OutputAudioBitrate, - state.OutputAudioChannels, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index d076a5b6ba..a01f37f91d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -119,7 +119,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var extractKeyFrameInterval = request.ExtractKeyFrameInterval && request.Protocol == MediaProtocol.File && request.VideoType == VideoType.VideoFile; return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, extractKeyFrameInterval, - GetProbeSizeArgument(inputFiles, request.Protocol), request.MediaType == DlnaProfileType.Audio, cancellationToken); + GetProbeSizeArgument(inputFiles, request.Protocol), request.MediaType == DlnaProfileType.Audio, request.VideoType, cancellationToken); } /// @@ -155,6 +155,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// if set to true [extract key frame interval]. /// The probe size argument. /// if set to true [is audio]. + /// Type of the video. /// The cancellation token. /// Task{MediaInfoResult}. /// @@ -165,6 +166,7 @@ namespace MediaBrowser.MediaEncoding.Encoder bool extractKeyFrameInterval, string probeSizeArgument, bool isAudio, + VideoType videoType, CancellationToken cancellationToken) { var args = extractChapters @@ -236,7 +238,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, isAudio, primaryPath, protocol); + var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); if (extractKeyFrameInterval && mediaInfo.RunTimeTicks.HasValue) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 267ff875a9..2cd855e966 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.MediaEncoding.Probing _fileSystem = fileSystem; } - public Model.MediaInfo.MediaInfo GetMediaInfo(InternalMediaInfoResult data, bool isAudio, string path, MediaProtocol protocol) + public Model.MediaInfo.MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType videoType, bool isAudio, string path, MediaProtocol protocol) { var info = new Model.MediaInfo.MediaInfo { @@ -79,7 +79,7 @@ namespace MediaBrowser.MediaEncoding.Probing var videoStream = info.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); - if (videoStream != null) + if (videoStream != null && videoType == VideoType.VideoFile) { UpdateFromMediaInfo(info, videoStream); } @@ -146,7 +146,44 @@ namespace MediaBrowser.MediaEncoding.Probing // string.Equals(stream.AspectRatio, "2.35:1", StringComparison.OrdinalIgnoreCase) || // string.Equals(stream.AspectRatio, "2.40:1", StringComparison.OrdinalIgnoreCase); - stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase); + if (string.Equals(streamInfo.sample_aspect_ratio, "1:1", StringComparison.OrdinalIgnoreCase)) + { + stream.IsAnamorphic = false; + } + else if (!((string.IsNullOrWhiteSpace(streamInfo.sample_aspect_ratio) || string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)))) + { + stream.IsAnamorphic = true; + } + else if (string.IsNullOrWhiteSpace(streamInfo.display_aspect_ratio) || string.Equals(streamInfo.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) + { + stream.IsAnamorphic = false; + } + else + { + var ratioParts = streamInfo.display_aspect_ratio.Split(':'); + if (ratioParts.Length != 2) + { + stream.IsAnamorphic = false; + } + else + { + int ratio0; + int ratio1; + if (!Int32.TryParse(ratioParts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out ratio0)) + { + stream.IsAnamorphic = false; + } + else if (!Int32.TryParse(ratioParts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out ratio1)) + { + stream.IsAnamorphic = false; + } + else + { + stream.IsAnamorphic = ((streamInfo.width * ratio1) != (stream.Height * ratio0)); + } + } + } + } else { @@ -863,12 +900,14 @@ namespace MediaBrowser.MediaEncoding.Probing private void UpdateFromMediaInfo(MediaSourceInfo video, MediaStream videoStream) { - if (video.VideoType == VideoType.VideoFile && video.Protocol == MediaProtocol.File) + if (video.Protocol == MediaProtocol.File) { if (videoStream != null) { try { + _logger.Debug("Running MediaInfo against {0}", video.Path); + var result = new MediaInfoLib().GetVideoInfo(video.Path); videoStream.IsCabac = result.IsCabac ?? videoStream.IsCabac; diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 87378fd5a7..f70fe628eb 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -383,9 +383,6 @@ Dlna\ProfileConditionValue.cs - - Dlna\Profiles\DefaultProfile.cs - Dlna\ResolutionConfiguration.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 61057e5bbb..bb8b096827 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -348,9 +348,6 @@ Dlna\ProfileConditionValue.cs - - Dlna\Profiles\DefaultProfile.cs - Dlna\ResolutionConfiguration.cs diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 8c7ca0ad97..026e65ec45 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -1499,5 +1499,11 @@ namespace MediaBrowser.Model.ApiClient /// The item ids. /// Task. Task CancelSyncLibraryItems(string targetId, IEnumerable itemIds); + /// + /// Gets the supported bitrate. + /// + /// The cancellation token. + /// Task<System.Int32>. + Task GetSupportedBitrate(CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs index 19620890e7..ca9db0bf08 100644 --- a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs +++ b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs @@ -50,6 +50,12 @@ namespace MediaBrowser.Model.Configuration /// The cache path. public string CachePath { get; set; } + /// + /// Gets or sets a value indicating whether [enable custom path sub folders]. + /// + /// true if [enable custom path sub folders]; otherwise, false. + public bool EnableCustomPathSubFolders { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index c44a7c94d2..afd67eb153 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Model.Configuration DownMixAudioBoost = 2; EncodingQuality = EncodingQuality.Auto; EnableThrottling = true; - ThrottleThresholdSeconds = 90; + ThrottleThresholdSeconds = 120; } } } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index ac9bd6b08f..8a3a2a3e43 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -185,8 +185,6 @@ namespace MediaBrowser.Model.Configuration public MetadataOptions[] MetadataOptions { get; set; } - public string TranscodingTempPath { get; set; } - public bool EnableAutomaticRestart { get; set; } public bool EnableRealtimeMonitor { get; set; } diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index 3769634440..793036f403 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -7,8 +7,6 @@ namespace MediaBrowser.Model.Dlna public class ConditionProcessor { public bool IsVideoConditionSatisfied(ProfileCondition condition, - int? audioBitrate, - int? audioChannels, int? width, int? height, int? bitDepth, @@ -44,10 +42,6 @@ namespace MediaBrowser.Model.Dlna return IsConditionSatisfied(condition, videoProfile); case ProfileConditionValue.PacketLength: return IsConditionSatisfied(condition, packetLength); - case ProfileConditionValue.AudioBitrate: - return IsConditionSatisfied(condition, audioBitrate); - case ProfileConditionValue.AudioChannels: - return IsConditionSatisfied(condition, audioChannels); case ProfileConditionValue.VideoBitDepth: return IsConditionSatisfied(condition, bitDepth); case ProfileConditionValue.VideoBitrate: diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index 8161f1c268..3a798e3fe7 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -105,8 +105,6 @@ namespace MediaBrowser.Model.Dlna int? height, int? bitDepth, int? videoBitrate, - int? audioChannels, - int? audioBitrate, TransportStreamTimestamp timestamp, bool isDirectStream, long? runtimeTicks, @@ -147,8 +145,6 @@ namespace MediaBrowser.Model.Dlna ResponseProfile mediaProfile = _profile.GetVideoMediaProfile(container, audioCodec, videoCodec, - audioBitrate, - audioChannels, width, height, bitDepth, diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index 8b9b2edf36..a78724bf2d 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -111,6 +111,10 @@ namespace MediaBrowser.Model.Dlna XmlRootAttributes = new XmlAttribute[] { }; SupportedMediaTypes = "Audio,Photo,Video"; + MaxStreamingBitrate = 8000000; + MaxStaticBitrate = 8000000; + MusicStreamingTranscodingBitrate = 128000; + MusicSyncBitrate = 128000; } public List GetSupportedMediaTypes() @@ -268,8 +272,6 @@ namespace MediaBrowser.Model.Dlna public ResponseProfile GetVideoMediaProfile(string container, string audioCodec, string videoCodec, - int? audioBitrate, - int? audioChannels, int? width, int? height, int? bitDepth, @@ -317,7 +319,7 @@ namespace MediaBrowser.Model.Dlna var anyOff = false; foreach (ProfileCondition c in i.Conditions) { - if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams)) + if (!conditionProcessor.IsVideoConditionSatisfied(c, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams)) { anyOff = true; break; diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 30da8bb4c9..715752d053 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -456,7 +456,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue); } - int audioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec); + int audioBitrate = GetAudioBitrate(options.GetMaxBitrate(), playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec, audioStream); playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate); int? maxBitrateSetting = options.GetMaxBitrate(); @@ -479,17 +479,35 @@ namespace MediaBrowser.Model.Dlna return playlistItem; } - private int GetAudioBitrate(int? channels, string codec) + private int GetAudioBitrate(int? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream) { - if (channels.HasValue) + var defaultBitrate = 128000; + + if (targetAudioChannels.HasValue) { - if (channels.Value >= 5) + if (targetAudioChannels.Value >= 5 && (maxTotalBitrate ?? 0) >= 1500000) { - return 320000; + defaultBitrate = 320000; } } - return 128000; + int encoderAudioBitrateLimit = int.MaxValue; + + if (audioStream != null) + { + // Seeing webm encoding failures when source has 1 audio channel and 22k bitrate. + // Any attempts to transcode over 64k will fail + if (audioStream.Channels.HasValue && + audioStream.Channels.Value == 1) + { + if ((audioStream.BitRate ?? 0) < 64000) + { + encoderAudioBitrateLimit = 64000; + } + } + } + + return Math.Min(defaultBitrate, encoderAudioBitrateLimit); } private PlayMethod? GetVideoDirectPlayProfile(DeviceProfile profile, @@ -560,7 +578,7 @@ namespace MediaBrowser.Model.Dlna // Check container conditions foreach (ProfileCondition i in conditions) { - if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams)) + if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams)) { LogConditionFailure(profile, "VideoContainerProfile", i, mediaSource); @@ -593,7 +611,7 @@ namespace MediaBrowser.Model.Dlna foreach (ProfileCondition i in conditions) { - if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams)) + if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams)) { LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource); diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index b062bc240f..645c1c7d02 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -233,6 +233,11 @@ namespace MediaBrowser.Model.Dlna string liveStreamId = item.MediaSource == null ? null : item.MediaSource.LiveStreamId; list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); + if (isDlna) + { + list.Add(new NameValuePair("ItemId", item.ItemId)); + } + return list; } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index af0cbb1665..340bd94623 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -130,7 +130,6 @@ - diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index 77b3dc0ee1..0362b7aedd 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -199,11 +199,6 @@ /// The series studio /// SeriesStudio, - - /// - /// The soundtrack ids - /// - SoundtrackIds, /// /// The sort name of the item diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs index 92327c9bc3..69b78b5f12 100644 --- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs +++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs @@ -38,10 +38,6 @@ namespace MediaBrowser.Providers.BoxSets list.AddRange(target.LinkedChildren.Where(i => i.Type == LinkedChildType.Manual)); target.LinkedChildren = list; - } - - if (replaceData || target.Shares.Count == 0) - { target.Shares = source.Shares; } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 334e148506..71bc9c0651 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -360,7 +360,7 @@ namespace MediaBrowser.Providers.Manager // If replacing all metadata, run internet providers first if (options.ReplaceAllMetadata) { - var remoteResult = await ExecuteRemoteProviders(item, temp, logName, id, providers.OfType>(), cancellationToken) + var remoteResult = await ExecuteRemoteProviders(temp, logName, id, providers.OfType>(), cancellationToken) .ConfigureAwait(false); refreshResult.UpdateType = refreshResult.UpdateType | remoteResult.UpdateType; @@ -372,9 +372,8 @@ namespace MediaBrowser.Providers.Manager var hasLocalMetadata = false; var userDataList = new List(); - var localProviders = providers.OfType>().ToList(); - foreach (var provider in localProviders) + foreach (var provider in providers.OfType>().ToList()) { var providerName = provider.GetType().Name; Logger.Debug("Running {0} for {1}", providerName, logName); @@ -433,7 +432,7 @@ namespace MediaBrowser.Providers.Manager // Local metadata is king - if any is found don't run remote providers if (!options.ReplaceAllMetadata && (!hasLocalMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh)) { - var remoteResult = await ExecuteRemoteProviders(item, temp, logName, id, providers.OfType>(), cancellationToken) + var remoteResult = await ExecuteRemoteProviders(temp, logName, id, providers.OfType>(), cancellationToken) .ConfigureAwait(false); refreshResult.UpdateType = refreshResult.UpdateType | remoteResult.UpdateType; @@ -447,17 +446,15 @@ namespace MediaBrowser.Providers.Manager if (providers.Any(i => !(i is ICustomMetadataProvider))) { - // If no local providers and doing a full refresh, take data from item itself - if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh && - localProviders.Count == 0 && - refreshResult.UpdateType > ItemUpdateType.None) - { - // TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields - MergeData(item, temp, new List(), false, true); - } - if (refreshResult.UpdateType > ItemUpdateType.None) { + // If no local metadata, take data from item itself + if (!hasLocalMetadata) + { + // TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields + MergeData(item, temp, new List(), false, true); + } + MergeData(temp, item, item.LockedFields, true, true); } } @@ -529,7 +526,7 @@ namespace MediaBrowser.Providers.Manager return new TItemType(); } - private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, string logName, TIdType id, IEnumerable> providers, CancellationToken cancellationToken) + private async Task ExecuteRemoteProviders(TItemType temp, string logName, TIdType id, IEnumerable> providers, CancellationToken cancellationToken) { var refreshResult = new RefreshResult(); diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs index 9741b772a5..c04f805495 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs @@ -122,7 +122,7 @@ namespace MediaBrowser.Providers.Music if (singleResult != null) { musicBrainzId = singleResult.GetProviderId(MetadataProviders.MusicBrainzArtist); - result.Item.Name = singleResult.Name; + //result.Item.Name = singleResult.Name; } } diff --git a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs index 2e407f10ca..c53a89db73 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs @@ -33,14 +33,10 @@ namespace MediaBrowser.Providers.Playlists target.PlaylistMediaType = source.PlaylistMediaType; } - if (replaceData || target.Shares.Count == 0) - { - target.Shares = source.Shares; - } - if (mergeMetadataSettings) { target.LinkedChildren = source.LinkedChildren; + target.Shares = source.Shares; } } } diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs index faf73c0592..796d5f6515 100644 --- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs +++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs @@ -81,7 +81,8 @@ namespace MediaBrowser.Server.Implementations.Collections ProviderIds = options.ProviderIds, Shares = options.UserIds.Select(i => new Share { - UserId = i.ToString("N") + UserId = i.ToString("N"), + CanEdit = true }).ToList() }; diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index bb9e9057a3..bf199503be 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -101,9 +101,22 @@ namespace MediaBrowser.Server.Implementations.Configuration /// private void UpdateMetadataPath() { - ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = string.IsNullOrEmpty(Configuration.MetadataPath) ? - GetInternalMetadataPath() : - Configuration.MetadataPath; + string metadataPath; + + if (string.IsNullOrWhiteSpace(Configuration.MetadataPath)) + { + metadataPath = GetInternalMetadataPath(); + } + else if (Configuration.EnableCustomPathSubFolders) + { + metadataPath = Path.Combine(Configuration.MetadataPath, "metadata"); + } + else + { + metadataPath = Configuration.MetadataPath; + } + + ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = metadataPath; if (Configuration.MergeMetadataAndImagesByName) { @@ -130,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.Configuration ((ServerApplicationPaths)ApplicationPaths).TranscodingTempPath = string.IsNullOrEmpty(encodingConfig.TranscodingTempPath) ? null : - encodingConfig.TranscodingTempPath; + Path.Combine(encodingConfig.TranscodingTempPath, "transcoding-temp"); } protected override void OnNamedConfigurationUpdated(string key, object configuration) diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index f44b7b5a84..402bd4d985 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -325,18 +325,6 @@ namespace MediaBrowser.Server.Implementations.Dto AttachBasicFields(dto, item, owner, options); - if (fields.Contains(ItemFields.SoundtrackIds)) - { - var hasSoundtracks = item as IHasSoundtracks; - - if (hasSoundtracks != null) - { - dto.SoundtrackIds = hasSoundtracks.SoundtrackIds - .Select(i => i.ToString("N")) - .ToArray(); - } - } - var playlist = item as Playlist; if (playlist != null) { diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 3fa0df7608..b5b63181a0 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -1,5 +1,6 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; using Mono.Nat; @@ -7,6 +8,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Net; using System.Text; using System.Threading; @@ -17,15 +19,17 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly IServerApplicationHost _appHost; private readonly ILogger _logger; private readonly IServerConfigurationManager _config; + private readonly ISsdpHandler _ssdp; private Timer _timer; private bool _isStarted; - public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config) + public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp) { _logger = logmanager.GetLogger("PortMapper"); _appHost = appHost; _config = config; + _ssdp = ssdp; } private string _lastConfigIdentifier; @@ -75,7 +79,10 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private void Start() { _logger.Debug("Starting NAT discovery"); - + NatUtility.EnabledProtocols = new List + { + NatProtocol.Pmp + }; NatUtility.DeviceFound += NatUtility_DeviceFound; // Mono.Nat does never rise this event. The event is there however it is useless. @@ -88,26 +95,38 @@ namespace MediaBrowser.Server.Implementations.EntryPoints NatUtility.UnhandledException += NatUtility_UnhandledException; NatUtility.StartDiscovery(); - _timer = new Timer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3)); + _timer = new Timer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); + + _ssdp.MessageReceived += _ssdp_MessageReceived; _lastConfigIdentifier = GetConfigIdentifier(); _isStarted = true; } + void _ssdp_MessageReceived(object sender, SsdpMessageEventArgs e) + { + var endpoint = e.EndPoint as IPEndPoint; + + if (endpoint != null && e.LocalIp != null) + { + NatUtility.Handle(e.LocalIp, e.Message, endpoint, NatProtocol.Upnp); + } + } + void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) { - //var ex = e.ExceptionObject as Exception; + var ex = e.ExceptionObject as Exception; - //if (ex == null) - //{ - // _logger.Error("Unidentified error reported by Mono.Nat"); - //} - //else - //{ - // // Seeing some blank exceptions coming through here - // _logger.ErrorException("Error reported by Mono.Nat: ", ex); - //} + if (ex == null) + { + //_logger.Error("Unidentified error reported by Mono.Nat"); + } + else + { + // Seeing some blank exceptions coming through here + //_logger.ErrorException("Error reported by Mono.Nat: ", ex); + } } void NatUtility_DeviceFound(object sender, DeviceEventArgs e) @@ -180,6 +199,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _timer = null; } + _ssdp.MessageReceived -= _ssdp_MessageReceived; + try { // This is not a significant improvement diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 106e3c76b8..e134670e39 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -8,7 +8,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.Logging; -using MediaBrowser.Naming.IO; using MediaBrowser.Server.Implementations.Library; using MediaBrowser.Server.Implementations.Logging; using System; @@ -60,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var namingOptions = ((LibraryManager) _libraryManager).GetNamingOptions(); var resolver = new Naming.TV.EpisodeResolver(namingOptions, new PatternsLogger()); - var episodeInfo = resolver.Resolve(path, FileInfoType.File) ?? + var episodeInfo = resolver.Resolve(path, false) ?? new Naming.TV.EpisodeInfo(); var seriesName = episodeInfo.SeriesName; diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index dcdf2aa7dc..bafbecbc57 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Extensions; +using Interfaces.IO; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Common.Progress; using MediaBrowser.Common.ScheduledTasks; @@ -17,7 +18,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Naming.Audio; using MediaBrowser.Naming.Common; -using MediaBrowser.Naming.IO; using MediaBrowser.Naming.TV; using MediaBrowser.Naming.Video; using MediaBrowser.Server.Implementations.Library.Validators; @@ -1767,14 +1767,13 @@ namespace MediaBrowser.Server.Implementations.Library var resolver = new EpisodeResolver(GetNamingOptions(), new PatternsLogger()); - var fileType = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd || episode.VideoType == VideoType.HdDvd ? - FileInfoType.Directory : - FileInfoType.File; + var isFolder = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd || + episode.VideoType == VideoType.HdDvd; var locationType = episode.LocationType; var episodeInfo = locationType == LocationType.FileSystem || locationType == LocationType.Offline ? - resolver.Resolve(episode.Path, fileType) : + resolver.Resolve(episode.Path, isFolder) : new Naming.TV.EpisodeInfo(); if (episodeInfo == null) @@ -1928,10 +1927,10 @@ namespace MediaBrowser.Server.Implementations.Library var videoListResolver = new VideoListResolver(GetNamingOptions(), new PatternsLogger()); - var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new PortableFileInfo + var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new FileMetadata { - FullName = i.FullName, - Type = GetFileType(i) + Id = i.FullName, + IsFolder = ((i.Attributes & FileAttributes.Directory) == FileAttributes.Directory) }).ToList()); @@ -1962,16 +1961,6 @@ namespace MediaBrowser.Server.Implementations.Library }).OrderBy(i => i.Path).ToList(); } - private FileInfoType GetFileType(FileSystemInfo info) - { - if ((info.Attributes & FileAttributes.Directory) == FileAttributes.Directory) - { - return FileInfoType.Directory; - } - - return FileInfoType.File; - } - public IEnumerable /// The name. - /// if set to true [check identifier]. /// User. - private User InstantiateNewUser(string name, bool checkId) + private User InstantiateNewUser(string name) { - var id = ("MBUser" + name).GetMD5(); - - if (checkId && Users.Select(i => i.Id).Contains(id)) - { - id = Guid.NewGuid(); - } - return new User { Name = name, - Id = id, + Id = Guid.NewGuid(), DateCreated = DateTime.UtcNow, DateModified = DateTime.UtcNow, UsesIdForConfigurationPath = true diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 51f23984a8..6aea6fcaaf 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1040,7 +1040,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv innerProgress.RegisterAction(p => progress.Report(90 + (p * .1))); await CleanDatabaseInternal(progress, cancellationToken).ConfigureAwait(false); - RefreshIfNeeded(GetPrograms().Where(i => (i.StartDate - DateTime.UtcNow).TotalDays <= 1).ToList()); + RefreshIfNeeded(GetPrograms().ToList()); } private async Task RefreshChannelsInternal(IProgress progress, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index 49ca737fee..c15e520e26 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -440,6 +440,7 @@ "HeaderVideo": "Video", "HeaderRuntime": "Runtime", "HeaderCommunityRating": "Community rating", + "HeaderPasswordReset": "Password Reset", "HeaderParentalRating": "Parental rating", "HeaderReleaseDate": "Release date", "HeaderDateAdded": "Date added", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json index ecdd36c0ea..918487d35c 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json @@ -602,17 +602,17 @@ "ValueArtist": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b: {0}", "ValueArtists": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440: {0}", "HeaderTags": "\u0422\u0435\u0433\u0442\u0435\u0440", - "MediaInfoCameraMake": "\u041a\u0430\u043c\u0435\u0440\u0430 \u04e9\u043d\u0434\u0456\u0440\u0443\u0448\u0456\u0441\u0456", + "MediaInfoCameraMake": "\u041a\u0430\u043c\u0435\u0440\u0430 \u04e9\u043d\u0434-\u0441\u0456", "MediaInfoCameraModel": "\u041a\u0430\u043c\u0435\u0440\u0430 \u043c\u043e\u0434\u0435\u043b\u0456", "MediaInfoAltitude": "\u0411\u0438\u0456\u043a\u0442\u0456\u0433\u0456", "MediaInfoAperture": "\u0414\u0438\u0430\u0444\u0440\u0430\u0433\u043c\u0430\u0441\u044b", - "MediaInfoExposureTime": "\u042d\u043a\u0441\u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0443\u0430\u049b\u044b\u0442\u044b", - "MediaInfoFocalLength": "\u0422\u043e\u0493\u044b\u0441 \u049b\u0430\u0448\u044b\u049b\u0442\u044b\u0493\u044b", + "MediaInfoExposureTime": "\u042d\u043a\u0441\u043f-\u0446\u0438\u044f \u0443\u0430\u049b\u044b\u0442\u044b", + "MediaInfoFocalLength": "\u0422\u043e\u0493\u044b\u0441 \u049b\u0430\u0448-\u0493\u044b", "MediaInfoOrientation": "\u0411\u0430\u0493\u0434\u0430\u0440\u044b", - "MediaInfoIsoSpeedRating": "ISO \u0436\u0430\u0440\u044b\u049b\u0442\u0430\u043d \u049b\u043e\u0440\u044b\u043d\u0493\u044b\u0448\u0442\u044b\u0493\u044b", + "MediaInfoIsoSpeedRating": "ISO \u0436\u0430\u0440. \u049b\u043e\u0440\u044b\u043d-\u0493\u044b", "MediaInfoLatitude": "\u0415\u043d\u0434\u0456\u0433\u0456", "MediaInfoLongitude": "\u0411\u043e\u0439\u043b\u044b\u0493\u044b", - "MediaInfoShutterSpeed": "\u0411\u0435\u043a\u0456\u0442\u043f\u0435 \u0436\u044b\u043b\u0434\u0430\u043c\u0434\u044b\u0493\u044b", + "MediaInfoShutterSpeed": "\u041e\u0431\u0442-\u0440 \u0436\u044b\u043b\u0434-\u0493\u044b", "MediaInfoSoftware": "\u0411\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b", "HeaderIfYouLikeCheckTheseOut": "\u0415\u0433\u0435\u0440 {0} \u04b1\u043d\u0430\u0441\u0430, \u0431\u04b1\u043b\u0430\u0440\u0434\u044b \u0431\u0430\u0439\u049b\u0430\u04a3\u044b\u0437...", "HeaderPlotKeywords": "\u0421\u044e\u0436\u0435\u0442\u0442\u0456\u043d \u043a\u0456\u043b\u0442 \u0441\u04e9\u0437\u0434\u0435\u0440\u0456", @@ -636,21 +636,21 @@ "MediaInfoForced": "\u041c\u04d9\u0436\u0431\u04af\u0440\u043b\u0456", "MediaInfoExternal": "\u0421\u044b\u0440\u0442\u049b\u044b", "MediaInfoTimestamp": "\u0423\u0430\u049b\u044b\u0442 \u0431\u0435\u043b\u0433\u0456\u0441\u0456", - "MediaInfoPixelFormat": "\u041f\u0438\u043a\u0441\u0435\u043b \u043f\u0456\u0448\u0456\u043c\u0456", - "MediaInfoBitDepth": "\u0411\u0438\u0442\u0442\u0456\u043a \u0442\u0435\u0440\u0435\u04a3\u0434\u0456\u0433\u0456", + "MediaInfoPixelFormat": "\u041f\u0438\u043a\u0441. \u043f\u0456\u0448\u0456\u043c\u0456", + "MediaInfoBitDepth": "\u0422\u04af\u0441 \u0442\u0435\u0440\u0435\u04a3\u0434\u0456\u0433\u0456", "MediaInfoSampleRate": "\u04ae\u043b\u0433\u0456 \u0436\u0438\u0456\u043b\u0456\u0433\u0456", "MediaInfoBitrate": "\u049a\u0430\u0440\u049b\u044b\u043d\u044b", "MediaInfoChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440\u044b", - "MediaInfoLayout": "\u049a\u04b1\u0440\u044b\u043b\u044b\u043c\u044b", + "MediaInfoLayout": "\u0416\u0430\u0439\u043b\u0430\u0441\u0442\u044b\u0440\u0443\u044b", "MediaInfoLanguage": "\u0422\u0456\u043b\u0456", "MediaInfoCodec": "\u041a\u043e\u0434\u0435\u043a", "MediaInfoProfile": "\u041f\u0440\u043e\u0444\u0430\u0439\u043b\u044b", "MediaInfoLevel": "\u0414\u0435\u04a3\u0433\u0435\u0439\u0456", "MediaInfoAspectRatio": "\u041f\u0456\u0448\u0456\u043c\u0434\u0456\u043a \u0430\u0440\u0430\u049b\u0430\u0442\u044b\u043d\u0430\u0441\u044b", "MediaInfoResolution": "\u0410\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u044b\u043c\u0434\u044b\u0493\u044b", - "MediaInfoAnamorphic": "\u0410\u043d\u0430\u043c\u043e\u0440\u0444\u0442\u044b", - "MediaInfoInterlaced": "\u041a\u0435\u0437\u0435\u043a\u0442\u0435\u0441\u0435\u0442\u0456\u043d", - "MediaInfoFramerate": "\u041a\u0430\u0434\u0440 \u0436\u044b\u043b\u0434\u0430\u043c\u0434\u044b\u0493\u044b:", + "MediaInfoAnamorphic": "\u0410\u043d\u0430\u043c\u043e\u0440\u0444\u0442\u044b\u049b", + "MediaInfoInterlaced": "\u041a\u0435\u0437\u0435\u043a\u0442\u0435\u0441\u0443\u043b\u0456\u043a", + "MediaInfoFramerate": "\u041a\u0430\u0434\u0440 \u0436\u044b\u043b\u0434-\u0493\u044b", "MediaInfoStreamTypeAudio": "\u0414\u044b\u0431\u044b\u0441", "MediaInfoStreamTypeData": "\u0414\u0435\u0440\u0435\u043a\u0442\u0435\u0440", "MediaInfoStreamTypeVideo": "\u0411\u0435\u0439\u043d\u0435", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json index d83de9d684..278c468672 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json @@ -123,7 +123,7 @@ "LabelFree": "Gratis", "HeaderPlaybackError": "Afspeel Fout", "MessagePlaybackErrorNotAllowed": "U bent niet bevoegd om deze content af te spelen. Neem contact op met uw systeembeheerder voor meer informatie.", - "MessagePlaybackErrorNoCompatibleStream": "Geen compatibele streams beschikbaar. Probeer het later opnieuw.", + "MessagePlaybackErrorNoCompatibleStream": "Geen compatibele streams beschikbaar. Probeer het later opnieuw of neem contact op met de serverbeheerder.", "MessagePlaybackErrorRateLimitExceeded": "Je afspeel rate limiet is overschreden. Neem contact op met de beheerder van de server voor details.", "MessagePlaybackErrorPlaceHolder": "De gekozen content is niet af te spelen vanaf dit apparaat.", "HeaderSelectAudio": "Selecteer Audio", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json index 7e9b1811d0..75382b5cd1 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json @@ -119,7 +119,7 @@ "MessageDeleteTaskTrigger": "Deseja realmente excluir este disparador de tarefa?", "MessageNoPluginsInstalled": "Voc\u00ea n\u00e3o possui plugins instalados.", "LabelVersionInstalled": "{0} instalado", - "LabelNumberReviews": "{0} Cr\u00edticas", + "LabelNumberReviews": "{0} Avalia\u00e7\u00f5es", "LabelFree": "Gr\u00e1tis", "HeaderPlaybackError": "Erro na Reprodu\u00e7\u00e3o", "MessagePlaybackErrorNotAllowed": "Voc\u00ea n\u00e3o est\u00e1 autorizado a reproduzir este conte\u00fado. Por favor, entre em contato com o administrador do sistema para mais detalhes.", @@ -537,7 +537,7 @@ "MessageFeatureIncludedWithSupporter": "Voc\u00ea est\u00e1 registrado para este recurso e poder\u00e1 continuar usando-o com uma ades\u00e3o ativa de colaborador.", "MessageChangeRecurringPlanConfirm": "Depois de completar esta transa\u00e7\u00e3o voc\u00ea precisar\u00e1 cancelar sua doa\u00e7\u00e3o recorrente anterior dentro da conta do PayPal. Obrigado por colaborar com o Emby.", "MessageSupporterMembershipExpiredOn": "Sua ades\u00e3o de colaborador expirou em {0}.", - "MessageYouHaveALifetimeMembership": "Voc\u00ea possui uma ades\u00e3o de colaborador vital\u00edcia. Voc\u00ea pode fazer doa\u00e7\u00f5es adicionais individuais ou de forma recorrente, usando as op\u00e7\u00f5es abaixo. Obrigado por colaborar com o Embu.", + "MessageYouHaveALifetimeMembership": "Voc\u00ea possui uma ades\u00e3o de colaborador vital\u00edcia. Voc\u00ea pode fazer doa\u00e7\u00f5es adicionais individuais ou de forma recorrente, usando as op\u00e7\u00f5es abaixo. Obrigado por colaborar com o Emby.", "MessageYouHaveAnActiveRecurringMembership": "Voc\u00ea tem uma ades\u00e3o {0} ativa. Voc\u00ea pode atualizar seu plano usando as op\u00e7\u00f5es abaixo.", "ButtonDelete": "Excluir", "HeaderEmbyAccountAdded": "Conta do Emby Adicionada", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json index 7a1fc51156..02a774c20c 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json @@ -30,12 +30,12 @@ "NoPluginConfigurationMessage": "\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u0435 \u043d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.", "NoPluginsInstalledMessage": "\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430.", "BrowsePluginCatalogMessage": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0438\u0441\u044f \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c\u0438.", - "MessageKeyEmailedTo": "\u041a\u043b\u044e\u0447 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u042d-\u043f\u043e\u0447\u0442\u043e\u0439 \u043a {0}.", + "MessageKeyEmailedTo": "\u041a\u043b\u044e\u0447 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043d\u0430 {0}.", "MessageKeysLinked": "\u041a\u043b\u044e\u0447\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u044b.", "HeaderConfirmation": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435", "MessageKeyUpdated": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0431\u044b\u043b \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d.", "MessageKeyRemoved": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0451\u043d.", - "HeaderSupportTheTeam": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 Emby", + "HeaderSupportTheTeam": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 Emby", "TextEnjoyBonusFeatures": "\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u0431\u043e\u043d\u0443\u0441\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438", "TitleLiveTV": "\u0422\u0412-\u044d\u0444\u0438\u0440", "TitleSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f", @@ -414,7 +414,7 @@ "ButtonNew": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c", "MessageInternetExplorerWebm": "\u0414\u043b\u044f \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432 Internet Explorer, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f WebM.", "HeaderVideoError": "\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0438\u0434\u0435\u043e", - "ButtonAddToPlaylist": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u0441\u043f\u0438\u0441\u043a\u0443 \u0432\u043e\u0441\u043f\u0440-\u0438\u044f", + "ButtonAddToPlaylist": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442", "HeaderAddToPlaylist": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a \u0441\u043f\u0438\u0441\u043a\u0443 \u0432\u043e\u0441\u043f\u0440-\u0438\u044f", "LabelName": "\u0418\u043c\u044f (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435):", "ButtonSubmit": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c", @@ -433,8 +433,8 @@ "HeaderRuntime": "\u0414\u043b\u0438\u0442-c\u0442\u044c", "HeaderCommunityRating": "\u041e\u0431\u0449-\u0430\u044f \u043e\u0446\u0435\u043d\u043a\u0430", "HeaderParentalRating": "\u0412\u043e\u0437\u0440-\u0430\u044f \u043a\u0430\u0442-\u0438\u044f", - "HeaderReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f\u0443\u0441\u043a\u0430", - "HeaderDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431-\u0438\u044f", + "HeaderReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u0445\u043e\u0434\u0430", + "HeaderDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f", "HeaderSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b", "HeaderSeason": "\u0421\u0435\u0437\u043e\u043d", "HeaderSeasonNumber": "\u041d\u043e\u043c\u0435\u0440 \u0441\u0435\u0437\u043e\u043d\u0430", @@ -442,14 +442,14 @@ "HeaderYear": "\u0413\u043e\u0434", "HeaderGameSystem": "\u0418\u0433\u0440\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430", "HeaderPlayers": "\u041f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u0438", - "HeaderEmbeddedImage": "\u0412\u043d\u0435\u0434\u0440\u0451\u043d\u043d\u044b\u0439 \u0440\u0438\u0441\u0443\u043d\u043e\u043a", + "HeaderEmbeddedImage": "\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435", "HeaderTrack": "\u0414\u043e\u0440\u043e\u0436\u043a\u0430", "HeaderDisc": "\u0414\u0438\u0441\u043a", "OptionMovies": "\u0424\u0438\u043b\u044c\u043c\u044b", "OptionCollections": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438", "OptionSeries": "\u0422\u0412-\u0441\u0435\u0440\u0438\u0430\u043b\u044b", "OptionSeasons": "\u0422\u0412-\u0441\u0435\u0437\u043e\u043d\u044b", - "OptionEpisodes": "\u0422\u0412-\u044d\u043f\u0438\u0437\u043e\u0434\u044b", + "OptionEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b", "OptionGames": "\u0418\u0433\u0440\u044b", "OptionGameSystems": "\u0418\u0433\u0440\u043e\u0432\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b", "OptionMusicArtists": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438", @@ -515,13 +515,13 @@ "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438", "FolderTypeTvShows": "\u0422\u0412", "TabMovies": "\u0424\u0438\u043b\u044c\u043c\u044b", - "TabSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b", + "TabSeries": "\u0422\u0412-\u0441\u0435\u0440\u0438\u0430\u043b\u044b", "TabEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b", "TabTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b", "TabGames": "\u0418\u0433\u0440\u044b", "TabAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u044b", "TabSongs": "\u041c\u0435\u043b\u043e\u0434\u0438\u0438", - "TabMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e", + "TabMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e\u043a\u043b\u0438\u043f\u044b", "BirthPlaceValue": "\u041c\u0435\u0441\u0442\u043e \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f: {0}", "DeathDateValue": "\u041a\u043e\u043d\u0447\u0438\u043d\u0430: {0}", "BirthDateValue": "\u0420\u043e\u0436\u0434\u0435\u043d\u0438\u0435: {0}", @@ -544,7 +544,7 @@ "MessageEmbyAccountAdded": "\u0423\u0447\u0451\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c Emby \u0431\u044b\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", "MessagePendingEmbyAccountAdded": "\u0423\u0447\u0451\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c Emby \u0431\u044b\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u042d-\u043f\u043e\u0447\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0443 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438. \u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c, \u0449\u0451\u043b\u043a\u043d\u0443\u0432 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0432 \u042d-\u043f\u043e\u0447\u0442\u0435.", "HeaderEmbyAccountRemoved": "\u0423\u0447\u0451\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c Emby \u0438\u0437\u044a\u044f\u0442\u0430", - "MessageEmbyAccontRemoved": "\u0423\u0447\u0451\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c Emby \u0431\u044b\u043b\u0430 \u0438\u0437\u044a\u044f\u0442\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", + "MessageEmbyAccontRemoved": "\u0423\u0447\u0451\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c Emby \u0431\u044b\u043b\u0430 \u0438\u0437\u044a\u044f\u0442\u0430 \u0443 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", "TooltipLinkedToEmbyConnect": "\u0418\u043c\u0435\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u044c \u0441 Emby Connect", "HeaderUnrated": "\u0411\u0435\u0437 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438", "ValueDiscNumber": "\u0414\u0438\u0441\u043a {0}", @@ -557,7 +557,7 @@ "ButtonImDone": "\u042f \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b", "OptionWatched": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e", "OptionUnwatched": "\u041d\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e", - "ExternalPlayerPlaystateOptionsHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435, \u043a\u0430\u043a \u0432\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0431\u044b \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043e \u0432\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437.", + "ExternalPlayerPlaystateOptionsHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435, \u043a\u0430\u043a \u0432\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0431\u044b \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437.", "LabelMarkAs": "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0430\u043a:", "OptionInProgress": "\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f", "LabelResumePoint": "\u0422\u043e\u0447\u043a\u0430 \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f:", @@ -585,7 +585,7 @@ "TooltipLike": "\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f", "TooltipDislike": "\u041d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f", "TooltipPlayed": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u043e", - "ValueSeriesYearToPresent": "{0} - \u043d\u044b\u043d\u0435", + "ValueSeriesYearToPresent": "{0} - \u0441\u0435\u0439\u0447\u0430\u0441", "ValueAwards": "\u041f\u0440\u0438\u0437\u044b: {0}", "ValueBudget": "\u0411\u044e\u0434\u0436\u0435\u0442: {0}", "ValueRevenue": "\u0412\u044b\u0440\u0443\u0447\u043a\u0430: {0}", @@ -609,10 +609,10 @@ "MediaInfoExposureTime": "\u0412\u044b\u0434\u0435\u0440\u0436\u043a\u0430", "MediaInfoFocalLength": "\u0424\u043e\u043a\u0443\u0441. \u0440\u0430\u0441\u0441\u0442-\u0438\u0435", "MediaInfoOrientation": "\u041e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u044f", - "MediaInfoIsoSpeedRating": "\u0421\u0432\u0435\u0442\u043e\u0447\u0443\u0432\u0441\u0442-\u0442\u044c ISO", + "MediaInfoIsoSpeedRating": "\u0421\u0432\u0435\u0442\u043e\u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c ISO", "MediaInfoLatitude": "\u0428\u0438\u0440\u043e\u0442\u0430", "MediaInfoLongitude": "\u0414\u043e\u043b\u0433\u043e\u0442\u0430", - "MediaInfoShutterSpeed": "\u0421\u043a\u043e\u0440. \u0437\u0430\u0442\u0432\u043e\u0440\u0430", + "MediaInfoShutterSpeed": "\u0412\u044b\u0434\u0435\u0440\u0436\u043a\u0430", "MediaInfoSoftware": "\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430", "HeaderIfYouLikeCheckTheseOut": "\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u00ab{0}\u00bb, \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441...", "HeaderPlotKeywords": "\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0441\u044e\u0436\u0435\u0442\u0430", @@ -633,12 +633,12 @@ "MediaInfoFormat": "\u0424\u043e\u0440\u043c\u0430\u0442", "MediaInfoContainer": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440", "MediaInfoDefault": "\u0423\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u0435", - "MediaInfoForced": "\u0424\u043e\u0440\u0441-\u044b\u0435", + "MediaInfoForced": "\u0424\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435", "MediaInfoExternal": "\u0412\u043d\u0435\u0448\u043d\u0438\u0435", "MediaInfoTimestamp": "\u041c\u0435\u0442\u043a\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438", - "MediaInfoPixelFormat": "\u041f\u0438\u043a\u0441. \u0444-\u0442", - "MediaInfoBitDepth": "\u0420\u0430\u0437\u0440\u044f\u0434\u043d\u043e\u0441\u0442\u044c", - "MediaInfoSampleRate": "\u0427-\u0442\u0430 \u0434\u0438\u0441\u043a\u0440.", + "MediaInfoPixelFormat": "\u041f\u0438\u043a\u0441. \u0444\u043e\u0440\u043c\u0430\u0442", + "MediaInfoBitDepth": "\u0413\u043b\u0443\u0431\u0438\u043d\u0430 \u0446\u0432\u0435\u0442\u0430", + "MediaInfoSampleRate": "\u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438", "MediaInfoBitrate": "\u041f\u043e\u0442\u043e\u043a. \u0441\u043a-\u0442\u044c", "MediaInfoChannels": "\u041a\u0430\u043d\u0430\u043b\u044b", "MediaInfoLayout": "\u041a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0430", @@ -648,8 +648,8 @@ "MediaInfoLevel": "\u0423\u0440\u043e\u0432\u0435\u043d\u044c", "MediaInfoAspectRatio": "\u0421\u043e\u043e\u0442-\u0438\u0435 \u0441\u0442\u043e\u0440\u043e\u043d", "MediaInfoResolution": "\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435", - "MediaInfoAnamorphic": "\u0410\u043d\u0430\u043c\u043e\u0440\u0444\u043d\u043e\u0435", - "MediaInfoInterlaced": "\u0427\u0435\u0440\u0435\u0441\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0435", + "MediaInfoAnamorphic": "\u0410\u043d\u0430\u043c\u043e\u0440\u0444\u043d\u043e\u0441\u0442\u044c", + "MediaInfoInterlaced": "\u0427\u0435\u0440\u0435\u0441\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0441\u0442\u044c", "MediaInfoFramerate": "\u0427-\u0442\u0430 \u043a\u0430\u0434\u0440\u043e\u0432", "MediaInfoStreamTypeAudio": "\u0410\u0443\u0434\u0438\u043e", "MediaInfoStreamTypeData": "\u0414\u0430\u043d\u043d\u044b\u0435", @@ -660,7 +660,7 @@ "TabPlayback": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435", "TabNotifications": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f", "TabExpert": "\u0414\u043b\u044f \u043e\u043f\u044b\u0442\u043d\u044b\u0445", - "HeaderSelectCustomIntrosPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u043a \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0430\u043c", + "HeaderSelectCustomIntrosPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0430\u043c", "HeaderRateAndReview": "\u041e\u0446\u0435\u043d\u043a\u0430 \u0438 \u043e\u0442\u0437\u044b\u0432", "HeaderThankYou": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0432\u0430\u0441", "MessageThankYouForYourReview": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0437\u0430 \u0432\u0430\u0448 \u043e\u0442\u0437\u044b\u0432.", @@ -668,30 +668,30 @@ "LabelFullReview": "\u041e\u0442\u0437\u044b\u0432 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e:", "LabelShortRatingDescription": "\u041a\u0440\u0430\u0442\u043a\u0430\u044f \u0441\u0432\u043e\u0434\u043a\u0430 \u043e\u0446\u0435\u043d\u043a\u0438:", "OptionIRecommendThisItem": "\u042f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u044d\u0442\u043e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442", - "WebClientTourContent": "\u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0441\u0432\u043e\u0438 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0438 \u0442.\u0434. \u0417\u0435\u043b\u0451\u043d\u044b\u0435 \u043a\u0440\u0443\u0436\u043e\u0447\u043a\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443 \u0432\u0430\u0441 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043d\u0435\u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.", - "WebClientTourMovies": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435 \u0444\u0438\u043b\u044c\u043c\u044b, \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u0442.\u043f., \u0441 \u043b\u044e\u0431\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e \u0432\u0435\u0431-\u0431\u0440\u0430\u0443\u0437\u0435\u0440.", + "WebClientTourContent": "\u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435, \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0438 \u0442.\u0434. \u0417\u0435\u043b\u0451\u043d\u044b\u0435 \u043a\u0440\u0443\u0436\u043e\u0447\u043a\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443 \u0432\u0430\u0441 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043d\u0435\u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.", + "WebClientTourMovies": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0438\u0442\u0435 \u0444\u0438\u043b\u044c\u043c\u044b, \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u0442.\u0434., \u0441 \u043b\u044e\u0431\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c.", "WebClientTourMouseOver": "\u0417\u0430\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043a\u0443\u0440\u0441\u043e\u0440 \u043c\u044b\u0448\u0438 \u043d\u0430\u0434 \u043b\u044e\u0431\u044b\u043c \u043f\u043e\u0441\u0442\u0435\u0440\u043e\u043c \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0432\u0430\u0436\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438", - "WebClientTourTapHold": "\u041a\u043e\u0441\u043d\u0438\u0442\u0435\u0441\u044c \u0438 \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u0438\u043b\u0438 \u0449\u0435\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043c\u044b\u0448\u0438 \u043f\u043e \u043b\u044e\u0431\u043e\u043c\u0443 \u043f\u043e\u0441\u0442\u0435\u0440\u0443 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e", - "WebClientTourMetadataManager": "\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u041f\u0440\u0430\u0432\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043e\u043a\u043d\u043e \u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445", - "WebClientTourPlaylists": "\u0421\u0432\u043e\u0431\u043e\u0434\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438 \u0430\u0432\u0442\u043e\u043c\u0438\u043a\u0441\u044b, \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435 \u0438\u0445 \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435", - "WebClientTourCollections": "\u0421\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0444\u0438\u043b\u044c\u043c\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u0435", - "WebClientTourUserPreferences1": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043f\u043e\u0441\u043e\u0431, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0432\u0430\u0448\u0430 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432\u043e \u0432\u0441\u0435\u0445 \u0432\u0430\u0448\u0438\u0445 Emby-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445.", + "WebClientTourTapHold": "\u041a\u043e\u0441\u043d\u0438\u0442\u0435\u0441\u044c \u0438 \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u0438\u043b\u0438 \u0449\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043c\u044b\u0448\u0438 \u043b\u044e\u0431\u043e\u0439 \u043f\u043e\u0441\u0442\u0435\u0440 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e", + "WebClientTourMetadataManager": "\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u041f\u0440\u0430\u0432\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445", + "WebClientTourPlaylists": "\u0411\u0435\u0437 \u0443\u0441\u0438\u043b\u0438\u0439 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438 \u0430\u0432\u0442\u043e\u043c\u0438\u043a\u0441\u044b, \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435 \u0438\u0445 \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435", + "WebClientTourCollections": "\u0421\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0444\u0438\u043b\u044c\u043c\u043e\u0432\u044b\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0442\u044b \u0432\u043c\u0435\u0441\u0442\u0435", + "WebClientTourUserPreferences1": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043f\u043e\u0441\u043e\u0431, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432\u043e \u0432\u0441\u0435\u0445 \u0432\u0430\u0448\u0438\u0445 Emby-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445.", "WebClientTourUserPreferences2": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0430\u0443\u0434\u0438\u043e \u0438 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432 \u0441\u0432\u043e\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0435\u0434\u0438\u043d\u043e\u0436\u0434\u044b, \u0434\u043b\u044f \u0432\u0441\u044f\u043a\u043e\u0433\u043e Emby-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f", "WebClientTourUserPreferences3": "\u041e\u0444\u043e\u0440\u044c\u043c\u0442\u0435 \u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043f\u043e \u0441\u0432\u043e\u0438\u043c \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0435\u043d\u0438\u044f\u043c", - "WebClientTourUserPreferences4": "\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u0435 \u0437\u0430\u0434\u043d\u0438\u043a\u0438, \u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0435\u043b\u043e\u0434\u0438\u0438 \u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u0438", + "WebClientTourUserPreferences4": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0437\u0430\u0434\u043d\u0438\u043a\u0438, \u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0435\u043b\u043e\u0434\u0438\u0438 \u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0442\u0435\u043b\u0438", "WebClientTourMobile1": "\u0412\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043d\u0430 \u0441\u043c\u0430\u0440\u0442\u0444\u043e\u043d\u0430\u0445 \u0438 \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u0430\u0445...", - "WebClientTourMobile2": "\u0438 \u0441 \u043b\u0451\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0438 Emby-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438", + "WebClientTourMobile2": "\u0438 \u043b\u0435\u0433\u043a\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0438 Emby-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438", "WebClientTourMySync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0441\u0432\u043e\u0438 \u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0432\u0430\u0448\u0438\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430.", - "MessageEnjoyYourStay": "\u041f\u0440\u0438\u044f\u0442\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u044f\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f", - "DashboardTourDashboard": "\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0412\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0437\u043d\u0430\u0442\u044c, \u043a\u0442\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u043c \u0438 \u0433\u0434\u0435 \u043e\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f.", + "MessageEnjoyYourStay": "\u041f\u0440\u0438\u044f\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0431\u044b\u0432\u0430\u043d\u0438\u044f", + "DashboardTourDashboard": "\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0441\u043b\u0435\u0436\u0435\u043d\u0438\u044f \u0437\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0438 \u0432\u0430\u0448\u0438\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438. \u0412\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442\u0435 \u0437\u043d\u0430\u0442\u044c, \u043a\u0442\u043e \u0447\u0435\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f, \u0438 \u043a\u0442\u043e \u0433\u0434\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f.", "DashboardTourHelp": "\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043a\u043d\u043e\u043f\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0432\u0438\u043a\u0438-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0445\u0441\u044f \u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e \u044d\u043a\u0440\u0430\u043d\u0430.", - "DashboardTourUsers": "\u0421\u0432\u043e\u0431\u043e\u0434\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0447\u0451\u0442\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0434\u043b\u044f \u0432\u0430\u0448\u0438\u0445 \u0434\u0440\u0443\u0437\u0435\u0439 \u0438 \u0447\u043b\u0435\u043d\u043e\u0432 \u0441\u0435\u043c\u044c\u0438, \u043a\u0430\u0436\u0434\u0443\u044e \u0441 \u0438\u0445 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0430\u043c\u0438, \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c \u0438 \u0442.\u0434.", - "DashboardTourCinemaMode": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430 \u043f\u0440\u0438\u0432\u043d\u043e\u0441\u0438\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u0438\u043d\u043e\u0437\u0430\u043b\u0430 \u043f\u0440\u044f\u043c\u0438\u043a\u043e\u043c \u0432\u043e \u0432\u0430\u0448\u0443 \u0433\u043e\u0441\u0442\u0438\u043d\u0443\u044e, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u043c.", + "DashboardTourUsers": "\u0411\u0435\u0437 \u0443\u0441\u0438\u043b\u0438\u0439 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0443\u0447\u0451\u0442\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u0430\u0448\u0438\u0445 \u0434\u0440\u0443\u0437\u0435\u0439 \u0438 \u0447\u043b\u0435\u043d\u043e\u0432 \u0441\u0435\u043c\u044c\u0438, \u043a\u0430\u0436\u0434\u0443\u044e \u0441 \u0438\u0445 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0430\u043c\u0438, \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c \u0438 \u0442.\u0434.", + "DashboardTourCinemaMode": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430 \u043f\u0440\u0438\u0432\u043d\u043e\u0441\u0438\u0442 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u0435 \u043a\u0438\u043d\u043e\u0437\u0430\u043b\u0430 \u043f\u0440\u044f\u043c\u0438\u043a\u043e\u043c \u0432\u043e \u0432\u0430\u0448\u0443 \u0433\u043e\u0441\u0442\u0438\u043d\u0443\u044e, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u043c.", "DashboardTourChapters": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043a \u0432\u0438\u0434\u0435\u043e, \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430.", - "DashboardTourSubtitles": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0439\u0442\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u0434\u043b\u044f \u0432\u0438\u0434\u0435\u043e \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u044f\u0437\u044b\u043a\u0435.", - "DashboardTourPlugins": "\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043a\u0430\u043d\u0430\u043b\u043e\u0432 \u0432\u0438\u0434\u0435\u043e, \u0422\u0412-\u044d\u0444\u0438\u0440\u0430, \u0441\u043a\u0430\u043d\u043d\u0435\u0440\u043e\u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442.\u0434.", + "DashboardTourSubtitles": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u0434\u043b\u044f \u0432\u0430\u0448\u0438\u0445 \u0432\u0438\u0434\u0435\u043e.", + "DashboardTourPlugins": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043a\u0430\u043d\u0430\u043b\u043e\u0432 \u0432\u0438\u0434\u0435\u043e, \u0422\u0412-\u044d\u0444\u0438\u0440\u0430, \u0441\u043a\u0430\u043d\u043d\u0435\u0440\u043e\u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442.\u0434.", "DashboardTourNotifications": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u0445 \u043d\u0430 \u0432\u0430\u0448\u0435 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430, \u044d-\u043f\u043e\u0447\u0442\u0443 \u0438 \u0442.\u0434.", - "DashboardTourScheduledTasks": "\u0421\u0432\u043e\u0431\u043e\u0434\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0434\u043e\u043b\u0433\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0439\u0442\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f, \u0438 \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u043e.", + "DashboardTourScheduledTasks": "\u0411\u0435\u0437 \u0443\u0441\u0438\u043b\u0438\u0439 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0434\u043e\u043b\u0433\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0439\u0442\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u044b, \u0438 \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u043e.", "DashboardTourMobile": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c Emby Server \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u0441\u043c\u0430\u0440\u0442\u0444\u043e\u043d\u0430\u0445 \u0438 \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u0430\u0445. \u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0441\u0432\u043e\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0441 \u043b\u0430\u0434\u043e\u043d\u0438 \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u0441 \u043b\u044e\u0431\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430.", "DashboardTourSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0441\u0432\u043e\u0438 \u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0432\u0430\u0448\u0438\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430.", "MessageRefreshQueued": "\u041f\u043e\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nl.json b/MediaBrowser.Server.Implementations/Localization/Server/nl.json index 36fe64f553..fbeb17e9b8 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json @@ -404,8 +404,8 @@ "ButtonRefresh": "Vernieuwen", "ButtonAdvancedRefresh": "Geavanceerd vernieuwen", "OptionPriority": "Prioriteit", - "OptionRecordOnAllChannels": "Programma van alle kanalen opnemen", - "OptionRecordAnytime": "Programma elke keer opnemen", + "OptionRecordOnAllChannels": "Op alle kanalen opnemen", + "OptionRecordAnytime": "Op elk tijdstip opnemen", "OptionRecordOnlyNewEpisodes": "Alleen nieuwe afleveringen opnemen", "HeaderRepeatingOptions": "Herhaling opties", "HeaderDays": "Dagen", @@ -551,7 +551,7 @@ "LabelPublicHttpsPort": "Publieke https poort nummer:", "LabelPublicHttpsPortHelp": "Het publieke poortnummer dat moet worden toegewezen aan de lokale https poort.", "LabelEnableHttps": "Rapporteer https als extern adres", - "LabelEnableHttpsHelp": "Indien ingeschakeld, zal de server een https url rapporteren aan de client als het externe adres. Dit kan clients die nog geen ondersteuning voor https hebben onbruikbaar maken.", + "LabelEnableHttpsHelp": "Indien ingeschakeld, zal de server een https url rapporteren aan de client als het externe adres.", "LabelHttpsPort": "Lokale https poort nummer:", "LabelHttpsPortHelp": "Het tcp poort nummer waar Emby's http server aan moet verbinden.", "LabelWebSocketPortNumber": "Web socket poortnummer:", @@ -1393,19 +1393,19 @@ "LabelShowLibraryTileNamesHelp": "Bepaalt of labels onder de bibliotheek tegels zullen worden weergegeven op de startpagina", "OptionEnableTranscodingThrottle": "Throtteling inschakelen", "OptionEnableTranscodingThrottleHelp": "Throtteling zal automatisch de snelheid van het transcoderen aanpassen om de cpu belasting laag te houden tijdens het afspelen.", - "LabelUploadSpeedLimit": "Upload limiet (mbps):", + "LabelUploadSpeedLimit": "Upload limiet (Mbps):", "OptionAllowSyncTranscoding": "Sta synchronisatie toe die transcodering vereist", "HeaderPlayback": "Media afspelen", "OptionAllowAudioPlaybackTranscoding": "Sta het afspelen van audio wat transcoding vereist toe", "OptionAllowVideoPlaybackTranscoding": "Sta het afspelen van video wat transcoding vereist toe", "OptionAllowMediaPlaybackTranscodingHelp": "Gebruikers zullen een bericht ontvangen als afspelen niet is toegestaan op basis van het beleid", "TabStreaming": "Streaming", - "LabelRemoteClientBitrateLimit": "Client bitrate limiet (mbps):", + "LabelRemoteClientBitrateLimit": "Client bitrate limiet (Mbps):", "LabelRemoteClientBitrateLimitHelp": "Een optionele streaming bitrate limiet voor alle clients. Dit wordt gebruikt om te voorkomen dat clients een hogere bitrate aanvragen dan de internet connectie kan leveren.", "LabelConversionCpuCoreLimit": "CPU core limiet:", "LabelConversionCpuCoreLimitHelp": "Limiteer het aantal CPU cores wat gebruikt mag worden bij een omzetteing om te synchroniseren.", "OptionEnableFullSpeedConversion": "Schakel hoge converteren op hoge snelheid in", - "OptionEnableFullSpeedConversionHelp": "Standaard wordt het converteren voor synchronisatie opdrachten op lage snelheid uitgevoerd zodat er weinig impact is op de server.", + "OptionEnableFullSpeedConversionHelp": "Standaard wordt het converteren voor synchronisatie opdrachten op lage snelheid uitgevoerd zodat er zo min mogelijke impact is op de server.", "HeaderPlaylists": "Afspeellijsten", "HeaderSelectDate": "Selecteer Datum", "HeaderWelcomeExclamation": "Welkom!", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json index 35144da5e0..58a99e5252 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json @@ -456,7 +456,7 @@ "LabelTime": "Hora:", "LabelEvent": "Evento:", "OptionWakeFromSleep": "Despertar da hiberna\u00e7\u00e3o", - "LabelEveryXMinutes": "Todo(a):", + "LabelEveryXMinutes": "A cada:", "HeaderTvTuners": "Sintonizador", "HeaderGallery": "Galeria", "HeaderLatestGames": "Jogos Recentes", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ru.json b/MediaBrowser.Server.Implementations/Localization/Server/ru.json index 60618b5ca4..257ee48d7e 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json @@ -18,7 +18,7 @@ "WelcomeToProject": "Emby \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0430\u0441!", "ThisWizardWillGuideYou": "\u042d\u0442\u043e\u0442 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043f\u0440\u043e\u0432\u0435\u0434\u0451\u0442 \u0432\u0430\u0441 \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0435 \u0444\u0430\u0437\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u044f\u0437\u044b\u043a.", "TellUsAboutYourself": "\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0438\u0442\u0435 \u043e \u0441\u0435\u0431\u0435", - "ButtonQuickStartGuide": "\u041a\u043e \u043a\u0440\u0430\u0442\u043a\u043e\u043c\u0443 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0443 \u043f\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443", + "ButtonQuickStartGuide": "\u041a \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0443 \u043f\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443", "LabelYourFirstName": "\u0412\u0430\u0448\u0435 \u0438\u043c\u044f:", "MoreUsersCanBeAddedLater": "\u041f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0449\u0451 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u00ab\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c\u00bb.", "UserProfilesIntro": "\u0412 Emby \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0438\u043c\u0435\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c.", @@ -78,17 +78,17 @@ "HeaderSyncRequiresSupporterMembership": "\u0414\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430", "HeaderEnjoyDayTrial": "\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u043c 14-\u0434\u043d\u0435\u0432\u043d\u044b\u043c \u043f\u0440\u043e\u0431\u043d\u044b\u043c \u043f\u0435\u0440\u0438\u043e\u0434\u043e\u043c", "LabelSyncTempPath": "\u041f\u0443\u0442\u044c \u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443:", - "LabelSyncTempPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0437\u0434\u0435\u0441\u044c.", + "LabelSyncTempPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0437\u0434\u0435\u0441\u044c.", "LabelCustomCertificatePath": "\u041f\u0443\u0442\u044c \u043a \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0443:", "LabelCustomCertificatePathHelp": "\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b .pfx SSL-\u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430. \u0415\u0441\u043b\u0438 \u043e\u043d \u043e\u043f\u0443\u0449\u0435\u043d, \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0441\u0430\u043c\u043e\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442.", "TitleNotifications": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f", "ButtonDonateWithPayPal": "\u041f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 PayPal", "OptionDetectArchiveFilesAsMedia": "\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0430\u0440\u0445\u0438\u0432\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445", - "OptionDetectArchiveFilesAsMediaHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0444\u0430\u0439\u043b\u044b \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 .RAR \u0438 .ZIP \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u043a\u0430\u043a \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b\u044b.", + "OptionDetectArchiveFilesAsMediaHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0444\u0430\u0439\u043b\u044b \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 .RAR \u0438 .ZIP \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b\u043e\u0432.", "LabelEnterConnectUserName": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u042d-\u043f\u043e\u0447\u0442\u0430", "LabelEnterConnectUserNameHelp": "\u042d\u0442\u043e - \u0432\u0430\u0448\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 Emby.", "LabelEnableEnhancedMovies": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0444\u0438\u043b\u044c\u043c\u043e\u0432", - "LabelEnableEnhancedMoviesHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0444\u0438\u043b\u044c\u043c\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043f\u0430\u043f\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b, \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u0441\u044a\u0451\u043c\u043e\u043a \u0438 \u0434\u0440\u0443\u0433\u043e\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0435\u0435\u0441\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435.", + "LabelEnableEnhancedMoviesHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0444\u0438\u043b\u044c\u043c\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043f\u0430\u043f\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b, \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u0441\u044a\u0451\u043c\u043e\u043a \u0438 \u0434\u0440\u0443\u0433\u043e\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435.", "HeaderSyncJobInfo": "\u0417\u0430\u0434\u0430\u043d\u0438\u0435 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438", "FolderTypeMixed": "\u0420\u0430\u0437\u043d\u043e\u0442\u0438\u043f\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435", "FolderTypeMovies": "\u041a\u0438\u043d\u043e", @@ -197,7 +197,7 @@ "TabAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u044b", "TabArtists": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438", "TabAlbumArtists": "\u0410\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438", - "TabMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e", + "TabMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e\u043a\u043b\u0438\u043f\u044b", "ButtonSort": "\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c", "HeaderSortBy": "\u0423\u0441\u043b\u043e\u0432\u0438\u0435:", "HeaderSortOrder": "\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435:", @@ -234,7 +234,7 @@ "TabMyPlugins": "\u041c\u043e\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b", "TabCatalog": "\u041a\u0430\u0442\u0430\u043b\u043e\u0433", "TitlePlugins": "\u041f\u043b\u0430\u0433\u0438\u043d\u044b", - "HeaderAutomaticUpdates": "\u0410\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f", + "HeaderAutomaticUpdates": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f", "HeaderNowPlaying": " \u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e\u0435", "HeaderLatestAlbums": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0430\u043b\u044c\u0431\u043e\u043c\u044b", "HeaderLatestSongs": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043c\u0435\u043b\u043e\u0434\u0438\u0438", @@ -324,7 +324,7 @@ "PismoMessage": "Pismo File Mount \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0434\u0430\u0440\u0435\u043d\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438.", "TangibleSoftwareMessage": "\u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440\u044b Java\/C# \u043e\u0442 Tangible Solutions \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0434\u0430\u0440\u0435\u043d\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438.", "HeaderCredits": "\u041f\u0440\u0430\u0432\u043e\u043e\u0431\u043b\u0430\u0434\u0430\u0442\u0435\u043b\u0438", - "PleaseSupportOtherProduces": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u0438 \u0438\u043d\u043e\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f:", + "PleaseSupportOtherProduces": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u044b \u043d\u0430\u043c\u0438:", "VersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}", "TabPaths": "\u041f\u0443\u0442\u0438", "TabServer": "\u0421\u0435\u0440\u0432\u0435\u0440", @@ -340,15 +340,15 @@ "LabelRunServerAtStartup": "\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b", "LabelRunServerAtStartupHelp": "\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0437\u043d\u0430\u0447\u043e\u043a \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043b\u043e\u0442\u043a\u0435 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0441\u0442\u0430\u0440\u0442\u0430 Windows. \u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043b\u0443\u0436\u0431\u044b Windows, \u0441\u043d\u0438\u043c\u0438\u0442\u0435 \u0444\u043b\u0430\u0436\u043e\u043a \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0441\u043b\u0443\u0436\u0431\u0443 \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f Windows. \u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a \u0432 \u043b\u043e\u0442\u043a\u0435 \u0434\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043b\u0443\u0436\u0431\u044b.", "ButtonSelectDirectory": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043a\u0430\u0442\u0430\u043b\u043e\u0433", - "LabelCustomPaths": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u043f\u043e \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u043c. \u041e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043f\u043e\u043b\u044f \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435.", + "LabelCustomPaths": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u043a\u0443\u0434\u0430 \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e. \u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u044f \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435.", "LabelCachePath": "\u041f\u0443\u0442\u044c \u043a\u043e \u043a\u0435\u0448\u0443:", - "LabelCachePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u043a\u044d\u0448\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432.", + "LabelCachePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u043a\u044d\u0448\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432.", "LabelImagesByNamePath": "\u041f\u0443\u0442\u044c \u043a \u0440\u0438\u0441\u0443\u043d\u043a\u0430\u043c \u0447\u0435\u0440\u0435\u0437 \u0438\u043c\u044f:", - "LabelImagesByNamePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0430\u043a\u0442\u0451\u0440\u043e\u0432, \u0436\u0430\u043d\u0440\u043e\u0432 \u0438 \u0441\u0442\u0443\u0434\u0438\u0439.", + "LabelImagesByNamePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0430\u043a\u0442\u0451\u0440\u043e\u0432, \u0436\u0430\u043d\u0440\u043e\u0432 \u0438 \u0441\u0442\u0443\u0434\u0438\u0439.", "LabelMetadataPath": "\u041f\u0443\u0442\u044c \u043a \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c:", "LabelMetadataPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0439 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043d\u0435 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a.", "LabelTranscodingTempPath": "\u041f\u0443\u0442\u044c \u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u0430\u043c \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438:", - "LabelTranscodingTempPathHelp": "\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u0444\u0430\u0439\u043b\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435. \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0438\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0430\u043f\u043a\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 data.", + "LabelTranscodingTempPathHelp": "\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u0444\u0430\u0439\u043b\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435. \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0438\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0430\u043f\u043a\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 data.", "TabBasics": "\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435", "TabTV": "\u0422\u0412", "TabGames": "\u0418\u0433\u0440\u044b", @@ -356,7 +356,7 @@ "TabOthers": "\u0414\u0440\u0443\u0433\u0438\u0435", "HeaderExtractChapterImagesFor": "\u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u0434\u043b\u044f:", "OptionMovies": "\u0424\u0438\u043b\u044c\u043c\u044b", - "OptionEpisodes": "\u0422\u0412-\u044d\u043f\u0438\u0437\u043e\u0434\u044b", + "OptionEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b", "OptionOtherVideos": "\u0414\u0440\u0443\u0433\u0438\u0435 \u0432\u0438\u0434\u0435\u043e", "TitleMetadata": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435", "LabelAutomaticUpdates": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f", @@ -371,7 +371,7 @@ "LabelMetadataDownloadLanguage": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u044f\u0437\u044b\u043a \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e:", "ButtonAutoScroll": "\u041a \u0430\u0432\u0442\u043e\u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0435", "LabelImageSavingConvention": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432:", - "LabelImageSavingConventionHelp": "\u0412 Emby \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u044e\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0438\u0437 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445. \u0412\u044b\u0431\u043e\u0440 \u0441\u0432\u043e\u0435\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u043c, \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0430\u043a\u0436\u0435 \u0438\u043d\u044b\u0445 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432.", + "LabelImageSavingConventionHelp": "\u0412 Emby \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u044e\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0438\u0437 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445. \u0412\u044b\u0431\u043e\u0440 \u0441\u0432\u043e\u0435\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u043c, \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0438\u043d\u044b\u0445 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432.", "OptionImageSavingCompatible": "\u0421\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 - Emby\/Kodi\/Plex", "OptionImageSavingStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 - MB2", "ButtonSignIn": "\u0412\u043e\u0439\u0442\u0438", @@ -387,7 +387,7 @@ "HeaderChannels": "\u041a\u0430\u043d\u0430\u043b\u044b", "TabRecordings": "\u0417\u0430\u043f\u0438\u0441\u0438", "TabScheduled": "\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0435", - "TabSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b", + "TabSeries": "\u0422\u0412-\u0441\u0435\u0440\u0438\u0430\u043b\u044b", "TabFavorites": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435", "TabMyLibrary": "\u041c\u043e\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430", "ButtonCancelRecording": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c", @@ -585,9 +585,9 @@ "LabelEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0430:", "LabelEndingEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u044d\u043f\u0438\u0437\u043e\u0434\u0430:", "LabelEndingEpisodeNumberHelp": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0445 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043f\u0438\u0437\u043e\u0434\u043e\u0432", - "HeaderSupportTheTeam": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 Emby", + "HeaderSupportTheTeam": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 Emby", "LabelSupportAmount": "\u0421\u0443\u043c\u043c\u0430 (USD)", - "HeaderSupportTheTeamHelp": "\u041f\u043e\u043c\u043e\u0433\u0438\u0442\u0435 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0427\u0430\u0441\u0442\u044c \u0432\u0441\u0435\u0445 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043b\u043e\u0436\u0435\u043d\u0430 \u0432 \u0438\u043d\u043e\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c.", + "HeaderSupportTheTeamHelp": "\u041f\u043e\u043c\u043e\u0433\u0438\u0442\u0435 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0427\u0430\u0441\u0442\u044c \u0432\u0441\u0435\u0445 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043b\u043e\u0436\u0435\u043d\u0430 \u0432 \u0434\u0440\u0443\u0433\u0438\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c\u0441\u044f.", "ButtonEnterSupporterKey": "\u0412\u0432\u0435\u0441\u0442\u0438 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430", "DonationNextStep": "\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u043d\u0438\u0442\u0435\u0441\u044c, \u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043f\u043e \u042d-\u043f\u043e\u0447\u0442\u0435.", "AutoOrganizeHelp": "\u0421\u0440\u0435\u0434\u0441\u0442\u0432\u043e \u0430\u0432\u0442\u043e\u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0438 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442 \u0438\u0445 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445.", @@ -654,7 +654,7 @@ "LabelEnableDlnaServer": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c DLNA-\u0441\u0435\u0440\u0432\u0435\u0440", "LabelEnableDlnaServerHelp": "UPnP-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c \u0432 \u0441\u0435\u0442\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f Emby.", "LabelEnableBlastAliveMessages": "\u0411\u043e\u043c\u0431\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438", - "LabelEnableBlastAliveMessagesHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435, \u0435\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0434\u0451\u0436\u043d\u043e \u0434\u0440\u0443\u0433\u0438\u043c\u0438 UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0432 \u0441\u0435\u0442\u0438.", + "LabelEnableBlastAliveMessagesHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435, \u0435\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0434\u0451\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c\u0438 UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0432 \u0441\u0435\u0442\u0438.", "LabelBlastMessageInterval": "\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438, \u0441", "LabelBlastMessageIntervalHelp": "\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.", "LabelDefaultUser": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c:", @@ -780,7 +780,7 @@ "TabResponses": "\u041e\u0442\u043a\u043b\u0438\u043a\u0438", "HeaderProfileInformation": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0435", "LabelEmbedAlbumArtDidl": "\u0412\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0435 \u043e\u0431\u043b\u043e\u0436\u043a\u0438 \u0432 DIDL", - "LabelEmbedAlbumArtDidlHelp": "\u0414\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0445 \u043e\u0431\u043b\u043e\u0436\u0435\u043a \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c. \u0414\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0436\u0435, \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0443\u0434\u0430\u0441\u0442\u0441\u044f.", + "LabelEmbedAlbumArtDidlHelp": "\u0414\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0445 \u043e\u0431\u043b\u043e\u0436\u0435\u043a \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c. \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0442\u0435\u0440\u043f\u0435\u0442\u044c \u043d\u0435\u0443\u0434\u0430\u0447\u0443 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438.", "LabelAlbumArtPN": "PN \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u043e\u0439 \u043e\u0431\u043b\u043e\u0436\u043a\u0438:", "LabelAlbumArtHelp": "PN \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0435 \u0434\u043b\u044f \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0445 \u043e\u0431\u043b\u043e\u0436\u0435\u043a, \u0432\u043d\u0443\u0442\u0440\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 dlna:profileID \u043f\u0440\u0438 upnp:albumArtURI. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0430.", "LabelAlbumArtMaxWidth": "\u041c\u0430\u043a\u0441. \u0448\u0438\u0440\u0438\u043d\u0430 \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u043e\u0439 \u043e\u0431\u043b\u043e\u0436\u043a\u0438:", @@ -920,9 +920,9 @@ "LabelEnableChannelContentDownloadingFor": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u0430 \u0434\u043b\u044f:", "LabelEnableChannelContentDownloadingForHelp": "\u041d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u0430\u043d\u0430\u043b\u0430\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u044f\u044e\u0449\u0435\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440. \u0412\u043a\u043b\u044e\u0447\u0430\u0439\u0442\u0435 \u043f\u0440\u0438 \u0441\u0440\u0435\u0434\u0430\u0445 \u0441 \u043d\u0438\u0437\u043a\u043e\u0439 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u043a\u0430\u043d\u0430\u043b\u0430 \u0432 \u043d\u0435\u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0432\u0440\u0435\u043c\u044f. \u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u00ab\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u043d\u0430\u043b\u043e\u0432\u00bb.", "LabelChannelDownloadPath": "\u041f\u0443\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u043a\u0430\u043d\u0430\u043b\u043e\u0432:", - "LabelChannelDownloadPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e, \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e. \u041d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044e\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 data.", + "LabelChannelDownloadPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e, \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e. \u041d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044e\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 data.", "LabelChannelDownloadAge": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437, \u0434\u043d\u0438:", - "LabelChannelDownloadAgeHelp": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0440\u0448\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u043e. \u041e\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u044b\u043c \u043f\u043e \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u0438.", + "LabelChannelDownloadAgeHelp": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0440\u0448\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u043e. \u0415\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u0438.", "ChannelSettingsFormHelp": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043a\u0430\u043d\u0430\u043b\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: Trailers \u0438\u043b\u0438 Vimeo) \u0438\u0437 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432.", "ButtonOptions": "\u041a \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c", "ViewTypePlaylists": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f", @@ -985,7 +985,7 @@ "LabelKodiMetadataEnablePathSubstitutionHelp": "\u0412\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0443\u0442\u0435\u0439 \u043a \u0440\u0438\u0441\u0443\u043d\u043a\u0430\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0443\u0442\u0435\u0439 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.", "LabelKodiMetadataEnablePathSubstitutionHelp2": "\u0421\u043c. \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0443\u0442\u0435\u0439", "LabelGroupChannelsIntoViews": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043c\u043e\u0438\u0445 \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u0430\u043d\u0430\u043b\u043e\u0432:", - "LabelGroupChannelsIntoViewsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u0430\u043d\u0430\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043d\u0430\u0440\u044f\u0434\u0443 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u0430\u043c\u0438. \u041f\u0440\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0430\u0441\u043f\u0435\u043a\u0442\u0430 \u00ab\u041a\u0430\u043d\u0430\u043b\u044b\u00bb.", + "LabelGroupChannelsIntoViewsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u0430\u043d\u0430\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0440\u044f\u0434\u043e\u043c \u0441 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u0430\u043c\u0438. \u041f\u0440\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0430\u0441\u043f\u0435\u043a\u0442\u0430 \u00ab\u041a\u0430\u043d\u0430\u043b\u044b\u00bb.", "LabelDisplayCollectionsView": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0430\u0441\u043f\u0435\u043a\u0442 \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0444\u0438\u043b\u044c\u043c\u043e\u0432", "LabelDisplayCollectionsViewHelp": "\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0430\u043c\u0438 \u0438\u043b\u0438 \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0438\u043c\u0435\u0435\u0442\u0435 \u0434\u043e\u0441\u0442\u0443\u043f. \u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u0449\u0435\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043c\u044b\u0448\u0438 \u0438\u043b\u0438 \u043a\u043e\u0441\u043d\u0438\u0442\u0435\u0441\u044c \u0438 \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u043b\u044e\u0431\u043e\u0439 \u0444\u0438\u043b\u044c\u043c, \u0438 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \"\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438\".", "LabelKodiMetadataEnableExtraThumbs": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c extrafanart \u0432\u043d\u0443\u0442\u0440\u044c extrathumbs", @@ -1052,7 +1052,7 @@ "LabelContext": "\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442:", "OptionContextStreaming": "\u0422\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u044f", "OptionContextStatic": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f", - "ButtonAddToPlaylist": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u0441\u043f\u0438\u0441\u043a\u0443 \u0432\u043e\u0441\u043f\u0440-\u0438\u044f", + "ButtonAddToPlaylist": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442", "TabPlaylists": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f", "ButtonClose": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c", "LabelAllLanguages": "\u0412\u0441\u0435 \u044f\u0437\u044b\u043a\u0438", @@ -1189,7 +1189,7 @@ "LabelAirTime:": "\u0412\u0440\u0435\u043c\u044f \u044d\u0444\u0438\u0440\u0430:", "LabelRuntimeMinutes": "\u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043c\u0438\u043d:", "LabelParentalRating": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f:", - "LabelCustomRating": "\u041d\u0435\u043e\u0444\u0438\u0446-\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f:", + "LabelCustomRating": "\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f:", "LabelBudget": "\u0411\u044e\u0434\u0436\u0435\u0442", "LabelRevenue": "\u0412\u044b\u0440\u0443\u0447\u043a\u0430, $:", "LabelOriginalAspectRatio": "\u0418\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u043e\u043e\u0442-\u0438\u0435 \u0441\u0442\u043e\u0440\u043e\u043d:", @@ -1278,7 +1278,7 @@ "TabCinemaMode": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430", "TitlePlayback": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435", "LabelEnableCinemaModeFor": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0440\u0435\u0436\u0438\u043c\u0430 \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430 \u0434\u043b\u044f:", - "CinemaModeConfigurationHelp": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430 \u043f\u0440\u0438\u0432\u043d\u043e\u0441\u0438\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u0438\u043d\u043e\u0437\u0430\u043b\u0430 \u043f\u0440\u044f\u043c\u0438\u043a\u043e\u043c \u0432 \u0432\u0430\u0448\u0443 \u0433\u043e\u0441\u0442\u0438\u043d\u0443\u044e, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u043c.", + "CinemaModeConfigurationHelp": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430 \u043f\u0440\u0438\u0432\u043d\u043e\u0441\u0438\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u0438\u043d\u043e\u0437\u0430\u043b\u0430 \u043f\u0440\u044f\u043c\u0438\u043a\u043e\u043c \u0432 \u0432\u0430\u0448\u0443 \u0433\u043e\u0441\u0442\u0438\u043d\u0443\u044e, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u043c.", "OptionTrailersFromMyMovies": "\u041e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u043a \u0444\u0438\u043b\u044c\u043c\u0430\u043c \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0441\u044f \u0432 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435", "OptionUpcomingMoviesInTheaters": "\u041e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u043a \u043d\u043e\u0432\u044b\u043c \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0444\u0438\u043b\u044c\u043c\u0430\u043c", "LabelLimitIntrosToUnwatchedContent": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u043d\u0435\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u043e\u043c\u0443 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e", @@ -1286,8 +1286,8 @@ "LabelEnableIntroParentalControlHelp": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0435\u0439 \u0440\u0430\u0432\u043d\u043e\u0439 \u0438\u043b\u0438 \u043c\u0435\u043d\u044c\u0448\u0435\u0439, \u0447\u0435\u043c \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435.", "LabelTheseFeaturesRequireSupporterHelpAndTrailers": "\u0414\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.", "OptionTrailersFromMyMoviesHelp": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.", - "LabelCustomIntrosPath": "\u041f\u0443\u0442\u044c \u043a \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0430\u043c:", - "LabelCustomIntrosPathHelp": "\u041f\u0430\u043f\u043a\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b. \u0412\u0438\u0434\u0435\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043e \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.", + "LabelCustomIntrosPath": "\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0430\u043c:", + "LabelCustomIntrosPathHelp": "\u041f\u0430\u043f\u043a\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b. \u0421\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0432\u0438\u0434\u0435\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.", "ValueSpecialEpisodeName": "\u0421\u043f\u0435\u0446\u044d\u043f\u0438\u0437\u043e\u0434 - {0}", "LabelSelectInternetTrailersForCinemaMode": "\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b:", "OptionUpcomingDvdMovies": "\u041e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u043a \u043d\u043e\u0432\u044b\u043c \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0444\u0438\u043b\u044c\u043c\u0430\u043c \u043d\u0430 DVD \u0438 BluRay", @@ -1308,11 +1308,11 @@ "HeaderCameraUploadHelp": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u0441\u043d\u044f\u0442\u044b\u0445 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0439 \u0438 \u0432\u0438\u0434\u0435\u043e \u0438\u0437 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0432 Emby.", "MessageNoDevicesSupportCameraUpload": "\u041d\u0435\u0442 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0445 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u0435 \u0441 \u043a\u0430\u043c\u0435\u0440\u044b.", "LabelCameraUploadPath": "\u041f\u0443\u0442\u044c \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0441 \u043a\u0430\u043c\u0435\u0440\u044b:", - "LabelCameraUploadPathHelp": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u044f, \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e. \u0415\u0441\u043b\u0438 \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u043e, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u043f\u0430\u043f\u043a\u0430. \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0442\u043e \u0435\u0433\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438.", + "LabelCameraUploadPathHelp": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u044f, \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e. \u0415\u0441\u043b\u0438 \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u043e, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u043f\u0430\u043f\u043a\u0430. \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0442\u043e \u0435\u0433\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438.", "LabelCreateCameraUploadSubfolder": "\u0421\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430", "LabelCreateCameraUploadSubfolderHelp": "\u041d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0449\u0435\u043b\u0447\u043a\u0435 \u043d\u0430 \u043d\u0451\u043c \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \"\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\".", "LabelCustomDeviceDisplayName": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435:", - "LabelCustomDeviceDisplayNameHelp": "\u041f\u0440\u0438\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u044f, \u0432\u044b\u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c.", + "LabelCustomDeviceDisplayNameHelp": "\u041f\u0440\u0438\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u044f, \u0432\u044b\u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c.", "HeaderInviteUser": "\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", "LabelConnectGuestUserNameHelp": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u044d-\u043f\u043e\u0447\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u0430\u0448 \u0434\u0440\u0443\u0433 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 \u043d\u0430 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442 Emby.", "HeaderInviteUserHelp": "\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0430\u0448\u0438\u043c \u0434\u0440\u0443\u0437\u044c\u044f\u043c \u043e\u0431\u0449\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 Emby Connect.", @@ -1403,7 +1403,7 @@ "LabelRemoteClientBitrateLimit": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u041c\u0431\u0438\u0442\/\u0441", "LabelRemoteClientBitrateLimitHelp": "\u041d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432. \u042d\u0442\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438 \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438, \u0447\u0435\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.", "LabelConversionCpuCoreLimit": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043d\u044b\u0445 \u044f\u0434\u0435\u0440:", - "LabelConversionCpuCoreLimitHelp": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u043b\u043e \u044f\u0434\u0435\u0440 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u044b \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438.", + "LabelConversionCpuCoreLimitHelp": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u043b\u043e \u044f\u0434\u0435\u0440 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u044b \u0432\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.", "OptionEnableFullSpeedConversion": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435", "OptionEnableFullSpeedConversionHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043d\u0438\u0437\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438, \u0447\u0442\u043e\u0431\u044b \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432.", "HeaderPlaylists": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index d0c4aa164d..caff2426a2 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -803,6 +803,7 @@ "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.", "LabelMaxStreamingBitrate": "Max streaming bitrate:", "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.", + "LabelMaxChromecastBitrate": "Max Chromecast bitrate:", "LabelMaxStaticBitrate": "Max sync bitrate:", "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.", "LabelMusicStaticBitrate": "Music sync bitrate:", @@ -1432,7 +1433,7 @@ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?", "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences.", "HeaderViewStyles": "View Styles", - "LabelSelectViewStyles": "Enable rich presentations for:", + "LabelSelectViewStyles": "Enable enhanced presentations for:", "LabelSelectViewStylesHelp": "If enabled, views will be built with metadata to offer categories such as Suggestions, Latest, Genres, and more. If disabled, they'll be displayed with simple folders.", "TabPhotos": "Photos", "TabVideos": "Videos", diff --git a/MediaBrowser.Server.Implementations/Localization/cultures.json b/MediaBrowser.Server.Implementations/Localization/cultures.json deleted file mode 100644 index e9732fda86..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/cultures.json +++ /dev/null @@ -1 +0,0 @@ -[{"Name":"af","DisplayName":"Afrikaans","TwoLetterISOLanguageName":"af","ThreeLetterISOLanguageName":"afr"},{"Name":"sq","DisplayName":"Albanian","TwoLetterISOLanguageName":"sq","ThreeLetterISOLanguageName":"sqi"},{"Name":"gsw","DisplayName":"Alsatian","TwoLetterISOLanguageName":"gsw","ThreeLetterISOLanguageName":"gsw"},{"Name":"am","DisplayName":"Amharic","TwoLetterISOLanguageName":"am","ThreeLetterISOLanguageName":"amh"},{"Name":"ar","DisplayName":"Arabic","TwoLetterISOLanguageName":"ar","ThreeLetterISOLanguageName":"ara"},{"Name":"hy","DisplayName":"Armenian","TwoLetterISOLanguageName":"hy","ThreeLetterISOLanguageName":"hye"},{"Name":"as","DisplayName":"Assamese","TwoLetterISOLanguageName":"as","ThreeLetterISOLanguageName":"asm"},{"Name":"az","DisplayName":"Azeri","TwoLetterISOLanguageName":"az","ThreeLetterISOLanguageName":"aze"},{"Name":"jv","DisplayName":"Basa Jawa","TwoLetterISOLanguageName":"jv","ThreeLetterISOLanguageName":"jav"},{"Name":"ba","DisplayName":"Bashkir","TwoLetterISOLanguageName":"ba","ThreeLetterISOLanguageName":"bak"},{"Name":"eu","DisplayName":"Basque","TwoLetterISOLanguageName":"eu","ThreeLetterISOLanguageName":"eus"},{"Name":"be","DisplayName":"Belarusian","TwoLetterISOLanguageName":"be","ThreeLetterISOLanguageName":"bel"},{"Name":"bn","DisplayName":"Bengali","TwoLetterISOLanguageName":"bn","ThreeLetterISOLanguageName":"bng"},{"Name":"bs","DisplayName":"Bosnian","TwoLetterISOLanguageName":"bs","ThreeLetterISOLanguageName":"bsb"},{"Name":"bs-Cyrl","DisplayName":"Bosnian (Cyrillic)","TwoLetterISOLanguageName":"bs","ThreeLetterISOLanguageName":"bsc"},{"Name":"br","DisplayName":"Breton","TwoLetterISOLanguageName":"br","ThreeLetterISOLanguageName":"bre"},{"Name":"bg","DisplayName":"Bulgarian","TwoLetterISOLanguageName":"bg","ThreeLetterISOLanguageName":"bul"},{"Name":"my","DisplayName":"Burmese","TwoLetterISOLanguageName":"my","ThreeLetterISOLanguageName":"mya"},{"Name":"ca","DisplayName":"Catalan","TwoLetterISOLanguageName":"ca","ThreeLetterISOLanguageName":"cat"},{"Name":"tzm-Tfng-MA","DisplayName":"Central Atlas Tamazight (Tifinagh, Morocco)","TwoLetterISOLanguageName":"tzm","ThreeLetterISOLanguageName":"tzm"},{"Name":"ku","DisplayName":"Central Kurdish","TwoLetterISOLanguageName":"ku","ThreeLetterISOLanguageName":"kur"},{"Name":"chr","DisplayName":"Cherokee","TwoLetterISOLanguageName":"chr","ThreeLetterISOLanguageName":"chr"},{"Name":"zh","DisplayName":"Chinese","TwoLetterISOLanguageName":"zh","ThreeLetterISOLanguageName":"zho"},{"Name":"sn","DisplayName":"chiShona","TwoLetterISOLanguageName":"sn","ThreeLetterISOLanguageName":"sna"},{"Name":"co","DisplayName":"Corsican","TwoLetterISOLanguageName":"co","ThreeLetterISOLanguageName":"cos"},{"Name":"hr","DisplayName":"Croatian","TwoLetterISOLanguageName":"hr","ThreeLetterISOLanguageName":"hrv"},{"Name":"hr-BA","DisplayName":"Croatian (Latin, Bosnia and Herzegovina)","TwoLetterISOLanguageName":"hr","ThreeLetterISOLanguageName":"hrb"},{"Name":"cs","DisplayName":"Czech","TwoLetterISOLanguageName":"cs","ThreeLetterISOLanguageName":"ces"},{"Name":"da","DisplayName":"Danish","TwoLetterISOLanguageName":"da","ThreeLetterISOLanguageName":"dan"},{"Name":"prs","DisplayName":"Dari","TwoLetterISOLanguageName":"prs","ThreeLetterISOLanguageName":"prs"},{"Name":"dv","DisplayName":"Divehi","TwoLetterISOLanguageName":"dv","ThreeLetterISOLanguageName":"div"},{"Name":"nl","DisplayName":"Dutch","TwoLetterISOLanguageName":"nl","ThreeLetterISOLanguageName":"nld"},{"Name":"en","DisplayName":"English","TwoLetterISOLanguageName":"en","ThreeLetterISOLanguageName":"eng"},{"Name":"et","DisplayName":"Estonian","TwoLetterISOLanguageName":"et","ThreeLetterISOLanguageName":"est"},{"Name":"fo","DisplayName":"Faroese","TwoLetterISOLanguageName":"fo","ThreeLetterISOLanguageName":"fao"},{"Name":"fil","DisplayName":"Filipino","TwoLetterISOLanguageName":"fil","ThreeLetterISOLanguageName":"fil"},{"Name":"fi","DisplayName":"Finnish","TwoLetterISOLanguageName":"fi","ThreeLetterISOLanguageName":"fin"},{"Name":"fr","DisplayName":"French","TwoLetterISOLanguageName":"fr","ThreeLetterISOLanguageName":"fra"},{"Name":"fy","DisplayName":"Frisian","TwoLetterISOLanguageName":"fy","ThreeLetterISOLanguageName":"fry"},{"Name":"ff","DisplayName":"Fulah","TwoLetterISOLanguageName":"ff","ThreeLetterISOLanguageName":"ful"},{"Name":"gl","DisplayName":"Galician","TwoLetterISOLanguageName":"gl","ThreeLetterISOLanguageName":"glg"},{"Name":"ka","DisplayName":"Georgian","TwoLetterISOLanguageName":"ka","ThreeLetterISOLanguageName":"kat"},{"Name":"de","DisplayName":"German","TwoLetterISOLanguageName":"de","ThreeLetterISOLanguageName":"deu"},{"Name":"el","DisplayName":"Greek","TwoLetterISOLanguageName":"el","ThreeLetterISOLanguageName":"ell"},{"Name":"kl","DisplayName":"Greenlandic","TwoLetterISOLanguageName":"kl","ThreeLetterISOLanguageName":"kal"},{"Name":"gn","DisplayName":"Guarani","TwoLetterISOLanguageName":"gn","ThreeLetterISOLanguageName":"grn"},{"Name":"gu","DisplayName":"Gujarati","TwoLetterISOLanguageName":"gu","ThreeLetterISOLanguageName":"guj"},{"Name":"ha","DisplayName":"Hausa","TwoLetterISOLanguageName":"ha","ThreeLetterISOLanguageName":"hau"},{"Name":"haw","DisplayName":"Hawaiian","TwoLetterISOLanguageName":"haw","ThreeLetterISOLanguageName":"haw"},{"Name":"he","DisplayName":"Hebrew","TwoLetterISOLanguageName":"he","ThreeLetterISOLanguageName":"heb"},{"Name":"hi","DisplayName":"Hindi","TwoLetterISOLanguageName":"hi","ThreeLetterISOLanguageName":"hin"},{"Name":"hu","DisplayName":"Hungarian","TwoLetterISOLanguageName":"hu","ThreeLetterISOLanguageName":"hun"},{"Name":"is","DisplayName":"Icelandic","TwoLetterISOLanguageName":"is","ThreeLetterISOLanguageName":"isl"},{"Name":"ig","DisplayName":"Igbo","TwoLetterISOLanguageName":"ig","ThreeLetterISOLanguageName":"ibo"},{"Name":"id","DisplayName":"Indonesian","TwoLetterISOLanguageName":"id","ThreeLetterISOLanguageName":"ind"},{"Name":"iu","DisplayName":"Inuktitut","TwoLetterISOLanguageName":"iu","ThreeLetterISOLanguageName":"iku"},{"Name":"ga","DisplayName":"Irish","TwoLetterISOLanguageName":"ga","ThreeLetterISOLanguageName":"gle"},{"Name":"xh","DisplayName":"isiXhosa","TwoLetterISOLanguageName":"xh","ThreeLetterISOLanguageName":"xho"},{"Name":"zu","DisplayName":"isiZulu","TwoLetterISOLanguageName":"zu","ThreeLetterISOLanguageName":"zul"},{"Name":"it","DisplayName":"Italian","TwoLetterISOLanguageName":"it","ThreeLetterISOLanguageName":"ita"},{"Name":"ja","DisplayName":"Japanese","TwoLetterISOLanguageName":"ja","ThreeLetterISOLanguageName":"jpn"},{"Name":"kn","DisplayName":"Kannada","TwoLetterISOLanguageName":"kn","ThreeLetterISOLanguageName":"kan"},{"Name":"kk","DisplayName":"Kazakh","TwoLetterISOLanguageName":"kk","ThreeLetterISOLanguageName":"kaz"},{"Name":"km","DisplayName":"Khmer","TwoLetterISOLanguageName":"km","ThreeLetterISOLanguageName":"khm"},{"Name":"qut","DisplayName":"K'iche","TwoLetterISOLanguageName":"qut","ThreeLetterISOLanguageName":"qut"},{"Name":"rw","DisplayName":"Kinyarwanda","TwoLetterISOLanguageName":"rw","ThreeLetterISOLanguageName":"kin"},{"Name":"sw","DisplayName":"Kiswahili","TwoLetterISOLanguageName":"sw","ThreeLetterISOLanguageName":"swa"},{"Name":"kok","DisplayName":"Konkani","TwoLetterISOLanguageName":"kok","ThreeLetterISOLanguageName":"kok"},{"Name":"ko","DisplayName":"Korean","TwoLetterISOLanguageName":"ko","ThreeLetterISOLanguageName":"kor"},{"Name":"ky","DisplayName":"Kyrgyz","TwoLetterISOLanguageName":"ky","ThreeLetterISOLanguageName":"kir"},{"Name":"lo","DisplayName":"Lao","TwoLetterISOLanguageName":"lo","ThreeLetterISOLanguageName":"lao"},{"Name":"lv","DisplayName":"Latvian","TwoLetterISOLanguageName":"lv","ThreeLetterISOLanguageName":"lav"},{"Name":"lt","DisplayName":"Lithuanian","TwoLetterISOLanguageName":"lt","ThreeLetterISOLanguageName":"lit"},{"Name":"dsb","DisplayName":"Lower Sorbian","TwoLetterISOLanguageName":"dsb","ThreeLetterISOLanguageName":"dsb"},{"Name":"lb","DisplayName":"Luxembourgish","TwoLetterISOLanguageName":"lb","ThreeLetterISOLanguageName":"ltz"},{"Name":"mk-MK","DisplayName":"Macedonian (Former Yugoslav Republic of Macedonia)","TwoLetterISOLanguageName":"mk","ThreeLetterISOLanguageName":"mkd"},{"Name":"mg","DisplayName":"Malagasy","TwoLetterISOLanguageName":"mg","ThreeLetterISOLanguageName":"mlg"},{"Name":"ms","DisplayName":"Malay","TwoLetterISOLanguageName":"ms","ThreeLetterISOLanguageName":"msa"},{"Name":"ml","DisplayName":"Malayalam","TwoLetterISOLanguageName":"ml","ThreeLetterISOLanguageName":"mym"},{"Name":"mt","DisplayName":"Maltese","TwoLetterISOLanguageName":"mt","ThreeLetterISOLanguageName":"mlt"},{"Name":"mi","DisplayName":"Maori","TwoLetterISOLanguageName":"mi","ThreeLetterISOLanguageName":"mri"},{"Name":"arn","DisplayName":"Mapudungun","TwoLetterISOLanguageName":"arn","ThreeLetterISOLanguageName":"arn"},{"Name":"mr","DisplayName":"Marathi","TwoLetterISOLanguageName":"mr","ThreeLetterISOLanguageName":"mar"},{"Name":"moh","DisplayName":"Mohawk","TwoLetterISOLanguageName":"moh","ThreeLetterISOLanguageName":"moh"},{"Name":"mn","DisplayName":"Mongolian","TwoLetterISOLanguageName":"mn","ThreeLetterISOLanguageName":"mon"},{"Name":"ne","DisplayName":"Nepali","TwoLetterISOLanguageName":"ne","ThreeLetterISOLanguageName":"nep"},{"Name":"no","DisplayName":"Norwegian","TwoLetterISOLanguageName":"nb","ThreeLetterISOLanguageName":"nob"},{"Name":"nn","DisplayName":"Norwegian (Nynorsk)","TwoLetterISOLanguageName":"nn","ThreeLetterISOLanguageName":"nno"},{"Name":"oc","DisplayName":"Occitan","TwoLetterISOLanguageName":"oc","ThreeLetterISOLanguageName":"oci"},{"Name":"or","DisplayName":"Oriya","TwoLetterISOLanguageName":"or","ThreeLetterISOLanguageName":"ori"},{"Name":"om","DisplayName":"Oromo","TwoLetterISOLanguageName":"om","ThreeLetterISOLanguageName":"orm"},{"Name":"ps","DisplayName":"Pashto","TwoLetterISOLanguageName":"ps","ThreeLetterISOLanguageName":"pus"},{"Name":"fa","DisplayName":"Persian","TwoLetterISOLanguageName":"fa","ThreeLetterISOLanguageName":"fas"},{"Name":"pl","DisplayName":"Polish","TwoLetterISOLanguageName":"pl","ThreeLetterISOLanguageName":"pol"},{"Name":"pt-AO","DisplayName":"português (Angola)","TwoLetterISOLanguageName":"pt","ThreeLetterISOLanguageName":"por"},{"Name":"pa","DisplayName":"Punjabi","TwoLetterISOLanguageName":"pa","ThreeLetterISOLanguageName":"pan"},{"Name":"quz","DisplayName":"Quechua","TwoLetterISOLanguageName":"quz","ThreeLetterISOLanguageName":"qub"},{"Name":"quz-EC","DisplayName":"Quechua (Ecuador)","TwoLetterISOLanguageName":"quz","ThreeLetterISOLanguageName":"que"},{"Name":"quz-PE","DisplayName":"Quechua (Peru)","TwoLetterISOLanguageName":"quz","ThreeLetterISOLanguageName":"qup"},{"Name":"ro","DisplayName":"Romanian","TwoLetterISOLanguageName":"ro","ThreeLetterISOLanguageName":"ron"},{"Name":"rm","DisplayName":"Romansh","TwoLetterISOLanguageName":"rm","ThreeLetterISOLanguageName":"roh"},{"Name":"ru","DisplayName":"Russian","TwoLetterISOLanguageName":"ru","ThreeLetterISOLanguageName":"rus"},{"Name":"sah","DisplayName":"Sakha","TwoLetterISOLanguageName":"sah","ThreeLetterISOLanguageName":"sah"},{"Name":"smn","DisplayName":"Sami (Inari)","TwoLetterISOLanguageName":"smn","ThreeLetterISOLanguageName":"smn"},{"Name":"smj","DisplayName":"Sami (Lule)","TwoLetterISOLanguageName":"smj","ThreeLetterISOLanguageName":"smj"},{"Name":"se","DisplayName":"Sami (Northern)","TwoLetterISOLanguageName":"se","ThreeLetterISOLanguageName":"sme"},{"Name":"sms","DisplayName":"Sami (Skolt)","TwoLetterISOLanguageName":"sms","ThreeLetterISOLanguageName":"sms"},{"Name":"sma","DisplayName":"Sami (Southern)","TwoLetterISOLanguageName":"sma","ThreeLetterISOLanguageName":"sma"},{"Name":"sa","DisplayName":"Sanskrit","TwoLetterISOLanguageName":"sa","ThreeLetterISOLanguageName":"san"},{"Name":"gd","DisplayName":"Scottish Gaelic","TwoLetterISOLanguageName":"gd","ThreeLetterISOLanguageName":"gla"},{"Name":"sr","DisplayName":"Serbian","TwoLetterISOLanguageName":"sr","ThreeLetterISOLanguageName":"srp"},{"Name":"sr-Cyrl-BA","DisplayName":"Serbian (Cyrillic, Bosnia and Herzegovina)","TwoLetterISOLanguageName":"sr","ThreeLetterISOLanguageName":"srn"},{"Name":"sr-Latn-BA","DisplayName":"Serbian (Latin, Bosnia and Herzegovina)","TwoLetterISOLanguageName":"sr","ThreeLetterISOLanguageName":"srs"},{"Name":"nso","DisplayName":"Sesotho sa Leboa","TwoLetterISOLanguageName":"nso","ThreeLetterISOLanguageName":"nso"},{"Name":"tn","DisplayName":"Setswana","TwoLetterISOLanguageName":"tn","ThreeLetterISOLanguageName":"tsn"},{"Name":"sd","DisplayName":"Sindhi","TwoLetterISOLanguageName":"sd","ThreeLetterISOLanguageName":"sin"},{"Name":"si","DisplayName":"Sinhala","TwoLetterISOLanguageName":"si","ThreeLetterISOLanguageName":"sin"},{"Name":"sk","DisplayName":"Slovak","TwoLetterISOLanguageName":"sk","ThreeLetterISOLanguageName":"slk"},{"Name":"sl","DisplayName":"Slovenian","TwoLetterISOLanguageName":"sl","ThreeLetterISOLanguageName":"slv"},{"Name":"so","DisplayName":"Somali","TwoLetterISOLanguageName":"so","ThreeLetterISOLanguageName":"som"},{"Name":"st","DisplayName":"Southern Sotho","TwoLetterISOLanguageName":"st","ThreeLetterISOLanguageName":"sot"},{"Name":"es","DisplayName":"Spanish","TwoLetterISOLanguageName":"es","ThreeLetterISOLanguageName":"spa"},{"Name":"zgh","DisplayName":"Standard Morrocan Tamazight","TwoLetterISOLanguageName":"zgh","ThreeLetterISOLanguageName":"zgh"},{"Name":"sv","DisplayName":"Swedish","TwoLetterISOLanguageName":"sv","ThreeLetterISOLanguageName":"swe"},{"Name":"syr","DisplayName":"Syriac","TwoLetterISOLanguageName":"syr","ThreeLetterISOLanguageName":"syr"},{"Name":"tg","DisplayName":"Tajik","TwoLetterISOLanguageName":"tg","ThreeLetterISOLanguageName":"tgk"},{"Name":"ta","DisplayName":"Tamil","TwoLetterISOLanguageName":"ta","ThreeLetterISOLanguageName":"tam"},{"Name":"tt","DisplayName":"Tatar","TwoLetterISOLanguageName":"tt","ThreeLetterISOLanguageName":"tat"},{"Name":"te","DisplayName":"Telugu","TwoLetterISOLanguageName":"te","ThreeLetterISOLanguageName":"tel"},{"Name":"th","DisplayName":"Thai","TwoLetterISOLanguageName":"th","ThreeLetterISOLanguageName":"tha"},{"Name":"bo","DisplayName":"Tibetan","TwoLetterISOLanguageName":"bo","ThreeLetterISOLanguageName":"bod"},{"Name":"ti","DisplayName":"Tigrinya","TwoLetterISOLanguageName":"ti","ThreeLetterISOLanguageName":"tir"},{"Name":"ts","DisplayName":"Tsonga","TwoLetterISOLanguageName":"ts","ThreeLetterISOLanguageName":"tso"},{"Name":"tr","DisplayName":"Turkish","TwoLetterISOLanguageName":"tr","ThreeLetterISOLanguageName":"tur"},{"Name":"tk","DisplayName":"Turkmen","TwoLetterISOLanguageName":"tk","ThreeLetterISOLanguageName":"tuk"},{"Name":"uk","DisplayName":"Ukrainian","TwoLetterISOLanguageName":"uk","ThreeLetterISOLanguageName":"ukr"},{"Name":"hsb","DisplayName":"Upper Sorbian","TwoLetterISOLanguageName":"hsb","ThreeLetterISOLanguageName":"hsb"},{"Name":"ur","DisplayName":"Urdu","TwoLetterISOLanguageName":"ur","ThreeLetterISOLanguageName":"urd"},{"Name":"ug","DisplayName":"Uyghur","TwoLetterISOLanguageName":"ug","ThreeLetterISOLanguageName":"uig"},{"Name":"uz","DisplayName":"Uzbek","TwoLetterISOLanguageName":"uz","ThreeLetterISOLanguageName":"uzb"},{"Name":"vi","DisplayName":"Vietnamese","TwoLetterISOLanguageName":"vi","ThreeLetterISOLanguageName":"vie"},{"Name":"cy","DisplayName":"Welsh","TwoLetterISOLanguageName":"cy","ThreeLetterISOLanguageName":"cym"},{"Name":"wo","DisplayName":"Wolof","TwoLetterISOLanguageName":"wo","ThreeLetterISOLanguageName":"wol"},{"Name":"ii","DisplayName":"Yi","TwoLetterISOLanguageName":"ii","ThreeLetterISOLanguageName":"iii"},{"Name":"yo","DisplayName":"Yoruba","TwoLetterISOLanguageName":"yo","ThreeLetterISOLanguageName":"yor"}] \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 0d545fb6a5..9e7810c761 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -50,11 +50,11 @@ False - ..\packages\MediaBrowser.Naming.1.0.0.32\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll + ..\packages\MediaBrowser.Naming.1.0.0.34\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll - + False - ..\packages\Mono.Nat.1.2.23.0\lib\net40\Mono.Nat.dll + ..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll False @@ -401,7 +401,6 @@ - diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 61432d00fb..e063d44dc6 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -435,7 +435,9 @@ namespace MediaBrowser.Server.Implementations.Persistence _shrinkMemoryTimer.Dispose(); _shrinkMemoryTimer = null; } - + + _writeLock.Wait(); + if (_connection != null) { if (_connection.IsOpen()) diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index fd4d5eb27d..be71a6408a 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Photos { var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png"); Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var imageCreated = CreateImage(item, itemsWithImages, outputPath, imageType, 0); + var imageCreated = await CreateImage(item, itemsWithImages, outputPath, imageType, 0).ConfigureAwait(false); if (!imageCreated) { @@ -103,9 +103,9 @@ namespace MediaBrowser.Server.Implementations.Photos return parts.GetMD5().ToString("N"); } - protected void CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) + protected Task CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) { - CreateCollage(primaryItem, items, outputPath, 960, 540, drawText, primaryItem.Name); + return CreateCollage(primaryItem, items, outputPath, 960, 540, drawText, primaryItem.Name); } protected virtual IEnumerable GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable items) @@ -115,22 +115,22 @@ namespace MediaBrowser.Server.Implementations.Photos .Where(i => !string.IsNullOrWhiteSpace(i)); } - protected void CreatePosterCollage(IHasImages primaryItem, List items, string outputPath) + protected Task CreatePosterCollage(IHasImages primaryItem, List items, string outputPath) { - CreateCollage(primaryItem, items, outputPath, 600, 900, true, primaryItem.Name); + return CreateCollage(primaryItem, items, outputPath, 600, 900, true, primaryItem.Name); } - protected void CreateSquareCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) + protected Task CreateSquareCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) { - CreateCollage(primaryItem, items, outputPath, 800, 800, drawText, primaryItem.Name); + return CreateCollage(primaryItem, items, outputPath, 800, 800, drawText, primaryItem.Name); } - protected void CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, int width, int height, bool drawText, string text) + protected Task CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, int width, int height, bool drawText, string text) { - CreateCollage(primaryItem, items, outputPath, width, height, drawText, text); + return CreateCollage(primaryItem, items, outputPath, width, height, drawText, text); } - private void CreateCollage(IHasImages primaryItem, List items, string outputPath, int width, int height, bool drawText, string text) + private Task CreateCollage(IHasImages primaryItem, List items, string outputPath, int width, int height, bool drawText, string text) { Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); @@ -143,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.Photos InputPaths = GetStripCollageImagePaths(primaryItem, items).ToArray() }; - ImageProcessor.CreateImageCollage(options); + return ImageProcessor.CreateImageCollage(options); } public string Name @@ -151,7 +151,7 @@ namespace MediaBrowser.Server.Implementations.Photos get { return "Dynamic Image Provider"; } } - protected virtual bool CreateImage(IHasImages item, + protected virtual async Task CreateImage(IHasImages item, List itemsWithImages, string outputPath, ImageType imageType, @@ -166,7 +166,7 @@ namespace MediaBrowser.Server.Implementations.Photos if (imageType == ImageType.Thumb) { - CreateThumbCollage(item, itemsWithImages, outputPath, drawText); + await CreateThumbCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false); return true; } @@ -174,15 +174,15 @@ namespace MediaBrowser.Server.Implementations.Photos { if (item is UserView) { - CreateSquareCollage(item, itemsWithImages, outputPath, drawText); + await CreateSquareCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false); } else if (item is PhotoAlbum || item is Playlist) { - CreateSquareCollage(item, itemsWithImages, outputPath, drawText); + await CreateSquareCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false); } else { - CreatePosterCollage(item, itemsWithImages, outputPath); + await CreatePosterCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); } return true; @@ -234,7 +234,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected virtual List GetFinalItems(List items, int limit) { // Rotate the images once every x days - var random = DateTime.Now.DayOfYear % 4; + var random = DateTime.Now.DayOfYear % 7; return items .OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5()) diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs index 992f1d16c0..6272fe9261 100644 --- a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs +++ b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; -using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dlna; +using System.Collections.Generic; namespace MediaBrowser.Server.Implementations.Sync { @@ -27,17 +27,17 @@ namespace MediaBrowser.Server.Implementations.Sync } var videoProfile = "high|main|baseline|constrained baseline"; - var videoLevel = "41"; + var videoLevel = "40"; DirectPlayProfiles = new[] { - new DirectPlayProfile - { - Container = "mkv", - VideoCodec = "h264,mpeg4", - AudioCodec = mkvAudio, - Type = DlnaProfileType.Video - }, + //new DirectPlayProfile + //{ + // Container = "mkv", + // VideoCodec = "h264,mpeg4", + // AudioCodec = mkvAudio, + // Type = DlnaProfileType.Video + //}, new DirectPlayProfile { Container = "mp4,mov,m4v", diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 235c36e8c4..0e4a3bcf13 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -512,7 +512,7 @@ namespace MediaBrowser.Server.Implementations.Sync var video = item as Video; if (video != null) { - if (video.VideoType == VideoType.Iso || video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd || video.VideoType == VideoType.HdDvd) + if (video.VideoType == VideoType.Iso || video.VideoType == VideoType.HdDvd) { return false; } @@ -758,6 +758,8 @@ namespace MediaBrowser.Server.Implementations.Sync var requiresSaving = false; var removeFromDevice = false; + var libraryItem = _libraryManager.GetItemById(jobItem.ItemId); + if (request.LocalItemIds.Contains(jobItem.ItemId, StringComparer.OrdinalIgnoreCase)) { var job = _repo.GetJob(jobItem.JobId); @@ -775,23 +777,18 @@ namespace MediaBrowser.Server.Implementations.Sync _logger.Debug("Adding ItemIdsToRemove {0} because the user is no longer valid.", jobItem.ItemId); removeFromDevice = true; } + else if (!IsLibraryItemAvailable(libraryItem)) + { + // Tell the device to remove it since it's no longer available + _logger.Debug("Adding ItemIdsToRemove {0} because it is no longer available.", jobItem.ItemId); + removeFromDevice = true; + } else if (job.UnwatchedOnly) { - var libraryItem = _libraryManager.GetItemById(jobItem.ItemId); - - if (IsLibraryItemAvailable(libraryItem)) + if (libraryItem.IsPlayed(user) && libraryItem is Video) { - if (libraryItem.IsPlayed(user) && libraryItem is Video) - { - // Tell the device to remove it since it has been played - _logger.Debug("Adding ItemIdsToRemove {0} because it has been marked played.", jobItem.ItemId); - removeFromDevice = true; - } - } - else - { - // Tell the device to remove it since it's no longer available - _logger.Debug("Adding ItemIdsToRemove {0} because it is no longer available.", jobItem.ItemId); + // Tell the device to remove it since it has been played + _logger.Debug("Adding ItemIdsToRemove {0} because it has been marked played.", jobItem.ItemId); removeFromDevice = true; } } @@ -866,6 +863,8 @@ namespace MediaBrowser.Server.Implementations.Sync var requiresSaving = false; var removeFromDevice = false; + var libraryItem = _libraryManager.GetItemById(jobItem.ItemId); + if (request.SyncJobItemIds.Contains(jobItem.Id, StringComparer.OrdinalIgnoreCase)) { var job = _repo.GetJob(jobItem.JobId); @@ -883,23 +882,18 @@ namespace MediaBrowser.Server.Implementations.Sync _logger.Debug("Adding ItemIdsToRemove {0} because the user is no longer valid.", jobItem.Id); removeFromDevice = true; } + else if (!IsLibraryItemAvailable(libraryItem)) + { + // Tell the device to remove it since it's no longer available + _logger.Debug("Adding ItemIdsToRemove {0} because it is no longer available.", jobItem.Id); + removeFromDevice = true; + } else if (job.UnwatchedOnly) { - var libraryItem = _libraryManager.GetItemById(jobItem.ItemId); - - if (IsLibraryItemAvailable(libraryItem)) + if (libraryItem.IsPlayed(user) && libraryItem is Video) { - if (libraryItem.IsPlayed(user) && libraryItem is Video) - { - // Tell the device to remove it since it has been played - _logger.Debug("Adding ItemIdsToRemove {0} because it has been marked played.", jobItem.Id); - removeFromDevice = true; - } - } - else - { - // Tell the device to remove it since it's no longer available - _logger.Debug("Adding ItemIdsToRemove {0} because it is no longer available.", jobItem.Id); + // Tell the device to remove it since it has been played + _logger.Debug("Adding ItemIdsToRemove {0} because it has been marked played.", jobItem.Id); removeFromDevice = true; } } diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs index 4a4d90d14f..93a9bc8f6f 100644 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -18,7 +18,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.UserViews { - public class DynamicImageProvider : BaseDynamicImageProvider, IPreRefreshProvider + public class DynamicImageProvider : BaseDynamicImageProvider { private readonly IUserManager _userManager; private readonly ILibraryManager _libraryManager; @@ -216,7 +216,7 @@ namespace MediaBrowser.Server.Implementations.UserViews return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty); } - protected override bool CreateImage(IHasImages item, List itemsWithImages, string outputPath, ImageType imageType, int imageIndex) + protected override async Task CreateImage(IHasImages item, List itemsWithImages, string outputPath, ImageType imageType, int imageIndex) { var view = (UserView)item; if (imageType == ImageType.Primary && IsUsingCollectionStrip(view)) @@ -226,11 +226,11 @@ namespace MediaBrowser.Server.Implementations.UserViews return false; } - CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540, false, item.Name); + await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540, false, item.Name).ConfigureAwait(false); return true; } - return base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex); + return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false); } protected override IEnumerable GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable items) diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 036dffe95b..7fb3691060 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,8 +1,8 @@  - - + + diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj index 8592fc460e..d1a24ab127 100644 --- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj +++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj @@ -538,6 +538,9 @@ Resources\dashboard-ui\nowplaying.html + + Resources\dashboard-ui\photos.html + Resources\dashboard-ui\playbackconfiguration.html @@ -1444,6 +1447,9 @@ Resources\dashboard-ui\scripts\nowplayingpage.js + + Resources\dashboard-ui\scripts\photos.js + Resources\dashboard-ui\scripts\playbackconfiguration.js diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 0579967394..c9a2d3f22c 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -48,6 +48,7 @@ using MediaBrowser.Dlna.ConnectionManager; using MediaBrowser.Dlna.ContentDirectory; using MediaBrowser.Dlna.Main; using MediaBrowser.Dlna.MediaReceiverRegistrar; +using MediaBrowser.Dlna.Ssdp; using MediaBrowser.LocalMetadata.Providers; using MediaBrowser.MediaEncoding.BdInfo; using MediaBrowser.MediaEncoding.Encoder; @@ -357,10 +358,7 @@ namespace MediaBrowser.Server.Startup.Common private void PerformPostInitMigrations() { - var migrations = new List - { - new MigrateTranscodingPath(ServerConfigurationManager) - }; + var migrations = new List(); foreach (var task in migrations) { @@ -442,7 +440,7 @@ namespace MediaBrowser.Server.Startup.Common var innerProgress = new ActionableProgress(); innerProgress.RegisterAction(p => progress.Report((.75 * p) + 15)); - ImageProcessor = new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, GetImageEncoder()); + ImageProcessor = GetImageProcessor(); RegisterSingleInstance(ImageProcessor); TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager); @@ -523,6 +521,8 @@ namespace MediaBrowser.Server.Startup.Common MediaEncoder, ChapterManager); RegisterSingleInstance(EncodingManager); + RegisterSingleInstance(new SsdpHandler(LogManager.GetLogger("SsdpHandler"), ServerConfigurationManager, this)); + var activityLogRepo = await GetActivityLogRepository().ConfigureAwait(false); RegisterSingleInstance(activityLogRepo); RegisterSingleInstance(new ActivityManager(LogManager.GetLogger("ActivityManager"), activityLogRepo, UserManager)); @@ -546,6 +546,18 @@ namespace MediaBrowser.Server.Startup.Common await ((UserManager)UserManager).Initialize().ConfigureAwait(false); } + private IImageProcessor GetImageProcessor() + { + var maxConcurrentImageProcesses = Math.Max(Environment.ProcessorCount, 4); + + if (_startupOptions.ContainsOption("-imagethreads")) + { + int.TryParse(_startupOptions.GetOption("-imagethreads"), NumberStyles.Any, CultureInfo.InvariantCulture, out maxConcurrentImageProcesses); + } + + return new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, GetImageEncoder(), maxConcurrentImageProcesses); + } + private IImageEncoder GetImageEncoder() { if (!_startupOptions.ContainsOption("-enablegdi")) diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index fb49692b54..4653e6ac77 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -66,7 +66,6 @@ - diff --git a/MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs b/MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs deleted file mode 100644 index 88f60841de..0000000000 --- a/MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Model.Configuration; - -namespace MediaBrowser.Server.Startup.Common.Migrations -{ - public class MigrateTranscodingPath : IVersionMigration - { - private readonly IServerConfigurationManager _config; - - public MigrateTranscodingPath(IServerConfigurationManager config) - { - _config = config; - } - - public void Run() - { - if (!string.IsNullOrWhiteSpace(_config.Configuration.TranscodingTempPath)) - { - var newConfig = _config.GetConfiguration("encoding"); - - newConfig.TranscodingTempPath = _config.Configuration.TranscodingTempPath; - _config.SaveConfiguration("encoding", newConfig); - - _config.Configuration.TranscodingTempPath = null; - _config.SaveConfiguration(); - } - } - } -} diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 5c4a15d70a..7e150248e3 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -60,9 +60,8 @@ true - - False - ..\packages\ImageMagickSharp.1.0.0.15\lib\net45\ImageMagickSharp.dll + + ..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll ..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 6c69a853d6..5007cf8af3 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index e45f524192..8f4d2ae8b7 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -14,199 +14,199 @@ using WebMarkupMin.Core.Settings; namespace MediaBrowser.WebDashboard.Api { - public class PackageCreator - { - private readonly IFileSystem _fileSystem; - private readonly ILocalizationManager _localization; - private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; - private readonly IJsonSerializer _jsonSerializer; + public class PackageCreator + { + private readonly IFileSystem _fileSystem; + private readonly ILocalizationManager _localization; + private readonly ILogger _logger; + private readonly IServerConfigurationManager _config; + private readonly IJsonSerializer _jsonSerializer; - public PackageCreator(IFileSystem fileSystem, ILocalizationManager localization, ILogger logger, IServerConfigurationManager config, IJsonSerializer jsonSerializer) - { - _fileSystem = fileSystem; - _localization = localization; - _logger = logger; - _config = config; - _jsonSerializer = jsonSerializer; - } + public PackageCreator(IFileSystem fileSystem, ILocalizationManager localization, ILogger logger, IServerConfigurationManager config, IJsonSerializer jsonSerializer) + { + _fileSystem = fileSystem; + _localization = localization; + _logger = logger; + _config = config; + _jsonSerializer = jsonSerializer; + } - public async Task GetResource(string path, - string localizationCulture, - string appVersion, bool enableMinification) - { - var isHtml = IsHtml(path); + public async Task GetResource(string path, + string localizationCulture, + string appVersion, bool enableMinification) + { + var isHtml = IsHtml(path); - Stream resourceStream; + Stream resourceStream; - if (path.Equals("scripts/all.js", StringComparison.OrdinalIgnoreCase)) - { - resourceStream = await GetAllJavascript(localizationCulture, appVersion, enableMinification).ConfigureAwait(false); - } - else if (path.Equals("css/all.css", StringComparison.OrdinalIgnoreCase)) - { - resourceStream = await GetAllCss(enableMinification).ConfigureAwait(false); - } - else - { - resourceStream = GetRawResourceStream(path); - } + if (path.Equals("scripts/all.js", StringComparison.OrdinalIgnoreCase)) + { + resourceStream = await GetAllJavascript(localizationCulture, appVersion, enableMinification).ConfigureAwait(false); + } + else if (path.Equals("css/all.css", StringComparison.OrdinalIgnoreCase)) + { + resourceStream = await GetAllCss(enableMinification).ConfigureAwait(false); + } + else + { + resourceStream = GetRawResourceStream(path); + } - if (resourceStream != null) - { - // Don't apply any caching for html pages - // jQuery ajax doesn't seem to handle if-modified-since correctly - if (isHtml) - { - resourceStream = await ModifyHtml(resourceStream, localizationCulture, enableMinification).ConfigureAwait(false); - } - } + if (resourceStream != null) + { + // Don't apply any caching for html pages + // jQuery ajax doesn't seem to handle if-modified-since correctly + if (isHtml) + { + resourceStream = await ModifyHtml(resourceStream, localizationCulture, enableMinification).ConfigureAwait(false); + } + } - return resourceStream; - } + return resourceStream; + } - /// - /// Determines whether the specified path is HTML. - /// - /// The path. - /// true if the specified path is HTML; otherwise, false. - private bool IsHtml(string path) - { - return Path.GetExtension(path).EndsWith("html", StringComparison.OrdinalIgnoreCase); - } + /// + /// Determines whether the specified path is HTML. + /// + /// The path. + /// true if the specified path is HTML; otherwise, false. + private bool IsHtml(string path) + { + return Path.GetExtension(path).EndsWith("html", StringComparison.OrdinalIgnoreCase); + } - /// - /// Gets the dashboard UI path. - /// - /// The dashboard UI path. - public string DashboardUIPath - { - get - { - if (!string.IsNullOrEmpty(_config.Configuration.DashboardSourcePath)) - { - return _config.Configuration.DashboardSourcePath; - } + /// + /// Gets the dashboard UI path. + /// + /// The dashboard UI path. + public string DashboardUIPath + { + get + { + if (!string.IsNullOrEmpty(_config.Configuration.DashboardSourcePath)) + { + return _config.Configuration.DashboardSourcePath; + } - return Path.Combine(_config.ApplicationPaths.ApplicationResourcesPath, "dashboard-ui"); - } - } + return Path.Combine(_config.ApplicationPaths.ApplicationResourcesPath, "dashboard-ui"); + } + } - /// - /// Gets the dashboard resource path. - /// - /// The virtual path. - /// System.String. - private string GetDashboardResourcePath(string virtualPath) - { - return Path.Combine(DashboardUIPath, virtualPath.Replace('/', Path.DirectorySeparatorChar)); - } + /// + /// Gets the dashboard resource path. + /// + /// The virtual path. + /// System.String. + private string GetDashboardResourcePath(string virtualPath) + { + return Path.Combine(DashboardUIPath, virtualPath.Replace('/', Path.DirectorySeparatorChar)); + } - /// - /// Modifies the HTML by adding common meta tags, css and js. - /// - /// The source stream. - /// The localization culture. - /// if set to true [enable minification]. - /// Task{Stream}. - public async Task ModifyHtml(Stream sourceStream, string localizationCulture, bool enableMinification) - { - using (sourceStream) - { - string html; + /// + /// Modifies the HTML by adding common meta tags, css and js. + /// + /// The source stream. + /// The localization culture. + /// if set to true [enable minification]. + /// Task{Stream}. + public async Task ModifyHtml(Stream sourceStream, string localizationCulture, bool enableMinification) + { + using (sourceStream) + { + string html; - using (var memoryStream = new MemoryStream()) - { - await sourceStream.CopyToAsync(memoryStream).ConfigureAwait(false); + using (var memoryStream = new MemoryStream()) + { + await sourceStream.CopyToAsync(memoryStream).ConfigureAwait(false); - html = Encoding.UTF8.GetString(memoryStream.ToArray()); + html = Encoding.UTF8.GetString(memoryStream.ToArray()); - if (!string.IsNullOrWhiteSpace(localizationCulture)) - { - var lang = localizationCulture.Split('-').FirstOrDefault(); + if (!string.IsNullOrWhiteSpace(localizationCulture)) + { + var lang = localizationCulture.Split('-').FirstOrDefault(); - html = _localization.LocalizeDocument(html, localizationCulture, GetLocalizationToken); + html = _localization.LocalizeDocument(html, localizationCulture, GetLocalizationToken); - html = html.Replace("", ""); - } + html = html.Replace("", ""); + } - if (enableMinification) - { - try - { - var minifier = new HtmlMinifier(new HtmlMinificationSettings()); - var result = minifier.Minify(html, false); + if (enableMinification) + { + try + { + var minifier = new HtmlMinifier(new HtmlMinificationSettings()); + var result = minifier.Minify(html, false); - if (result.Errors.Count > 0) - { - _logger.Error("Error minifying html: " + result.Errors[0].Message); - } - else - { - html = result.MinifiedContent; - } - } - catch (Exception ex) - { - _logger.ErrorException("Error minifying html", ex); - } - } - } + if (result.Errors.Count > 0) + { + _logger.Error("Error minifying html: " + result.Errors[0].Message); + } + else + { + html = result.MinifiedContent; + } + } + catch (Exception ex) + { + _logger.ErrorException("Error minifying html", ex); + } + } + } - var version = GetType().Assembly.GetName().Version; + var version = GetType().Assembly.GetName().Version; - html = html.Replace("", "" + GetMetaTags() + GetCommonCss(version) + GetCommonJavascript(version)); + html = html.Replace("", "" + GetMetaTags() + GetCommonCss(version) + GetCommonJavascript(version)); - var bytes = Encoding.UTF8.GetBytes(html); + var bytes = Encoding.UTF8.GetBytes(html); - return new MemoryStream(bytes); - } - } + return new MemoryStream(bytes); + } + } - private string GetLocalizationToken(string phrase) - { - return "${" + phrase + "}"; - } + private string GetLocalizationToken(string phrase) + { + return "${" + phrase + "}"; + } - /// - /// Gets the meta tags. - /// - /// System.String. - private static string GetMetaTags() - { - var sb = new StringBuilder(); + /// + /// Gets the meta tags. + /// + /// System.String. + private static string GetMetaTags() + { + var sb = new StringBuilder(); - sb.Append(""); - sb.Append(""); - //sb.Append(""); - sb.Append(""); - sb.Append(""); - //sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + //sb.Append(""); - sb.Append(""); + sb.Append(""); - // http://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html - sb.Append(""); - sb.Append(""); - sb.Append(""); - sb.Append(""); - sb.Append(""); - sb.Append(""); - sb.Append(""); + // http://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); - return sb.ToString(); - } + return sb.ToString(); + } - /// - /// Gets the common CSS. - /// - /// The version. - /// System.String. - private string GetCommonCss(Version version) - { - var versionString = "?v=" + version; + /// + /// Gets the common CSS. + /// + /// The version. + /// System.String. + private string GetCommonCss(Version version) + { + var versionString = "?v=" + version; - var files = new[] + var files = new[] { "thirdparty/jquerymobile-1.4.5/jquery.mobile-1.4.5.min.css", "thirdparty/swipebox-master/css/swipebox.min.css" + versionString, @@ -215,68 +215,68 @@ namespace MediaBrowser.WebDashboard.Api "css/all.css" + versionString }; - var tags = files.Select(s => string.Format("", s)).ToArray(); + var tags = files.Select(s => string.Format("", s)).ToArray(); - return string.Join(string.Empty, tags); - } + return string.Join(string.Empty, tags); + } - /// - /// Gets the common javascript. - /// - /// The version. - /// System.String. - private string GetCommonJavascript(Version version) - { - var builder = new StringBuilder(); + /// + /// Gets the common javascript. + /// + /// The version. + /// System.String. + private string GetCommonJavascript(Version version) + { + var builder = new StringBuilder(); - var versionString = "?v=" + version; + var versionString = "?v=" + version; - var files = new[] + var files = new[] { "scripts/all.js" + versionString, "thirdparty/swipebox-master/js/jquery.swipebox.min.js" + versionString }; - var tags = files.Select(s => string.Format("", s)).ToArray(); + var tags = files.Select(s => string.Format("", s)).ToArray(); - builder.Append(string.Join(string.Empty, tags)); + builder.Append(string.Join(string.Empty, tags)); - return builder.ToString(); - } + return builder.ToString(); + } - /// - /// Gets a stream containing all concatenated javascript - /// - /// Task{Stream}. - private async Task GetAllJavascript(string culture, string version, bool enableMinification) - { - var memoryStream = new MemoryStream(); - var newLineBytes = Encoding.UTF8.GetBytes(Environment.NewLine); + /// + /// Gets a stream containing all concatenated javascript + /// + /// Task{Stream}. + private async Task GetAllJavascript(string culture, string version, bool enableMinification) + { + var memoryStream = new MemoryStream(); + var newLineBytes = Encoding.UTF8.GetBytes(Environment.NewLine); - // jQuery + jQuery mobile - await AppendResource(memoryStream, "thirdparty/jquery-2.1.1.min.js", newLineBytes).ConfigureAwait(false); - await AppendResource(memoryStream, "thirdparty/jquerymobile-1.4.5/jquery.mobile-1.4.5.min.js", newLineBytes).ConfigureAwait(false); + // jQuery + jQuery mobile + await AppendResource(memoryStream, "thirdparty/jquery-2.1.1.min.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/jquerymobile-1.4.5/jquery.mobile-1.4.5.min.js", newLineBytes).ConfigureAwait(false); - await AppendResource(memoryStream, "thirdparty/jquery.unveil-custom.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/jquery.unveil-custom.js", newLineBytes).ConfigureAwait(false); - await AppendResource(memoryStream, "thirdparty/cast_sender.js", newLineBytes).ConfigureAwait(false); - await AppendResource(memoryStream, "thirdparty/browser.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/cast_sender.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/browser.js", newLineBytes).ConfigureAwait(false); - await AppendResource(memoryStream, "thirdparty/jstree3.0.8/jstree.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/jstree3.0.8/jstree.js", newLineBytes).ConfigureAwait(false); - await AppendLocalization(memoryStream, culture).ConfigureAwait(false); - await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); + await AppendLocalization(memoryStream, culture).ConfigureAwait(false); + await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); - // Write the version string for the dashboard comparison function - var versionString = string.Format("window.dashboardVersion='{0}';", version); - var versionBytes = Encoding.UTF8.GetBytes(versionString); + // Write the version string for the dashboard comparison function + var versionString = string.Format("window.dashboardVersion='{0}';", version); + var versionBytes = Encoding.UTF8.GetBytes(versionString); - await memoryStream.WriteAsync(versionBytes, 0, versionBytes.Length).ConfigureAwait(false); - await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); + await memoryStream.WriteAsync(versionBytes, 0, versionBytes.Length).ConfigureAwait(false); + await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); - var builder = new StringBuilder(); + var builder = new StringBuilder(); - foreach (var file in new[] + foreach (var file in new[] { "thirdparty/apiclient/logger.js", "thirdparty/apiclient/md5.js", @@ -293,65 +293,65 @@ namespace MediaBrowser.WebDashboard.Api "thirdparty/apiclient/serverdiscovery.js", "thirdparty/apiclient/connectionmanager.js" }) - { - using (var fs = _fileSystem.GetFileStream(GetDashboardResourcePath(file), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) - { - using (var streamReader = new StreamReader(fs)) - { - var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); - builder.Append(text); - builder.Append(Environment.NewLine); - } - } - } + { + using (var fs = _fileSystem.GetFileStream(GetDashboardResourcePath(file), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) + { + using (var streamReader = new StreamReader(fs)) + { + var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); + builder.Append(text); + builder.Append(Environment.NewLine); + } + } + } - foreach (var file in GetScriptFiles()) - { - var path = GetDashboardResourcePath("scripts/" + file); + foreach (var file in GetScriptFiles()) + { + var path = GetDashboardResourcePath("scripts/" + file); - using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) - { - using (var streamReader = new StreamReader(fs)) - { - var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); - builder.Append(text); - builder.Append(Environment.NewLine); - } - } - } + using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) + { + using (var streamReader = new StreamReader(fs)) + { + var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); + builder.Append(text); + builder.Append(Environment.NewLine); + } + } + } - var js = builder.ToString(); + var js = builder.ToString(); - if (enableMinification) - { - try - { - var result = new CrockfordJsMinifier().Minify(js, false, Encoding.UTF8); + if (enableMinification) + { + try + { + var result = new CrockfordJsMinifier().Minify(js, false, Encoding.UTF8); - if (result.Errors.Count > 0) - { - _logger.Error("Error minifying javascript: " + result.Errors[0].Message); - } - else - { - js = result.MinifiedContent; - } - } - catch (Exception ex) - { - _logger.ErrorException("Error minifying javascript", ex); - } - } + if (result.Errors.Count > 0) + { + _logger.Error("Error minifying javascript: " + result.Errors[0].Message); + } + else + { + js = result.MinifiedContent; + } + } + catch (Exception ex) + { + _logger.ErrorException("Error minifying javascript", ex); + } + } - var bytes = Encoding.UTF8.GetBytes(js); - await memoryStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + var bytes = Encoding.UTF8.GetBytes(js); + await memoryStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - memoryStream.Position = 0; - return memoryStream; - } - private IEnumerable GetScriptFiles() - { - return new[] + memoryStream.Position = 0; + return memoryStream; + } + private IEnumerable GetScriptFiles() + { + return new[] { "extensions.js", "site.js", @@ -422,7 +422,7 @@ namespace MediaBrowser.WebDashboard.Api "itemlistpage.js", "kids.js", "librarypathmapping.js", - "reportmanager.js", + "reports.js", "librarysettings.js", "livetvchannel.js", "livetvchannels.js", @@ -511,48 +511,48 @@ namespace MediaBrowser.WebDashboard.Api "wizardsettings.js", "wizarduserpage.js" }; - } + } - private async Task AppendLocalization(Stream stream, string culture) - { - var js = "window.localizationGlossary=" + _jsonSerializer.SerializeToString(_localization.GetJavaScriptLocalizationDictionary(culture)); + private async Task AppendLocalization(Stream stream, string culture) + { + var js = "window.localizationGlossary=" + _jsonSerializer.SerializeToString(_localization.GetJavaScriptLocalizationDictionary(culture)); - var bytes = Encoding.UTF8.GetBytes(js); - await stream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - } + var bytes = Encoding.UTF8.GetBytes(js); + await stream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + } - /// - /// Appends the resource. - /// - /// The output stream. - /// The path. - /// The new line bytes. - /// Task. - private async Task AppendResource(Stream outputStream, string path, byte[] newLineBytes) - { - path = GetDashboardResourcePath(path); + /// + /// Appends the resource. + /// + /// The output stream. + /// The path. + /// The new line bytes. + /// Task. + private async Task AppendResource(Stream outputStream, string path, byte[] newLineBytes) + { + path = GetDashboardResourcePath(path); - using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) - { - using (var streamReader = new StreamReader(fs)) - { - var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); - var bytes = Encoding.UTF8.GetBytes(text); - await outputStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - } - } + using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) + { + using (var streamReader = new StreamReader(fs)) + { + var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); + var bytes = Encoding.UTF8.GetBytes(text); + await outputStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + } + } - await outputStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); - } + await outputStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); + } - /// - /// Gets all CSS. - /// - /// Task{Stream}. - private async Task GetAllCss(bool enableMinification) - { - var files = new[] + /// + /// Gets all CSS. + /// + /// Task{Stream}. + private async Task GetAllCss(bool enableMinification) + { + var files = new[] { "site.css", "chromecast.css", @@ -575,61 +575,61 @@ namespace MediaBrowser.WebDashboard.Api "materialize.css" }; - var builder = new StringBuilder(); + var builder = new StringBuilder(); - foreach (var file in files) - { - var path = GetDashboardResourcePath("css/" + file); + foreach (var file in files) + { + var path = GetDashboardResourcePath("css/" + file); - using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) - { - using (var streamReader = new StreamReader(fs)) - { - var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); - builder.Append(text); - builder.Append(Environment.NewLine); - } - } - } + using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) + { + using (var streamReader = new StreamReader(fs)) + { + var text = await streamReader.ReadToEndAsync().ConfigureAwait(false); + builder.Append(text); + builder.Append(Environment.NewLine); + } + } + } - var css = builder.ToString(); + var css = builder.ToString(); - if (enableMinification) - { - try - { - var result = new KristensenCssMinifier().Minify(builder.ToString(), false, Encoding.UTF8); + if (enableMinification) + { + try + { + var result = new KristensenCssMinifier().Minify(builder.ToString(), false, Encoding.UTF8); - if (result.Errors.Count > 0) - { - _logger.Error("Error minifying css: " + result.Errors[0].Message); - } - else - { - css = result.MinifiedContent; - } - } - catch (Exception ex) - { - _logger.ErrorException("Error minifying css", ex); - } - } + if (result.Errors.Count > 0) + { + _logger.Error("Error minifying css: " + result.Errors[0].Message); + } + else + { + css = result.MinifiedContent; + } + } + catch (Exception ex) + { + _logger.ErrorException("Error minifying css", ex); + } + } - var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(css)); + var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(css)); - memoryStream.Position = 0; - return memoryStream; - } + memoryStream.Position = 0; + return memoryStream; + } - /// - /// Gets the raw resource stream. - /// - /// The path. - /// Task{Stream}. - private Stream GetRawResourceStream(string path) - { - return _fileSystem.GetFileStream(GetDashboardResourcePath(path), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true); - } + /// + /// Gets the raw resource stream. + /// + /// The path. + /// Task{Stream}. + private Stream GetRawResourceStream(string path) + { + return _fileSystem.GetFileStream(GetDashboardResourcePath(path), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true); + } - } + } } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 269fc720a0..497c1e070d 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.621 + 3.0.622 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,8 +12,8 @@ Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption. Copyright © Emby 2013 - - + + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index e2577369a0..ab7d095f31 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.621 + 3.0.622 MediaBrowser.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index cb467b5e5b..67385bc3d3 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.621 + 3.0.622 MediaBrowser.Model - Signed Edition Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index a576cab49f..e91b974643 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.621 + 3.0.622 Media Browser.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + diff --git a/README.md b/README.md index 8d8ac63aff..e7f3b7e86f 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,10 @@ It features a REST-based api with built-in documention to facilitate client deve ## Emby Apps -- [Android (Play Store)](https://play.google.com/store/apps/details?id=com.mb.android "Android (Play Store)") -- [Android (Amazon)](http://www.amazon.com/Emby-for-Android/dp/B00GVH9O0I "Android (Amazon)") +- [Android Mobile (Play Store)](https://play.google.com/store/apps/details?id=com.mb.android "Android Mobile (Play Store)") +- [Android Mobile (Amazon)](http://www.amazon.com/Emby-for-Android/dp/B00GVH9O0I "Android Mobile (Amazon)") - [Android TV](https://play.google.com/store/apps/details?id=tv.emby.embyatv "Android TV") +- [Amazon Fire TV](http://www.amazon.com/Emby-for-Fire-TV/dp/B00VVJKTW8 "Amazon Fire TV") - [HTML5](http://app.emby.media "HTML5") - [iPad](https://itunes.apple.com/us/app/media-browser-client/id879475585 "iPad") - [iPhone](https://itunes.apple.com/us/app/media-browser-for-ios/id705058087?mt=8 "iPhone") @@ -21,7 +22,6 @@ It features a REST-based api with built-in documention to facilitate client deve - [Windows Phone](http://www.windowsphone.com/s?appid=f4971ed9-f651-4bf6-84bb-94fd98613b86 "Windows Phone") - [Windows 8](http://apps.microsoft.com/windows/en-us/app/media-browser/ad55a2f0-9897-47bd-8944-bed3aefd5d06 "Windows 8.1") - ## New Users ## If you're a new user looking to install Emby Server, please head over to [emby.media](http://www.emby.media/ "emby.media") diff --git a/SharedVersion.cs b/SharedVersion.cs index f4ee55b0b2..396cefc3fe 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; [assembly: AssemblyVersion("3.0.*")] -//[assembly: AssemblyVersion("3.0.5588.0")] +//[assembly: AssemblyVersion("3.0.5597.1")]