From 933443c2b948d43e4ec41d7f8c11fd6ab3a0ab7e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Jun 2014 13:35:05 -0400 Subject: added modular configuration --- MediaBrowser.Model/Configuration/ChannelOptions.cs | 18 +++++++ MediaBrowser.Model/Configuration/ChapterOptions.cs | 27 ++++++++++ .../Configuration/ServerConfiguration.cs | 61 ++++------------------ .../Configuration/SubtitlePlaybackMode.cs | 10 ++++ .../Configuration/UserConfiguration.cs | 8 --- 5 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 MediaBrowser.Model/Configuration/ChannelOptions.cs create mode 100644 MediaBrowser.Model/Configuration/ChapterOptions.cs create mode 100644 MediaBrowser.Model/Configuration/SubtitlePlaybackMode.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Model/Configuration/ChannelOptions.cs b/MediaBrowser.Model/Configuration/ChannelOptions.cs new file mode 100644 index 0000000000..f0fc4d47c4 --- /dev/null +++ b/MediaBrowser.Model/Configuration/ChannelOptions.cs @@ -0,0 +1,18 @@ +namespace MediaBrowser.Model.Configuration +{ + public class ChannelOptions + { + public int? PreferredStreamingWidth { get; set; } + + public string DownloadPath { get; set; } + public int? MaxDownloadAge { get; set; } + + public string[] DownloadingChannels { get; set; } + + public ChannelOptions() + { + DownloadingChannels = new string[] { }; + MaxDownloadAge = 30; + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/ChapterOptions.cs b/MediaBrowser.Model/Configuration/ChapterOptions.cs new file mode 100644 index 0000000000..8a059a0a4a --- /dev/null +++ b/MediaBrowser.Model/Configuration/ChapterOptions.cs @@ -0,0 +1,27 @@ +namespace MediaBrowser.Model.Configuration +{ + public class ChapterOptions + { + public bool EnableMovieChapterImageExtraction { get; set; } + public bool EnableEpisodeChapterImageExtraction { get; set; } + public bool EnableOtherVideoChapterImageExtraction { get; set; } + + public bool DownloadMovieChapters { get; set; } + public bool DownloadEpisodeChapters { get; set; } + + public string[] FetcherOrder { get; set; } + public string[] DisabledFetchers { get; set; } + + public ChapterOptions() + { + EnableMovieChapterImageExtraction = true; + EnableEpisodeChapterImageExtraction = false; + EnableOtherVideoChapterImageExtraction = false; + + DownloadMovieChapters = true; + + DisabledFetchers = new string[] { }; + FetcherOrder = new string[] { }; + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 0d728ec75e..3d5e0a9c92 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -211,6 +211,7 @@ namespace MediaBrowser.Model.Configuration public string UICulture { get; set; } + [Obsolete] public DlnaOptions DlnaOptions { get; set; } public double DownMixAudioBoost { get; set; } @@ -223,6 +224,8 @@ namespace MediaBrowser.Model.Configuration public string[] ManualLoginClients { get; set; } public ChannelOptions ChannelOptions { get; set; } + + [Obsolete] public ChapterOptions ChapterOptions { get; set; } /// @@ -268,73 +271,27 @@ namespace MediaBrowser.Model.Configuration SeasonZeroDisplayName = "Specials"; - LiveTvOptions = new LiveTvOptions(); - - TvFileOrganizationOptions = new TvFileOrganizationOptions(); - EnableRealtimeMonitor = true; - List options = new List + UICulture = "en-us"; + + MetadataOptions = new List { new MetadataOptions(1, 1280) {ItemType = "Book"}, new MetadataOptions(1, 1280) {ItemType = "MusicAlbum"}, new MetadataOptions(1, 1280) {ItemType = "MusicArtist"}, new MetadataOptions(0, 1280) {ItemType = "Season"} - }; - - MetadataOptions = options.ToArray(); - DlnaOptions = new DlnaOptions(); - - UICulture = "en-us"; + }.ToArray(); NotificationOptions = new NotificationOptions(); SubtitleOptions = new SubtitleOptions(); ChannelOptions = new ChannelOptions(); - ChapterOptions = new ChapterOptions(); - } - } - - public class ChannelOptions - { - public int? PreferredStreamingWidth { get; set; } - public string DownloadPath { get; set; } - public int? MaxDownloadAge { get; set; } - - public string[] DownloadingChannels { get; set; } - - public ChannelOptions() - { - DownloadingChannels = new string[] { }; - MaxDownloadAge = 30; - } - } - - public class ChapterOptions - { - public bool EnableMovieChapterImageExtraction { get; set; } - public bool EnableEpisodeChapterImageExtraction { get; set; } - public bool EnableOtherVideoChapterImageExtraction { get; set; } - - public bool DownloadMovieChapters { get; set; } - public bool DownloadEpisodeChapters { get; set; } - - public string[] FetcherOrder { get; set; } - public string[] DisabledFetchers { get; set; } - - public ChapterOptions() - { - EnableMovieChapterImageExtraction = true; - EnableEpisodeChapterImageExtraction = false; - EnableOtherVideoChapterImageExtraction = false; - - DownloadMovieChapters = true; - - DisabledFetchers = new string[] { }; - FetcherOrder = new string[] { }; + LiveTvOptions = new LiveTvOptions(); + TvFileOrganizationOptions = new TvFileOrganizationOptions(); } } } diff --git a/MediaBrowser.Model/Configuration/SubtitlePlaybackMode.cs b/MediaBrowser.Model/Configuration/SubtitlePlaybackMode.cs new file mode 100644 index 0000000000..e6a3c3091e --- /dev/null +++ b/MediaBrowser.Model/Configuration/SubtitlePlaybackMode.cs @@ -0,0 +1,10 @@ +namespace MediaBrowser.Model.Configuration +{ + public enum SubtitlePlaybackMode + { + Default = 0, + Always = 1, + OnlyForced = 2, + None = 3 + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 885172bed7..94a41bdda0 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -91,12 +91,4 @@ namespace MediaBrowser.Model.Configuration ExcludeFoldersFromGrouping = new string[] { }; } } - - public enum SubtitlePlaybackMode - { - Default = 0, - Always = 1, - OnlyForced = 2, - None = 3 - } } -- cgit v1.2.3 From 1a5a75854bd3ec4cdd771c9afdaefe0acb62c03c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Jun 2014 15:59:52 -0400 Subject: update translations --- .../Updates/InstallationManager.cs | 24 +- .../Entities/Audio/MusicAlbum.cs | 1 + MediaBrowser.Dlna/Didl/Filter.cs | 35 + MediaBrowser.Dlna/Eventing/EventSubscription.cs | 34 + MediaBrowser.Dlna/MediaBrowser.Dlna.csproj | 2 + .../MediaBrowser.Model.Portable.csproj | 9 +- .../MediaBrowser.Model.net35.csproj | 9 +- .../Configuration/ServerConfiguration.cs | 6 +- MediaBrowser.Model/Dlna/ConditionProcessor.cs | 29 + MediaBrowser.Model/Dlna/EventSubscription.cs | 34 - MediaBrowser.Model/Dlna/Filter.cs | 35 - MediaBrowser.Model/Dto/BaseItemDto.cs | 8 +- MediaBrowser.Model/Dto/BaseItemPerson.cs | 3 +- MediaBrowser.Model/Dto/ChapterInfoDto.cs | 3 +- MediaBrowser.Model/Dto/UserDto.cs | 3 +- MediaBrowser.Model/Dto/UserItemDataDto.cs | 3 +- MediaBrowser.Model/Entities/DisplayPreferences.cs | 3 +- MediaBrowser.Model/Entities/MediaStream.cs | 2 +- .../Extensions/IHasPropertyChangedEvent.cs | 8 + MediaBrowser.Model/Extensions/ListHelper.cs | 11 +- MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs | 3 +- MediaBrowser.Model/LiveTv/ChannelInfoDto.cs | 3 +- MediaBrowser.Model/LiveTv/ProgramInfoDto.cs | 3 +- MediaBrowser.Model/LiveTv/RecordingGroupDto.cs | 3 +- MediaBrowser.Model/LiveTv/RecordingInfoDto.cs | 3 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 3 +- .../Notifications/NotificationRequest.cs | 6 +- MediaBrowser.Model/Session/GeneralCommand.cs | 5 +- MediaBrowser.Model/Session/SessionInfoDto.cs | 3 +- MediaBrowser.Model/Themes/AppTheme.cs | 5 +- MediaBrowser.Model/Updates/CheckForUpdateResult.cs | 7 +- MediaBrowser.Model/Updates/PackageVersionInfo.cs | 30 +- .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 4 +- .../Localization/JavaScript/de.json | 20 +- .../Localization/JavaScript/es.json | 26 +- .../Localization/JavaScript/es_MX.json | 10 +- .../Localization/JavaScript/fr.json | 8 +- .../Localization/JavaScript/pl.json | 198 +++++ .../Localization/JavaScript/pt_BR.json | 10 +- .../Localization/JavaScript/ru.json | 4 +- .../Localization/JavaScript/sv.json | 10 +- .../Localization/LocalizationManager.cs | 1 + .../Localization/Server/de.json | 64 +- .../Localization/Server/es.json | 22 +- .../Localization/Server/es_MX.json | 12 +- .../Localization/Server/fr.json | 6 +- .../Localization/Server/pl.json | 825 +++++++++++++++++++++ .../Localization/Server/pt_BR.json | 12 +- .../Localization/Server/ru.json | 18 +- .../Localization/Server/sv.json | 10 +- .../MediaBrowser.Server.Implementations.csproj | 2 + MediaBrowser.ServerApplication/ApplicationHost.cs | 18 +- 52 files changed, 1340 insertions(+), 276 deletions(-) create mode 100644 MediaBrowser.Dlna/Didl/Filter.cs create mode 100644 MediaBrowser.Dlna/Eventing/EventSubscription.cs delete mode 100644 MediaBrowser.Model/Dlna/EventSubscription.cs delete mode 100644 MediaBrowser.Model/Dlna/Filter.cs create mode 100644 MediaBrowser.Model/Extensions/IHasPropertyChangedEvent.cs create mode 100644 MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json create mode 100644 MediaBrowser.Server.Implementations/Localization/Server/pl.json (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs index 895c430767..751ff55a57 100644 --- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs +++ b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs @@ -68,7 +68,7 @@ namespace MediaBrowser.Common.Implementations.Updates /// The new version. private void OnPluginUpdated(IPlugin plugin, PackageVersionInfo newVersion) { - _logger.Info("Plugin updated: {0} {1} {2}", newVersion.name, newVersion.version, newVersion.classification); + _logger.Info("Plugin updated: {0} {1} {2}", newVersion.name, newVersion.versionStr ?? string.Empty, newVersion.classification); EventHelper.FireEventIfNotNull(PluginUpdated, this, new GenericEventArgs> { Argument = new Tuple(plugin, newVersion) }, _logger); @@ -87,7 +87,7 @@ namespace MediaBrowser.Common.Implementations.Updates /// The package. private void OnPluginInstalled(PackageVersionInfo package) { - _logger.Info("New plugin installed: {0} {1} {2}", package.name, package.version, package.classification); + _logger.Info("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification); EventHelper.FireEventIfNotNull(PluginInstalled, this, new GenericEventArgs { Argument = package }, _logger); @@ -133,6 +133,16 @@ namespace MediaBrowser.Common.Implementations.Updates _logger = logger; } + private Version GetPackageVersion(PackageVersionInfo version) + { + return new Version(ValueOrDefault(version.versionStr, "0.0.0.1")); + } + + private static string ValueOrDefault(string str, string def) + { + return string.IsNullOrEmpty(str) ? def : str; + } + /// /// Gets all available packages. /// @@ -197,7 +207,7 @@ namespace MediaBrowser.Common.Implementations.Updates foreach (var package in packages) { package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl)) - .OrderByDescending(v => v.version).ToList(); + .OrderByDescending(GetPackageVersion).ToList(); } // Remove packages with no versions @@ -211,7 +221,7 @@ namespace MediaBrowser.Common.Implementations.Updates foreach (var package in packages) { package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl)) - .OrderByDescending(v => v.version).ToList(); + .OrderByDescending(GetPackageVersion).ToList(); } if (packageType.HasValue) @@ -272,7 +282,7 @@ namespace MediaBrowser.Common.Implementations.Updates return null; } - return package.versions.FirstOrDefault(v => v.version.Equals(version) && v.classification == classification); + return package.versions.FirstOrDefault(v => GetPackageVersion(v).Equals(version) && v.classification == classification); } /// @@ -309,7 +319,7 @@ namespace MediaBrowser.Common.Implementations.Updates } return package.versions - .OrderByDescending(v => v.version) + .OrderByDescending(GetPackageVersion) .FirstOrDefault(v => v.classification <= classification && IsPackageVersionUpToDate(v, currentServerVersion)); } @@ -338,7 +348,7 @@ namespace MediaBrowser.Common.Implementations.Updates { var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, _config.CommonConfiguration.SystemUpdateLevel); - return latestPluginInfo != null && latestPluginInfo.version != null && latestPluginInfo.version > p.Version ? latestPluginInfo : null; + return latestPluginInfo != null && GetPackageVersion(latestPluginInfo) > p.Version ? latestPluginInfo : null; }).Where(i => i != null).ToList(); diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index eef2c84321..9ddd10f4aa 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -194,6 +194,7 @@ namespace MediaBrowser.Controller.Entities.Audio } } + [Obsolete] public class MusicAlbumDisc : Folder { diff --git a/MediaBrowser.Dlna/Didl/Filter.cs b/MediaBrowser.Dlna/Didl/Filter.cs new file mode 100644 index 0000000000..c980a2a2e9 --- /dev/null +++ b/MediaBrowser.Dlna/Didl/Filter.cs @@ -0,0 +1,35 @@ +using MediaBrowser.Model.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.Dlna.Didl +{ + public class Filter + { + private readonly List _fields; + private readonly bool _all; + + public Filter() + : this("*") + { + + } + + public Filter(string filter) + { + _all = StringHelper.EqualsIgnoreCase(filter, "*"); + + var list = (filter ?? string.Empty).Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList(); + + _fields = list; + } + + public bool Contains(string field) + { + // Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back. + return true; + //return _all || ListHelper.ContainsIgnoreCase(_fields, field); + } + } +} diff --git a/MediaBrowser.Dlna/Eventing/EventSubscription.cs b/MediaBrowser.Dlna/Eventing/EventSubscription.cs new file mode 100644 index 0000000000..bd4cbdd55d --- /dev/null +++ b/MediaBrowser.Dlna/Eventing/EventSubscription.cs @@ -0,0 +1,34 @@ +using System; + +namespace MediaBrowser.Dlna.Eventing +{ + public class EventSubscription + { + public string Id { get; set; } + public string CallbackUrl { get; set; } + public string NotificationType { get; set; } + + public DateTime SubscriptionTime { get; set; } + public int TimeoutSeconds { get; set; } + + public long TriggerCount { get; set; } + + public void IncrementTriggerCount() + { + if (TriggerCount == long.MaxValue) + { + TriggerCount = 0; + } + + TriggerCount++; + } + + public bool IsExpired + { + get + { + return SubscriptionTime.AddSeconds(TimeoutSeconds) >= DateTime.UtcNow; + } + } + } +} diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index 1d51fc60ff..94f9c03919 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -56,9 +56,11 @@ + + diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 3c34652c32..4237c2974f 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -212,12 +212,6 @@ Dlna\DlnaProfileType.cs - - Dlna\EventSubscription.cs - - - Dlna\Filter.cs - Dlna\HeaderMatchType.cs @@ -443,6 +437,9 @@ Extensions\DoubleHelper.cs + + Extensions\IHasPropertyChangedEvent.cs + Extensions\IntHelper.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 9e3df382ef..262ad62670 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -199,12 +199,6 @@ Dlna\DlnaProfileType.cs - - Dlna\EventSubscription.cs - - - Dlna\Filter.cs - Dlna\HeaderMatchType.cs @@ -430,6 +424,9 @@ Extensions\DoubleHelper.cs + + Extensions\IHasPropertyChangedEvent.cs + Extensions\IntHelper.cs diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 3d5e0a9c92..542020483d 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Weather; using System; -using System.Collections.Generic; namespace MediaBrowser.Model.Configuration { @@ -275,14 +274,13 @@ namespace MediaBrowser.Model.Configuration UICulture = "en-us"; - MetadataOptions = new List + MetadataOptions = new[] { new MetadataOptions(1, 1280) {ItemType = "Book"}, new MetadataOptions(1, 1280) {ItemType = "MusicAlbum"}, new MetadataOptions(1, 1280) {ItemType = "MusicArtist"}, new MetadataOptions(0, 1280) {ItemType = "Season"} - - }.ToArray(); + }; NotificationOptions = new NotificationOptions(); diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index 66c3e0b195..89b844ae50 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -175,6 +175,35 @@ namespace MediaBrowser.Model.Dlna return false; } + + private bool IsConditionSatisfied(ProfileCondition condition, float? currentValue) + { + if (!currentValue.HasValue) + { + // If the value is unknown, it satisfies if not marked as required + return !condition.IsRequired; + } + + float expected; + if (FloatHelper.TryParseCultureInvariant(condition.Value, out expected)) + { + switch (condition.Condition) + { + case ProfileConditionType.Equals: + return currentValue.Value.Equals(expected); + case ProfileConditionType.GreaterThanEqual: + return currentValue.Value >= expected; + case ProfileConditionType.LessThanEqual: + return currentValue.Value <= expected; + case ProfileConditionType.NotEquals: + return !currentValue.Value.Equals(expected); + default: + throw new InvalidOperationException("Unexpected ProfileConditionType"); + } + } + + return false; + } private bool IsConditionSatisfied(ProfileCondition condition, double? currentValue) { diff --git a/MediaBrowser.Model/Dlna/EventSubscription.cs b/MediaBrowser.Model/Dlna/EventSubscription.cs deleted file mode 100644 index 863ea508a7..0000000000 --- a/MediaBrowser.Model/Dlna/EventSubscription.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; - -namespace MediaBrowser.Model.Dlna -{ - public class EventSubscription - { - public string Id { get; set; } - public string CallbackUrl { get; set; } - public string NotificationType { get; set; } - - public DateTime SubscriptionTime { get; set; } - public int TimeoutSeconds { get; set; } - - public long TriggerCount { get; set; } - - public void IncrementTriggerCount() - { - if (TriggerCount == long.MaxValue) - { - TriggerCount = 0; - } - - TriggerCount++; - } - - public bool IsExpired - { - get - { - return SubscriptionTime.AddSeconds(TimeoutSeconds) >= DateTime.UtcNow; - } - } - } -} diff --git a/MediaBrowser.Model/Dlna/Filter.cs b/MediaBrowser.Model/Dlna/Filter.cs deleted file mode 100644 index a419970104..0000000000 --- a/MediaBrowser.Model/Dlna/Filter.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediaBrowser.Model.Extensions; -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Model.Dlna -{ - public class Filter - { - private readonly List _fields; - private readonly bool _all; - - public Filter() - : this("*") - { - - } - - public Filter(string filter) - { - _all = StringHelper.EqualsIgnoreCase(filter, "*"); - - List list = new List(); - foreach (string s in (filter ?? string.Empty).Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)) - list.Add(s); - _fields = list; - } - - public bool Contains(string field) - { - // Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back. - return true; - //return _all || ListHelper.ContainsIgnoreCase(_fields, field); - } - } -} diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 1d20080dd0..7f7a4b8f08 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Model.Dto /// This holds information about a BaseItem in a format that is convenient for the client. /// [DebuggerDisplay("Name = {Name}, ID = {Id}, Type = {Type}")] - public class BaseItemDto : IHasProviderIds, INotifyPropertyChanged, IItemDto + public class BaseItemDto : IHasProviderIds, IHasPropertyChangedEvent, IItemDto { /// /// Gets or sets the name. @@ -844,7 +844,7 @@ namespace MediaBrowser.Model.Dto [IgnoreDataMember] public bool IsVideo { - get { return StringHelper.EqualsIgnoreCase(MediaType, Entities.MediaType.Video); } + get { return StringHelper.EqualsIgnoreCase(MediaType, MediaBrowser.Model.Entities.MediaType.Video); } } /// @@ -854,7 +854,7 @@ namespace MediaBrowser.Model.Dto [IgnoreDataMember] public bool IsAudio { - get { return StringHelper.EqualsIgnoreCase(MediaType, Entities.MediaType.Audio); } + get { return StringHelper.EqualsIgnoreCase(MediaType, MediaBrowser.Model.Entities.MediaType.Audio); } } /// @@ -864,7 +864,7 @@ namespace MediaBrowser.Model.Dto [IgnoreDataMember] public bool IsGame { - get { return StringHelper.EqualsIgnoreCase(MediaType, Entities.MediaType.Game); } + get { return StringHelper.EqualsIgnoreCase(MediaType, MediaBrowser.Model.Entities.MediaType.Game); } } /// diff --git a/MediaBrowser.Model/Dto/BaseItemPerson.cs b/MediaBrowser.Model/Dto/BaseItemPerson.cs index b8393f4447..46485316e0 100644 --- a/MediaBrowser.Model/Dto/BaseItemPerson.cs +++ b/MediaBrowser.Model/Dto/BaseItemPerson.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Runtime.Serialization; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Dto { @@ -8,7 +9,7 @@ namespace MediaBrowser.Model.Dto /// This is used by the api to get information about a Person within a BaseItem /// [DebuggerDisplay("Name = {Name}, Role = {Role}, Type = {Type}")] - public class BaseItemPerson : INotifyPropertyChanged + public class BaseItemPerson : IHasPropertyChangedEvent { /// /// Gets or sets the name. diff --git a/MediaBrowser.Model/Dto/ChapterInfoDto.cs b/MediaBrowser.Model/Dto/ChapterInfoDto.cs index 1ec4251697..62b1839d4e 100644 --- a/MediaBrowser.Model/Dto/ChapterInfoDto.cs +++ b/MediaBrowser.Model/Dto/ChapterInfoDto.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Runtime.Serialization; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Dto { @@ -8,7 +9,7 @@ namespace MediaBrowser.Model.Dto /// Class ChapterInfo /// [DebuggerDisplay("Name = {Name}")] - public class ChapterInfoDto : INotifyPropertyChanged + public class ChapterInfoDto : IHasPropertyChangedEvent { /// /// Gets or sets the start position ticks. diff --git a/MediaBrowser.Model/Dto/UserDto.cs b/MediaBrowser.Model/Dto/UserDto.cs index c4a43c512f..fec22e11c5 100644 --- a/MediaBrowser.Model/Dto/UserDto.cs +++ b/MediaBrowser.Model/Dto/UserDto.cs @@ -3,6 +3,7 @@ using System; using System.ComponentModel; using System.Diagnostics; using System.Runtime.Serialization; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Dto { @@ -10,7 +11,7 @@ namespace MediaBrowser.Model.Dto /// Class UserDto /// [DebuggerDisplay("Name = {Name}, ID = {Id}, HasPassword = {HasPassword}")] - public class UserDto : INotifyPropertyChanged, IItemDto + public class UserDto : IHasPropertyChangedEvent, IItemDto { /// /// Gets or sets the name. diff --git a/MediaBrowser.Model/Dto/UserItemDataDto.cs b/MediaBrowser.Model/Dto/UserItemDataDto.cs index 8e8e7adbe2..26b0e9d9e8 100644 --- a/MediaBrowser.Model/Dto/UserItemDataDto.cs +++ b/MediaBrowser.Model/Dto/UserItemDataDto.cs @@ -1,12 +1,13 @@ using System; using System.ComponentModel; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Dto { /// /// Class UserItemDataDto /// - public class UserItemDataDto : INotifyPropertyChanged + public class UserItemDataDto : IHasPropertyChangedEvent { /// /// Gets or sets the rating. diff --git a/MediaBrowser.Model/Entities/DisplayPreferences.cs b/MediaBrowser.Model/Entities/DisplayPreferences.cs index 56a2c61944..cac703c910 100644 --- a/MediaBrowser.Model/Entities/DisplayPreferences.cs +++ b/MediaBrowser.Model/Entities/DisplayPreferences.cs @@ -2,13 +2,14 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Entities { /// /// Defines the display preferences for any item that supports them (usually Folders) /// - public class DisplayPreferences : INotifyPropertyChanged + public class DisplayPreferences : IHasPropertyChangedEvent { /// /// Occurs when [property changed]. diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 7be8a64b74..fe05483e77 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -136,7 +136,7 @@ namespace MediaBrowser.Model.Entities { if (Type != MediaStreamType.Subtitle) return false; - var codec = Codec ?? string.Empty; + string codec = Codec ?? string.Empty; return StringHelper.IndexOfIgnoreCase(codec, "pgs") == -1 && StringHelper.IndexOfIgnoreCase(codec, "dvd") == -1; diff --git a/MediaBrowser.Model/Extensions/IHasPropertyChangedEvent.cs b/MediaBrowser.Model/Extensions/IHasPropertyChangedEvent.cs new file mode 100644 index 0000000000..c875506207 --- /dev/null +++ b/MediaBrowser.Model/Extensions/IHasPropertyChangedEvent.cs @@ -0,0 +1,8 @@ +using System.ComponentModel; + +namespace MediaBrowser.Model.Extensions +{ + public interface IHasPropertyChangedEvent : INotifyPropertyChanged + { + } +} diff --git a/MediaBrowser.Model/Extensions/ListHelper.cs b/MediaBrowser.Model/Extensions/ListHelper.cs index 6c5d471c08..d929866bd4 100644 --- a/MediaBrowser.Model/Extensions/ListHelper.cs +++ b/MediaBrowser.Model/Extensions/ListHelper.cs @@ -6,7 +6,16 @@ namespace MediaBrowser.Model.Extensions { public static class ListHelper { - public static bool ContainsIgnoreCase(IEnumerable list, string value) + public static bool ContainsIgnoreCase(List list, string value) + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + + return list.Contains(value, StringComparer.OrdinalIgnoreCase); + } + public static bool ContainsIgnoreCase(string[] list, string value) { if (value == null) { diff --git a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs index 2d88215bb5..27001f7215 100644 --- a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs @@ -1,9 +1,10 @@ using System; using System.ComponentModel; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.LiveTv { - public class BaseTimerInfoDto : INotifyPropertyChanged + public class BaseTimerInfoDto : IHasPropertyChangedEvent { /// /// Occurs when a property value changes. diff --git a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs index a48006755e..351378eea1 100644 --- a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs @@ -1,5 +1,6 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Library; using System.Collections.Generic; using System.ComponentModel; @@ -12,7 +13,7 @@ namespace MediaBrowser.Model.LiveTv /// Class ChannelInfoDto /// [DebuggerDisplay("Name = {Name}, Number = {Number}")] - public class ChannelInfoDto : INotifyPropertyChanged, IItemDto + public class ChannelInfoDto : IHasPropertyChangedEvent, IItemDto { /// /// Gets or sets the name. diff --git a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs index 644af027d8..50881f72fe 100644 --- a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs @@ -5,12 +5,13 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Library; namespace MediaBrowser.Model.LiveTv { [DebuggerDisplay("Name = {Name}, StartTime = {StartDate}, EndTime = {EndDate}")] - public class ProgramInfoDto : INotifyPropertyChanged, IItemDto + public class ProgramInfoDto : IHasPropertyChangedEvent, IItemDto { /// /// Id of the program. diff --git a/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs b/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs index db96d56b44..07c5ac32f9 100644 --- a/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs +++ b/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using System.Diagnostics; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.LiveTv { @@ -7,7 +8,7 @@ namespace MediaBrowser.Model.LiveTv /// Class RecordingGroupDto. /// [DebuggerDisplay("Name = {Name}, Count = {RecordingCount}")] - public class RecordingGroupDto : INotifyPropertyChanged + public class RecordingGroupDto : IHasPropertyChangedEvent { /// /// Gets or sets the name. diff --git a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs index 58bca06bd2..43ae9681e3 100644 --- a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs @@ -1,5 +1,6 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Library; using System; using System.Collections.Generic; @@ -10,7 +11,7 @@ using System.Runtime.Serialization; namespace MediaBrowser.Model.LiveTv { [DebuggerDisplay("Name = {Name}, ChannelName = {ChannelName}")] - public class RecordingInfoDto : INotifyPropertyChanged, IItemDto + public class RecordingInfoDto : IHasPropertyChangedEvent, IItemDto { /// /// Id of the recording. diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 5d753f9c29..fc79b7e758 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -109,8 +109,6 @@ - - @@ -155,6 +153,7 @@ + diff --git a/MediaBrowser.Model/Notifications/NotificationRequest.cs b/MediaBrowser.Model/Notifications/NotificationRequest.cs index d47e9c4f22..f511d41a97 100644 --- a/MediaBrowser.Model/Notifications/NotificationRequest.cs +++ b/MediaBrowser.Model/Notifications/NotificationRequest.cs @@ -1,6 +1,6 @@ -using System; +using MediaBrowser.Model.Configuration; +using System; using System.Collections.Generic; -using MediaBrowser.Model.Configuration; namespace MediaBrowser.Model.Notifications { @@ -34,7 +34,7 @@ namespace MediaBrowser.Model.Notifications UserIds = new List(); Date = DateTime.UtcNow; - Variables = new Dictionary(StringComparer.OrdinalIgnoreCase); + Variables = new Dictionary(); ExcludeUserIds = new List(); } diff --git a/MediaBrowser.Model/Session/GeneralCommand.cs b/MediaBrowser.Model/Session/GeneralCommand.cs index 7e818245de..ae9ab3adc4 100644 --- a/MediaBrowser.Model/Session/GeneralCommand.cs +++ b/MediaBrowser.Model/Session/GeneralCommand.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; namespace MediaBrowser.Model.Session { @@ -13,7 +12,7 @@ namespace MediaBrowser.Model.Session public GeneralCommand() { - Arguments = new Dictionary(StringComparer.OrdinalIgnoreCase); + Arguments = new Dictionary(); } } } diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs index 7217e28f41..40723eff83 100644 --- a/MediaBrowser.Model/Session/SessionInfoDto.cs +++ b/MediaBrowser.Model/Session/SessionInfoDto.cs @@ -3,11 +3,12 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Session { [DebuggerDisplay("Client = {Client}, Username = {UserName}")] - public class SessionInfoDto : INotifyPropertyChanged + public class SessionInfoDto : IHasPropertyChangedEvent { /// /// Gets or sets a value indicating whether this instance can seek. diff --git a/MediaBrowser.Model/Themes/AppTheme.cs b/MediaBrowser.Model/Themes/AppTheme.cs index 40a729963a..527f1de728 100644 --- a/MediaBrowser.Model/Themes/AppTheme.cs +++ b/MediaBrowser.Model/Themes/AppTheme.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; namespace MediaBrowser.Model.Themes { @@ -15,7 +14,7 @@ namespace MediaBrowser.Model.Themes public AppTheme() { - Options = new Dictionary(StringComparer.Ordinal); + Options = new Dictionary(); Images = new List(); } diff --git a/MediaBrowser.Model/Updates/CheckForUpdateResult.cs b/MediaBrowser.Model/Updates/CheckForUpdateResult.cs index c9bc2d6b9d..ff0bba197e 100644 --- a/MediaBrowser.Model/Updates/CheckForUpdateResult.cs +++ b/MediaBrowser.Model/Updates/CheckForUpdateResult.cs @@ -1,5 +1,4 @@ -using System; - + namespace MediaBrowser.Model.Updates { /// @@ -17,9 +16,9 @@ namespace MediaBrowser.Model.Updates /// Gets or sets the available version. /// /// The available version. - public Version AvailableVersion + public string AvailableVersion { - get { return Package != null ? Package.version : new Version(0, 0); } + get { return Package != null ? Package.versionStr : "0.0.0.1"; } set { } // need this for the serializer } diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs index b3d297e8ee..de8f4e8b86 100644 --- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs +++ b/MediaBrowser.Model/Updates/PackageVersionInfo.cs @@ -1,6 +1,4 @@ -using System; -using System.Runtime.Serialization; - + namespace MediaBrowser.Model.Updates { /// @@ -26,32 +24,6 @@ namespace MediaBrowser.Model.Updates /// The version STR. public string versionStr { get; set; } - /// - /// The _version - /// - private Version _version; - /// - /// Gets or sets the version. - /// Had to make this an interpreted property since Protobuf can't handle Version - /// - /// The version. - [IgnoreDataMember] - public Version version - { - get { return _version ?? (_version = new Version(ValueOrDefault(versionStr, "0.0.0.1"))); } - } - - /// - /// Values the or default. - /// - /// The STR. - /// The def. - /// System.String. - private static string ValueOrDefault(string str, string def) - { - return string.IsNullOrEmpty(str) ? def : str; - } - /// /// Gets or sets the classification. /// diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 24c9b111a1..64d2db2e45 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -157,8 +157,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio private static bool IsAdditionalSubfolderAllowed(FileSystemInfo directory) { - // TOOD: allow some metadata folders like extrafanart, extrathumbs - return false; + // Resolver will ignore them based on rules engine + return true; } } } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json index e48b788b07..9fa6b0ca23 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json @@ -55,22 +55,22 @@ "LabelDefaultStream": "(Default)", "LabelForcedStream": "(Forced)", "LabelDefaultForcedStream": "(Default\/Forced)", - "LabelUnknownLanguage": "Unknown language", + "LabelUnknownLanguage": "Unbekannte Sprache", "ButtonMute": "Stumm", "ButtonUnmute": "Unmute", "ButtonNextTrack": "N\u00e4chster Track", "ButtonPause": "Pause", "ButtonPlay": "Abspielen", "ButtonEdit": "Bearbeiten", - "ButtonQueue": "Queue", + "ButtonQueue": "Warteschlange", "ButtonPlayTrailer": "Spiele Trailer", "ButtonPlaylist": "Playlist", "ButtonPreviousTrack": "Vorheriger Track", - "LabelEnabled": "Enabled", - "LabelDisabled": "Disabled", - "ButtonMoreInformation": "More Information", - "LabelNoUnreadNotifications": "No unread notifications.", - "ButtonViewNotifications": "View notifications", + "LabelEnabled": "Aktivieren", + "LabelDisabled": "Deaktivieren", + "ButtonMoreInformation": "mehr Informationen", + "LabelNoUnreadNotifications": "keine ungelesenen Benachrichtigungen", + "ButtonViewNotifications": "Benachrichtigungen anschauen", "ButtonMarkTheseRead": "Mark these read", "ButtonClose": "Close", "LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.", @@ -100,7 +100,7 @@ "OptionSaturday": "Samstag", "HeaderConfirmDeletion": "Confirm Deletion", "MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?", - "LiveTvUpdateAvailable": "(Update available)", + "LiveTvUpdateAvailable": "(Update verf\u00fcgbar)", "LabelVersionUpToDate": "Auf dem neuesten Stand!", "ButtonResetTuner": "Tuner zur\u00fccksetzen", "HeaderResetTuner": "Tuner zur\u00fccksetzen", @@ -109,8 +109,8 @@ "LabelAllChannels": "Alle Channel", "HeaderSeriesRecordings": "Series Recordings", "LabelAnytime": "Jederzeit", - "StatusRecording": "Recording", - "StatusWatching": "Watching", + "StatusRecording": "Aufnehmen", + "StatusWatching": "Anschauing", "StatusRecordingProgram": "Recording {0}", "StatusWatchingProgram": "Watching {0}", "HeaderSplitMedia": "Trenne Medien ab", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json index f4f1264224..3873a10fc2 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json @@ -121,7 +121,7 @@ "MessageTheFollowingItemsWillBeGrouped": "Los siguientes t\u00edtulos se agrupar\u00e1n en un elemento.", "MessageConfirmItemGrouping": "Los clientes de Media Browser elegir\u00e1n autom\u00e1ticamente la mejor forma de reproduccion sobre la base de dispositivo y rendimiento de la red. \u00bfEst\u00e1 seguro que desea continuar?", "HeaderResume": "Continuar", - "HeaderMyViews": "My Views", + "HeaderMyViews": "Mis vistas", "HeaderLibraryFolders": "Vista de carpeta", "HeaderLatestMedia": "\u00daltimos medios", "ButtonMore": "M\u00e1s...", @@ -181,18 +181,18 @@ "LabelRunningOnPort": "Ejecut\u00e1ndose en el puerto {0}.", "LabelRunningOnPorts": "Ejecut\u00e1ndose en los puertos {0} y {1}.", "HeaderLatestFromChannel": "Lo \u00faltimo de {0}", - "ButtonDownload": "Download", - "LabelUnknownLanaguage": "Unknown language", - "HeaderCurrentSubtitles": "Current Subtitles", - "MessageDownloadQueued": "The download has been queued.", - "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", - "ButtonRemoteControl": "Remote Control", - "HeaderLatestTvRecordings": "Latest Recordings", + "ButtonDownload": "Descargar", + "LabelUnknownLanaguage": "Idioma desconocido", + "HeaderCurrentSubtitles": "Subt\u00edtulos actuales", + "MessageDownloadQueued": "La descarga se ha a\u00f1adido a la cola", + "MessageAreYouSureDeleteSubtitles": "\u00bfEst\u00e1 seguro que desea eliminar este archivo de subt\u00edtulos?", + "ButtonRemoteControl": "Control remoto", + "HeaderLatestTvRecordings": "\u00daltimas grabaciones", "ButtonOk": "OK", "ButtonCancel": "Cancelar", - "ButtonRefresh": "Refresh", - "LabelCurrentPath": "Current path:", - "HeaderSelectMediaPath": "Select Media Path", - "ButtonNetwork": "Network", - "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}." + "ButtonRefresh": "Refrescar", + "LabelCurrentPath": "Ruta actual:", + "HeaderSelectMediaPath": "Seleccionar la ruta para Medios", + "ButtonNetwork": "Red", + "MessageDirectoryPickerInstruction": "Rutas de red pueden ser introducidas manualmente en el caso de que el bot\u00f3n de la red no pueda localizar sus dispositivos. Por ejemplo, {0} o {1}." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json index 6b609dde17..d72c295e38 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json @@ -190,9 +190,9 @@ "HeaderLatestTvRecordings": "\u00daltimas Grabaciones", "ButtonOk": "Ok", "ButtonCancel": "Cancelar", - "ButtonRefresh": "Refresh", - "LabelCurrentPath": "Current path:", - "HeaderSelectMediaPath": "Select Media Path", - "ButtonNetwork": "Network", - "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}." + "ButtonRefresh": "Refrescar", + "LabelCurrentPath": "Trayectoria actual:", + "HeaderSelectMediaPath": "Seleccionar trayectoria a medios", + "ButtonNetwork": "Red", + "MessageDirectoryPickerInstruction": "Las trayectorias de red pueden ser ingresadas manualmente en caso de que el bot\u00f3n de Red no pueda localizar sus dispositivos. Por ejemplo, {0} or {1}." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json index 4ba25ce7ab..a452eb02d5 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json @@ -136,7 +136,7 @@ "HeaderSelectTranscodingPath": "S\u00e9lectionner le chemin d'acc\u00e8s du transcodage temporaire", "HeaderSelectImagesByNamePath": "S\u00e9lectionner le chemin d'acc\u00e8s du \"Images By Name\"", "HeaderSelectMetadataPath": "S\u00e9lectionner le chemin d'acc\u00e8s des m\u00e9tadonn\u00e9es", - "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.", + "HeaderSelectServerCachePathHelp": "Parcourez ou entrez le chemin \u00e0 utiliser pour les fichiers caches du serveur. Le dossier doit \u00eatre accessible en \u00e9criture. L'emplacement de ce fichier aura un impact direct sur les performances du serveur et devrait \u00eatre plac\u00e9 id\u00e9alement sur un SSD.", "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.", "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.", "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.", @@ -190,9 +190,9 @@ "HeaderLatestTvRecordings": "Les plus r\u00e9cents enregistrements", "ButtonOk": "Ok", "ButtonCancel": "Annuler", - "ButtonRefresh": "Refresh", - "LabelCurrentPath": "Current path:", + "ButtonRefresh": "Actualiser", + "LabelCurrentPath": "Chemin actuel:", "HeaderSelectMediaPath": "Select Media Path", - "ButtonNetwork": "Network", + "ButtonNetwork": "R\u00e9seau", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json new file mode 100644 index 0000000000..b3ab8d3b90 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json @@ -0,0 +1,198 @@ +{ + "SettingsSaved": "Ustawienia zapisane.", + "AddUser": "Dodaj u\u017cytkownika", + "Users": "U\u017cytkownicy", + "Delete": "Usu\u0144", + "Administrator": "Administrator", + "Password": "Has\u0142o", + "DeleteImage": "Usu\u0144 zdj\u0119cie", + "DeleteImageConfirmation": "Jeste\u015b pewien \u017ce chcesz usun\u0105\u0107 to zdj\u0119cie?", + "FileReadCancelled": "Odczytywanie pliku zosta\u0142o anulowane.", + "FileNotFound": "Plik nie znaleziony.", + "FileReadError": "Wyst\u0105pi\u0142 b\u0142\u0105d podczas odczytywania pliku.", + "DeleteUser": "Usu\u0144 u\u017cytkownika", + "DeleteUserConfirmation": "Jeste\u015b pewien \u017ce chcesz usun\u0105\u0107 {0}?", + "PasswordResetHeader": "Zresetuj has\u0142o", + "PasswordResetComplete": "Has\u0142o zosta\u0142o zresetowane.", + "PasswordResetConfirmation": "Jeste\u015b pewien \u017ce chcesz zresetowa\u0107 has\u0142o?", + "PasswordSaved": "Has\u0142o zapisane.", + "PasswordMatchError": "Has\u0142o i potwierdzenie has\u0142a musz\u0105 si\u0119 zgadza\u0107.", + "OptionRelease": "Oficjalne wydanie", + "OptionBeta": "Beta", + "OptionDev": "Dev (Niestabilne)", + "UninstallPluginHeader": "Usu\u0144 wtyczk\u0119", + "UninstallPluginConfirmation": "Czy na pewno chcesz usun\u0105\u0107 {0}?", + "NoPluginConfigurationMessage": "Ta wtyczka nie ma \u017cadnych ustawie\u0144.", + "NoPluginsInstalledMessage": "Nie masz \u017cadnych wtyczek zainstalowanych.", + "BrowsePluginCatalogMessage": "Przejrzyj nasz katalog wtyczek \u017ceby zobaczy\u0107 dost\u0119pne wtyczki.", + "MessageKeyEmailedTo": "Key emailed to {0}.", + "MessageKeysLinked": "Keys linked.", + "HeaderConfirmation": "Confirmation", + "MessageKeyUpdated": "Thank you. Your supporter key has been updated.", + "MessageKeyRemoved": "Thank you. Your supporter key has been removed.", + "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.", + "HeaderSearch": "Search", + "LabelArtist": "Artist", + "LabelMovie": "Movie", + "LabelMusicVideo": "Music Video", + "LabelEpisode": "Episode", + "LabelSeries": "Series", + "LabelStopping": "Stopping", + "ButtonStop": "Stop", + "LabelCancelled": "(cancelled)", + "LabelFailed": "(failed)", + "LabelAbortedByServerShutdown": "(Aborted by server shutdown)", + "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.", + "HeaderDeleteTaskTrigger": "Delete Task Trigger", + "HeaderTaskTriggers": "Task Triggers", + "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?", + "MessageNoPluginsInstalled": "You have no plugins installed.", + "LabelVersionInstalled": "{0} installed", + "LabelNumberReviews": "{0} Reviews", + "LabelFree": "Free", + "HeaderSelectAudio": "Select Audio", + "HeaderSelectSubtitles": "Select Subtitles", + "LabelDefaultStream": "(Default)", + "LabelForcedStream": "(Forced)", + "LabelDefaultForcedStream": "(Default\/Forced)", + "LabelUnknownLanguage": "Unknown language", + "ButtonMute": "Mute", + "ButtonUnmute": "Unmute", + "ButtonNextTrack": "Next track", + "ButtonPause": "Pause", + "ButtonPlay": "Play", + "ButtonEdit": "Edit", + "ButtonQueue": "Queue", + "ButtonPlayTrailer": "PlayTrailer", + "ButtonPlaylist": "Playlist", + "ButtonPreviousTrack": "Previous track", + "LabelEnabled": "Enabled", + "LabelDisabled": "Disabled", + "ButtonMoreInformation": "More Information", + "LabelNoUnreadNotifications": "No unread notifications.", + "ButtonViewNotifications": "View notifications", + "ButtonMarkTheseRead": "Mark these read", + "ButtonClose": "Close", + "LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.", + "MessageInvalidUser": "Invalid user or password.", + "HeaderAllRecordings": "All Recordings", + "RecommendationBecauseYouLike": "Because you like {0}", + "RecommendationBecauseYouWatched": "Because you watched {0}", + "RecommendationDirectedBy": "Directed by {0}", + "RecommendationStarring": "Starring {0}", + "HeaderConfirmRecordingCancellation": "Confirm Recording Cancellation", + "MessageConfirmRecordingCancellation": "Are you sure you wish to cancel this recording?", + "MessageRecordingCancelled": "Recording cancelled.", + "HeaderConfirmSeriesCancellation": "Confirm Series Cancellation", + "MessageConfirmSeriesCancellation": "Are you sure you wish to cancel this series?", + "MessageSeriesCancelled": "Series cancelled.", + "HeaderConfirmRecordingDeletion": "Confirm Recording Deletion", + "MessageConfirmRecordingDeletion": "Are you sure you wish to delete this recording?", + "MessageRecordingDeleted": "Recording deleted.", + "ButonCancelRecording": "Cancel Recording", + "MessageRecordingSaved": "Recording saved.", + "OptionSunday": "Niedziela", + "OptionMonday": "Poniedzia\u0142ek", + "OptionTuesday": "Wtorek", + "OptionWednesday": "\u015aroda", + "OptionThursday": "Czwartek", + "OptionFriday": "Pi\u0105tek", + "OptionSaturday": "Sobota", + "HeaderConfirmDeletion": "Confirm Deletion", + "MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?", + "LiveTvUpdateAvailable": "(Update available)", + "LabelVersionUpToDate": "Up to date!", + "ButtonResetTuner": "Reset tuner", + "HeaderResetTuner": "Reset Tuner", + "MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.", + "ButtonCancelSeries": "Cancel Series", + "LabelAllChannels": "All channels", + "HeaderSeriesRecordings": "Series Recordings", + "LabelAnytime": "Any time", + "StatusRecording": "Recording", + "StatusWatching": "Watching", + "StatusRecordingProgram": "Recording {0}", + "StatusWatchingProgram": "Watching {0}", + "HeaderSplitMedia": "Split Media Apart", + "MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?", + "HeaderError": "Error", + "MessagePleaseSelectOneItem": "Please select at least one item.", + "MessagePleaseSelectTwoItems": "Please select at least two items.", + "MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:", + "MessageConfirmItemGrouping": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?", + "HeaderResume": "Wzn\u00f3w", + "HeaderMyViews": "My Views", + "HeaderLibraryFolders": "Media Folders", + "HeaderLatestMedia": "Latest Media", + "ButtonMore": "More...", + "HeaderFavoriteMovies": "Favorite Movies", + "HeaderFavoriteShows": "Favorite Shows", + "HeaderFavoriteEpisodes": "Favorite Episodes", + "HeaderFavoriteGames": "Favorite Games", + "HeaderRatingsDownloads": "Rating \/ Downloads", + "HeaderConfirmProfileDeletion": "Confirm Profile Deletion", + "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?", + "HeaderSelectServerCachePath": "Select Server Cache Path", + "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path", + "HeaderSelectImagesByNamePath": "Select Images By Name Path", + "HeaderSelectMetadataPath": "Select Metadata Path", + "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.", + "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.", + "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.", + "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.", + "HeaderSelectChannelDownloadPath": "Select Channel Download Path", + "HeaderSelectChannelDownloadPathHelp": "Browse or enter the path to use for storing channel cache files. The folder must be writeable.", + "OptionNewCollection": "New...", + "ButtonAdd": "Add", + "ButtonRemove": "Remove", + "LabelChapterDownloaders": "Chapter downloaders:", + "LabelChapterDownloadersHelp": "Enable and rank your preferred chapter downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.", + "HeaderFavoriteAlbums": "Favorite Albums", + "HeaderLatestChannelMedia": "Latest Channel Items", + "ButtonOrganizeFile": "Organize File", + "ButtonDeleteFile": "Delete File", + "HeaderOrganizeFile": "Organize File", + "HeaderDeleteFile": "Delete File", + "StatusSkipped": "Skipped", + "StatusFailed": "Failed", + "StatusSuccess": "Success", + "MessageFileWillBeDeleted": "The following file will be deleted:", + "MessageSureYouWishToProceed": "Are you sure you wish to proceed?", + "MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:", + "MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:", + "MessageDestinationTo": "to:", + "HeaderSelectWatchFolder": "Select Watch Folder", + "HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.", + "OrganizePatternResult": "Result: {0}", + "HeaderRestart": "Restart", + "HeaderShutdown": "Shutdown", + "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?", + "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?", + "ButtonUpdateNow": "Update Now", + "NewVersionOfSomethingAvailable": "A new version of {0} is available!", + "VersionXIsAvailableForDownload": "Version {0} is now available for download.", + "LabelVersionNumber": "Version {0}", + "LabelPlayMethodTranscoding": "Transcoding", + "LabelPlayMethodDirectStream": "Direct Streaming", + "LabelPlayMethodDirectPlay": "Direct Playing", + "LabelAudioCodec": "Audio: {0}", + "LabelVideoCodec": "Video: {0}", + "LabelRemoteAccessUrl": "Remote access: {0}", + "LabelRunningOnPort": "Running on port {0}.", + "LabelRunningOnPorts": "Running on ports {0} and {1}.", + "HeaderLatestFromChannel": "Latest from {0}", + "ButtonDownload": "Download", + "LabelUnknownLanaguage": "Unknown language", + "HeaderCurrentSubtitles": "Current Subtitles", + "MessageDownloadQueued": "The download has been queued.", + "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?", + "ButtonRemoteControl": "Remote Control", + "HeaderLatestTvRecordings": "Latest Recordings", + "ButtonOk": "Ok", + "ButtonCancel": "Anuluj", + "ButtonRefresh": "Refresh", + "LabelCurrentPath": "Current path:", + "HeaderSelectMediaPath": "Select Media Path", + "ButtonNetwork": "Network", + "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json index 5b1667db68..5443451d60 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json @@ -190,9 +190,9 @@ "HeaderLatestTvRecordings": "\u00daltimas Grava\u00e7\u00f5es", "ButtonOk": "Ok", "ButtonCancel": "Cancelar", - "ButtonRefresh": "Refresh", - "LabelCurrentPath": "Current path:", - "HeaderSelectMediaPath": "Select Media Path", - "ButtonNetwork": "Network", - "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}." + "ButtonRefresh": "Atualizar", + "LabelCurrentPath": "Caminho atual:", + "HeaderSelectMediaPath": "Selecionar o Caminho da M\u00eddia", + "ButtonNetwork": "Rede", + "MessageDirectoryPickerInstruction": "Os caminhos da rede podem ser digitados manualmente caso o bot\u00e3o de Rede n\u00e3o consiga localizar seus dispositivos. Por exemplo, {0} ou {1}." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json index 3661e5f601..afabb17e70 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json @@ -25,7 +25,7 @@ "NoPluginConfigurationMessage": "\u041d\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430.", "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, \u0447\u0442\u043e\u0431\u044b \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c\u0438.", - "MessageKeyEmailedTo": "\u041a\u043b\u044e\u0447 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u043e\u044e \u0434\u043b\u044f {0}.", + "MessageKeyEmailedTo": "\u041a\u043b\u044e\u0447 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u042d-\u043f\u043e\u0447\u0442\u043e\u044e \u0434\u043b\u044f {0}.", "MessageKeysLinked": "\u041a\u043b\u044e\u0447\u0438 \u0431\u044b\u043b\u0438 \u043f\u0440\u0438\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.", @@ -73,7 +73,7 @@ "ButtonViewNotifications": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f", "ButtonMarkTheseRead": "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0430\u043a \u043f\u0440\u043e\u0447\u0442\u0451\u043d\u043d\u044b\u0435", "ButtonClose": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c", - "LabelAllPlaysSentToPlayer": "\u0412\u0441\u0451 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u043d\u0430 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043b\u0435\u0439\u0435\u0440", + "LabelAllPlaysSentToPlayer": "\u0412\u0441\u0451 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043f\u043b\u0435\u0439\u0435\u0440", "MessageInvalidUser": "\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\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.", "HeaderAllRecordings": "\u0412\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438", "RecommendationBecauseYouLike": "\u0422\u0430\u043a \u043a\u0430\u043a \u0432\u0430\u043c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f {0}", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json index 7bb4f54092..b41dba8107 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json @@ -190,9 +190,9 @@ "HeaderLatestTvRecordings": "Senaste inspelningar", "ButtonOk": "OK", "ButtonCancel": "Avbryt", - "ButtonRefresh": "Refresh", - "LabelCurrentPath": "Current path:", - "HeaderSelectMediaPath": "Select Media Path", - "ButtonNetwork": "Network", - "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}." + "ButtonRefresh": "Uppdatera", + "LabelCurrentPath": "Aktuell s\u00f6kv\u00e4g:", + "HeaderSelectMediaPath": "V\u00e4lj s\u00f6kv\u00e4g till media", + "ButtonNetwork": "N\u00e4tverk", + "MessageDirectoryPickerInstruction": "N\u00e4tverkss\u00f6kv\u00e4gar kan anges manuellt om \"N\u00e4tverk\" inte hittar dina enheter. T ex {0} eller {1}." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs index e1f5bcfdc9..c21c9fa179 100644 --- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs +++ b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs @@ -371,6 +371,7 @@ namespace MediaBrowser.Server.Implementations.Localization new LocalizatonOption{ Name="Italian", Value="it"}, new LocalizatonOption{ Name="Kazakh", Value="kk"}, new LocalizatonOption{ Name="Norwegian Bokmål", Value="nb"}, + new LocalizatonOption{ Name="Polish", Value="pl"}, new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"}, new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"}, new LocalizatonOption{ Name="Russian", Value="ru"}, diff --git a/MediaBrowser.Server.Implementations/Localization/Server/de.json b/MediaBrowser.Server.Implementations/Localization/Server/de.json index c5fc62bed3..05e6e7202f 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/de.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json @@ -63,14 +63,14 @@ "HeaderPlaybackSettings": "Wiedergabe Einstellungen", "LabelAudioLanguagePreference": "Audiosprache Einstellungen:", "LabelSubtitleLanguagePreference": "Untertitelsprache Einstellungen:", - "OptionDefaultSubtitles": "Default", + "OptionDefaultSubtitles": "Standard", "OptionOnlyForcedSubtitles": "Only forced subtitles", - "OptionAlwaysPlaySubtitles": "Always play subtitles", + "OptionAlwaysPlaySubtitles": "Untertitel immer anzeigen", "OptionNoSubtitles": "Keine Untertitel", "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.", "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.", "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", - "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.", + "OptionNoSubtitlesHelp": "Untertitel wird standardm\u00e4\u00dfig nicht geladen.", "TabProfiles": "Profile", "TabSecurity": "Sicherheit", "ButtonAddUser": "User hinzuf\u00fcgen", @@ -295,13 +295,13 @@ "PasswordLocalhostMessage": "Passw\u00f6rter werden nich gebraucht, wenn Sie sich vom Localhost aus einloggen.", "TabGuide": "Programm", "TabChannels": "Kan\u00e4le", - "TabCollections": "Collections", + "TabCollections": "Sammlungen", "HeaderChannels": "Kan\u00e4le", "TabRecordings": "Aufnahmen", "TabScheduled": "Geplant", "TabSeries": "Serie", - "TabFavorites": "Favorites", - "TabMyLibrary": "My Library", + "TabFavorites": "Favoriten", + "TabMyLibrary": "Meine Bibliothek", "ButtonCancelRecording": "Aufnahme abbrechen", "HeaderPrePostPadding": "Pufferzeit vor\/nach der Aufnahme", "LabelPrePaddingMinutes": "Minuten vor der Aufnahme", @@ -470,7 +470,7 @@ "LabelMinResumePercentageHelp": "Titel werden als nicht abgespielt angenommen, wenn sie vor dieser Zeit gestoppt werden", "LabelMaxResumePercentageHelp": "Titel werden als komplett abgespielt angenommen, wenn sie nach dieser Zeit gestoppt werden", "LabelMinResumeDurationHelp": "Titel k\u00fcrzer als dies werden nicht fortsetzbar sein", - "TitleAutoOrganize": "Auto-Organize", + "TitleAutoOrganize": "automatische Sortierung", "TabActivityLog": "Aktivit\u00e4tsverlauf", "HeaderName": "Name", "HeaderDate": "Datum", @@ -481,7 +481,7 @@ "LabelCompleted": "Fertiggestellt", "LabelFailed": "Gescheitert", "LabelSkipped": "\u00dcbersprungen", - "HeaderEpisodeOrganization": "Episode Organization", + "HeaderEpisodeOrganization": "Episodensortierung", "LabelSeries": "Serien:", "LabelSeasonNumber": "Staffelnummer", "LabelEpisodeNumber": "Episodennummer", @@ -494,7 +494,7 @@ "DonationNextStep": "Sobald abgeschlossen, kehren Sie bitte hierher zur\u00fcck und tragen Sie den Unterst\u00fctzerschl\u00fcssel ein, den Sie per E-Mail erhalten haben.", "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.", "AutoOrganizeTvHelp": "TV Dateien Organisation wird nur Episoden zu bereits vorhandenen Serien hinzuf\u00fcgen. Es werden keine neuen Serien angelegt.", - "OptionEnableEpisodeOrganization": "Enable new episode organization", + "OptionEnableEpisodeOrganization": "Aktiviere die Sortierung neuer Episoden", "LabelWatchFolder": "\u00dcberwachungsordner:", "LabelWatchFolderHelp": "Der Server wird diesen Ordner, w\u00e4hrend des geplanten Tasks \"Organisiere neue Mediendateien\", abfragen.", "ButtonViewScheduledTasks": "Zeige Geplante Aufgaben", @@ -573,7 +573,7 @@ "HeaderRequireManualLoginHelp": "Wenn deaktiviert k\u00f6nnen Clients einen Loginbildschirm mit einer visuellen Auswahl der User anzeigen.", "OptionOtherApps": "Andere Apps", "OptionMobileApps": "Mobile Apps", - "HeaderNotificationList": "Click on a notification to configure it's sending options.", + "HeaderNotificationList": "Klicke auf eine Benachrichtigung um die Benachrichtigungseinstellungen zu bearbeiten", "NotificationOptionApplicationUpdateAvailable": "Anwendungsaktualisierung verf\u00fcgbar", "NotificationOptionApplicationUpdateInstalled": "Anwendungsaktualisierung installiert", "NotificationOptionPluginUpdateInstalled": "Pluginaktualisierung installiert", @@ -588,7 +588,7 @@ "NotificationOptionTaskFailed": "Scheduled task failure", "NotificationOptionInstallationFailed": "Installationsfehler", "NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugef\u00fcgt", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionNewLibraryContentMultiple": "Neuen Inhalte hinzugef\u00fcgt (mehrere)", "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", "NotificationOptionServerRestartRequired": "Serverneustart notwendig", "LabelNotificationEnabled": "Aktiviere diese Benachrichtigung", @@ -721,11 +721,11 @@ "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.", - "HeaderDownloadSubtitlesFor": "Download subtitles for:", + "HeaderDownloadSubtitlesFor": "Lade Untertitel runter f\u00fcr", "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.", - "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles", + "LabelSkipIfGraphicalSubsPresent": "\u00dcberspringen, falls das Video bereits grafische Untertitel enth\u00e4lt", "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.", - "TabSubtitles": "Subtitles", + "TabSubtitles": "Untertitel", "TabChapters": "Chapters", "HeaderDownloadChaptersFor": "Download chapter names for:", "LabelOpenSubtitlesUsername": "Open Subtitles username:", @@ -734,33 +734,33 @@ "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", "LabelSubtitlePlaybackMode": "Subtitle mode:", "LabelDownloadLanguages": "Download languages:", - "ButtonRegister": "Register", - "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", + "ButtonRegister": "Registrierung", + "LabelSkipIfAudioTrackPresent": "\u00dcberspringen, falls der Ton bereits der herunterladbaren Sprache entspricht", "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", - "HeaderSendMessage": "Send Message", - "ButtonSend": "Send", - "LabelMessageText": "Message text:", - "MessageNoAvailablePlugins": "No available plugins.", + "HeaderSendMessage": "sende Nachricht", + "ButtonSend": "senden", + "LabelMessageText": "Inhalt der Nachricht", + "MessageNoAvailablePlugins": "Keine verf\u00fcgbaren Erweiterungen.", "LabelDisplayPluginsFor": "Display plugins for:", "PluginTabMediaBrowserClassic": "MB Classic", "PluginTabMediaBrowserTheater": "MB Theater", - "TabOtherPlugins": "Others", - "LabelEpisodeName": "Episode name", - "LabelSeriesName": "Series name", + "TabOtherPlugins": "Andere", + "LabelEpisodeName": "Episodentitel", + "LabelSeriesName": "Serientitel", "ValueSeriesNamePeriod": "Series.name", "ValueSeriesNameUnderscore": "Series_name", - "ValueEpisodeNamePeriod": "Episode.name", + "ValueEpisodeNamePeriod": "Episodentitel", "ValueEpisodeNameUnderscore": "Episode_name", "HeaderTypeText": "Enter Text", "LabelTypeText": "Text", "HeaderSearchForSubtitles": "Search for Subtitles", "MessageNoSubtitleSearchResultsFound": "No search results founds.", - "TabDisplay": "Display", - "TabLanguages": "Languages", - "TabWebClient": "Web Client", - "LabelEnableThemeSongs": "Enable theme songs", + "TabDisplay": "Anzeige", + "TabLanguages": "Sprachen", + "TabWebClient": "Webclient", + "LabelEnableThemeSongs": "Aktiviere Titelmelodie", "LabelEnableBackdrops": "Aktiviere Backdrops", - "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.", + "LabelEnableThemeSongsHelp": "Wenn aktiviert, wird die Titelmusik w\u00e4hrend dem Durchsuchen durch die Bibliothek im Hintergrund abgespielt", "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.", "HeaderHomePage": "Home Page", "HeaderSettingsForThisDevice": "Einstellungen f\u00fcr dieses Ger\u00e4t", @@ -775,13 +775,13 @@ "OptionMyViews": "My views", "OptionMyViewsSmall": "My views (small)", "OptionResumablemedia": "Resume", - "OptionLatestMedia": "Latest media", + "OptionLatestMedia": "Neuste Medien", "OptionLatestChannelMedia": "Latest channel items", "HeaderLatestChannelItems": "Latest Channel Items", "OptionNone": "None", - "HeaderLiveTv": "Live TV", + "HeaderLiveTv": "Live Fernsehn", "HeaderReports": "Meldungen", - "HeaderMetadataManager": "Metadata Manager", + "HeaderMetadataManager": "Metadaten-Manager", "HeaderPreferences": "Einstellungen", "MessageLoadingChannels": "Lade Channel Inhalt...", "ButtonMarkRead": "Als gelesen markieren", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es.json b/MediaBrowser.Server.Implementations/Localization/Server/es.json index 9811cb9511..125693f340 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es.json @@ -770,14 +770,14 @@ "LabelHomePageSection1": "Secci\u00f3n uno de la p\u00e1gina de inicio:", "LabelHomePageSection2": "Secci\u00f3n dos de la p\u00e1gina de inicio:", "LabelHomePageSection3": "Secci\u00f3n tres de la p\u00e1gina de inicio:", - "LabelHomePageSection4": "Home page section four:", - "OptionMyViewsButtons": "My views (buttons)", - "OptionMyViews": "My views", - "OptionMyViewsSmall": "My views (small)", + "LabelHomePageSection4": "Secci\u00f3n cuarta de la p\u00e1gina de inicio", + "OptionMyViewsButtons": "Mis vistas (botones)", + "OptionMyViews": "Mis vistas", + "OptionMyViewsSmall": "Mis vistas (peque\u00f1o)", "OptionResumablemedia": "Continuar", "OptionLatestMedia": "\u00daltimos medios", - "OptionLatestChannelMedia": "Latest channel items", - "HeaderLatestChannelItems": "Latest Channel Items", + "OptionLatestChannelMedia": "Ultimos elementos de canales", + "HeaderLatestChannelItems": "Ultimos elementos de canales", "OptionNone": "Nada", "HeaderLiveTv": "TV en vivo", "HeaderReports": "Informes", @@ -813,13 +813,13 @@ "ViewTypeChannels": "Canales", "ViewTypeLiveTV": "Tv en vivo", "HeaderOtherDisplaySettings": "Configuraci\u00f3n de pantalla", - "HeaderMyViews": "My Views", + "HeaderMyViews": "Mis vistas", "LabelSelectFolderGroups": "Agrupar autom\u00e1ticamente las siguientes carpetas en vistas tales como pel\u00edculas, m\u00fasica y televisi\u00f3n", "LabelSelectFolderGroupsHelp": "Las carpetas que no est\u00e9n marcadas se mostrar\u00e1n por s\u00ed mismas en su propia secci\u00f3n.", "OptionDisplayAdultContent": "Mostrar contenido para adultos", "OptionLibraryFolders": "Vista de carpeta", - "TitleRemoteControl": "Remote Control", - "OptionLatestTvRecordings": "Latest recordings", - "LabelProtocolInfo": "Protocol info:", - "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device." + "TitleRemoteControl": "Control remoto", + "OptionLatestTvRecordings": "\u00daltimas grabaciones", + "LabelProtocolInfo": "Informaci\u00f3n de protocolo:", + "LabelProtocolInfoHelp": "El valor que se utilizar\u00e1 cuando se responde a una solicitud GetProtocolInfo desde el dispositivo." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json index 407cd6ace7..7ddd4c9872 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json @@ -94,7 +94,7 @@ "MessagePleaseEnsureInternetMetadata": "Por favor aseg\u00farese que la descarga de metadatos de internet esta habilitada.", "TabSuggested": "Sugerencias", "TabLatest": "Recientes", - "TabUpcoming": "Pr\u00f3ximo Estreno", + "TabUpcoming": "Por Estrenar", "TabShows": "Programas", "TabEpisodes": "Episodios", "TabGenres": "G\u00e9neros", @@ -771,9 +771,9 @@ "LabelHomePageSection2": "Pagina principal secci\u00f3n dos:", "LabelHomePageSection3": "Pagina principal secci\u00f3n tres:", "LabelHomePageSection4": "Pagina principal secci\u00f3n cuatro:", - "OptionMyViewsButtons": "My views (buttons)", - "OptionMyViews": "My views", - "OptionMyViewsSmall": "My views (small)", + "OptionMyViewsButtons": "Mis vistas (botones)", + "OptionMyViews": "Mis vistas", + "OptionMyViewsSmall": "Mis vistas (peque\u00f1o)", "OptionResumablemedia": "Reanudar", "OptionLatestMedia": "Agregados recientemente", "OptionLatestChannelMedia": "Elementos recientes de canales", @@ -820,6 +820,6 @@ "OptionLibraryFolders": "Carpetas de medios", "TitleRemoteControl": "Control Remoto", "OptionLatestTvRecordings": "\u00daltimas grabaciones", - "LabelProtocolInfo": "Protocol info:", - "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device." + "LabelProtocolInfo": "Informaci\u00f3n del protocolo:", + "LabelProtocolInfoHelp": "El valor que ser\u00e1 utilizado cuando se responde a solicitudes GetProtocolInfo desde el dispositivo." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fr.json b/MediaBrowser.Server.Implementations/Localization/Server/fr.json index 299868a541..69f75dd949 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json @@ -772,8 +772,8 @@ "LabelHomePageSection3": "Section 3 de la page de d\u00e9marrage:", "LabelHomePageSection4": "Section 4 de la page de d\u00e9marrage:", "OptionMyViewsButtons": "My views (buttons)", - "OptionMyViews": "My views", - "OptionMyViewsSmall": "My views (small)", + "OptionMyViews": "Mes vues", + "OptionMyViewsSmall": "Mes vues (petit)", "OptionResumablemedia": "Reprendre", "OptionLatestMedia": "Les plus r\u00e9cents", "OptionLatestChannelMedia": "Items de cha\u00eene les plus r\u00e9cents", @@ -820,6 +820,6 @@ "OptionLibraryFolders": "R\u00e9pertoires de m\u00e9dias", "TitleRemoteControl": "Acc\u00e8s \u00e0 distance", "OptionLatestTvRecordings": "Les plus r\u00e9cents enregistrements", - "LabelProtocolInfo": "Protocol info:", + "LabelProtocolInfo": "Infos sur le protocol:", "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pl.json b/MediaBrowser.Server.Implementations/Localization/Server/pl.json new file mode 100644 index 0000000000..4970fdccc6 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/Server/pl.json @@ -0,0 +1,825 @@ +{ + "LabelExit": "Wyj\u015b\u0107", + "LabelVisitCommunity": "Odwied\u017a spo\u0142eczno\u015b\u0107", + "LabelGithubWiki": "Wiki Github", + "LabelSwagger": "Swagger", + "LabelStandard": "Standardowy", + "LabelViewApiDocumentation": "Zobacz dokumentacj\u0119 Api", + "LabelBrowseLibrary": "Przejrzyj bibliotek\u0119", + "LabelConfigureMediaBrowser": "Skonfiguruj Media Browser", + "LabelOpenLibraryViewer": "Otw\u00f3rz przegl\u0105dark\u0119 biblioteki", + "LabelRestartServer": "Uruchom serwer ponownie", + "LabelShowLogWindow": "Show Log Window", + "LabelPrevious": "Wstecz", + "LabelFinish": "Koniec", + "LabelNext": "Dalej", + "LabelYoureDone": "Sko\u0144czy\u0142e\u015b!", + "WelcomeToMediaBrowser": "Witaj w Media Browser!", + "TitleMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "Asystent pomo\u017ce Ci podczas instalacji. Na pocz\u0105tku, wybierz tw\u00f3j preferowany j\u0119zyk.", + "TellUsAboutYourself": "Opowiedz nam o sobie", + "LabelYourFirstName": "Twoje imi\u0119:", + "MoreUsersCanBeAddedLater": "Mo\u017cesz doda\u0107 wi\u0119cej u\u017cytkownik\u00f3w p\u00f3\u017aniej przez tablic\u0119 rozdzielcz\u0105.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Serwis Windows", + "AWindowsServiceHasBeenInstalled": "Serwis Windows zosta\u0142 zainstalowany.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "To wszystko na teraz. Media Browser zacz\u0105\u0142 zbiera\u0107 informacje o twojej bibliotece. Zapoznaj si\u0119 z aplikacjami po czym kliknij Koniec<\/b> \u017ceby zobaczy\u0107 Tablic\u0119 rozdzielcz\u0105<\/b>.", + "LabelConfigureSettings": "Skonfiguruj ustawienia", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "Dla filmik\u00f3w kt\u00f3re nie maj\u0105 jeszcze obraz\u00f3w i dla kt\u00f3rych nie mo\u017cemy \u017cadnych znale\u017a\u0107 na internecie. Zwi\u0119kszy to czas wst\u0119pnego skanowania biblioteki ale wynikiem b\u0119dzie \u0142adniejsza prezentacja.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Anuluj", + "ButtonNew": "New", + "HeaderSetupLibrary": "Ustaw swoj\u0105 bibliotek\u0119", + "ButtonAddMediaFolder": "Dodaj folder", + "LabelFolderType": "Typ folderu:", + "MediaFolderHelpPluginRequired": "* Wymaga u\u017cycia wtyczki tak jak GameBrowser lub MB Bookshelf.", + "ReferToMediaLibraryWiki": "Odnie\u015b si\u0119 do wiki biblioteki.", + "LabelCountry": "Kraj:", + "LabelLanguage": "J\u0119zyk:", + "HeaderPreferredMetadataLanguage": "Preferowany j\u0119zyk metadanych:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.", + "TabPreferences": "Preferencje", + "TabPassword": "Has\u0142o", + "TabLibraryAccess": "Dost\u0119p do biblioteki", + "TabImage": "Obraz", + "TabProfile": "Profil", + "TabMetadata": "Metadata", + "TabImages": "Images", + "TabNotifications": "Notifications", + "TabCollectionTitles": "Titles", + "LabelDisplayMissingEpisodesWithinSeasons": "Wy\u015bwietl brakuj\u0105ce odcinki w sezonach", + "LabelUnairedMissingEpisodesWithinSeasons": "Wy\u015bwietl nie wydanie odcinki w sezonach", + "HeaderVideoPlaybackSettings": "Ustawienia odtwarzania wideo", + "HeaderPlaybackSettings": "Playback Settings", + "LabelAudioLanguagePreference": "Preferencje j\u0119zyka audio:", + "LabelSubtitleLanguagePreference": "Preferencje j\u0119zyka napis\u00f3w:", + "OptionDefaultSubtitles": "Default", + "OptionOnlyForcedSubtitles": "Only forced subtitles", + "OptionAlwaysPlaySubtitles": "Always play subtitles", + "OptionNoSubtitles": "No Subtitles", + "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.", + "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.", + "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", + "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.", + "TabProfiles": "Profile", + "TabSecurity": "Zabezpieczenie", + "ButtonAddUser": "Dodaj u\u017cytkownika", + "ButtonSave": "Zapisz", + "ButtonResetPassword": "Zresetuj has\u0142o", + "LabelNewPassword": "Nowe has\u0142o:", + "LabelNewPasswordConfirm": "Potwierd\u017a nowe has\u0142o:", + "HeaderCreatePassword": "Stw\u00f3rz has\u0142o:", + "LabelCurrentPassword": "Bie\u017c\u0105ce has\u0142o:", + "LabelMaxParentalRating": "Maksymalna dozwolona ocena rodzicielska:", + "MaxParentalRatingHelp": "Zawarto\u015b\u0107 z wy\u017csz\u0105 ocen\u0105 b\u0119dzie schowana dla tego u\u017cytkownika.", + "LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.", + "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", + "ButtonDeleteImage": "Usu\u0144 obrazek", + "LabelSelectUsers": "Select users:", + "ButtonUpload": "Wy\u015blij", + "HeaderUploadNewImage": "Wy\u015blij nowy obrazek", + "LabelDropImageHere": "Wrzu\u0107 obrazek tutaj", + "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.", + "MessageNothingHere": "Nic tutaj nie ma.", + "MessagePleaseEnsureInternetMetadata": "Upewnij si\u0119 \u017ce pobieranie metadanych z internetu jest w\u0142\u0105czone.", + "TabSuggested": "Sugerowane", + "TabLatest": "Ostatnie", + "TabUpcoming": "Upcoming", + "TabShows": "Seriale", + "TabEpisodes": "Odcinki", + "TabGenres": "Rodzaje", + "TabPeople": "Osoby", + "TabNetworks": "Sieci", + "HeaderUsers": "U\u017cytkownicy", + "HeaderFilters": "Filtry:", + "ButtonFilter": "Filtr", + "OptionFavorite": "Ulubione", + "OptionLikes": "Likes", + "OptionDislikes": "Dislikes", + "OptionActors": "Aktorzy", + "OptionGuestStars": "Guest Stars", + "OptionDirectors": "Dyrektorzy", + "OptionWriters": "Pisarze", + "OptionProducers": "Producenci", + "HeaderResume": "Wzn\u00f3w", + "HeaderNextUp": "Next Up", + "NoNextUpItemsMessage": "Nie znaleziono \u017cadnego. Zacznij ogl\u0105da\u0107 Twoje seriale!", + "HeaderLatestEpisodes": "Ostanie odcinki", + "HeaderPersonTypes": "Person Types:", + "TabSongs": "Utwory", + "TabAlbums": "Albumy", + "TabArtists": "Arty\u015bci", + "TabAlbumArtists": "Arty\u015bci albumu", + "TabMusicVideos": "Teledyski", + "ButtonSort": "Sortuj", + "HeaderSortBy": "Sortuj wed\u0142ug:", + "HeaderSortOrder": "Kolejno\u015b\u0107 sortowania:", + "OptionPlayed": "Played", + "OptionUnplayed": "Unplayed", + "OptionAscending": "Rosn\u0105co", + "OptionDescending": "Malej\u0105co", + "OptionRuntime": "D\u0142ugo\u015b\u0107 filmu", + "OptionReleaseDate": "Data wydania", + "OptionPlayCount": "Ilo\u015b\u0107 odtworze\u0144", + "OptionDatePlayed": "Data odtworzenia", + "OptionDateAdded": "Data dodania", + "OptionAlbumArtist": "Artysta albumu", + "OptionArtist": "Artysta", + "OptionAlbum": "Album", + "OptionTrackName": "Nazwa utworu", + "OptionCommunityRating": "Ocena spo\u0142eczno\u015bci", + "OptionNameSort": "Nazwa", + "OptionFolderSort": "Folders", + "OptionBudget": "Bud\u017cet", + "OptionRevenue": "Doch\u00f3d", + "OptionPoster": "Plakat", + "OptionBackdrop": "Backdrop", + "OptionTimeline": "Timeline", + "OptionThumb": "Thumb", + "OptionBanner": "Banner", + "OptionCriticRating": "Ocena krytyk\u00f3w", + "OptionVideoBitrate": "Video Bitrate", + "OptionResumable": "Resumable", + "ScheduledTasksHelp": "Click a task to adjust its schedule.", + "ScheduledTasksTitle": "Zaplanowane zadania", + "TabMyPlugins": "Moje wtyczki", + "TabCatalog": "Katalog", + "PluginsTitle": "Wtyczki", + "HeaderAutomaticUpdates": "Automatyczne aktualizacje", + "HeaderNowPlaying": "Now Playing", + "HeaderLatestAlbums": "Ostatnie albumy", + "HeaderLatestSongs": "Ostatnie utwory", + "HeaderRecentlyPlayed": "Ostatnio grane", + "HeaderFrequentlyPlayed": "Cz\u0119sto grane", + "DevBuildWarning": "Dev builds are the bleeding edge. Released often, these build have not been tested. The application may crash and entire features may not work at all.", + "LabelVideoType": "Type widea", + "OptionBluray": "Bluray", + "OptionDvd": "Dvd", + "OptionIso": "Iso", + "Option3D": "3D", + "LabelFeatures": "W\u0142a\u015bciwo\u015bci", + "LabelService": "Service:", + "LabelStatus": "Status:", + "LabelVersion": "Version:", + "LabelLastResult": "Last result:", + "OptionHasSubtitles": "Napisy", + "OptionHasTrailer": "Zwiastun", + "OptionHasThemeSong": "Theme Song", + "OptionHasThemeVideo": "Theme Video", + "TabMovies": "Filmy", + "TabStudios": "Studia", + "TabTrailers": "Zwiastuny", + "HeaderLatestMovies": "Ostatnie filmy", + "HeaderLatestTrailers": "Ostatnie zwiastuny", + "OptionHasSpecialFeatures": "Special Features", + "OptionImdbRating": "Ocena IMDb", + "OptionParentalRating": "Ocena rodzicielska", + "OptionPremiereDate": "Data premiery", + "TabBasic": "Podstawowe", + "TabAdvanced": "Zaawansowane", + "HeaderStatus": "Status", + "OptionContinuing": "Continuing", + "OptionEnded": "Ended", + "HeaderAirDays": "Air Days:", + "OptionSunday": "Niedziela", + "OptionMonday": "Poniedzia\u0142ek", + "OptionTuesday": "Wtorek", + "OptionWednesday": "\u015aroda", + "OptionThursday": "Czwartek", + "OptionFriday": "Pi\u0105tek", + "OptionSaturday": "Sobota", + "HeaderManagement": "Management:", + "OptionMissingImdbId": "Brakuje Id IMDb", + "OptionMissingTvdbId": "Brakuje Id TheTVDB", + "OptionMissingOverview": "Missing Overview", + "OptionFileMetadataYearMismatch": "File\/Metadata Years Mismatched", + "TabGeneral": "Og\u00f3lne", + "TitleSupport": "Wesprzyj", + "TabLog": "Log", + "TabAbout": "A propos", + "TabSupporterKey": "Supporter Key", + "TabBecomeSupporter": "Become a Supporter", + "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.", + "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.", + "SearchKnowledgeBase": "Search the Knowledge Base", + "VisitTheCommunity": "Odwied\u017a spo\u0142eczno\u015b\u0107", + "VisitMediaBrowserWebsite": "Odwied\u017a stron\u0119 Media Browser", + "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.", + "OptionHideUser": "Hide this user from login screens", + "OptionDisableUser": "Disable this user", + "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.", + "HeaderAdvancedControl": "Advanced Control", + "LabelName": "Name:", + "OptionAllowUserToManageServer": "Allow this user to manage the server", + "HeaderFeatureAccess": "Feature Access", + "OptionAllowMediaPlayback": "Allow media playback", + "OptionAllowBrowsingLiveTv": "Allow browsing of live tv", + "OptionAllowDeleteLibraryContent": "Allow this user to delete library content", + "OptionAllowManageLiveTv": "Allow management of live tv recordings", + "OptionAllowRemoteControlOthers": "Allow this user to remote control other users", + "OptionMissingTmdbId": "Missing Tmdb Id", + "OptionIsHD": "HD", + "OptionIsSD": "SD", + "OptionMetascore": "Metascore", + "ButtonSelect": "Select", + "ButtonSearch": "Search", + "ButtonGroupVersions": "Group Versions", + "ButtonAddToCollection": "Add to Collection", + "PismoMessage": "Utilizing Pismo File Mount through a donated license.", + "TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.", + "HeaderCredits": "Credits", + "PleaseSupportOtherProduces": "Please support other free products we utilize:", + "VersionNumber": "Version {0}", + "TabPaths": "Paths", + "TabServer": "Server", + "TabTranscoding": "Transcoding", + "TitleAdvanced": "Advanced", + "LabelAutomaticUpdateLevel": "Automatic update level", + "OptionRelease": "Oficjalne wydanie", + "OptionBeta": "Beta", + "OptionDev": "Dev (Niestabilne)", + "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates", + "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.", + "LabelEnableDebugLogging": "Enable debug logging", + "LabelRunServerAtStartup": "Run server at startup", + "LabelRunServerAtStartupHelp": "This will start the tray icon on windows startup. To start the windows service, uncheck this and run the service from the windows control panel. Please note that you cannot run both at the same time, so you will need to exit the tray icon before starting the service.", + "ButtonSelectDirectory": "Select Directory", + "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", + "LabelCachePath": "Cache path:", + "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelImagesByNamePath": "Images by name path:", + "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.", + "LabelMetadataPath": "Metadata path:", + "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelTranscodingTempPath": "Transcoding temporary path:", + "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder.", + "TabBasics": "Basics", + "TabTV": "TV", + "TabGames": "Games", + "TabMusic": "Music", + "TabOthers": "Others", + "HeaderExtractChapterImagesFor": "Extract chapter images for:", + "OptionMovies": "Movies", + "OptionEpisodes": "Episodes", + "OptionOtherVideos": "Other Videos", + "TitleMetadata": "Metadata", + "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", + "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", + "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", + "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", + "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelMetadataDownloadLanguage": "Preferred download language:", + "ButtonAutoScroll": "Auto-scroll", + "LabelImageSavingConvention": "Image saving convention:", + "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.", + "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc", + "OptionImageSavingStandard": "Standard - MB2", + "ButtonSignIn": "Sign In", + "TitleSignIn": "Sign In", + "HeaderPleaseSignIn": "Please sign in", + "LabelUser": "User:", + "LabelPassword": "Password:", + "ButtonManualLogin": "Manual Login", + "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.", + "TabGuide": "Guide", + "TabChannels": "Channels", + "TabCollections": "Collections", + "HeaderChannels": "Channels", + "TabRecordings": "Recordings", + "TabScheduled": "Scheduled", + "TabSeries": "Series", + "TabFavorites": "Favorites", + "TabMyLibrary": "My Library", + "ButtonCancelRecording": "Cancel Recording", + "HeaderPrePostPadding": "Pre\/Post Padding", + "LabelPrePaddingMinutes": "Pre-padding minutes:", + "OptionPrePaddingRequired": "Pre-padding is required in order to record.", + "LabelPostPaddingMinutes": "Post-padding minutes:", + "OptionPostPaddingRequired": "Post-padding is required in order to record.", + "HeaderWhatsOnTV": "What's On", + "HeaderUpcomingTV": "Upcoming TV", + "TabStatus": "Status", + "TabSettings": "Settings", + "ButtonRefreshGuideData": "Refresh Guide Data", + "OptionPriority": "Priority", + "OptionRecordOnAllChannels": "Record program on all channels", + "OptionRecordAnytime": "Record program at any time", + "OptionRecordOnlyNewEpisodes": "Record only new episodes", + "HeaderDays": "Days", + "HeaderActiveRecordings": "Active Recordings", + "HeaderLatestRecordings": "Latest Recordings", + "HeaderAllRecordings": "All Recordings", + "ButtonPlay": "Play", + "ButtonEdit": "Edit", + "ButtonRecord": "Record", + "ButtonDelete": "Delete", + "ButtonRemove": "Remove", + "OptionRecordSeries": "Record Series", + "HeaderDetails": "Details", + "TitleLiveTV": "Live TV", + "LabelNumberOfGuideDays": "Number of days of guide data to download:", + "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.", + "LabelActiveService": "Active Service:", + "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.", + "OptionAutomatic": "Auto", + "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.", + "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.", + "LabelCustomizeOptionsPerMediaType": "Customize for media type:", + "OptionDownloadThumbImage": "Thumb", + "OptionDownloadMenuImage": "Menu", + "OptionDownloadLogoImage": "Logo", + "OptionDownloadBoxImage": "Box", + "OptionDownloadDiscImage": "Disc", + "OptionDownloadBannerImage": "Banner", + "OptionDownloadBackImage": "Back", + "OptionDownloadArtImage": "Art", + "OptionDownloadPrimaryImage": "Primary", + "HeaderFetchImages": "Fetch Images:", + "HeaderImageSettings": "Image Settings", + "TabOther": "Other", + "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:", + "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:", + "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:", + "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:", + "ButtonAddScheduledTaskTrigger": "Add Task Trigger", + "HeaderAddScheduledTaskTrigger": "Add Task Trigger", + "ButtonAdd": "Add", + "LabelTriggerType": "Trigger Type:", + "OptionDaily": "Daily", + "OptionWeekly": "Weekly", + "OptionOnInterval": "On an interval", + "OptionOnAppStartup": "On application startup", + "OptionAfterSystemEvent": "After a system event", + "LabelDay": "Day:", + "LabelTime": "Time:", + "LabelEvent": "Event:", + "OptionWakeFromSleep": "Wake from sleep", + "LabelEveryXMinutes": "Every:", + "HeaderTvTuners": "Tuners", + "HeaderGallery": "Gallery", + "HeaderLatestGames": "Latest Games", + "HeaderRecentlyPlayedGames": "Recently Played Games", + "TabGameSystems": "Game Systems", + "TitleMediaLibrary": "Media Library", + "TabFolders": "Folders", + "TabPathSubstitution": "Path Substitution", + "LabelSeasonZeroDisplayName": "Season 0 display name:", + "LabelEnableRealtimeMonitor": "Enable real time monitoring", + "LabelEnableRealtimeMonitorHelp": "Changes will be processed immediately, on supported file systems.", + "ButtonScanLibrary": "Scan Library", + "HeaderNumberOfPlayers": "Players:", + "OptionAnyNumberOfPlayers": "Any", + "Option1Player": "1+", + "Option2Player": "2+", + "Option3Player": "3+", + "Option4Player": "4+", + "HeaderMediaFolders": "Media Folders", + "HeaderThemeVideos": "Theme Videos", + "HeaderThemeSongs": "Theme Songs", + "HeaderScenes": "Scenes", + "HeaderAwardsAndReviews": "Awards and Reviews", + "HeaderSoundtracks": "Soundtracks", + "HeaderMusicVideos": "Music Videos", + "HeaderSpecialFeatures": "Special Features", + "HeaderCastCrew": "Cast & Crew", + "HeaderAdditionalParts": "Additional Parts", + "ButtonSplitVersionsApart": "Split Versions Apart", + "ButtonPlayTrailer": "Trailer", + "LabelMissing": "Missing", + "LabelOffline": "Offline", + "PathSubstitutionHelp": "Path substitutions are used for mapping a path on the server to a path that clients are able to access. By allowing clients direct access to media on the server they may be able to play them directly over the network and avoid using server resources to stream and transcode them.", + "HeaderFrom": "From", + "HeaderTo": "To", + "LabelFrom": "From:", + "LabelFromHelp": "Example: D:\\Movies (on the server)", + "LabelTo": "To:", + "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)", + "ButtonAddPathSubstitution": "Add Substitution", + "OptionSpecialEpisode": "Specials", + "OptionMissingEpisode": "Missing Episodes", + "OptionUnairedEpisode": "Unaired Episodes", + "OptionEpisodeSortName": "Episode Sort Name", + "OptionSeriesSortName": "Series Name", + "OptionTvdbRating": "Tvdb Rating", + "HeaderTranscodingQualityPreference": "Transcoding Quality Preference:", + "OptionAutomaticTranscodingHelp": "The server will decide quality and speed", + "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding", + "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding", + "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage", + "OptionHighSpeedTranscoding": "Higher speed", + "OptionHighQualityTranscoding": "Higher quality", + "OptionMaxQualityTranscoding": "Max quality", + "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging", + "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.", + "OptionUpscaling": "Allow clients to request upscaled video", + "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.", + "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.", + "HeaderAddTitles": "Add Titles", + "LabelEnableDlnaPlayTo": "Enable DLNA Play To", + "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.", + "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", + "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.", + "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)", + "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.", + "HeaderCustomDlnaProfiles": "Custom Profiles", + "HeaderSystemDlnaProfiles": "System Profiles", + "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", + "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", + "TitleDashboard": "Dashboard", + "TabHome": "Home", + "TabInfo": "Info", + "HeaderLinks": "Links", + "HeaderSystemPaths": "System Paths", + "LinkCommunity": "Community", + "LinkGithub": "Github", + "LinkApiDocumentation": "Api Documentation", + "LabelFriendlyServerName": "Friendly server name:", + "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", + "LabelPreferredDisplayLanguage": "Preferred display language", + "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", + "LabelReadHowYouCanContribute": "Read about how you can contribute.", + "HeaderNewCollection": "New Collection", + "HeaderAddToCollection": "Add to Collection", + "ButtonSubmit": "Submit", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "ButtonCreate": "Create", + "LabelHttpServerPortNumber": "Http server port number:", + "LabelWebSocketPortNumber": "Web socket port number:", + "LabelEnableAutomaticPortHelp": "UPnP allows automated router configuration for remote access. This may not work with some router models.", + "LabelExternalDDNS": "External DDNS:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "TabResume": "Resume", + "TabWeather": "Weather", + "TitleAppSettings": "App Settings", + "LabelMinResumePercentage": "Min resume percentage:", + "LabelMaxResumePercentage": "Max resume percentage:", + "LabelMinResumeDuration": "Min resume duration (seconds):", + "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time", + "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time", + "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable", + "TitleAutoOrganize": "Auto-Organize", + "TabActivityLog": "Activity Log", + "HeaderName": "Name", + "HeaderDate": "Date", + "HeaderSource": "Source", + "HeaderDestination": "Destination", + "HeaderProgram": "Program", + "HeaderClients": "Clients", + "LabelCompleted": "Completed", + "LabelFailed": "Failed", + "LabelSkipped": "Skipped", + "HeaderEpisodeOrganization": "Episode Organization", + "LabelSeries": "Series:", + "LabelSeasonNumber": "Season number", + "LabelEpisodeNumber": "Episode number", + "LabelEndingEpisodeNumber": "Ending episode number", + "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files", + "HeaderSupportTheTeam": "Support the Media Browser Team", + "LabelSupportAmount": "Amount (USD)", + "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.", + "ButtonEnterSupporterKey": "Enter supporter key", + "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.", + "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.", + "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.", + "OptionEnableEpisodeOrganization": "Enable new episode organization", + "LabelWatchFolder": "Watch folder:", + "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.", + "ButtonViewScheduledTasks": "View scheduled tasks", + "LabelMinFileSizeForOrganize": "Minimum file size (MB):", + "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.", + "LabelSeasonFolderPattern": "Season folder pattern:", + "LabelSeasonZeroFolderName": "Season zero folder name:", + "HeaderEpisodeFilePattern": "Episode file pattern", + "LabelEpisodePattern": "Episode pattern:", + "LabelMultiEpisodePattern": "Multi-Episode pattern:", + "HeaderSupportedPatterns": "Supported Patterns", + "HeaderTerm": "Term", + "HeaderPattern": "Pattern", + "HeaderResult": "Result", + "LabelDeleteEmptyFolders": "Delete empty folders after organizing", + "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.", + "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:", + "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt", + "OptionOverwriteExistingEpisodes": "Overwrite existing episodes", + "LabelTransferMethod": "Transfer method", + "OptionCopy": "Copy", + "OptionMove": "Move", + "LabelTransferMethodHelp": "Copy or move files from the watch folder", + "HeaderLatestNews": "Latest News", + "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser", + "HeaderRunningTasks": "Running Tasks", + "HeaderActiveDevices": "Active Devices", + "HeaderPendingInstallations": "Pending Installations", + "HeaerServerInformation": "Server Information", + "ButtonRestartNow": "Restart Now", + "ButtonRestart": "Restart", + "ButtonShutdown": "Shutdown", + "ButtonUpdateNow": "Update Now", + "PleaseUpdateManually": "Please shutdown the server and update manually.", + "NewServerVersionAvailable": "A new version of Media Browser Server is available!", + "ServerUpToDate": "Media Browser Server is up to date", + "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.", + "LabelComponentsUpdated": "The following components have been installed or updated:", + "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.", + "LabelDownMixAudioScale": "Audio boost when downmixing:", + "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.", + "ButtonLinkKeys": "Link Keys", + "LabelOldSupporterKey": "Old supporter key", + "LabelNewSupporterKey": "New supporter key", + "HeaderMultipleKeyLinking": "Multiple Key Linking", + "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.", + "LabelCurrentEmailAddress": "Current email address", + "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.", + "HeaderForgotKey": "Forgot Key", + "LabelEmailAddress": "Email address", + "LabelSupporterEmailAddress": "The email address that was used to purchase the key.", + "ButtonRetrieveKey": "Retrieve Key", + "LabelSupporterKey": "Supporter Key (paste from email)", + "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.", + "MessageInvalidKey": "Supporter key is missing or invalid.", + "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.", + "HeaderDisplaySettings": "Display Settings", + "TabPlayTo": "Play To", + "LabelEnableDlnaServer": "Enable Dlna server", + "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.", + "LabelEnableBlastAliveMessages": "Blast alive messages", + "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", + "LabelBlastMessageInterval": "Alive message interval (seconds)", + "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.", + "LabelDefaultUser": "Default user:", + "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", + "TitleDlna": "DLNA", + "TitleChannels": "Channels", + "HeaderServerSettings": "Server Settings", + "LabelWeatherDisplayLocation": "Weather display location:", + "LabelWeatherDisplayLocationHelp": "US zip code \/ City, State, Country \/ City, Country", + "LabelWeatherDisplayUnit": "Weather display unit:", + "OptionCelsius": "Celsius", + "OptionFahrenheit": "Fahrenheit", + "HeaderRequireManualLogin": "Require manual username entry for:", + "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.", + "OptionOtherApps": "Other apps", + "OptionMobileApps": "Mobile apps", + "HeaderNotificationList": "Click on a notification to configure it's sending options.", + "NotificationOptionApplicationUpdateAvailable": "Application update available", + "NotificationOptionApplicationUpdateInstalled": "Application update installed", + "NotificationOptionPluginUpdateInstalled": "Plugin update installed", + "NotificationOptionPluginInstalled": "Plugin installed", + "NotificationOptionPluginUninstalled": "Plugin uninstalled", + "NotificationOptionVideoPlayback": "Video playback started", + "NotificationOptionAudioPlayback": "Audio playback started", + "NotificationOptionGamePlayback": "Game playback started", + "NotificationOptionVideoPlaybackStopped": "Video playback stopped", + "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", + "NotificationOptionGamePlaybackStopped": "Game playback stopped", + "NotificationOptionTaskFailed": "Scheduled task failure", + "NotificationOptionInstallationFailed": "Installation failure", + "NotificationOptionNewLibraryContent": "New content added", + "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", + "NotificationOptionServerRestartRequired": "Server restart required", + "LabelNotificationEnabled": "Enable this notification", + "LabelMonitorUsers": "Monitor activity from:", + "LabelSendNotificationToUsers": "Send the notification to:", + "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.", + "LabelUseNotificationServices": "Use the following services:", + "CategoryUser": "User", + "CategorySystem": "System", + "CategoryApplication": "Application", + "CategoryPlugin": "Plugin", + "LabelMessageTitle": "Message title:", + "LabelAvailableTokens": "Available tokens:", + "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.", + "OptionAllUsers": "All users", + "OptionAdminUsers": "Administrators", + "OptionCustomUsers": "Custom", + "ButtonArrowUp": "Up", + "ButtonArrowDown": "Down", + "ButtonArrowLeft": "Left", + "ButtonArrowRight": "Right", + "ButtonBack": "Back", + "ButtonInfo": "Info", + "ButtonOsd": "On screen display", + "ButtonPageUp": "Page Up", + "ButtonPageDown": "Page Down", + "PageAbbreviation": "PG", + "ButtonHome": "Home", + "ButtonSettings": "Settings", + "ButtonTakeScreenshot": "Capture Screenshot", + "ButtonLetterUp": "Letter Up", + "ButtonLetterDown": "Letter Down", + "PageButtonAbbreviation": "PG", + "LetterButtonAbbreviation": "A", + "TabNowPlaying": "Now Playing", + "TabNavigation": "Navigation", + "TabControls": "Controls", + "ButtonFullscreen": "Toggle fullscreen", + "ButtonScenes": "Scenes", + "ButtonSubtitles": "Subtitles", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", + "ButtonStop": "Stop", + "ButtonPause": "Pause", + "LabelGroupMoviesIntoCollections": "Group movies into collections", + "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.", + "NotificationOptionPluginError": "Plugin failure", + "ButtonVolumeUp": "Volume up", + "ButtonVolumeDown": "Volume down", + "ButtonMute": "Mute", + "HeaderLatestMedia": "Latest Media", + "OptionSpecialFeatures": "Special Features", + "HeaderCollections": "Collections", + "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", + "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", + "HeaderResponseProfile": "Response Profile", + "LabelType": "Type:", + "LabelProfileContainer": "Container:", + "LabelProfileVideoCodecs": "Video codecs:", + "LabelProfileAudioCodecs": "Audio codecs:", + "LabelProfileCodecs": "Codecs:", + "HeaderDirectPlayProfile": "Direct Play Profile", + "HeaderTranscodingProfile": "Transcoding Profile", + "HeaderCodecProfile": "Codec Profile", + "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.", + "HeaderContainerProfile": "Container Profile", + "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.", + "OptionProfileVideo": "Video", + "OptionProfileAudio": "Audio", + "OptionProfileVideoAudio": "Video Audio", + "OptionProfilePhoto": "Photo", + "LabelUserLibrary": "User library:", + "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.", + "OptionPlainStorageFolders": "Display all folders as plain storage folders", + "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".", + "OptionPlainVideoItems": "Display all videos as plain video items", + "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", + "LabelSupportedMediaTypes": "Supported Media Types:", + "TabIdentification": "Identification", + "TabDirectPlay": "Direct Play", + "TabContainers": "Containers", + "TabCodecs": "Codecs", + "TabResponses": "Responses", + "HeaderProfileInformation": "Profile Information", + "LabelEmbedAlbumArtDidl": "Embed album art in Didl", + "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.", + "LabelAlbumArtPN": "Album art PN:", + "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.", + "LabelAlbumArtMaxWidth": "Album art max width:", + "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.", + "LabelAlbumArtMaxHeight": "Album art max height:", + "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.", + "LabelIconMaxWidth": "Icon max width:", + "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.", + "LabelIconMaxHeight": "Icon max height:", + "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.", + "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", + "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.", + "LabelMaxBitrate": "Max bitrate:", + "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.", + "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", + "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.", + "LabelFriendlyName": "Friendly name", + "LabelManufacturer": "Manufacturer", + "LabelManufacturerUrl": "Manufacturer url", + "LabelModelName": "Model name", + "LabelModelNumber": "Model number", + "LabelModelDescription": "Model description", + "LabelModelUrl": "Model url", + "LabelSerialNumber": "Serial number", + "LabelDeviceDescription": "Device description", + "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", + "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.", + "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", + "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", + "LabelXDlnaCap": "X-Dlna cap:", + "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelXDlnaDoc": "X-Dlna doc:", + "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelSonyAggregationFlags": "Sony aggregation flags:", + "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.", + "LabelTranscodingContainer": "Container:", + "LabelTranscodingVideoCodec": "Video codec:", + "LabelTranscodingVideoProfile": "Video profile:", + "LabelTranscodingAudioCodec": "Audio codec:", + "OptionEnableM2tsMode": "Enable M2ts mode", + "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.", + "OptionEstimateContentLength": "Estimate content length when transcoding", + "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", + "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", + "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.", + "HeaderDownloadSubtitlesFor": "Download subtitles for:", + "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.", + "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles", + "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.", + "TabSubtitles": "Subtitles", + "TabChapters": "Chapters", + "HeaderDownloadChaptersFor": "Download chapter names for:", + "LabelOpenSubtitlesUsername": "Open Subtitles username:", + "LabelOpenSubtitlesPassword": "Open Subtitles password:", + "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.", + "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", + "LabelSubtitlePlaybackMode": "Subtitle mode:", + "LabelDownloadLanguages": "Download languages:", + "ButtonRegister": "Register", + "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", + "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", + "HeaderSendMessage": "Send Message", + "ButtonSend": "Send", + "LabelMessageText": "Message text:", + "MessageNoAvailablePlugins": "No available plugins.", + "LabelDisplayPluginsFor": "Display plugins for:", + "PluginTabMediaBrowserClassic": "MB Classic", + "PluginTabMediaBrowserTheater": "MB Theater", + "TabOtherPlugins": "Others", + "LabelEpisodeName": "Episode name", + "LabelSeriesName": "Series name", + "ValueSeriesNamePeriod": "Series.name", + "ValueSeriesNameUnderscore": "Series_name", + "ValueEpisodeNamePeriod": "Episode.name", + "ValueEpisodeNameUnderscore": "Episode_name", + "HeaderTypeText": "Enter Text", + "LabelTypeText": "Text", + "HeaderSearchForSubtitles": "Search for Subtitles", + "MessageNoSubtitleSearchResultsFound": "No search results founds.", + "TabDisplay": "Display", + "TabLanguages": "Languages", + "TabWebClient": "Web Client", + "LabelEnableThemeSongs": "Enable theme songs", + "LabelEnableBackdrops": "Enable backdrops", + "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.", + "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.", + "HeaderHomePage": "Home Page", + "HeaderSettingsForThisDevice": "Settings for This Device", + "OptionAuto": "Auto", + "OptionYes": "Yes", + "OptionNo": "No", + "LabelHomePageSection1": "Home page section one:", + "LabelHomePageSection2": "Home page section two:", + "LabelHomePageSection3": "Home page section three:", + "LabelHomePageSection4": "Home page section four:", + "OptionMyViewsButtons": "My views (buttons)", + "OptionMyViews": "My views", + "OptionMyViewsSmall": "My views (small)", + "OptionResumablemedia": "Resume", + "OptionLatestMedia": "Latest media", + "OptionLatestChannelMedia": "Latest channel items", + "HeaderLatestChannelItems": "Latest Channel Items", + "OptionNone": "None", + "HeaderLiveTv": "Live TV", + "HeaderReports": "Reports", + "HeaderMetadataManager": "Metadata Manager", + "HeaderPreferences": "Preferences", + "MessageLoadingChannels": "Loading channel content...", + "ButtonMarkRead": "Mark Read", + "OptionDefaultSort": "Default", + "OptionCommunityMostWatchedSort": "Most Watched", + "TabNextUp": "Next Up", + "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", + "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the New button to start creating Collections.", + "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", + "ButtonDismiss": "Dismiss", + "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.", + "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.", + "LabelChannelStreamQuality": "Preferred internet stream quality:", + "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.", + "OptionBestAvailableStreamQuality": "Best available", + "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:", + "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.", + "LabelChannelDownloadPath": "Channel content download path:", + "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.", + "LabelChannelDownloadAge": "Delete content after: (days)", + "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", + "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", + "LabelSelectCollection": "Select collection:", + "ViewTypeMovies": "Movies", + "ViewTypeTvShows": "TV", + "ViewTypeGames": "Games", + "ViewTypeMusic": "Music", + "ViewTypeBoxSets": "Collections", + "ViewTypeChannels": "Channels", + "ViewTypeLiveTV": "Live TV", + "HeaderOtherDisplaySettings": "Display Settings", + "HeaderMyViews": "My Views", + "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", + "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", + "OptionDisplayAdultContent": "Display adult content", + "OptionLibraryFolders": "Media folders", + "TitleRemoteControl": "Remote Control", + "OptionLatestTvRecordings": "Latest recordings", + "LabelProtocolInfo": "Protocol info:", + "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json index 31282dfeed..9dbd946fe4 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json @@ -770,10 +770,10 @@ "LabelHomePageSection1": "Se\u00e7\u00e3o um da tela de in\u00edcio:", "LabelHomePageSection2": "Se\u00e7\u00e3o dois da tela de in\u00edcio:", "LabelHomePageSection3": "Se\u00e7\u00e3o tr\u00eas da tela de in\u00edcio:", - "LabelHomePageSection4": "Se\u00e7\u00e3o quatro da tela de inicio", - "OptionMyViewsButtons": "My views (buttons)", - "OptionMyViews": "My views", - "OptionMyViewsSmall": "My views (small)", + "LabelHomePageSection4": "Se\u00e7\u00e3o quatro da tela de in\u00edcio", + "OptionMyViewsButtons": "Minhas visualiza\u00e7\u00f5es (bot\u00f5es)", + "OptionMyViews": "Minhas visualiza\u00e7\u00f5es", + "OptionMyViewsSmall": "Minhas visualiza\u00e7\u00f5es (pequeno)", "OptionResumablemedia": "Retomar", "OptionLatestMedia": "M\u00eddias recentes", "OptionLatestChannelMedia": "Itens recentes de canal", @@ -820,6 +820,6 @@ "OptionLibraryFolders": "Pastas de m\u00eddias", "TitleRemoteControl": "Controle Remoto", "OptionLatestTvRecordings": "\u00daltimas grava\u00e7\u00f5es", - "LabelProtocolInfo": "Protocol info:", - "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device." + "LabelProtocolInfo": "Informa\u00e7\u00e3o do protocolo:", + "LabelProtocolInfoHelp": "O valor que ser\u00e1 usado ao responder os pedidos GetProtocolInfo do dispositivo." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ru.json b/MediaBrowser.Server.Implementations/Localization/Server/ru.json index 203454e3f4..e92a234179 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json @@ -491,7 +491,7 @@ "LabelSupportAmount": "\u0421\u0443\u043c\u043c\u0430 (USD)", "HeaderSupportTheTeamHelp": "\u041f\u043e\u043c\u043e\u0433\u0438\u0442\u0435 \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 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u0443\u0442\u0451\u043c \u0434\u0430\u0440\u0435\u043d\u0438\u044f. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0447\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\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\u043e\u0435 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e.", "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 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u0435.", + "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": "\u041f\u0440\u0438 \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\u0441\u044f \u043f\u0430\u043f\u043a\u0430, \u043a\u0443\u0434\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b, \u0430 \u0437\u0430\u0442\u0435\u043c \u0442\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u044b \u0432 \u0432\u0430\u0448\u0438 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438.", "AutoOrganizeTvHelp": "\u041f\u0440\u0438 \u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0422\u0412 \u0444\u0430\u0439\u043b\u043e\u0432 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u0435\u0440\u0438\u0430\u043b\u044b. \u041d\u043e\u0432\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u044b.", "OptionEnableEpisodeOrganization": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u043e\u0432\u044b\u0445 \u044d\u043f\u0438\u0437\u043e\u0434\u043e\u0432", @@ -532,7 +532,7 @@ "NewServerVersionAvailable": "\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f Media Browser Server!", "ServerUpToDate": "Media Browser Server - \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d", "ErrorConnectingToMediaBrowserRepository": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u043c\u0443 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e Media Browser.", - "LabelComponentsUpdated": "\u0411\u044b\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b :", + "LabelComponentsUpdated": "\u0411\u044b\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:", "MessagePleaseRestartServerToFinishUpdating": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0441\u0435\u0440\u0432\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439.", "LabelDownMixAudioScale": "\u0423\u0441\u0438\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043f\u043e\u043d\u0438\u0436\u0430\u044e\u0449\u0435\u043c \u043c\u0438\u043a\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438:", "LabelDownMixAudioScaleHelp": "\u0423\u0441\u0438\u043b\u0435\u043d\u0438\u0435 \u0437\u0432\u0443\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043d\u0438\u0436\u0430\u044e\u0449\u0435\u043c \u043c\u0438\u043a\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438. \u0412\u0432\u0435\u0434\u0438\u0442\u0435 1, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f.", @@ -541,13 +541,13 @@ "LabelNewSupporterKey": "\u041d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430", "HeaderMultipleKeyLinking": "\u0421\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043b\u044e\u0447\u0435\u0439", "MultipleKeyLinkingHelp": "\u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u043e\u0434\u0438\u043d \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u044d\u0442\u043e\u0439 \u0444\u043e\u0440\u043c\u043e\u0439, \u0447\u0442\u043e\u0431\u044b \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0441\u0442\u0430\u0440\u044b\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u044e\u0447\u0435\u0439 \u0441 \u043d\u043e\u0432\u043e\u0439.", - "LabelCurrentEmailAddress": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b", - "LabelCurrentEmailAddressHelp": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447.", + "LabelCurrentEmailAddress": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 \u042d-\u043f\u043e\u0447\u0442\u044b", + "LabelCurrentEmailAddressHelp": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 \u042d-\u043f\u043e\u0447\u0442\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447.", "HeaderForgotKey": "\u041a\u043b\u044e\u0447 \u0431\u044b\u043b \u0437\u0430\u0431\u044b\u0442", - "LabelEmailAddress": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b", - "LabelSupporterEmailAddress": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0430.", + "LabelEmailAddress": "\u0410\u0434\u0440\u0435\u0441 \u042d-\u043f\u043e\u0447\u0442\u044b", + "LabelSupporterEmailAddress": "\u0410\u0434\u0440\u0435\u0441 \u042d-\u043f\u043e\u0447\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0430.", "ButtonRetrieveKey": "\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u043b\u044e\u0447", - "LabelSupporterKey": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 (\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u0437 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b)", + "LabelSupporterKey": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 (\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u0437 \u043f\u0438\u0441\u044c\u043c\u0430 \u043f\u043e \u042d-\u043f\u043e\u0447\u0442\u0435)", "LabelSupporterKeyHelp": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043d\u0430\u0441\u043b\u0430\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u043c \u0434\u043b\u044f Media Browser.", "MessageInvalidKey": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043b\u0438 \u043d\u0435\u0432\u0435\u0440\u0435\u043d", "ErrorMessageInvalidKey": "\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u043f\u0440\u0435\u043c\u0438\u0443\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435, \u0432\u044b \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u043c Media Browser. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0430\u0440\u0441\u0442\u0432\u0443\u0439\u0442\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e\u0449\u0435\u0435\u0441\u044f \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u043e\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0432\u0430\u0441.", @@ -589,7 +589,7 @@ "NotificationOptionInstallationFailed": "\u0421\u0431\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438", "NotificationOptionNewLibraryContent": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e", "NotificationOptionNewLibraryContentMultiple": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e (\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e)", - "SendNotificationHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u044f\u0449\u0438\u043a \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u0430\u043d\u0435\u043b\u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430. \u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.", + "SendNotificationHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u044f\u0449\u0438\u043a \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u0430\u043d\u0435\u043b\u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430. \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 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.", "NotificationOptionServerRestartRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430", "LabelNotificationEnabled": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435", "LabelMonitorUsers": "\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043e\u0442:", @@ -778,7 +778,7 @@ "OptionLatestMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0435\u0439", "OptionLatestChannelMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432", "HeaderLatestChannelItems": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432", - "OptionNone": "\u041d\u0438\u043a\u0430\u043a\u043e\u0435", + "OptionNone": "\u041d\u0438\u0447\u0435\u0433\u043e", "HeaderLiveTv": "\u0422\u0412 \u044d\u0444\u0438\u0440", "HeaderReports": "\u041e\u0442\u0447\u0451\u0442\u044b", "HeaderMetadataManager": "\u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445", diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sv.json b/MediaBrowser.Server.Implementations/Localization/Server/sv.json index 8d14dbf8e7..79f1f58266 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/sv.json @@ -771,9 +771,9 @@ "LabelHomePageSection2": "Hemsk\u00e4rmens del 2:", "LabelHomePageSection3": "Hemsk\u00e4rmens del 3:", "LabelHomePageSection4": "Hemsidans del 4:", - "OptionMyViewsButtons": "My views (buttons)", - "OptionMyViews": "My views", - "OptionMyViewsSmall": "My views (small)", + "OptionMyViewsButtons": "Mina vyer (knappar)", + "OptionMyViews": "Mina vyer", + "OptionMyViewsSmall": "Mina vyer (liten)", "OptionResumablemedia": "\u00c5teruppta", "OptionLatestMedia": "Nytillkommet", "OptionLatestChannelMedia": "Senaste objekten i Kanaler", @@ -820,6 +820,6 @@ "OptionLibraryFolders": "Mappvy", "TitleRemoteControl": "Fj\u00e4rrkontroll", "OptionLatestTvRecordings": "Senaste inspelningar", - "LabelProtocolInfo": "Protocol info:", - "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device." + "LabelProtocolInfo": "Protokollinfo:", + "LabelProtocolInfoHelp": "V\u00e4rde att anv\u00e4nda vid svar p\u00e5 GetProtocolInfo-beg\u00e4ran fr\u00e5n enheter." } \ 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 c6a105e222..7410f63778 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -344,6 +344,8 @@ + + diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 8007e05062..470786ba24 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -41,7 +41,6 @@ using MediaBrowser.Dlna.Main; using MediaBrowser.MediaEncoding.BdInfo; using MediaBrowser.MediaEncoding.Encoder; using MediaBrowser.MediaEncoding.Subtitles; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; @@ -288,17 +287,24 @@ namespace MediaBrowser.ServerApplication private void MigrateModularConfigurations() { + var saveConfig = false; + if (ServerConfigurationManager.Configuration.DlnaOptions != null) { ServerConfigurationManager.SaveConfiguration("dlna", ServerConfigurationManager.Configuration.DlnaOptions); ServerConfigurationManager.Configuration.DlnaOptions = null; - ServerConfigurationManager.SaveConfiguration(); + saveConfig = true; } if (ServerConfigurationManager.Configuration.ChapterOptions != null) { ServerConfigurationManager.SaveConfiguration("chapters", ServerConfigurationManager.Configuration.ChapterOptions); ServerConfigurationManager.Configuration.ChapterOptions = null; + saveConfig = true; + } + + if (saveConfig) + { ServerConfigurationManager.SaveConfiguration(); } } @@ -1088,10 +1094,12 @@ namespace MediaBrowser.ServerApplication var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, "MBServer", null, ApplicationVersion, ConfigurationManager.CommonConfiguration.SystemUpdateLevel); - HasUpdateAvailable = version != null && version.version >= ApplicationVersion; + var versionObject = version == null || string.IsNullOrWhiteSpace(version.versionStr) ? null : new Version(version.versionStr); + + HasUpdateAvailable = versionObject != null && versionObject >= ApplicationVersion; - return version != null ? new CheckForUpdateResult { AvailableVersion = version.version, IsUpdateAvailable = version.version > ApplicationVersion, Package = version } : - new CheckForUpdateResult { AvailableVersion = ApplicationVersion, IsUpdateAvailable = false }; + return versionObject != null ? new CheckForUpdateResult { AvailableVersion = versionObject.ToString(), IsUpdateAvailable = versionObject > ApplicationVersion, Package = version } : + new CheckForUpdateResult { AvailableVersion = ApplicationVersion.ToString(), IsUpdateAvailable = false }; } /// -- cgit v1.2.3 From 3d47b495a96fce84c03d9f3177dc6dbc8a4afa3c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Jun 2014 23:04:50 -0400 Subject: fixes #795 - Support reading Xbmc nfo's --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 16 +- MediaBrowser.Api/Playback/BifService.cs | 5 + .../Playback/Progressive/VideoService.cs | 3 +- MediaBrowser.Controller/Entities/Folder.cs | 5 - MediaBrowser.Dlna/PlayTo/PlayToController.cs | 2 +- MediaBrowser.LocalMetadata/BaseXmlProvider.cs | 89 ++ .../Images/CollectionFolderImageProvider.cs | 35 + .../Images/EpisodeLocalImageProvider.cs | 81 ++ .../Images/ImagesByNameImageProvider.cs | 56 ++ .../Images/InternalMetadataFolderImageProvider.cs | 68 ++ .../Images/LocalImageProvider.cs | 327 +++++++ .../MediaBrowser.LocalMetadata.csproj | 110 +++ .../Parsers/BoxSetXmlParser.cs | 129 +++ .../Parsers/EpisodeXmlParser.cs | 271 ++++++ .../Parsers/GameSystemXmlParser.cs | 64 ++ .../Parsers/GameXmlParser.cs | 105 +++ .../Parsers/MovieXmlParser.cs | 67 ++ .../Parsers/MusicVideoXmlParser.cs | 42 + .../Parsers/SeasonXmlParser.cs | 46 + .../Parsers/SeriesXmlParser.cs | 118 +++ .../Properties/AssemblyInfo.cs | 36 + .../Providers/AdultVideoXmlProvider.cs | 37 + .../Providers/AlbumXmlProvider.cs | 30 + .../Providers/ArtistXmlProvider.cs | 30 + .../Providers/BoxSetXmlProvider.cs | 34 + .../Providers/ChannelXmlProvider.cs | 30 + .../Providers/EpisodeXmlProvider.cs | 53 ++ .../Providers/FolderXmlProvider.cs | 33 + .../Providers/GameSystemXmlProvider.cs | 31 + .../Providers/GameXmlProvider.cs | 46 + .../Providers/MovieXmlProvider.cs | 66 ++ .../Providers/MusicVideoXmlProvider.cs | 31 + .../Providers/PersonXmlProvider.cs | 30 + .../Providers/SeasonXmlProvider.cs | 44 + .../Providers/SeriesXmlProvider.cs | 43 + .../Providers/TrailerXmlProvider.cs | 37 + .../Providers/VideoXmlProvider.cs | 37 + MediaBrowser.LocalMetadata/Savers/AlbumXmlSaver.cs | 68 ++ .../Savers/ArtistXmlSaver.cs | 68 ++ .../Savers/BoxSetXmlSaver.cs | 68 ++ .../Savers/ChannelXmlSaver.cs | 73 ++ .../Savers/EpisodeXmlSaver.cs | 151 ++++ .../Savers/FolderXmlSaver.cs | 80 ++ .../Savers/GameSystemXmlSaver.cs | 75 ++ MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs | 112 +++ MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs | 133 +++ .../Savers/PersonXmlSaver.cs | 81 ++ .../Savers/SeasonXmlSaver.cs | 87 ++ .../Savers/SeriesXmlSaver.cs | 135 +++ .../Savers/XmlSaverHelpers.cs | 718 +++++++++++++++ .../MediaBrowser.Model.Portable.csproj | 3 + .../MediaBrowser.Model.net35.csproj | 3 + .../Configuration/ServerConfiguration.cs | 19 +- .../Configuration/XbmcMetadataOptions.cs | 21 + MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + .../AdultVideos/AdultVideoXmlProvider.cs | 37 - .../All/InternalMetadataFolderImageProvider.cs | 68 -- MediaBrowser.Providers/All/LocalImageProvider.cs | 327 ------- MediaBrowser.Providers/BaseXmlProvider.cs | 89 -- MediaBrowser.Providers/BoxSets/BoxSetXmlParser.cs | 129 --- .../BoxSets/BoxSetXmlProvider.cs | 33 - .../Channels/AudioChannelItemMetadataService.cs | 32 + .../Channels/VideoChannelItemMetadataService.cs | 32 + .../Folders/CollectionFolderImageProvider.cs | 37 - .../Folders/FolderXmlProvider.cs | 33 - .../Folders/ImagesByNameImageProvider.cs | 57 -- .../GameGenres/AudioChannelItemMetadataService.cs | 32 - .../GameGenres/VideoChannelItemMetadataService.cs | 32 - .../Games/GameSystemXmlParser.cs | 64 -- .../Games/GameSystemXmlProvider.cs | 30 - MediaBrowser.Providers/Games/GameXmlParser.cs | 105 --- MediaBrowser.Providers/Games/GameXmlProvider.cs | 45 - .../LiveTv/ChannelXmlProvider.cs | 30 - .../MediaBrowser.Providers.csproj | 49 +- MediaBrowser.Providers/Movies/MovieXmlParser.cs | 67 -- MediaBrowser.Providers/Movies/MovieXmlProvider.cs | 65 -- .../Movies/TrailerXmlProvider.cs | 36 - MediaBrowser.Providers/Music/AlbumXmlProvider.cs | 30 - MediaBrowser.Providers/Music/ArtistXmlProvider.cs | 30 - .../Music/MusicVideoXmlParser.cs | 43 - .../Music/MusicVideoXmlProvider.cs | 32 - MediaBrowser.Providers/People/PersonXmlProvider.cs | 30 - MediaBrowser.Providers/Savers/AlbumXmlSaver.cs | 68 -- MediaBrowser.Providers/Savers/ArtistXmlSaver.cs | 68 -- MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs | 69 -- MediaBrowser.Providers/Savers/ChannelXmlSaver.cs | 74 -- MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs | 151 ---- MediaBrowser.Providers/Savers/FolderXmlSaver.cs | 81 -- .../Savers/GameSystemXmlSaver.cs | 75 -- MediaBrowser.Providers/Savers/GameXmlSaver.cs | 112 --- MediaBrowser.Providers/Savers/MovieXmlSaver.cs | 134 --- MediaBrowser.Providers/Savers/PersonXmlSaver.cs | 83 -- MediaBrowser.Providers/Savers/SeasonXmlSaver.cs | 87 -- MediaBrowser.Providers/Savers/SeriesXmlSaver.cs | 135 --- MediaBrowser.Providers/Savers/XmlSaverHelpers.cs | 718 --------------- .../TV/EpisodeLocalImageProvider.cs | 81 -- MediaBrowser.Providers/TV/EpisodeXmlParser.cs | 271 ------ MediaBrowser.Providers/TV/EpisodeXmlProvider.cs | 43 - MediaBrowser.Providers/TV/SeasonXmlParser.cs | 46 - MediaBrowser.Providers/TV/SeasonXmlProvider.cs | 34 - MediaBrowser.Providers/TV/SeriesXmlParser.cs | 118 --- MediaBrowser.Providers/TV/SeriesXmlProvider.cs | 33 - MediaBrowser.Providers/Videos/VideoXmlProvider.cs | 37 - MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs | 272 ------ .../Localization/Server/server.json | 13 +- MediaBrowser.ServerApplication/ApplicationHost.cs | 84 ++ .../MediaBrowser.ServerApplication.csproj | 8 + MediaBrowser.WebDashboard/Api/DashboardService.cs | 1 + .../MediaBrowser.WebDashboard.csproj | 6 + .../Configuration/NfoOptions.cs | 29 + MediaBrowser.XbmcMetadata/EntryPoint.cs | 99 ++ MediaBrowser.XbmcMetadata/Images/XbmcImageSaver.cs | 272 ++++++ .../MediaBrowser.XbmcMetadata.csproj | 89 ++ MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 992 +++++++++++++++++++++ .../Parsers/EpisodeNfoParser.cs | 211 +++++ .../Parsers/MovieNfoParser.cs | 97 ++ .../Parsers/SeasonNfoParser.cs | 45 + .../Parsers/SeriesNfoParser.cs | 93 ++ .../Properties/AssemblyInfo.cs | 36 + .../Providers/AlbumNfoProvider.cs | 34 + .../Providers/ArtistNfoProvider.cs | 34 + .../Providers/BaseNfoProvider.cs | 89 ++ .../Providers/BaseVideoNfoProvider.cs | 55 ++ .../Providers/EpisodeNfoProvider.cs | 44 + .../Providers/MovieNfoProvider.cs | 45 + .../Providers/SeasonNfoProvider.cs | 35 + .../Providers/SeriesNfoProvider.cs | 34 + MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs | 143 +++ MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs | 124 +++ .../Savers/EpisodeXmlSaver.cs | 149 ++++ MediaBrowser.XbmcMetadata/Savers/MovieXmlSaver.cs | 143 +++ MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs | 90 ++ MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs | 130 +++ .../Savers/XmlSaverHelpers.cs | 906 +++++++++++++++++++ MediaBrowser.sln | 36 +- 135 files changed, 8388 insertions(+), 4345 deletions(-) create mode 100644 MediaBrowser.LocalMetadata/BaseXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs create mode 100644 MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj create mode 100644 MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs create mode 100644 MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs create mode 100644 MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs create mode 100644 MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs create mode 100644 MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs create mode 100644 MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs create mode 100644 MediaBrowser.LocalMetadata/Parsers/SeasonXmlParser.cs create mode 100644 MediaBrowser.LocalMetadata/Parsers/SeriesXmlParser.cs create mode 100644 MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/AdultVideoXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/AlbumXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/ArtistXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/ChannelXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/SeasonXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/TrailerXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/AlbumXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/ArtistXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/SeasonXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs create mode 100644 MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs create mode 100644 MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs delete mode 100644 MediaBrowser.Providers/AdultVideos/AdultVideoXmlProvider.cs delete mode 100644 MediaBrowser.Providers/All/InternalMetadataFolderImageProvider.cs delete mode 100644 MediaBrowser.Providers/All/LocalImageProvider.cs delete mode 100644 MediaBrowser.Providers/BaseXmlProvider.cs delete mode 100644 MediaBrowser.Providers/BoxSets/BoxSetXmlParser.cs delete mode 100644 MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs create mode 100644 MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs create mode 100644 MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs delete mode 100644 MediaBrowser.Providers/Folders/CollectionFolderImageProvider.cs delete mode 100644 MediaBrowser.Providers/Folders/FolderXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Folders/ImagesByNameImageProvider.cs delete mode 100644 MediaBrowser.Providers/GameGenres/AudioChannelItemMetadataService.cs delete mode 100644 MediaBrowser.Providers/GameGenres/VideoChannelItemMetadataService.cs delete mode 100644 MediaBrowser.Providers/Games/GameSystemXmlParser.cs delete mode 100644 MediaBrowser.Providers/Games/GameSystemXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Games/GameXmlParser.cs delete mode 100644 MediaBrowser.Providers/Games/GameXmlProvider.cs delete mode 100644 MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Movies/MovieXmlParser.cs delete mode 100644 MediaBrowser.Providers/Movies/MovieXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Movies/TrailerXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Music/AlbumXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Music/ArtistXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Music/MusicVideoXmlParser.cs delete mode 100644 MediaBrowser.Providers/Music/MusicVideoXmlProvider.cs delete mode 100644 MediaBrowser.Providers/People/PersonXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Savers/AlbumXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/ArtistXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/ChannelXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/FolderXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/GameXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/MovieXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/PersonXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/SeasonXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/SeriesXmlSaver.cs delete mode 100644 MediaBrowser.Providers/Savers/XmlSaverHelpers.cs delete mode 100644 MediaBrowser.Providers/TV/EpisodeLocalImageProvider.cs delete mode 100644 MediaBrowser.Providers/TV/EpisodeXmlParser.cs delete mode 100644 MediaBrowser.Providers/TV/EpisodeXmlProvider.cs delete mode 100644 MediaBrowser.Providers/TV/SeasonXmlParser.cs delete mode 100644 MediaBrowser.Providers/TV/SeasonXmlProvider.cs delete mode 100644 MediaBrowser.Providers/TV/SeriesXmlParser.cs delete mode 100644 MediaBrowser.Providers/TV/SeriesXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Videos/VideoXmlProvider.cs delete mode 100644 MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs create mode 100644 MediaBrowser.XbmcMetadata/Configuration/NfoOptions.cs create mode 100644 MediaBrowser.XbmcMetadata/EntryPoint.cs create mode 100644 MediaBrowser.XbmcMetadata/Images/XbmcImageSaver.cs create mode 100644 MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj create mode 100644 MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs create mode 100644 MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs create mode 100644 MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs create mode 100644 MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs create mode 100644 MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs create mode 100644 MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs create mode 100644 MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs create mode 100644 MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs create mode 100644 MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs create mode 100644 MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs create mode 100644 MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs create mode 100644 MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs create mode 100644 MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs create mode 100644 MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs create mode 100644 MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs create mode 100644 MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs create mode 100644 MediaBrowser.XbmcMetadata/Savers/EpisodeXmlSaver.cs create mode 100644 MediaBrowser.XbmcMetadata/Savers/MovieXmlSaver.cs create mode 100644 MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs create mode 100644 MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs create mode 100644 MediaBrowser.XbmcMetadata/Savers/XmlSaverHelpers.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 3cb7b914ad..bdd1b76d07 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1447,6 +1447,16 @@ namespace MediaBrowser.Api.Playback state.MediaPath = mediaUrl; state.InputProtocol = MediaProtocol.Http; } + else + { + // No media info, so this is probably needed + state.DeInterlace = true; + } + + if (recording.RecordingInfo.Status == RecordingStatus.InProgress) + { + state.ReadInputAtNativeFramerate = true; + } state.RunTimeTicks = recording.RunTimeTicks; @@ -1455,9 +1465,7 @@ namespace MediaBrowser.Api.Playback await Task.Delay(1000, cancellationToken).ConfigureAwait(false); } - state.ReadInputAtNativeFramerate = recording.RecordingInfo.Status == RecordingStatus.InProgress; state.OutputAudioSync = "1000"; - state.DeInterlace = true; state.InputVideoSync = "-1"; state.InputAudioSync = "1"; state.InputContainer = recording.Container; @@ -1524,7 +1532,9 @@ namespace MediaBrowser.Api.Playback state.RunTimeTicks = mediaSource.RunTimeTicks; } - if (string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase)) + // If it's a wtv and we don't have media info, we will probably need to deinterlace + if (string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase) && + mediaStreams.Count == 0) { state.DeInterlace = true; } diff --git a/MediaBrowser.Api/Playback/BifService.cs b/MediaBrowser.Api/Playback/BifService.cs index 7a3a7d32dc..057d814417 100644 --- a/MediaBrowser.Api/Playback/BifService.cs +++ b/MediaBrowser.Api/Playback/BifService.cs @@ -72,6 +72,11 @@ namespace MediaBrowser.Api.Playback try { + if (File.Exists(path)) + { + return path; + } + await _mediaEncoder.ExtractVideoImagesOnInterval(inputPath, protocol, mediaSource.Video3DFormat, TimeSpan.FromSeconds(10), Path.GetDirectoryName(path), "img_", request.MaxWidth, CancellationToken.None) .ConfigureAwait(false); diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 937df513e6..bedacc0d29 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -144,7 +144,8 @@ namespace MediaBrowser.Api.Playback.Progressive return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args; } - const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))"; + var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})", + 5.ToString(UsCulture)); args += keyFrameArg; diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 87b1cc7a3d..f503a5ff44 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -445,11 +445,6 @@ namespace MediaBrowser.Controller.Entities cancellationToken.ThrowIfCancellationRequested(); - if (this is UserRootFolder) - { - var b = true; - } - foreach (var child in nonCachedChildren) { BaseItem currentChild; diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index 89d61bb21f..0bc9215081 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Dlna.PlayTo _updateTimer = new Timer(updateTimer_Elapsed, null, 60000, 60000); } - private async void updateTimer_Elapsed(object state) + private void updateTimer_Elapsed(object state) { if (DateTime.UtcNow >= _device.DateLastActivity.AddSeconds(120)) { diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs new file mode 100644 index 0000000000..cc9bc7bed7 --- /dev/null +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -0,0 +1,89 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.LocalMetadata +{ + public abstract class BaseXmlProvider : ILocalMetadataProvider, IHasChangeMonitor + where T : IHasMetadata, new() + { + protected IFileSystem FileSystem; + + public async Task> GetMetadata(ItemInfo info, CancellationToken cancellationToken) + { + var result = new LocalMetadataResult(); + + var file = GetXmlFile(info, new DirectoryService(new NullLogger())); + + if (file == null) + { + return result; + } + + var path = file.FullName; + + await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + result.Item = new T(); + + Fetch(result, path, cancellationToken); + result.HasMetadata = true; + } + catch (FileNotFoundException) + { + result.HasMetadata = false; + } + catch (DirectoryNotFoundException) + { + result.HasMetadata = false; + } + finally + { + XmlProviderUtils.XmlParsingResourcePool.Release(); + } + + return result; + } + + protected abstract void Fetch(LocalMetadataResult result, string path, CancellationToken cancellationToken); + + protected BaseXmlProvider(IFileSystem fileSystem) + { + FileSystem = fileSystem; + } + + protected abstract FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService); + + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + { + var file = GetXmlFile(new ItemInfo { IsInMixedFolder = item.IsInMixedFolder, Path = item.Path }, directoryService); + + if (file == null) + { + return false; + } + + return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > date; + } + + public string Name + { + get + { + return "Media Browser Xml"; + } + } + } + + static class XmlProviderUtils + { + internal static readonly SemaphoreSlim XmlParsingResourcePool = new SemaphoreSlim(4, 4); + } +} diff --git a/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs new file mode 100644 index 0000000000..29fd76aa56 --- /dev/null +++ b/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; + +namespace MediaBrowser.LocalMetadata.Images +{ + public class CollectionFolderLocalImageProvider : ILocalImageFileProvider, IHasOrder + { + public string Name + { + get { return "Collection Folder Images"; } + } + + public bool Supports(IHasImages item) + { + return item is CollectionFolder && item.SupportsLocalMetadata; + } + + public int Order + { + get + { + // Run after LocalImageProvider + return 1; + } + } + + public List GetImages(IHasImages item, IDirectoryService directoryService) + { + var collectionFolder = (CollectionFolder)item; + + return new LocalImageProvider().GetImages(item, collectionFolder.PhysicalLocations, directoryService); + } + } +} diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs new file mode 100644 index 0000000000..f1e7426aad --- /dev/null +++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.LocalMetadata.Images +{ + public class EpisodeLocalLocalImageProvider : ILocalImageFileProvider + { + public string Name + { + get { return "Local Images"; } + } + + public bool Supports(IHasImages item) + { + return item is Episode && item.SupportsLocalMetadata; + } + + public List GetImages(IHasImages item, IDirectoryService directoryService) + { + var parentPath = Path.GetDirectoryName(item.Path); + + var parentPathFiles = directoryService.GetFileSystemEntries(parentPath); + + var nameWithoutExtension = Path.GetFileNameWithoutExtension(item.Path); + + var files = GetFilesFromParentFolder(nameWithoutExtension, parentPathFiles); + + if (files.Count > 0) + { + return files; + } + + var metadataPath = Path.Combine(parentPath, "metadata"); + + if (parentPathFiles.Any(i => string.Equals(i.FullName, metadataPath, StringComparison.OrdinalIgnoreCase))) + { + return GetFilesFromParentFolder(nameWithoutExtension, directoryService.GetFiles(metadataPath)); + } + + return new List(); + } + + private List GetFilesFromParentFolder(string filenameWithoutExtension, IEnumerable parentPathFiles) + { + var thumbName = filenameWithoutExtension + "-thumb"; + + return parentPathFiles + .Where(i => + { + if (BaseItem.SupportedImageExtensions.Contains(i.Extension)) + { + var currentNameWithoutExtension = Path.GetFileNameWithoutExtension(i.Name); + + if (string.Equals(filenameWithoutExtension, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + if (string.Equals(thumbName, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + }) + .Select(i => new LocalImageInfo + { + FileInfo = (FileInfo)i, + Type = ImageType.Primary + }) + .ToList(); + } + } +} diff --git a/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs b/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs new file mode 100644 index 0000000000..3f84df462d --- /dev/null +++ b/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.IO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; + +namespace MediaBrowser.LocalMetadata.Images +{ + public class ImagesByNameImageProvider : ILocalImageFileProvider, IHasOrder + { + private readonly IFileSystem _fileSystem; + private readonly IServerConfigurationManager _config; + + public ImagesByNameImageProvider(IFileSystem fileSystem, IServerConfigurationManager config) + { + _fileSystem = fileSystem; + _config = config; + } + + public string Name + { + get { return "Images By Name"; } + } + + public bool Supports(IHasImages item) + { + return item is CollectionFolder; + } + + public int Order + { + get + { + // Run after LocalImageProvider, and after CollectionFolderImageProvider + return 2; + } + } + + public List GetImages(IHasImages item, IDirectoryService directoryService) + { + var name = _fileSystem.GetValidFilename(item.Name); + + var path = Path.Combine(_config.ApplicationPaths.GeneralPath, name); + + try + { + return new LocalImageProvider().GetImages(item, path, directoryService); + } + catch (DirectoryNotFoundException) + { + return new List(); + } + } + } +} diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs new file mode 100644 index 0000000000..8c4f6247cb --- /dev/null +++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Providers; + +namespace MediaBrowser.LocalMetadata.Images +{ + public class InternalMetadataFolderImageProvider : ILocalImageFileProvider, IHasOrder + { + private readonly IServerConfigurationManager _config; + + public InternalMetadataFolderImageProvider(IServerConfigurationManager config) + { + _config = config; + } + + public string Name + { + get { return "Internal Images"; } + } + + public bool Supports(IHasImages item) + { + if (!item.IsSaveLocalMetadataEnabled()) + { + return true; + } + + // Extracted images will be saved in here + if (item is Audio) + { + return true; + } + + if (item.SupportsLocalMetadata) + { + return false; + } + + return true; + } + + public int Order + { + get + { + // Make sure this is last so that all other locations are scanned first + return 1000; + } + } + + public List GetImages(IHasImages item, IDirectoryService directoryService) + { + var path = _config.ApplicationPaths.GetInternalMetadataPath(item.Id); + + try + { + return new LocalImageProvider().GetImages(item, path, directoryService); + } + catch (DirectoryNotFoundException) + { + return new List(); + } + } + } +} diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs new file mode 100644 index 0000000000..a5ef7977bc --- /dev/null +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.LocalMetadata.Images +{ + public class LocalImageProvider : ILocalImageFileProvider + { + public string Name + { + get { return "Local Images"; } + } + + public int Order + { + get { return 0; } + } + + public bool Supports(IHasImages item) + { + if (item.SupportsLocalMetadata) + { + // Episode has it's own provider + if (item.IsOwnedItem || item is Episode || item is Audio) + { + return false; + } + + return true; + } + + if (item.LocationType == LocationType.Virtual) + { + var season = item as Season; + + if (season != null) + { + var series = season.Series; + + if (series != null && series.LocationType == LocationType.FileSystem) + { + return true; + } + } + } + + return false; + } + + private IEnumerable GetFiles(IHasImages item, bool includeDirectories, IDirectoryService directoryService) + { + if (item.LocationType != LocationType.FileSystem) + { + return new List(); + } + + var path = item.ContainingFolderPath; + + if (includeDirectories) + { + return directoryService.GetFileSystemEntries(path) + .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase) || + (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory); + } + + return directoryService.GetFiles(path) + .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase)); + } + + public List GetImages(IHasImages item, IDirectoryService directoryService) + { + var files = GetFiles(item, true, directoryService).ToList(); + + var list = new List(); + + PopulateImages(item, list, files, true, directoryService); + + return list; + } + + public List GetImages(IHasImages item, string path, IDirectoryService directoryService) + { + return GetImages(item, new[] { path }, directoryService); + } + + public List GetImages(IHasImages item, IEnumerable paths, IDirectoryService directoryService) + { + var files = paths.SelectMany(directoryService.GetFiles) + .Where(i => + { + var ext = i.Extension; + + return !string.IsNullOrEmpty(ext) && + BaseItem.SupportedImageExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase); + }) + .ToList(); + + var list = new List(); + + PopulateImages(item, list, files, false, directoryService); + + return list; + } + + private void PopulateImages(IHasImages item, List images, List files, bool supportParentSeriesFiles, IDirectoryService directoryService) + { + var imagePrefix = string.Empty; + + var baseItem = item as BaseItem; + if (baseItem != null && baseItem.IsInMixedFolder) + { + imagePrefix = Path.GetFileNameWithoutExtension(item.Path) + "-"; + } + + PopulatePrimaryImages(item, images, files, imagePrefix); + PopulateBackdrops(item, images, files, imagePrefix, directoryService); + PopulateScreenshots(images, files, imagePrefix); + + AddImage(files, images, imagePrefix + "logo", ImageType.Logo); + AddImage(files, images, imagePrefix + "clearart", ImageType.Art); + AddImage(files, images, imagePrefix + "disc", ImageType.Disc); + AddImage(files, images, imagePrefix + "cdart", ImageType.Disc); + AddImage(files, images, imagePrefix + "box", ImageType.Box); + AddImage(files, images, imagePrefix + "back", ImageType.BoxRear); + AddImage(files, images, imagePrefix + "boxrear", ImageType.BoxRear); + AddImage(files, images, imagePrefix + "menu", ImageType.Menu); + + // Banner + AddImage(files, images, imagePrefix + "banner", ImageType.Banner); + + // Thumb + AddImage(files, images, imagePrefix + "thumb", ImageType.Thumb); + AddImage(files, images, imagePrefix + "landscape", ImageType.Thumb); + + if (supportParentSeriesFiles) + { + var season = item as Season; + + if (season != null) + { + PopulateSeasonImagesFromSeriesFolder(season, images, directoryService); + } + } + } + + private void PopulatePrimaryImages(IHasImages item, List images, List files, string imagePrefix) + { + AddImage(files, images, imagePrefix + "folder", ImageType.Primary); + AddImage(files, images, imagePrefix + "cover", ImageType.Primary); + AddImage(files, images, imagePrefix + "poster", ImageType.Primary); + AddImage(files, images, imagePrefix + "default", ImageType.Primary); + + // Support plex/xbmc convention + if (item is Series) + { + AddImage(files, images, imagePrefix + "show", ImageType.Primary); + } + + // Support plex/xbmc convention + if (item is Movie || item is MusicVideo || item is AdultVideo) + { + AddImage(files, images, imagePrefix + "movie", ImageType.Primary); + } + + if (!string.IsNullOrEmpty(item.Path)) + { + var name = Path.GetFileNameWithoutExtension(item.Path); + + if (!string.IsNullOrEmpty(name)) + { + AddImage(files, images, name, ImageType.Primary); + AddImage(files, images, name + "-poster", ImageType.Primary); + } + } + } + + private void PopulateBackdrops(IHasImages item, List images, List files, string imagePrefix, IDirectoryService directoryService) + { + PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", ImageType.Backdrop); + + if (!string.IsNullOrEmpty(item.Path)) + { + var name = Path.GetFileNameWithoutExtension(item.Path); + + if (!string.IsNullOrEmpty(name)) + { + AddImage(files, images, imagePrefix + name + "-fanart", ImageType.Backdrop); + } + } + + PopulateBackdrops(images, files, imagePrefix, "fanart", "fanart-", ImageType.Backdrop); + PopulateBackdrops(images, files, imagePrefix, "background", "background-", ImageType.Backdrop); + PopulateBackdrops(images, files, imagePrefix, "art", "art-", ImageType.Backdrop); + + var extraFanartFolder = files + .FirstOrDefault(i => string.Equals(i.Name, "extrafanart", StringComparison.OrdinalIgnoreCase)); + + if (extraFanartFolder != null) + { + PopulateBackdropsFromExtraFanart(extraFanartFolder.FullName, images, directoryService); + } + } + + private void PopulateBackdropsFromExtraFanart(string path, List images, IDirectoryService directoryService) + { + var imageFiles = directoryService.GetFiles(path) + .Where(i => + { + var extension = i.Extension; + + if (string.IsNullOrEmpty(extension)) + { + return false; + } + + return BaseItem.SupportedImageExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase); + }); + + images.AddRange(imageFiles.Select(i => new LocalImageInfo + { + FileInfo = i, + Type = ImageType.Backdrop + })); + } + + private void PopulateScreenshots(List images, List files, string imagePrefix) + { + PopulateBackdrops(images, files, imagePrefix, "screenshot", "screenshot", ImageType.Screenshot); + } + + private void PopulateBackdrops(List images, List files, string imagePrefix, string firstFileName, string subsequentFileNamePrefix, ImageType type) + { + AddImage(files, images, imagePrefix + firstFileName, type); + + var unfound = 0; + for (var i = 1; i <= 20; i++) + { + // Screenshot Image + var found = AddImage(files, images, imagePrefix + subsequentFileNamePrefix + i, type); + + if (!found) + { + unfound++; + + if (unfound >= 3) + { + break; + } + } + } + } + + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private void PopulateSeasonImagesFromSeriesFolder(Season season, List images, IDirectoryService directoryService) + { + var seasonNumber = season.IndexNumber; + + var series = season.Series; + if (!seasonNumber.HasValue || series.LocationType != LocationType.FileSystem) + { + return; + } + + var seriesFiles = GetFiles(series, false, directoryService).ToList(); + + // Try using the season name + var prefix = season.Name.ToLower().Replace(" ", string.Empty); + + var filenamePrefixes = new List { prefix }; + + var seasonMarker = seasonNumber.Value == 0 + ? "-specials" + : seasonNumber.Value.ToString("00", _usCulture); + + // Get this one directly from the file system since we have to go up a level + if (!string.Equals(prefix, seasonMarker, StringComparison.OrdinalIgnoreCase)) + { + filenamePrefixes.Add("season" + seasonMarker); + } + + foreach (var filename in filenamePrefixes) + { + AddImage(seriesFiles, images, filename + "-poster", ImageType.Primary); + AddImage(seriesFiles, images, filename + "-fanart", ImageType.Backdrop); + AddImage(seriesFiles, images, filename + "-banner", ImageType.Banner); + AddImage(seriesFiles, images, filename + "-landscape", ImageType.Thumb); + } + } + + private bool AddImage(IEnumerable files, List images, string name, ImageType type) + { + var image = GetImage(files, name) as FileInfo; + + if (image != null) + { + images.Add(new LocalImageInfo + { + FileInfo = image, + Type = type + }); + + return true; + } + + return false; + } + + private FileSystemInfo GetImage(IEnumerable files, string name) + { + var candidates = files + .Where(i => string.Equals(name, Path.GetFileNameWithoutExtension(i.Name), StringComparison.OrdinalIgnoreCase)) + .ToList(); + + return BaseItem.SupportedImageExtensions + .Select(i => candidates.FirstOrDefault(c => string.Equals(c.Extension, i, StringComparison.OrdinalIgnoreCase))) + .FirstOrDefault(i => i != null); + } + } +} diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj new file mode 100644 index 0000000000..0d2c0b97f2 --- /dev/null +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -0,0 +1,110 @@ + + + + + Debug + AnyCPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392} + Library + Properties + MediaBrowser.LocalMetadata + MediaBrowser.LocalMetadata + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {9142eefa-7570-41e1-bfcc-468bb571af2f} + MediaBrowser.Common + + + {17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2} + MediaBrowser.Controller + + + {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} + MediaBrowser.Model + + + + + + \ No newline at end of file diff --git a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs new file mode 100644 index 0000000000..51a4684d70 --- /dev/null +++ b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Xml; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.LocalMetadata.Parsers +{ + public class BoxSetXmlParser : BaseItemXmlParser + { + private readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + public BoxSetXmlParser(ILogger logger) + : base(logger) + { + } + + protected override void FetchDataFromXmlNode(XmlReader reader, BoxSet item) + { + switch (reader.Name) + { + case "CollectionItems": + + using (var subReader = reader.ReadSubtree()) + { + FetchFromCollectionItemsNode(subReader, item); + } + break; + + default: + base.FetchDataFromXmlNode(reader, item); + break; + } + } + + private void FetchFromCollectionItemsNode(XmlReader reader, BoxSet item) + { + reader.MoveToContent(); + + var list = new List(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "CollectionItem": + { + using (var subReader = reader.ReadSubtree()) + { + var child = GetLinkedChild(subReader); + + if (child != null) + { + list.Add(child); + } + } + + break; + } + + default: + reader.Skip(); + break; + } + } + } + + item.LinkedChildren = list; + } + + private LinkedChild GetLinkedChild(XmlReader reader) + { + reader.MoveToContent(); + + var linkedItem = new LinkedChild + { + Type = LinkedChildType.Manual + }; + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Name": + { + linkedItem.ItemName = reader.ReadElementContentAsString(); + break; + } + + case "Type": + { + linkedItem.ItemType = reader.ReadElementContentAsString(); + break; + } + + case "Year": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + linkedItem.ItemYear = rval; + } + } + + break; + } + + default: + reader.Skip(); + break; + } + } + } + + return string.IsNullOrWhiteSpace(linkedItem.ItemName) || string.IsNullOrWhiteSpace(linkedItem.ItemType) ? null : linkedItem; + } + } +} diff --git a/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs new file mode 100644 index 0000000000..8430f3b3c7 --- /dev/null +++ b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Xml; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.LocalMetadata.Parsers +{ + /// + /// Class EpisodeXmlParser + /// + public class EpisodeXmlParser : BaseItemXmlParser + { + private List _imagesFound; + private List _chaptersFound; + + public EpisodeXmlParser(ILogger logger) + : base(logger) + { + } + + private string _xmlPath; + + public void Fetch(Episode item, + List images, + List chapters, + string metadataFile, + CancellationToken cancellationToken) + { + _imagesFound = images; + _chaptersFound = chapters; + _xmlPath = metadataFile; + + Fetch(item, metadataFile, cancellationToken); + } + + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + /// + /// Fetches the data from XML node. + /// + /// The reader. + /// The item. + protected override void FetchDataFromXmlNode(XmlReader reader, Episode item) + { + switch (reader.Name) + { + case "Chapters": + + _chaptersFound.AddRange(FetchChaptersFromXmlNode(item, reader.ReadSubtree())); + break; + + case "Episode": + + //MB generated metadata is within an "Episode" node + using (var subTree = reader.ReadSubtree()) + { + subTree.MoveToContent(); + + // Loop through each element + while (subTree.Read()) + { + if (subTree.NodeType == XmlNodeType.Element) + { + FetchDataFromXmlNode(subTree, item); + } + } + + } + break; + + case "filename": + { + var filename = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(filename)) + { + // Strip off everything but the filename. Some metadata tools like MetaBrowser v1.0 will have an 'episodes' prefix + // even though it's actually using the metadata folder. + filename = Path.GetFileName(filename); + + var parentFolder = Path.GetDirectoryName(_xmlPath); + filename = Path.Combine(parentFolder, filename); + var file = new FileInfo(filename); + + if (file.Exists) + { + _imagesFound.Add(new LocalImageInfo + { + Type = ImageType.Primary, + FileInfo = file + }); + } + } + break; + } + case "SeasonNumber": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + int num; + + if (int.TryParse(number, out num)) + { + item.ParentIndexNumber = num; + } + } + break; + } + + case "EpisodeNumber": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + int num; + + if (int.TryParse(number, out num)) + { + item.IndexNumber = num; + } + } + break; + } + + case "EpisodeNumberEnd": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + int num; + + if (int.TryParse(number, out num)) + { + item.IndexNumberEnd = num; + } + } + break; + } + + case "absolute_number": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + item.AbsoluteEpisodeNumber = rval; + } + } + + break; + } + case "DVD_episodenumber": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + float num; + + if (float.TryParse(number, NumberStyles.Any, UsCulture, out num)) + { + item.DvdEpisodeNumber = num; + } + } + break; + } + + case "DVD_season": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + float num; + + if (float.TryParse(number, NumberStyles.Any, UsCulture, out num)) + { + item.DvdSeasonNumber = Convert.ToInt32(num); + } + } + break; + } + + case "airsbefore_episode": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + item.AirsBeforeEpisodeNumber = rval; + } + } + + break; + } + + case "airsafter_season": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + item.AirsAfterSeasonNumber = rval; + } + } + + break; + } + + case "airsbefore_season": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + item.AirsBeforeSeasonNumber = rval; + } + } + + break; + } + + case "EpisodeName": + { + var name = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(name)) + { + item.Name = name; + } + break; + } + + + default: + base.FetchDataFromXmlNode(reader, item); + break; + } + } + } +} diff --git a/MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs new file mode 100644 index 0000000000..d449108c4b --- /dev/null +++ b/MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs @@ -0,0 +1,64 @@ +using System.Threading; +using System.Threading.Tasks; +using System.Xml; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.LocalMetadata.Parsers +{ + public class GameSystemXmlParser : BaseItemXmlParser + { + public GameSystemXmlParser(ILogger logger) + : base(logger) + { + } + + private readonly Task _cachedTask = Task.FromResult(true); + public Task FetchAsync(GameSystem item, string metadataFile, CancellationToken cancellationToken) + { + Fetch(item, metadataFile, cancellationToken); + + cancellationToken.ThrowIfCancellationRequested(); + + return _cachedTask; + } + + /// + /// Fetches the data from XML node. + /// + /// The reader. + /// The item. + protected override void FetchDataFromXmlNode(XmlReader reader, GameSystem item) + { + switch (reader.Name) + { + case "GameSystem": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + item.GameSystemName = val; + } + break; + } + + case "GamesDbId": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + item.SetProviderId(MetadataProviders.Gamesdb, val); + } + break; + } + + + default: + base.FetchDataFromXmlNode(reader, item); + break; + } + } + } +} diff --git a/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs new file mode 100644 index 0000000000..2caced8a94 --- /dev/null +++ b/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs @@ -0,0 +1,105 @@ +using System.Globalization; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.LocalMetadata.Parsers +{ + /// + /// Class EpisodeXmlParser + /// + public class GameXmlParser : BaseItemXmlParser + { + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + public GameXmlParser(ILogger logger) + : base(logger) + { + } + + private readonly Task _cachedTask = Task.FromResult(true); + public Task FetchAsync(Game item, string metadataFile, CancellationToken cancellationToken) + { + Fetch(item, metadataFile, cancellationToken); + + cancellationToken.ThrowIfCancellationRequested(); + + return _cachedTask; + } + + /// + /// Fetches the data from XML node. + /// + /// The reader. + /// The item. + protected override void FetchDataFromXmlNode(XmlReader reader, Game item) + { + switch (reader.Name) + { + case "GameSystem": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + item.GameSystem = val; + } + break; + } + + case "GamesDbId": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + item.SetProviderId(MetadataProviders.Gamesdb, val); + } + break; + } + + case "NesBox": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + item.SetProviderId(MetadataProviders.NesBox, val); + } + break; + } + + case "NesBoxRom": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + item.SetProviderId(MetadataProviders.NesBoxRom, val); + } + break; + } + + case "Players": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + int num; + + if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num)) + { + item.PlayersSupported = num; + } + } + break; + } + + + default: + base.FetchDataFromXmlNode(reader, item); + break; + } + } + } +} diff --git a/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs new file mode 100644 index 0000000000..388a0d20d7 --- /dev/null +++ b/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using System.Threading; +using System.Xml; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.LocalMetadata.Parsers +{ + /// + /// Class EpisodeXmlParser + /// + public class MovieXmlParser : BaseItemXmlParser + /// The path. + /// The XML tags used. + /// System.String. + private static string GetCustomTags(string path, List xmlTagsUsed) + { + var settings = new XmlReaderSettings + { + CheckCharacters = false, + IgnoreProcessingInstructions = true, + IgnoreComments = true, + ValidationType = ValidationType.None + }; + + var builder = new StringBuilder(); + + using (var streamReader = new StreamReader(path, Encoding.UTF8)) + { + // Use XmlReader for best performance + using (var reader = XmlReader.Create(streamReader, settings)) + { + reader.MoveToContent(); + + // Loop through each element + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + var name = reader.Name; + + if (!CommonTags.ContainsKey(name) && !xmlTagsUsed.Contains(name, StringComparer.OrdinalIgnoreCase)) + { + builder.AppendLine(reader.ReadOuterXml()); + } + else + { + reader.Skip(); + } + } + } + } + } + + return builder.ToString(); + } + + /// + /// Adds the common nodes. + /// + /// The item. + /// The builder. + public static void AddCommonNodes(BaseItem item, StringBuilder builder) + { + if (!string.IsNullOrEmpty(item.OfficialRating)) + { + builder.Append("" + SecurityElement.Escape(item.OfficialRating) + ""); + } + + builder.Append("" + SecurityElement.Escape(item.DateCreated.ToLocalTime().ToString("G")) + ""); + + builder.Append("" + item.IsLocked.ToString().ToLower() + ""); + + if (item.LockedFields.Count > 0) + { + builder.Append("" + string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()) + ""); + } + + if (!string.IsNullOrEmpty(item.DisplayMediaType)) + { + builder.Append("" + SecurityElement.Escape(item.DisplayMediaType) + ""); + } + + var hasCriticRating = item as IHasCriticRating; + if (hasCriticRating != null) + { + if (hasCriticRating.CriticRating.HasValue) + { + builder.Append("" + SecurityElement.Escape(hasCriticRating.CriticRating.Value.ToString(UsCulture)) + ""); + } + + if (!string.IsNullOrEmpty(hasCriticRating.CriticRatingSummary)) + { + builder.Append(""); + } + } + + if (!string.IsNullOrEmpty(item.Overview)) + { + builder.Append(""); + } + + var hasShortOverview = item as IHasShortOverview; + if (hasShortOverview != null) + { + if (!string.IsNullOrEmpty(hasShortOverview.ShortOverview)) + { + builder.Append(""); + } + } + + if (!string.IsNullOrEmpty(item.CustomRating)) + { + builder.Append("" + SecurityElement.Escape(item.CustomRating) + ""); + } + + if (!string.IsNullOrEmpty(item.Name) && !(item is Episode)) + { + builder.Append("" + SecurityElement.Escape(item.Name) + ""); + } + + if (!string.IsNullOrEmpty(item.ForcedSortName)) + { + builder.Append("" + SecurityElement.Escape(item.ForcedSortName) + ""); + } + + if (item.PremiereDate.HasValue) + { + if (item is Person) + { + builder.Append("" + SecurityElement.Escape(item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + ""); + } + else if (!(item is Episode)) + { + builder.Append("" + SecurityElement.Escape(item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + ""); + } + } + + if (item.EndDate.HasValue) + { + if (item is Person) + { + builder.Append("" + SecurityElement.Escape(item.EndDate.Value.ToString("yyyy-MM-dd")) + ""); + } + else if (!(item is Episode)) + { + builder.Append("" + SecurityElement.Escape(item.EndDate.Value.ToString("yyyy-MM-dd")) + ""); + } + } + + var hasTrailers = item as IHasTrailers; + if (hasTrailers != null) + { + if (hasTrailers.RemoteTrailers.Count > 0) + { + builder.Append(""); + + foreach (var trailer in hasTrailers.RemoteTrailers) + { + builder.Append("" + SecurityElement.Escape(trailer.Url) + ""); + } + + builder.Append(""); + } + } + + var hasProductionLocations = item as IHasProductionLocations; + if (hasProductionLocations != null) + { + if (hasProductionLocations.ProductionLocations.Count > 0) + { + builder.Append(""); + + foreach (var name in hasProductionLocations.ProductionLocations) + { + builder.Append("" + SecurityElement.Escape(name) + ""); + } + + builder.Append(""); + } + } + + var hasDisplayOrder = item as IHasDisplayOrder; + if (hasDisplayOrder != null && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder)) + { + builder.Append("" + SecurityElement.Escape(hasDisplayOrder.DisplayOrder) + ""); + } + + var hasMetascore = item as IHasMetascore; + if (hasMetascore != null && hasMetascore.Metascore.HasValue) + { + builder.Append("" + SecurityElement.Escape(hasMetascore.Metascore.Value.ToString(UsCulture)) + ""); + } + + var hasAwards = item as IHasAwards; + if (hasAwards != null && !string.IsNullOrEmpty(hasAwards.AwardSummary)) + { + builder.Append("" + SecurityElement.Escape(hasAwards.AwardSummary) + ""); + } + + var hasBudget = item as IHasBudget; + if (hasBudget != null) + { + if (hasBudget.Budget.HasValue) + { + builder.Append("" + SecurityElement.Escape(hasBudget.Budget.Value.ToString(UsCulture)) + ""); + } + + if (hasBudget.Revenue.HasValue) + { + builder.Append("" + SecurityElement.Escape(hasBudget.Revenue.Value.ToString(UsCulture)) + ""); + } + } + + if (item.CommunityRating.HasValue) + { + builder.Append("" + SecurityElement.Escape(item.CommunityRating.Value.ToString(UsCulture)) + ""); + } + if (item.VoteCount.HasValue) + { + builder.Append("" + SecurityElement.Escape(item.VoteCount.Value.ToString(UsCulture)) + ""); + } + + if (item.ProductionYear.HasValue && !(item is Person)) + { + builder.Append("" + SecurityElement.Escape(item.ProductionYear.Value.ToString(UsCulture)) + ""); + } + + if (!string.IsNullOrEmpty(item.HomePageUrl)) + { + builder.Append("" + SecurityElement.Escape(item.HomePageUrl) + ""); + } + + var hasAspectRatio = item as IHasAspectRatio; + if (hasAspectRatio != null) + { + if (!string.IsNullOrEmpty(hasAspectRatio.AspectRatio)) + { + builder.Append("" + SecurityElement.Escape(hasAspectRatio.AspectRatio) + ""); + } + } + + var hasLanguage = item as IHasPreferredMetadataLanguage; + if (hasLanguage != null) + { + if (!string.IsNullOrEmpty(hasLanguage.PreferredMetadataLanguage)) + { + builder.Append("" + SecurityElement.Escape(hasLanguage.PreferredMetadataLanguage) + ""); + } + } + + // Use original runtime here, actual file runtime later in MediaInfo + var runTimeTicks = item.RunTimeTicks; + + if (runTimeTicks.HasValue) + { + var timespan = TimeSpan.FromTicks(runTimeTicks.Value); + + builder.Append("" + Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture) + ""); + } + + var imdb = item.GetProviderId(MetadataProviders.Imdb); + + if (!string.IsNullOrEmpty(imdb)) + { + builder.Append("" + SecurityElement.Escape(imdb) + ""); + } + + var tmdb = item.GetProviderId(MetadataProviders.Tmdb); + + if (!string.IsNullOrEmpty(tmdb)) + { + builder.Append("" + SecurityElement.Escape(tmdb) + ""); + } + + if (!(item is Series)) + { + var tvdb = item.GetProviderId(MetadataProviders.Tvdb); + + if (!string.IsNullOrEmpty(tvdb)) + { + builder.Append("" + SecurityElement.Escape(tvdb) + ""); + } + } + + var externalId = item.GetProviderId(MetadataProviders.Tvcom); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.RottenTomatoes); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.Zap2It); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbum); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.MusicBrainzArtist); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.Gamesdb); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.TmdbCollection); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.AudioDbArtist); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.AudioDbAlbum); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.TvRage); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + var hasTagline = item as IHasTaglines; + if (hasTagline != null) + { + if (hasTagline.Taglines.Count > 0) + { + builder.Append(""); + + foreach (var tagline in hasTagline.Taglines) + { + builder.Append("" + SecurityElement.Escape(tagline) + ""); + } + + builder.Append(""); + } + } + + if (item.Genres.Count > 0) + { + builder.Append(""); + + foreach (var genre in item.Genres) + { + builder.Append("" + SecurityElement.Escape(genre) + ""); + } + + builder.Append(""); + } + + if (item.Studios.Count > 0) + { + builder.Append(""); + + foreach (var studio in item.Studios) + { + builder.Append("" + SecurityElement.Escape(studio) + ""); + } + + builder.Append(""); + } + + var hasTags = item as IHasTags; + if (hasTags != null) + { + if (hasTags.Tags.Count > 0) + { + builder.Append(""); + + foreach (var tag in hasTags.Tags) + { + builder.Append("" + SecurityElement.Escape(tag) + ""); + } + + builder.Append(""); + } + } + + var hasKeywords = item as IHasKeywords; + if (hasKeywords != null) + { + if (hasKeywords.Keywords.Count > 0) + { + builder.Append(""); + + foreach (var tag in hasKeywords.Keywords) + { + builder.Append("" + SecurityElement.Escape(tag) + ""); + } + + builder.Append(""); + } + } + + if (item.People.Count > 0) + { + builder.Append(""); + + foreach (var person in item.People) + { + builder.Append(""); + builder.Append("" + SecurityElement.Escape(person.Name) + ""); + builder.Append("" + SecurityElement.Escape(person.Type) + ""); + builder.Append("" + SecurityElement.Escape(person.Role) + ""); + + if (person.SortOrder.HasValue) + { + builder.Append("" + SecurityElement.Escape(person.SortOrder.Value.ToString(UsCulture)) + ""); + } + + builder.Append(""); + } + + builder.Append(""); + } + + var folder = item as BoxSet; + if (folder != null) + { + AddCollectionItems(folder, builder); + } + } + + public static void AddChapters(Video item, StringBuilder builder, IItemRepository repository) + { + var chapters = repository.GetChapters(item.Id); + + builder.Append(""); + + foreach (var chapter in chapters) + { + builder.Append(""); + builder.Append("" + SecurityElement.Escape(chapter.Name) + ""); + + var time = TimeSpan.FromTicks(chapter.StartPositionTicks); + var ms = Convert.ToInt64(time.TotalMilliseconds); + + builder.Append("" + SecurityElement.Escape(ms.ToString(UsCulture)) + ""); + builder.Append(""); + } + + builder.Append(""); + } + + /// + /// Appends the media info. + /// + /// + public static void AddMediaInfo(T item, StringBuilder builder, IItemRepository itemRepository) + where T : BaseItem + { + var video = item as Video; + + if (video != null) + { + //AddChapters(video, builder, itemRepository); + + if (video.Video3DFormat.HasValue) + { + switch (video.Video3DFormat.Value) + { + case Video3DFormat.FullSideBySide: + builder.Append("FSBS"); + break; + case Video3DFormat.FullTopAndBottom: + builder.Append("FTAB"); + break; + case Video3DFormat.HalfSideBySide: + builder.Append("HSBS"); + break; + case Video3DFormat.HalfTopAndBottom: + builder.Append("HTAB"); + break; + } + } + } + } + + public static void AddCollectionItems(Folder item, StringBuilder builder) + { + var items = item.LinkedChildren + .Where(i => i.Type == LinkedChildType.Manual && !string.IsNullOrWhiteSpace(i.ItemName)) + .ToList(); + + if (items.Count == 0) + { + return; + } + + builder.Append(""); + foreach (var link in items) + { + builder.Append(""); + + builder.Append("" + SecurityElement.Escape(link.ItemName) + ""); + builder.Append("" + SecurityElement.Escape(link.ItemType) + ""); + + if (link.ItemYear.HasValue) + { + builder.Append("" + SecurityElement.Escape(link.ItemYear.Value.ToString(UsCulture)) + ""); + } + + builder.Append(""); + } + builder.Append(""); + } + } +} diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 4237c2974f..2d19d335d2 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -170,6 +170,9 @@ Configuration\UserConfiguration.cs + + Configuration\XbmcMetadataOptions.cs + Dlna\AudioOptions.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 262ad62670..c0c886c8a2 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -157,6 +157,9 @@ Configuration\UserConfiguration.cs + + Configuration\XbmcMetadataOptions.cs + Dlna\AudioOptions.cs diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 542020483d..af09a25acf 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Weather; +using System.Linq; +using MediaBrowser.Model.Weather; using System; namespace MediaBrowser.Model.Configuration @@ -68,24 +69,12 @@ namespace MediaBrowser.Model.Configuration /// The display name of the season zero. public string SeasonZeroDisplayName { get; set; } - /// - /// Gets or sets the metadata refresh days. - /// - /// The metadata refresh days. - public int MetadataRefreshDays { get; set; } - /// /// Gets or sets a value indicating whether [save local meta]. /// /// true if [save local meta]; otherwise, false. public bool SaveLocalMeta { get; set; } - /// - /// Gets or sets a value indicating whether [refresh item images]. - /// - /// true if [refresh item images]; otherwise, false. - public bool RefreshItemImages { get; set; } - /// /// Gets or sets the preferred metadata language. /// @@ -227,6 +216,9 @@ namespace MediaBrowser.Model.Configuration [Obsolete] public ChapterOptions ChapterOptions { get; set; } + [Obsolete] + public bool DefaultMetadataSettingsApplied { get; set; } + /// /// Initializes a new instance of the class. /// @@ -258,7 +250,6 @@ namespace MediaBrowser.Model.Configuration PathSubstitutions = new PathSubstitution[] { }; - MetadataRefreshDays = 30; PreferredMetadataLanguage = "en"; MetadataCountryCode = "US"; diff --git a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs new file mode 100644 index 0000000000..db8b69951a --- /dev/null +++ b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs @@ -0,0 +1,21 @@ + +namespace MediaBrowser.Model.Configuration +{ + public class XbmcMetadataOptions + { + public string UserId { get; set; } + + public string ReleaseDateFormat { get; set; } + + public bool SaveImagePathsInNfo { get; set; } + public bool EnablePathSubstitution { get; set; } + + public XbmcMetadataOptions() + { + ReleaseDateFormat = "yyyy-MM-dd"; + + SaveImagePathsInNfo = true; + EnablePathSubstitution = true; + } + } +} diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index fc79b7e758..d2b0a8caf3 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -75,6 +75,7 @@ + diff --git a/MediaBrowser.Providers/AdultVideos/AdultVideoXmlProvider.cs b/MediaBrowser.Providers/AdultVideos/AdultVideoXmlProvider.cs deleted file mode 100644 index 07b24c57d6..0000000000 --- a/MediaBrowser.Providers/AdultVideos/AdultVideoXmlProvider.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Providers.Movies; -using System.Collections.Generic; -using System.IO; -using System.Threading; - -namespace MediaBrowser.Providers.AdultVideos -{ - class AdultVideoXmlProvider : BaseXmlProvider - { - private readonly ILogger _logger; - - public AdultVideoXmlProvider(IFileSystem fileSystem, ILogger logger) - : base(fileSystem) - { - _logger = logger; - } - - protected override void Fetch(LocalMetadataResult result, string path, CancellationToken cancellationToken) - { - var chapters = new List(); - - new MovieXmlParser(_logger).Fetch(result.Item, chapters, path, cancellationToken); - - result.Chapters = chapters; - } - - protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService) - { - return MovieXmlProvider.GetXmlFileInfo(info, FileSystem); - } - } -} diff --git a/MediaBrowser.Providers/All/InternalMetadataFolderImageProvider.cs b/MediaBrowser.Providers/All/InternalMetadataFolderImageProvider.cs deleted file mode 100644 index edaa5edafd..0000000000 --- a/MediaBrowser.Providers/All/InternalMetadataFolderImageProvider.cs +++ /dev/null @@ -1,68 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Providers; -using System.Collections.Generic; -using System.IO; - -namespace MediaBrowser.Providers.All -{ - public class InternalMetadataFolderImageProvider : ILocalImageFileProvider, IHasOrder - { - private readonly IServerConfigurationManager _config; - - public InternalMetadataFolderImageProvider(IServerConfigurationManager config) - { - _config = config; - } - - public string Name - { - get { return "Internal Images"; } - } - - public bool Supports(IHasImages item) - { - if (!item.IsSaveLocalMetadataEnabled()) - { - return true; - } - - // Extracted images will be saved in here - if (item is Audio) - { - return true; - } - - if (item.SupportsLocalMetadata) - { - return false; - } - - return true; - } - - public int Order - { - get - { - // Make sure this is last so that all other locations are scanned first - return 1000; - } - } - - public List GetImages(IHasImages item, IDirectoryService directoryService) - { - var path = _config.ApplicationPaths.GetInternalMetadataPath(item.Id); - - try - { - return new LocalImageProvider().GetImages(item, path, directoryService); - } - catch (DirectoryNotFoundException) - { - return new List(); - } - } - } -} diff --git a/MediaBrowser.Providers/All/LocalImageProvider.cs b/MediaBrowser.Providers/All/LocalImageProvider.cs deleted file mode 100644 index 1d10fcfa35..0000000000 --- a/MediaBrowser.Providers/All/LocalImageProvider.cs +++ /dev/null @@ -1,327 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Providers.All -{ - public class LocalImageProvider : ILocalImageFileProvider - { - public string Name - { - get { return "Local Images"; } - } - - public int Order - { - get { return 0; } - } - - public bool Supports(IHasImages item) - { - if (item.SupportsLocalMetadata) - { - // Episode has it's own provider - if (item.IsOwnedItem || item is Episode || item is Audio) - { - return false; - } - - return true; - } - - if (item.LocationType == LocationType.Virtual) - { - var season = item as Season; - - if (season != null) - { - var series = season.Series; - - if (series != null && series.LocationType == LocationType.FileSystem) - { - return true; - } - } - } - - return false; - } - - private IEnumerable GetFiles(IHasImages item, bool includeDirectories, IDirectoryService directoryService) - { - if (item.LocationType != LocationType.FileSystem) - { - return new List(); - } - - var path = item.ContainingFolderPath; - - if (includeDirectories) - { - return directoryService.GetFileSystemEntries(path) - .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase) || - (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory); - } - - return directoryService.GetFiles(path) - .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase)); - } - - public List GetImages(IHasImages item, IDirectoryService directoryService) - { - var files = GetFiles(item, true, directoryService).ToList(); - - var list = new List(); - - PopulateImages(item, list, files, true, directoryService); - - return list; - } - - public List GetImages(IHasImages item, string path, IDirectoryService directoryService) - { - return GetImages(item, new[] { path }, directoryService); - } - - public List GetImages(IHasImages item, IEnumerable paths, IDirectoryService directoryService) - { - var files = paths.SelectMany(directoryService.GetFiles) - .Where(i => - { - var ext = i.Extension; - - return !string.IsNullOrEmpty(ext) && - BaseItem.SupportedImageExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase); - }) - .ToList(); - - var list = new List(); - - PopulateImages(item, list, files, false, directoryService); - - return list; - } - - private void PopulateImages(IHasImages item, List images, List files, bool supportParentSeriesFiles, IDirectoryService directoryService) - { - var imagePrefix = string.Empty; - - var baseItem = item as BaseItem; - if (baseItem != null && baseItem.IsInMixedFolder) - { - imagePrefix = Path.GetFileNameWithoutExtension(item.Path) + "-"; - } - - PopulatePrimaryImages(item, images, files, imagePrefix); - PopulateBackdrops(item, images, files, imagePrefix, directoryService); - PopulateScreenshots(images, files, imagePrefix); - - AddImage(files, images, imagePrefix + "logo", ImageType.Logo); - AddImage(files, images, imagePrefix + "clearart", ImageType.Art); - AddImage(files, images, imagePrefix + "disc", ImageType.Disc); - AddImage(files, images, imagePrefix + "cdart", ImageType.Disc); - AddImage(files, images, imagePrefix + "box", ImageType.Box); - AddImage(files, images, imagePrefix + "back", ImageType.BoxRear); - AddImage(files, images, imagePrefix + "boxrear", ImageType.BoxRear); - AddImage(files, images, imagePrefix + "menu", ImageType.Menu); - - // Banner - AddImage(files, images, imagePrefix + "banner", ImageType.Banner); - - // Thumb - AddImage(files, images, imagePrefix + "thumb", ImageType.Thumb); - AddImage(files, images, imagePrefix + "landscape", ImageType.Thumb); - - if (supportParentSeriesFiles) - { - var season = item as Season; - - if (season != null) - { - PopulateSeasonImagesFromSeriesFolder(season, images, directoryService); - } - } - } - - private void PopulatePrimaryImages(IHasImages item, List images, List files, string imagePrefix) - { - AddImage(files, images, imagePrefix + "folder", ImageType.Primary); - AddImage(files, images, imagePrefix + "cover", ImageType.Primary); - AddImage(files, images, imagePrefix + "poster", ImageType.Primary); - AddImage(files, images, imagePrefix + "default", ImageType.Primary); - - // Support plex/xbmc convention - if (item is Series) - { - AddImage(files, images, imagePrefix + "show", ImageType.Primary); - } - - // Support plex/xbmc convention - if (item is Movie || item is MusicVideo || item is AdultVideo) - { - AddImage(files, images, imagePrefix + "movie", ImageType.Primary); - } - - if (!string.IsNullOrEmpty(item.Path)) - { - var name = Path.GetFileNameWithoutExtension(item.Path); - - if (!string.IsNullOrEmpty(name)) - { - AddImage(files, images, name, ImageType.Primary); - AddImage(files, images, name + "-poster", ImageType.Primary); - } - } - } - - private void PopulateBackdrops(IHasImages item, List images, List files, string imagePrefix, IDirectoryService directoryService) - { - PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", ImageType.Backdrop); - - if (!string.IsNullOrEmpty(item.Path)) - { - var name = Path.GetFileNameWithoutExtension(item.Path); - - if (!string.IsNullOrEmpty(name)) - { - AddImage(files, images, imagePrefix + name + "-fanart", ImageType.Backdrop); - } - } - - PopulateBackdrops(images, files, imagePrefix, "fanart", "fanart-", ImageType.Backdrop); - PopulateBackdrops(images, files, imagePrefix, "background", "background-", ImageType.Backdrop); - PopulateBackdrops(images, files, imagePrefix, "art", "art-", ImageType.Backdrop); - - var extraFanartFolder = files - .FirstOrDefault(i => string.Equals(i.Name, "extrafanart", StringComparison.OrdinalIgnoreCase)); - - if (extraFanartFolder != null) - { - PopulateBackdropsFromExtraFanart(extraFanartFolder.FullName, images, directoryService); - } - } - - private void PopulateBackdropsFromExtraFanart(string path, List images, IDirectoryService directoryService) - { - var imageFiles = directoryService.GetFiles(path) - .Where(i => - { - var extension = i.Extension; - - if (string.IsNullOrEmpty(extension)) - { - return false; - } - - return BaseItem.SupportedImageExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase); - }); - - images.AddRange(imageFiles.Select(i => new LocalImageInfo - { - FileInfo = i, - Type = ImageType.Backdrop - })); - } - - private void PopulateScreenshots(List images, List files, string imagePrefix) - { - PopulateBackdrops(images, files, imagePrefix, "screenshot", "screenshot", ImageType.Screenshot); - } - - private void PopulateBackdrops(List images, List files, string imagePrefix, string firstFileName, string subsequentFileNamePrefix, ImageType type) - { - AddImage(files, images, imagePrefix + firstFileName, type); - - var unfound = 0; - for (var i = 1; i <= 20; i++) - { - // Screenshot Image - var found = AddImage(files, images, imagePrefix + subsequentFileNamePrefix + i, type); - - if (!found) - { - unfound++; - - if (unfound >= 3) - { - break; - } - } - } - } - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private void PopulateSeasonImagesFromSeriesFolder(Season season, List images, IDirectoryService directoryService) - { - var seasonNumber = season.IndexNumber; - - var series = season.Series; - if (!seasonNumber.HasValue || series.LocationType != LocationType.FileSystem) - { - return; - } - - var seriesFiles = GetFiles(series, false, directoryService).ToList(); - - // Try using the season name - var prefix = season.Name.ToLower().Replace(" ", string.Empty); - - var filenamePrefixes = new List { prefix }; - - var seasonMarker = seasonNumber.Value == 0 - ? "-specials" - : seasonNumber.Value.ToString("00", _usCulture); - - // Get this one directly from the file system since we have to go up a level - if (!string.Equals(prefix, seasonMarker, StringComparison.OrdinalIgnoreCase)) - { - filenamePrefixes.Add("season" + seasonMarker); - } - - foreach (var filename in filenamePrefixes) - { - AddImage(seriesFiles, images, filename + "-poster", ImageType.Primary); - AddImage(seriesFiles, images, filename + "-fanart", ImageType.Backdrop); - AddImage(seriesFiles, images, filename + "-banner", ImageType.Banner); - AddImage(seriesFiles, images, filename + "-landscape", ImageType.Thumb); - } - } - - private bool AddImage(IEnumerable files, List images, string name, ImageType type) - { - var image = GetImage(files, name) as FileInfo; - - if (image != null) - { - images.Add(new LocalImageInfo - { - FileInfo = image, - Type = type - }); - - return true; - } - - return false; - } - - private FileSystemInfo GetImage(IEnumerable files, string name) - { - var candidates = files - .Where(i => string.Equals(name, Path.GetFileNameWithoutExtension(i.Name), StringComparison.OrdinalIgnoreCase)) - .ToList(); - - return BaseItem.SupportedImageExtensions - .Select(i => candidates.FirstOrDefault(c => string.Equals(c.Extension, i, StringComparison.OrdinalIgnoreCase))) - .FirstOrDefault(i => i != null); - } - } -} diff --git a/MediaBrowser.Providers/BaseXmlProvider.cs b/MediaBrowser.Providers/BaseXmlProvider.cs deleted file mode 100644 index a5a3ba146a..0000000000 --- a/MediaBrowser.Providers/BaseXmlProvider.cs +++ /dev/null @@ -1,89 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers -{ - public abstract class BaseXmlProvider : ILocalMetadataProvider, IHasChangeMonitor - where T : IHasMetadata, new() - { - protected IFileSystem FileSystem; - - public async Task> GetMetadata(ItemInfo info, CancellationToken cancellationToken) - { - var result = new LocalMetadataResult(); - - var file = GetXmlFile(info, new DirectoryService(new NullLogger())); - - if (file == null) - { - return result; - } - - var path = file.FullName; - - await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - result.Item = new T(); - - Fetch(result, path, cancellationToken); - result.HasMetadata = true; - } - catch (FileNotFoundException) - { - result.HasMetadata = false; - } - catch (DirectoryNotFoundException) - { - result.HasMetadata = false; - } - finally - { - XmlProviderUtils.XmlParsingResourcePool.Release(); - } - - return result; - } - - protected abstract void Fetch(LocalMetadataResult result, string path, CancellationToken cancellationToken); - - protected BaseXmlProvider(IFileSystem fileSystem) - { - FileSystem = fileSystem; - } - - protected abstract FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService); - - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) - { - var file = GetXmlFile(new ItemInfo { IsInMixedFolder = item.IsInMixedFolder, Path = item.Path }, directoryService); - - if (file == null) - { - return false; - } - - return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > date; - } - - public string Name - { - get - { - return "Media Browser Xml"; - } - } - } - - static class XmlProviderUtils - { - internal static readonly SemaphoreSlim XmlParsingResourcePool = new SemaphoreSlim(4, 4); - } -} diff --git a/MediaBrowser.Providers/BoxSets/BoxSetXmlParser.cs b/MediaBrowser.Providers/BoxSets/BoxSetXmlParser.cs deleted file mode 100644 index eb3c99cef5..0000000000 --- a/MediaBrowser.Providers/BoxSets/BoxSetXmlParser.cs +++ /dev/null @@ -1,129 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System.Collections.Generic; -using System.Globalization; -using System.Xml; - -namespace MediaBrowser.Providers.BoxSets -{ - public class BoxSetXmlParser : BaseItemXmlParser - { - private readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - public BoxSetXmlParser(ILogger logger) - : base(logger) - { - } - - protected override void FetchDataFromXmlNode(XmlReader reader, BoxSet item) - { - switch (reader.Name) - { - case "CollectionItems": - - using (var subReader = reader.ReadSubtree()) - { - FetchFromCollectionItemsNode(subReader, item); - } - break; - - default: - base.FetchDataFromXmlNode(reader, item); - break; - } - } - - private void FetchFromCollectionItemsNode(XmlReader reader, BoxSet item) - { - reader.MoveToContent(); - - var list = new List(); - - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "CollectionItem": - { - using (var subReader = reader.ReadSubtree()) - { - var child = GetLinkedChild(subReader); - - if (child != null) - { - list.Add(child); - } - } - - break; - } - - default: - reader.Skip(); - break; - } - } - } - - item.LinkedChildren = list; - } - - private LinkedChild GetLinkedChild(XmlReader reader) - { - reader.MoveToContent(); - - var linkedItem = new LinkedChild - { - Type = LinkedChildType.Manual - }; - - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "Name": - { - linkedItem.ItemName = reader.ReadElementContentAsString(); - break; - } - - case "Type": - { - linkedItem.ItemType = reader.ReadElementContentAsString(); - break; - } - - case "Year": - { - var val = reader.ReadElementContentAsString(); - - if (!string.IsNullOrWhiteSpace(val)) - { - int rval; - - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) - { - linkedItem.ItemYear = rval; - } - } - - break; - } - - default: - reader.Skip(); - break; - } - } - } - - return string.IsNullOrWhiteSpace(linkedItem.ItemName) || string.IsNullOrWhiteSpace(linkedItem.ItemType) ? null : linkedItem; - } - } -} diff --git a/MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs b/MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs deleted file mode 100644 index 1d4d893ed7..0000000000 --- a/MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System.IO; -using System.Threading; - -namespace MediaBrowser.Providers.BoxSets -{ - /// - /// Class BoxSetXmlProvider. - /// - public class BoxSetXmlProvider : BaseXmlProvider - { - private readonly ILogger _logger; - - public BoxSetXmlProvider(IFileSystem fileSystem, ILogger logger) - : base(fileSystem) - { - _logger = logger; - } - - protected override void Fetch(LocalMetadataResult result, string path, CancellationToken cancellationToken) - { - new BoxSetXmlParser(_logger).Fetch(result.Item, path, cancellationToken); - } - - protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService) - { - return directoryService.GetFile(Path.Combine(info.Path, "collection.xml")); - } - } -} diff --git a/MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs b/MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs new file mode 100644 index 0000000000..42b1ea4ded --- /dev/null +++ b/MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Providers.Manager; + +namespace MediaBrowser.Providers.Channels +{ + public class AudioChannelItemMetadataService : MetadataService + { + public AudioChannelItemMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) + { + } + + /// + /// Merges the specified source. + /// + /// The source. + /// The target. + /// The locked fields. + /// if set to true [replace data]. + /// if set to true [merge metadata settings]. + protected override void MergeData(ChannelAudioItem source, ChannelAudioItem target, List lockedFields, bool replaceData, bool mergeMetadataSettings) + { + ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); + } + } +} diff --git a/MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs b/MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs new file mode 100644 index 0000000000..ddd1122073 --- /dev/null +++ b/MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Providers.Manager; + +namespace MediaBrowser.Providers.Channels +{ + public class VideoChannelItemMetadataService : MetadataService + { + public VideoChannelItemMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) + { + } + + /// + /// Merges the specified source. + /// + /// The source. + /// The target. + /// The locked fields. + /// if set to true [replace data]. + /// if set to true [merge metadata settings]. + protected override void MergeData(ChannelVideoItem source, ChannelVideoItem target, List lockedFields, bool replaceData, bool mergeMetadataSettings) + { + ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); + } + } +} diff --git a/MediaBrowser.Providers/Folders/CollectionFolderImageProvider.cs b/MediaBrowser.Providers/Folders/CollectionFolderImageProvider.cs deleted file mode 100644 index fa5946bd5c..0000000000 --- a/MediaBrowser.Providers/Folders/CollectionFolderImageProvider.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Providers.All; -using System.Collections.Generic; - -namespace MediaBrowser.Providers.Folders -{ - public class CollectionFolderLocalImageProvider : ILocalImageFileProvider, IHasOrder - { - public string Name - { - get { return "Collection Folder Images"; } - } - - public bool Supports(IHasImages item) - { - return item is CollectionFolder && item.SupportsLocalMetadata; - } - - public int Order - { - get - { - // Run after LocalImageProvider - return 1; - } - } - - public List GetImages(IHasImages item, IDirectoryService directoryService) - { - var collectionFolder = (CollectionFolder)item; - - return new LocalImageProvider().GetImages(item, collectionFolder.PhysicalLocations, directoryService); - } - } -} diff --git a/MediaBrowser.Providers/Folders/FolderXmlProvider.cs b/MediaBrowser.Providers/Folders/FolderXmlProvider.cs deleted file mode 100644 index 144d1b752e..0000000000 --- a/MediaBrowser.Providers/Folders/FolderXmlProvider.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System.IO; -using System.Threading; - -namespace MediaBrowser.Providers.Folders -{ - /// - /// Provides metadata for Folders and all subclasses by parsing folder.xml - /// - public class FolderXmlProvider : BaseXmlProvider - { - private readonly ILogger _logger; - - public FolderXmlProvider(IFileSystem fileSystem, ILogger logger) - : base(fileSystem) - { - _logger = logger; - } - - protected override void Fetch(LocalMetadataResult result, string path, CancellationToken cancellationToken) - { - new BaseItemXmlParser(_logger).Fetch(result.Item, path, cancellationToken); - } - - protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService) - { - return new FileInfo(Path.Combine(info.Path, "folder.xml")); - } - } -} diff --git a/MediaBrowser.Providers/Folders/ImagesByNameImageProvider.cs b/MediaBrowser.Providers/Folders/ImagesByNameImageProvider.cs deleted file mode 100644 index 5dcf3bc596..0000000000 --- a/MediaBrowser.Providers/Folders/ImagesByNameImageProvider.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Providers.All; -using System.Collections.Generic; -using System.IO; - -namespace MediaBrowser.Providers.Folders -{ - public class ImagesByNameImageProvider : ILocalImageFileProvider, IHasOrder - { - private readonly IFileSystem _fileSystem; - private readonly IServerConfigurationManager _config; - - public ImagesByNameImageProvider(IFileSystem fileSystem, IServerConfigurationManager config) - { - _fileSystem = fileSystem; - _config = config; - } - - public string Name - { - get { return "Images By Name"; } - } - - public bool Supports(IHasImages item) - { - return item is CollectionFolder; - } - - public int Order - { - get - { - // Run after LocalImageProvider, and after CollectionFolderImageProvider - return 2; - } - } - - public List GetImages(IHasImages item, IDirectoryService directoryService) - { - var name = _fileSystem.GetValidFilename(item.Name); - - var path = Path.Combine(_config.ApplicationPaths.GeneralPath, name); - - try - { - return new LocalImageProvider().GetImages(item, path, directoryService); - } - catch (DirectoryNotFoundException) - { - return new List(); - } - } - } -} diff --git a/MediaBrowser.Providers/GameGenres/AudioChannelItemMetadataService.cs b/MediaBrowser.Providers/GameGenres/AudioChannelItemMetadataService.cs deleted file mode 100644 index c8e496b710..0000000000 --- a/MediaBrowser.Providers/GameGenres/AudioChannelItemMetadataService.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Providers.Manager; -using System.Collections.Generic; - -namespace MediaBrowser.Providers.GameGenres -{ - public class AudioChannelItemMetadataService : MetadataService - { - public AudioChannelItemMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem) - : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) - { - } - - /// - /// Merges the specified source. - /// - /// The source. - /// The target. - /// The locked fields. - /// if set to true [replace data]. - /// if set to true [merge metadata settings]. - protected override void MergeData(ChannelAudioItem source, ChannelAudioItem target, List lockedFields, bool replaceData, bool mergeMetadataSettings) - { - ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); - } - } -} diff --git a/MediaBrowser.Providers/GameGenres/VideoChannelItemMetadataService.cs b/MediaBrowser.Providers/GameGenres/VideoChannelItemMetadataService.cs deleted file mode 100644 index 9dd37c9595..0000000000 --- a/MediaBrowser.Providers/GameGenres/VideoChannelItemMetadataService.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Providers.Manager; -using System.Collections.Generic; - -namespace MediaBrowser.Providers.GameGenres -{ - public class VideoChannelItemMetadataService : MetadataService - { - public VideoChannelItemMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem) - : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) - { - } - - /// - /// Merges the specified source. - /// - /// The source. - /// The target. - /// The locked fields. - /// if set to true [replace data]. - /// if set to true [merge metadata settings]. - protected override void MergeData(ChannelVideoItem source, ChannelVideoItem target, List lockedFields, bool replaceData, bool mergeMetadataSettings) - { - ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); - } - } -} diff --git a/MediaBrowser.Providers/Games/GameSystemXmlParser.cs b/MediaBrowser.Providers/Games/GameSystemXmlParser.cs deleted file mode 100644 index 85ee509ca1..0000000000 --- a/MediaBrowser.Providers/Games/GameSystemXmlParser.cs +++ /dev/null @@ -1,64 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; - -namespace MediaBrowser.Providers.Games -{ - public class GameSystemXmlParser : BaseItemXmlParser - { - public GameSystemXmlParser(ILogger logger) - : base(logger) - { - } - - private readonly Task _cachedTask = Task.FromResult(true); - public Task FetchAsync(GameSystem item, string metadataFile, CancellationToken cancellationToken) - { - Fetch(item, metadataFile, cancellationToken); - - cancellationToken.ThrowIfCancellationRequested(); - - return _cachedTask; - } - - /// - /// Fetches the data from XML node. - /// - /// The reader. - /// The item. - protected override void FetchDataFromXmlNode(XmlReader reader, GameSystem item) - { - switch (reader.Name) - { - case "GameSystem": - { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - item.GameSystemName = val; - } - break; - } - - case "GamesDbId": - { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - item.SetProviderId(MetadataProviders.Gamesdb, val); - } - break; - } - - - default: - base.FetchDataFromXmlNode(reader, item); - break; - } - } - } -} diff --git a/MediaBrowser.Providers/Games/GameSystemXmlProvider.cs b/MediaBrowser.Providers/Games/GameSystemXmlProvider.cs deleted file mode 100644 index db9c8f063c..0000000000 --- a/MediaBrowser.Providers/Games/GameSystemXmlProvider.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System.IO; -using System.Threading; - -namespace MediaBrowser.Providers.Games -{ - public class GameSystemXmlProvider : BaseXmlProvider - { - private readonly ILogger _logger; - - public GameSystemXmlProvider(IFileSystem fileSystem, ILogger logger) - : base(fileSystem) - { - _logger = logger; - } - - protected override void Fetch(LocalMetadataResult result, string path, CancellationToken cancellationToken) - { - new GameSystemXmlParser(_logger).Fetch(result.Item, path, cancellationToken); - } - - protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService) - { - return directoryService.GetFile(Path.Combine(info.Path, "gamesystem.xml")); - } - } -} diff --git a/MediaBrowser.Providers/Games/GameXmlParser.cs b/MediaBrowser.Providers/Games/GameXmlParser.cs deleted file mode 100644 index dfa71e5f44..0000000000 --- a/MediaBrowser.Providers/Games/GameXmlParser.cs +++ /dev/null @@ -1,105 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; - -namespace MediaBrowser.Providers.Games -{ - /// - /// Class EpisodeXmlParser - /// - public class GameXmlParser : BaseItemXmlParser - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - public GameXmlParser(ILogger logger) - : base(logger) - { - } - - private readonly Task _cachedTask = Task.FromResult(true); - public Task FetchAsync(Game item, string metadataFile, CancellationToken cancellationToken) - { - Fetch(item, metadataFile, cancellationToken); - - cancellationToken.ThrowIfCancellationRequested(); - - return _cachedTask; - } - - /// - /// Fetches the data from XML node. - /// - /// The reader. - /// The item. - protected override void FetchDataFromXmlNode(XmlReader reader, Game item) - { - switch (reader.Name) - { - case "GameSystem": - { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - item.GameSystem = val; - } - break; - } - - case "GamesDbId": - { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - item.SetProviderId(MetadataProviders.Gamesdb, val); - } - break; - } - - case "NesBox": - { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - item.SetProviderId(MetadataProviders.NesBox, val); - } - break; - } - - case "NesBoxRom": - { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - item.SetProviderId(MetadataProviders.NesBoxRom, val); - } - break; - } - - case "Players": - { - var val = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(val)) - { - int num; - - if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num)) - { - item.PlayersSupported = num; - } - } - break; - } - - - default: - base.FetchDataFromXmlNode(reader, item); - break; - } - } - } -} diff --git a/MediaBrowser.Providers/Games/GameXmlProvider.cs b/MediaBrowser.Providers/Games/GameXmlProvider.cs deleted file mode 100644 index 6609f9d5e7..0000000000 --- a/MediaBrowser.Providers/Games/GameXmlProvider.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System.IO; -using System.Threading; - -namespace MediaBrowser.Providers.Games -{ - public class GameXmlProvider : BaseXmlProvider - { - private readonly ILogger _logger; - - public GameXmlProvider(IFileSystem fileSystem, ILogger logger) - : base(fileSystem) - { - _logger = logger; - } - - protected override void Fetch(LocalMetadataResult result, string path, CancellationToken cancellationToken) - { - new GameXmlParser(_logger).Fetch(result.Item, path, cancellationToken); - } - - protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService) - { - var fileInfo = FileSystem.GetFileSystemInfo(info.Path); - - var directoryInfo = fileInfo as DirectoryInfo; - - if (directoryInfo == null) - { - directoryInfo = new DirectoryInfo(Path.GetDirectoryName(info.Path)); - } - - var directoryPath = directoryInfo.FullName; - - var specificFile = Path.Combine(directoryPath, Path.GetFileNameWithoutExtension(info.Path) + ".xml"); - - var file = new FileInfo(specificFile); - - return info.IsInMixedFolder || file.Exists ? file : new FileInfo(Path.Combine(directoryPath, "game.xml")); - } - } -} diff --git a/MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs b/MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs deleted file mode 100644 index 44a312e24c..0000000000 --- a/MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System.IO; -using System.Threading; - -namespace MediaBrowser.Providers.LiveTv -{ - public class ChannelXmlProvider : BaseXmlProvider - { - private readonly ILogger _logger; - - public ChannelXmlProvider(IFileSystem fileSystem, ILogger logger) - : base(fileSystem) - { - _logger = logger; - } - - protected override void Fetch(LocalMetadataResult result, string path, CancellationToken cancellationToken) - { - new BaseItemXmlParser(_logger).Fetch(result.Item, path, cancellationToken); - } - - protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService) - { - return directoryService.GetFile(Path.Combine(info.Path, "channel.xml")); - } - } -} diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 3234a8ae04..4c9d2416f0 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -70,41 +70,28 @@ Properties\SharedVersion.cs - - - - - - - + - + - - - - - - - @@ -118,16 +105,13 @@ - - - @@ -146,16 +130,12 @@ - - - - @@ -163,10 +143,8 @@ - - @@ -175,34 +153,17 @@ - - - - - - - - - - - - - - - - - @@ -212,16 +173,11 @@ - - - - - @@ -248,6 +204,7 @@ + + \ No newline at end of file diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs new file mode 100644 index 0000000000..0515148f02 --- /dev/null +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -0,0 +1,992 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.XbmcMetadata.Configuration; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Xml; + +namespace MediaBrowser.XbmcMetadata.Parsers +{ + public class BaseNfoParser + where T : BaseItem + { + /// + /// The logger + /// + protected ILogger Logger { get; private set; } + + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private readonly IConfigurationManager _config; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The configuration. + public BaseNfoParser(ILogger logger, IConfigurationManager config) + { + Logger = logger; + _config = config; + } + + /// + /// Fetches metadata for an item from one xml file + /// + /// The item. + /// The metadata file. + /// The cancellation token. + /// + public void Fetch(T item, string metadataFile, CancellationToken cancellationToken) + { + if (item == null) + { + throw new ArgumentNullException(); + } + + if (string.IsNullOrEmpty(metadataFile)) + { + throw new ArgumentNullException(); + } + + var settings = new XmlReaderSettings + { + CheckCharacters = false, + IgnoreProcessingInstructions = true, + IgnoreComments = true, + ValidationType = ValidationType.None + }; + + //Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken); + Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken); + } + + /// + /// Fetches the specified item. + /// + /// The item. + /// The metadata file. + /// The settings. + /// The encoding. + /// The cancellation token. + private void Fetch(T item, string metadataFile, XmlReaderSettings settings, Encoding encoding, CancellationToken cancellationToken) + { + using (var streamReader = new StreamReader(metadataFile, encoding)) + { + // Use XmlReader for best performance + using (var reader = XmlReader.Create(streamReader, settings)) + { + reader.MoveToContent(); + + // Loop through each element + while (reader.Read()) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + FetchDataFromXmlNode(reader, item); + } + } + } + } + } + + protected virtual void FetchDataFromXmlNode(XmlReader reader, T item) + { + switch (reader.Name) + { + // DateCreated + case "dateadded": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + DateTime added; + if (DateTime.TryParse(val, out added)) + { + item.DateCreated = added.ToUniversalTime(); + } + else + { + Logger.Warn("Invalid Added value found: " + val); + } + } + break; + } + + case "title": + case "localtitle": + item.Name = reader.ReadElementContentAsString(); + break; + + case "criticrating": + { + var text = reader.ReadElementContentAsString(); + + var hasCriticRating = item as IHasCriticRating; + + if (hasCriticRating != null && !string.IsNullOrEmpty(text)) + { + float value; + if (float.TryParse(text, NumberStyles.Any, _usCulture, out value)) + { + hasCriticRating.CriticRating = value; + } + } + + break; + } + + case "budget": + { + var text = reader.ReadElementContentAsString(); + var hasBudget = item as IHasBudget; + if (hasBudget != null) + { + double value; + if (double.TryParse(text, NumberStyles.Any, _usCulture, out value)) + { + hasBudget.Budget = value; + } + } + + break; + } + + case "revenue": + { + var text = reader.ReadElementContentAsString(); + var hasBudget = item as IHasBudget; + if (hasBudget != null) + { + double value; + if (double.TryParse(text, NumberStyles.Any, _usCulture, out value)) + { + hasBudget.Revenue = value; + } + } + + break; + } + + case "metascore": + { + var text = reader.ReadElementContentAsString(); + var hasMetascore = item as IHasMetascore; + if (hasMetascore != null) + { + float value; + if (float.TryParse(text, NumberStyles.Any, _usCulture, out value)) + { + hasMetascore.Metascore = value; + } + } + + break; + } + + case "awardsummary": + { + var text = reader.ReadElementContentAsString(); + var hasAwards = item as IHasAwards; + if (hasAwards != null) + { + if (!string.IsNullOrWhiteSpace(text)) + { + hasAwards.AwardSummary = text; + } + } + + break; + } + + case "sorttitle": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.ForcedSortName = val; + } + break; + } + + case "outline": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + var hasShortOverview = item as IHasShortOverview; + + if (hasShortOverview != null) + { + hasShortOverview.ShortOverview = val; + } + } + break; + } + + case "biography": + case "plot": + case "review": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.Overview = val; + } + + break; + } + + case "criticratingsummary": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + var hasCriticRating = item as IHasCriticRating; + + if (hasCriticRating != null) + { + hasCriticRating.CriticRatingSummary = val; + } + } + + break; + } + + case "language": + { + var val = reader.ReadElementContentAsString(); + + var hasLanguage = item as IHasPreferredMetadataLanguage; + if (hasLanguage != null) + { + hasLanguage.PreferredMetadataLanguage = val; + } + + break; + } + + case "website": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.HomePageUrl = val; + } + + break; + } + + case "lockedfields": + { + var fields = new List(); + + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + var list = val.Split('|').Select(i => + { + MetadataFields field; + + if (Enum.TryParse(i, true, out field)) + { + return (MetadataFields?)field; + } + + return null; + + }).Where(i => i.HasValue).Select(i => i.Value); + + fields.AddRange(list); + } + + item.LockedFields = fields; + + break; + } + + case "tagline": + { + var val = reader.ReadElementContentAsString(); + + var hasTagline = item as IHasTaglines; + if (hasTagline != null) + { + if (!string.IsNullOrWhiteSpace(val)) + { + hasTagline.AddTagline(val); + } + } + break; + } + + case "country": + { + var val = reader.ReadElementContentAsString(); + + var hasProductionLocations = item as IHasProductionLocations; + if (hasProductionLocations != null) + { + if (!string.IsNullOrWhiteSpace(val)) + { + hasProductionLocations.AddProductionLocation(val); + } + } + break; + } + + case "mpaa": + { + var rating = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(rating)) + { + item.OfficialRating = rating; + } + break; + } + + case "mpaadescription": + { + var rating = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(rating)) + { + item.OfficialRatingDescription = rating; + } + break; + } + + case "customrating": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.CustomRating = val; + } + break; + } + + case "runtime": + { + var text = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(text)) + { + int runtime; + if (int.TryParse(text.Split(' ')[0], NumberStyles.Integer, _usCulture, out runtime)) + { + item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; + } + } + break; + } + + case "aspectratio": + { + var val = reader.ReadElementContentAsString(); + + var hasAspectRatio = item as IHasAspectRatio; + if (!string.IsNullOrWhiteSpace(val) && hasAspectRatio != null) + { + hasAspectRatio.AspectRatio = val; + } + break; + } + + case "lockdata": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.IsLocked = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); + } + break; + } + + case "studio": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.AddStudio(val); + } + break; + } + + case "director": + { + foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new PersonInfo { Name = v.Trim(), Type = PersonType.Director })) + { + if (string.IsNullOrWhiteSpace(p.Name)) + { + continue; + } + item.AddPerson(p); + } + break; + } + case "credits": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + var parts = val.Split('/').Select(i => i.Trim()) + .Where(i => !string.IsNullOrEmpty(i)); + + foreach (var p in parts.Select(v => new PersonInfo { Name = v.Trim(), Type = PersonType.Writer })) + { + if (string.IsNullOrWhiteSpace(p.Name)) + { + continue; + } + item.AddPerson(p); + } + } + break; + } + + case "writer": + { + foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new PersonInfo { Name = v.Trim(), Type = PersonType.Writer })) + { + if (string.IsNullOrWhiteSpace(p.Name)) + { + continue; + } + item.AddPerson(p); + } + break; + } + + case "actor": + { + using (var subtree = reader.ReadSubtree()) + { + var person = GetPersonFromXmlNode(subtree); + + item.AddPerson(person); + } + break; + } + + case "trailer": + { + var val = reader.ReadElementContentAsString(); + + var hasTrailer = item as IHasTrailers; + if (hasTrailer != null) + { + if (!string.IsNullOrWhiteSpace(val)) + { + hasTrailer.AddTrailerUrl(val, false); + } + } + break; + } + + case "displayorder": + { + var val = reader.ReadElementContentAsString(); + + var hasDisplayOrder = item as IHasDisplayOrder; + if (hasDisplayOrder != null) + { + if (!string.IsNullOrWhiteSpace(val)) + { + hasDisplayOrder.DisplayOrder = val; + } + } + break; + } + + case "year": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int productionYear; + if (int.TryParse(val, out productionYear) && productionYear > 1850) + { + item.ProductionYear = productionYear; + } + } + + break; + } + + case "rating": + { + + var rating = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(rating)) + { + float val; + // All external meta is saving this as '.' for decimal I believe...but just to be sure + if (float.TryParse(rating.Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out val)) + { + item.CommunityRating = val; + } + } + break; + } + + case "aired": + case "formed": + case "premiered": + case "releasedate": + { + var formatString = _config.GetNfoConfiguration().ReleaseDateFormat; + + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + DateTime date; + + if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out date) && date.Year > 1850) + { + item.PremiereDate = date.ToUniversalTime(); + item.ProductionYear = date.Year; + } + } + + break; + } + + case "enddate": + { + var formatString = _config.GetNfoConfiguration().ReleaseDateFormat; + + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + DateTime date; + + if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out date) && date.Year > 1850) + { + item.EndDate = date.ToUniversalTime(); + } + } + + break; + } + + case "tvdbid": + var tvdbId = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(tvdbId)) + { + item.SetProviderId(MetadataProviders.Tvdb, tvdbId); + } + break; + + case "votes": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + int num; + + if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num)) + { + item.VoteCount = num; + } + } + break; + } + case "musicbrainzalbumid": + { + var mbz = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(mbz)) + { + item.SetProviderId(MetadataProviders.MusicBrainzAlbum, mbz); + } + break; + } + case "musicbrainzalbumartistid": + { + var mbz = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(mbz)) + { + item.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, mbz); + } + break; + } + case "musicbrainzartistid": + { + var mbz = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(mbz)) + { + item.SetProviderId(MetadataProviders.MusicBrainzArtist, mbz); + } + break; + } + case "musicbrainzreleasegroupid": + { + var mbz = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(mbz)) + { + item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, mbz); + } + break; + } + case "tvrageid": + { + var id = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(id)) + { + item.SetProviderId(MetadataProviders.TvRage, id); + } + break; + } + case "audiodbartistid": + { + var id = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(id)) + { + item.SetProviderId(MetadataProviders.AudioDbArtist, id); + } + break; + } + case "audiodbalbumid": + { + var id = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(id)) + { + item.SetProviderId(MetadataProviders.AudioDbAlbum, id); + } + break; + } + case "rottentomatoesid": + var rtId = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(rtId)) + { + item.SetProviderId(MetadataProviders.RottenTomatoes, rtId); + } + break; + + case "tmdbid": + var tmdb = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(tmdb)) + { + item.SetProviderId(MetadataProviders.Tmdb, tmdb); + } + break; + + case "collectionnumber": + var tmdbCollection = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(tmdbCollection)) + { + item.SetProviderId(MetadataProviders.TmdbCollection, tmdbCollection); + } + break; + + case "tvcomid": + var TVcomId = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(TVcomId)) + { + item.SetProviderId(MetadataProviders.Tvcom, TVcomId); + } + break; + + case "zap2itid": + var zap2ItId = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(zap2ItId)) + { + item.SetProviderId(MetadataProviders.Zap2It, zap2ItId); + } + break; + + case "imdb_id": + case "imdbid": + var imDbId = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(imDbId)) + { + item.SetProviderId(MetadataProviders.Imdb, imDbId); + } + break; + + case "genre": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + item.AddGenre(val); + } + break; + } + + case "style": + case "tag": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + var hasTags = item as IHasTags; + if (hasTags != null) + { + hasTags.AddTag(val); + } + } + break; + } + + case "plotkeyword": + { + var val = reader.ReadElementContentAsString(); + + var hasKeywords = item as IHasKeywords; + if (hasKeywords != null) + { + if (!string.IsNullOrWhiteSpace(val)) + { + hasKeywords.AddKeyword(val); + } + } + break; + } + + case "fileinfo": + { + using (var subtree = reader.ReadSubtree()) + { + FetchFromFileInfoNode(subtree, item); + } + break; + } + + default: + reader.Skip(); + break; + } + } + + private void FetchFromFileInfoNode(XmlReader reader, T item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "streamdetails": + { + using (var subtree = reader.ReadSubtree()) + { + FetchFromStreamDetailsNode(subtree, item); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + private void FetchFromStreamDetailsNode(XmlReader reader, T item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "video": + { + using (var subtree = reader.ReadSubtree()) + { + FetchFromVideoNode(subtree, item); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + private void FetchFromVideoNode(XmlReader reader, T item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "format3d": + { + var video = item as Video; + + if (video != null) + { + var val = reader.ReadElementContentAsString(); + + if (string.Equals("HSBS", val, StringComparison.CurrentCulture)) + { + video.Video3DFormat = Video3DFormat.HalfSideBySide; + } + else if (string.Equals("HTAB", val, StringComparison.CurrentCulture)) + { + video.Video3DFormat = Video3DFormat.HalfTopAndBottom; + } + else if (string.Equals("FTAB", val, StringComparison.CurrentCulture)) + { + video.Video3DFormat = Video3DFormat.FullTopAndBottom; + } + else if (string.Equals("FSBS", val, StringComparison.CurrentCulture)) + { + video.Video3DFormat = Video3DFormat.FullSideBySide; + } + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + /// + /// Gets the persons from XML node. + /// + /// The reader. + /// IEnumerable{PersonInfo}. + private PersonInfo GetPersonFromXmlNode(XmlReader reader) + { + var name = string.Empty; + var type = PersonType.Actor; // If type is not specified assume actor + var role = string.Empty; + int? sortOrder = null; + + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "name": + name = reader.ReadElementContentAsString() ?? string.Empty; + break; + + case "type": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + type = val; + } + break; + } + + case "role": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + role = val; + } + break; + } + case "sortorder": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int intVal; + if (int.TryParse(val, NumberStyles.Integer, _usCulture, out intVal)) + { + sortOrder = intVal; + } + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + + return new PersonInfo + { + Name = name.Trim(), + Role = role, + Type = type, + SortOrder = sortOrder + }; + } + + /// + /// Used to split names of comma or pipe delimeted genres and people + /// + /// The value. + /// IEnumerable{System.String}. + private IEnumerable SplitNames(string value) + { + value = value ?? string.Empty; + + // Only split by comma if there is no pipe in the string + // We have to be careful to not split names like Matthew, Jr. + var separator = value.IndexOf('|') == -1 && value.IndexOf(';') == -1 ? new[] { ',' } : new[] { '|', ';' }; + + value = value.Trim().Trim(separator); + + return string.IsNullOrWhiteSpace(value) ? new string[] { } : Split(value, separator, StringSplitOptions.RemoveEmptyEntries); + } + + /// + /// Provides an additional overload for string.split + /// + /// The val. + /// The separators. + /// The options. + /// System.String[][]. + private static string[] Split(string val, char[] separators, StringSplitOptions options) + { + return val.Split(separators, options); + } + } +} diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs new file mode 100644 index 0000000000..ba7b48b1fd --- /dev/null +++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs @@ -0,0 +1,211 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Threading; +using System.Xml; + +namespace MediaBrowser.XbmcMetadata.Parsers +{ + public class EpisodeNfoParser : BaseNfoParser + { + private List _imagesFound; + private List _chaptersFound; + private string _xmlPath; + + public EpisodeNfoParser(ILogger logger, IConfigurationManager config) : base(logger, config) + { + } + + public void Fetch(Episode item, + List images, + List chapters, + string metadataFile, + CancellationToken cancellationToken) + { + _imagesFound = images; + _chaptersFound = chapters; + _xmlPath = metadataFile; + + Fetch(item, metadataFile, cancellationToken); + } + + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + /// + /// Fetches the data from XML node. + /// + /// The reader. + /// The item. + protected override void FetchDataFromXmlNode(XmlReader reader, Episode item) + { + switch (reader.Name) + { + //case "Chapters": + + // _chaptersFound.AddRange(FetchChaptersFromXmlNode(item, reader.ReadSubtree())); + // break; + + case "season": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + int num; + + if (int.TryParse(number, out num)) + { + item.ParentIndexNumber = num; + } + } + break; + } + + case "episode": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + int num; + + if (int.TryParse(number, out num)) + { + item.IndexNumber = num; + } + } + break; + } + + case "episodenumberend": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + int num; + + if (int.TryParse(number, out num)) + { + item.IndexNumberEnd = num; + } + } + break; + } + + case "absolute_number": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + item.AbsoluteEpisodeNumber = rval; + } + } + + break; + } + case "DVD_episodenumber": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + float num; + + if (float.TryParse(number, NumberStyles.Any, UsCulture, out num)) + { + item.DvdEpisodeNumber = num; + } + } + break; + } + + case "DVD_season": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + float num; + + if (float.TryParse(number, NumberStyles.Any, UsCulture, out num)) + { + item.DvdSeasonNumber = Convert.ToInt32(num); + } + } + break; + } + + case "airsbefore_episode": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + item.AirsBeforeEpisodeNumber = rval; + } + } + + break; + } + + case "airsafter_season": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + item.AirsAfterSeasonNumber = rval; + } + } + + break; + } + + case "airsbefore_season": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int rval; + + // int.TryParse is local aware, so it can be probamatic, force us culture + if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) + { + item.AirsBeforeSeasonNumber = rval; + } + } + + break; + } + + + default: + base.FetchDataFromXmlNode(reader, item); + break; + } + } + } +} diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs new file mode 100644 index 0000000000..9b90b2bb34 --- /dev/null +++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs @@ -0,0 +1,97 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using System.Collections.Generic; +using System.Threading; +using System.Xml; + +namespace MediaBrowser.XbmcMetadata.Parsers +{ + class MovieNfoParser : BaseNfoParser + /// The path. + /// The XML tags used. + /// System.String. + private static string GetCustomTags(string path, List xmlTagsUsed) + { + var settings = new XmlReaderSettings + { + CheckCharacters = false, + IgnoreProcessingInstructions = true, + IgnoreComments = true, + ValidationType = ValidationType.None + }; + + var builder = new StringBuilder(); + + using (var streamReader = new StreamReader(path, Encoding.UTF8)) + { + // Use XmlReader for best performance + using (var reader = XmlReader.Create(streamReader, settings)) + { + reader.MoveToContent(); + + // Loop through each element + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + var name = reader.Name; + + if (!CommonTags.ContainsKey(name) && !xmlTagsUsed.Contains(name, StringComparer.OrdinalIgnoreCase)) + { + builder.AppendLine(reader.ReadOuterXml()); + } + else + { + reader.Skip(); + } + } + } + } + } + + return builder.ToString(); + } + + public static void AddMediaInfo(T item, StringBuilder builder) + where T : BaseItem, IHasMediaSources + { + builder.Append(""); + builder.Append(""); + + foreach (var stream in item.GetMediaSources(false).First().MediaStreams) + { + builder.Append("<" + stream.Type.ToString().ToLower() + ">"); + + if (!string.IsNullOrEmpty(stream.Codec)) + { + builder.Append("" + SecurityElement.Escape(stream.Codec) + ""); + builder.Append("" + SecurityElement.Escape(stream.Codec) + ""); + } + + if (stream.BitRate.HasValue) + { + builder.Append("" + stream.BitRate.Value.ToString(UsCulture) + ""); + } + + if (stream.Width.HasValue) + { + builder.Append("" + stream.Width.Value.ToString(UsCulture) + ""); + } + + if (stream.Height.HasValue) + { + builder.Append("" + stream.Height.Value.ToString(UsCulture) + ""); + } + + if (!string.IsNullOrEmpty(stream.AspectRatio)) + { + builder.Append("" + SecurityElement.Escape(stream.AspectRatio) + ""); + builder.Append("" + SecurityElement.Escape(stream.AspectRatio) + ""); + } + + var framerate = stream.AverageFrameRate ?? stream.RealFrameRate; + + if (framerate.HasValue) + { + builder.Append("" + framerate.Value.ToString(UsCulture) + ""); + } + + if (!string.IsNullOrEmpty(stream.Language)) + { + builder.Append("" + SecurityElement.Escape(stream.Language) + ""); + } + + var scanType = stream.IsInterlaced ? "interlaced" : "progressive"; + if (!string.IsNullOrEmpty(scanType)) + { + builder.Append("" + SecurityElement.Escape(scanType) + ""); + } + + if (stream.Channels.HasValue) + { + builder.Append("" + stream.Channels.Value.ToString(UsCulture) + ""); + } + + if (stream.SampleRate.HasValue) + { + builder.Append("" + stream.SampleRate.Value.ToString(UsCulture) + ""); + } + + builder.Append("" + SecurityElement.Escape(stream.IsDefault.ToString()) + ""); + builder.Append("" + SecurityElement.Escape(stream.IsForced.ToString()) + ""); + + if (stream.Type == MediaStreamType.Video) + { + if (item.RunTimeTicks.HasValue) + { + var timespan = TimeSpan.FromTicks(item.RunTimeTicks.Value); + + builder.Append("" + Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture) + ""); + builder.Append("" + Convert.ToInt32(timespan.TotalSeconds).ToString(UsCulture) + ""); + } + + var video = item as Video; + + if (video != null) + { + //AddChapters(video, builder, itemRepository); + + if (video.Video3DFormat.HasValue) + { + switch (video.Video3DFormat.Value) + { + case Video3DFormat.FullSideBySide: + builder.Append("FSBS"); + break; + case Video3DFormat.FullTopAndBottom: + builder.Append("FTAB"); + break; + case Video3DFormat.HalfSideBySide: + builder.Append("HSBS"); + break; + case Video3DFormat.HalfTopAndBottom: + builder.Append("HTAB"); + break; + } + } + } + } + + builder.Append(""); + } + + builder.Append(""); + builder.Append(""); + } + + /// + /// Adds the common nodes. + /// + /// Task. + public static void AddCommonNodes(BaseItem item, StringBuilder builder, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) + { + var overview = (item.Overview ?? string.Empty) + .StripHtml() + .Replace(""", "'"); + + var options = config.GetNfoConfiguration(); + + if (item is MusicArtist) + { + builder.Append(""); + } + else if (item is MusicAlbum) + { + builder.Append(""); + } + else + { + builder.Append(""); + } + + var hasShortOverview = item as IHasShortOverview; + if (hasShortOverview != null) + { + var outline = (hasShortOverview.ShortOverview ?? string.Empty) + .StripHtml() + .Replace(""", "'"); + + builder.Append(""); + } + else + { + builder.Append(""); + } + + builder.Append("" + SecurityElement.Escape(item.CustomRating ?? string.Empty) + ""); + builder.Append("" + item.IsLocked.ToString().ToLower() + ""); + + if (item.LockedFields.Count > 0) + { + builder.Append("" + string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()) + ""); + } + + if (!string.IsNullOrEmpty(item.DisplayMediaType)) + { + builder.Append("" + SecurityElement.Escape(item.DisplayMediaType) + ""); + } + + builder.Append("" + SecurityElement.Escape(item.DateCreated.ToString("yyyy-MM-dd HH:mm:ss")) + ""); + + builder.Append("" + SecurityElement.Escape(item.Name ?? string.Empty) + ""); + builder.Append("" + SecurityElement.Escape(item.Name ?? string.Empty) + ""); + + var directors = item.People + .Where(i => IsPersonType(i, PersonType.Director)) + .Select(i => i.Name) + .ToList(); + + foreach (var person in directors) + { + builder.Append("" + SecurityElement.Escape(person) + ""); + } + + var writers = item.People + .Where(i => IsPersonType(i, PersonType.Director)) + .Select(i => i.Name) + .ToList(); + + foreach (var person in writers) + { + builder.Append("" + SecurityElement.Escape(person) + ""); + } + + var credits = writers.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); + + if (credits.Count > 0) + { + builder.Append("" + SecurityElement.Escape(string.Join(" / ", credits.ToArray())) + ""); + } + + var hasTrailer = item as IHasTrailers; + if (hasTrailer != null) + { + foreach (var trailer in hasTrailer.RemoteTrailers) + { + builder.Append("" + SecurityElement.Escape(GetOutputTrailerUrl(trailer.Url)) + ""); + } + } + + if (item.CommunityRating.HasValue) + { + builder.Append("" + SecurityElement.Escape(item.CommunityRating.Value.ToString(UsCulture)) + ""); + } + + if (item.ProductionYear.HasValue) + { + builder.Append("" + SecurityElement.Escape(item.ProductionYear.Value.ToString(UsCulture)) + ""); + } + + if (!string.IsNullOrEmpty(item.ForcedSortName)) + { + builder.Append("" + SecurityElement.Escape(item.ForcedSortName) + ""); + } + + if (!string.IsNullOrEmpty(item.OfficialRating)) + { + builder.Append("" + SecurityElement.Escape(item.OfficialRating) + ""); + } + + if (!string.IsNullOrEmpty(item.OfficialRatingDescription)) + { + builder.Append("" + SecurityElement.Escape(item.OfficialRatingDescription) + ""); + } + + var hasAspectRatio = item as IHasAspectRatio; + if (hasAspectRatio != null) + { + if (!string.IsNullOrEmpty(hasAspectRatio.AspectRatio)) + { + builder.Append("" + SecurityElement.Escape(hasAspectRatio.AspectRatio) + ""); + } + } + + if (!string.IsNullOrEmpty(item.HomePageUrl)) + { + builder.Append("" + SecurityElement.Escape(item.HomePageUrl) + ""); + } + + var rt = item.GetProviderId(MetadataProviders.RottenTomatoes); + + if (!string.IsNullOrEmpty(rt)) + { + builder.Append("" + SecurityElement.Escape(rt) + ""); + } + + var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection); + + if (!string.IsNullOrEmpty(tmdbCollection)) + { + builder.Append("" + SecurityElement.Escape(tmdbCollection) + ""); + } + + var imdb = item.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrEmpty(imdb)) + { + if (item is Series) + { + builder.Append("" + SecurityElement.Escape(imdb) + ""); + } + else + { + builder.Append("" + SecurityElement.Escape(imdb) + ""); + } + } + + // Series xml saver already saves this + if (!(item is Series)) + { + var tvdb = item.GetProviderId(MetadataProviders.Tvdb); + if (!string.IsNullOrEmpty(tvdb)) + { + builder.Append("" + SecurityElement.Escape(tvdb) + ""); + } + } + + var tmdb = item.GetProviderId(MetadataProviders.Tmdb); + if (!string.IsNullOrEmpty(tmdb)) + { + builder.Append("" + SecurityElement.Escape(tmdb) + ""); + } + + var tvcom = item.GetProviderId(MetadataProviders.Tvcom); + if (!string.IsNullOrEmpty(tvcom)) + { + builder.Append("" + SecurityElement.Escape(tvcom) + ""); + } + + var hasLanguage = item as IHasPreferredMetadataLanguage; + if (hasLanguage != null) + { + if (!string.IsNullOrEmpty(hasLanguage.PreferredMetadataLanguage)) + { + builder.Append("" + SecurityElement.Escape(hasLanguage.PreferredMetadataLanguage) + ""); + } + } + + if (item.PremiereDate.HasValue && !(item is Episode)) + { + var formatString = options.ReleaseDateFormat; + + if (item is MusicArtist) + { + builder.Append("" + SecurityElement.Escape(item.PremiereDate.Value.ToString(formatString)) + ""); + } + else + { + builder.Append("" + SecurityElement.Escape(item.PremiereDate.Value.ToString(formatString)) + ""); + builder.Append("" + SecurityElement.Escape(item.PremiereDate.Value.ToString(formatString)) + ""); + } + } + + if (item.EndDate.HasValue) + { + if (!(item is Episode)) + { + var formatString = options.ReleaseDateFormat; + + builder.Append("" + SecurityElement.Escape(item.EndDate.Value.ToString(formatString)) + ""); + } + } + + var hasCriticRating = item as IHasCriticRating; + + if (hasCriticRating != null) + { + if (hasCriticRating.CriticRating.HasValue) + { + builder.Append("" + SecurityElement.Escape(hasCriticRating.CriticRating.Value.ToString(UsCulture)) + ""); + } + + if (!string.IsNullOrEmpty(hasCriticRating.CriticRatingSummary)) + { + builder.Append(""); + } + } + + var hasDisplayOrder = item as IHasDisplayOrder; + + if (hasDisplayOrder != null) + { + if (!string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder)) + { + builder.Append("" + SecurityElement.Escape(hasDisplayOrder.DisplayOrder) + ""); + } + } + + if (item.VoteCount.HasValue) + { + builder.Append("" + SecurityElement.Escape(item.VoteCount.Value.ToString(UsCulture)) + ""); + } + + var hasBudget = item as IHasBudget; + if (hasBudget != null) + { + if (hasBudget.Budget.HasValue) + { + builder.Append("" + SecurityElement.Escape(hasBudget.Budget.Value.ToString(UsCulture)) + ""); + } + + if (hasBudget.Revenue.HasValue) + { + builder.Append("" + SecurityElement.Escape(hasBudget.Revenue.Value.ToString(UsCulture)) + ""); + } + } + + var hasMetascore = item as IHasMetascore; + if (hasMetascore != null && hasMetascore.Metascore.HasValue) + { + builder.Append("" + SecurityElement.Escape(hasMetascore.Metascore.Value.ToString(UsCulture)) + ""); + } + + // Use original runtime here, actual file runtime later in MediaInfo + var runTimeTicks = item.RunTimeTicks; + + if (runTimeTicks.HasValue) + { + var timespan = TimeSpan.FromTicks(runTimeTicks.Value); + + builder.Append("" + Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture) + ""); + } + + var hasTaglines = item as IHasTaglines; + if (hasTaglines != null) + { + foreach (var tagline in hasTaglines.Taglines) + { + builder.Append("" + SecurityElement.Escape(tagline) + ""); + } + } + + var hasProductionLocations = item as IHasProductionLocations; + if (hasProductionLocations != null) + { + foreach (var country in hasProductionLocations.ProductionLocations) + { + builder.Append("" + SecurityElement.Escape(country) + ""); + } + } + + foreach (var genre in item.Genres) + { + builder.Append("" + SecurityElement.Escape(genre) + ""); + } + + foreach (var studio in item.Studios) + { + builder.Append("" + SecurityElement.Escape(studio) + ""); + } + + var hasTags = item as IHasTags; + if (hasTags != null) + { + foreach (var tag in hasTags.Tags) + { + if (item is MusicAlbum || item is MusicArtist) + { + builder.Append(""); + } + else + { + builder.Append("" + SecurityElement.Escape(tag) + ""); + } + } + } + + var hasKeywords = item as IHasKeywords; + if (hasKeywords != null) + { + foreach (var tag in hasKeywords.Keywords) + { + builder.Append("" + SecurityElement.Escape(tag) + ""); + } + } + + var hasAwards = item as IHasAwards; + if (hasAwards != null && !string.IsNullOrEmpty(hasAwards.AwardSummary)) + { + builder.Append("" + SecurityElement.Escape(hasAwards.AwardSummary) + ""); + } + + var externalId = item.GetProviderId(MetadataProviders.AudioDbArtist); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.AudioDbAlbum); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.Zap2It); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbum); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.MusicBrainzArtist); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.Gamesdb); + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + externalId = item.GetProviderId(MetadataProviders.TvRage); + if (!string.IsNullOrEmpty(externalId)) + { + builder.Append("" + SecurityElement.Escape(externalId) + ""); + } + + if (options.SaveImagePathsInNfo) + { + AddImages(item, builder, fileSystem, config); + } + + AddUserData(item, builder, userManager, userDataRepo, options); + + AddActors(item, builder, libraryManager, fileSystem, config); + + var folder = item as BoxSet; + if (folder != null) + { + AddCollectionItems(folder, builder); + } + } + + public static void AddChapters(Video item, StringBuilder builder, IItemRepository repository) + { + var chapters = repository.GetChapters(item.Id); + + foreach (var chapter in chapters) + { + builder.Append(""); + builder.Append("" + SecurityElement.Escape(chapter.Name) + ""); + + var time = TimeSpan.FromTicks(chapter.StartPositionTicks); + var ms = Convert.ToInt64(time.TotalMilliseconds); + + builder.Append("" + SecurityElement.Escape(ms.ToString(UsCulture)) + ""); + builder.Append(""); + } + } + + public static void AddCollectionItems(Folder item, StringBuilder builder) + { + var items = item.LinkedChildren + .Where(i => i.Type == LinkedChildType.Manual && !string.IsNullOrWhiteSpace(i.ItemName)) + .ToList(); + + foreach (var link in items) + { + builder.Append(""); + + builder.Append("" + SecurityElement.Escape(link.ItemName) + ""); + builder.Append("" + SecurityElement.Escape(link.ItemType) + ""); + + if (link.ItemYear.HasValue) + { + builder.Append("" + SecurityElement.Escape(link.ItemYear.Value.ToString(UsCulture)) + ""); + } + + builder.Append(""); + } + } + + /// + /// Gets the output trailer URL. + /// + /// The URL. + /// System.String. + private static string GetOutputTrailerUrl(string url) + { + // This is what xbmc expects + + return url.Replace("http://www.youtube.com/watch?v=", + "plugin://plugin.video.youtube/?action=play_video&videoid=", + StringComparison.OrdinalIgnoreCase); + } + + private static void AddImages(BaseItem item, StringBuilder builder, IFileSystem fileSystem, IServerConfigurationManager config) + { + builder.Append(""); + + var poster = item.PrimaryImagePath; + + if (!string.IsNullOrEmpty(poster)) + { + builder.Append("" + SecurityElement.Escape(GetPathToSave(item.PrimaryImagePath, fileSystem, config)) + ""); + } + + foreach (var backdrop in item.GetImages(ImageType.Backdrop)) + { + builder.Append("" + SecurityElement.Escape(GetPathToSave(backdrop.Path, fileSystem, config)) + ""); + } + + builder.Append(""); + } + + private static void AddUserData(BaseItem item, StringBuilder builder, IUserManager userManager, IUserDataManager userDataRepo, XbmcMetadataOptions options) + { + var userId = options.UserId; + if (string.IsNullOrWhiteSpace(userId)) + { + return; + } + + var user = userManager.GetUserById(new Guid(userId)); + + if (user == null) + { + return; + } + + if (item.IsFolder) + { + return; + } + + var userdata = userDataRepo.GetUserData(user.Id, item.GetUserDataKey()); + + builder.Append("" + userdata.PlayCount.ToString(UsCulture) + ""); + builder.Append("" + userdata.Played.ToString().ToLower() + ""); + + if (userdata.LastPlayedDate.HasValue) + { + builder.Append("" + SecurityElement.Escape(userdata.LastPlayedDate.Value.ToString("yyyy-MM-dd HH:mm:ss")) + ""); + } + + builder.Append(""); + + var runTimeTicks = item.RunTimeTicks ?? 0; + + builder.Append("" + TimeSpan.FromTicks(userdata.PlaybackPositionTicks).TotalSeconds.ToString(UsCulture) + ""); + builder.Append("" + TimeSpan.FromTicks(runTimeTicks).TotalSeconds.ToString(UsCulture) + ""); + + builder.Append(""); + } + + public static void AddActors(BaseItem item, StringBuilder builder, ILibraryManager libraryManager, IFileSystem fileSystem, IServerConfigurationManager config) + { + var actors = item.People + .Where(i => !IsPersonType(i, PersonType.Director) && !IsPersonType(i, PersonType.Writer)) + .ToList(); + + foreach (var person in actors) + { + builder.Append(""); + builder.Append("" + SecurityElement.Escape(person.Name ?? string.Empty) + ""); + builder.Append("" + SecurityElement.Escape(person.Role ?? string.Empty) + ""); + builder.Append("" + SecurityElement.Escape(person.Type ?? string.Empty) + ""); + + try + { + var personEntity = libraryManager.GetPerson(person.Name); + + if (!string.IsNullOrEmpty(personEntity.PrimaryImagePath)) + { + builder.Append("" + SecurityElement.Escape(GetPathToSave(personEntity.PrimaryImagePath, fileSystem, config)) + ""); + } + } + catch (Exception) + { + // Already logged in core + } + + builder.Append(""); + } + } + + private static bool IsPersonType(PersonInfo person, string type) + { + return string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); + } + + private static string GetPathToSave(string path, IFileSystem fileSystem, IServerConfigurationManager config) + { + foreach (var map in config.Configuration.PathSubstitutions) + { + path = fileSystem.SubstitutePath(path, map.From, map.To); + } + + return path; + } + + public static string ReplaceString(string str, string oldValue, string newValue, StringComparison comparison) + { + var sb = new StringBuilder(); + + int previousIndex = 0; + int index = str.IndexOf(oldValue, comparison); + while (index != -1) + { + sb.Append(str.Substring(previousIndex, index - previousIndex)); + sb.Append(newValue); + index += oldValue.Length; + + previousIndex = index; + index = str.IndexOf(oldValue, index, comparison); + } + sb.Append(str.Substring(previousIndex)); + + return sb.ToString(); + } + } +} diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 1b132e07f1..f8c1701bb9 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -1,8 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 -MinimumVisualStudioVersion = 10.0.40219.1 +# Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}" @@ -47,6 +45,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSubtitlesHandler", "OpenSubtitlesHandler\OpenSubtitlesHandler.csproj", "{4A4402D4-E910-443B-B8FC-2C18286A2CA0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.XbmcMetadata", "MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj", "{23499896-B135-4527-8574-C26E926EA99E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.LocalMetadata", "MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj", "{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -281,6 +283,34 @@ Global {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Win32.ActiveCfg = Release|Any CPU {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x64.ActiveCfg = Release|Any CPU {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.ActiveCfg = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|Win32.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|x64.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|x86.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.Build.0 = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|Win32.ActiveCfg = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|x64.ActiveCfg = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|x86.ActiveCfg = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Win32.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x64.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x86.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.Build.0 = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Win32.ActiveCfg = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x64.ActiveCfg = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- cgit v1.2.3 From 62d98551edf421ba50f2eadf95d6c3d1fb1d20ae Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Jun 2014 23:32:43 -0400 Subject: remove obsolete markings --- .../Configuration/ServerConfiguration.cs | 3 -- MediaBrowser.ServerApplication/ApplicationHost.cs | 4 +-- MediaBrowser.XbmcMetadata/EntryPoint.cs | 35 ++++++++++++++-------- MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs | 12 ++------ MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs | 12 ++------ .../Savers/EpisodeXmlSaver.cs | 12 ++------ MediaBrowser.XbmcMetadata/Savers/MovieXmlSaver.cs | 18 ++++------- MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs | 11 +++---- MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs | 12 ++------ 9 files changed, 43 insertions(+), 76 deletions(-) (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index af09a25acf..a5d19b5cbf 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -199,7 +199,6 @@ namespace MediaBrowser.Model.Configuration public string UICulture { get; set; } - [Obsolete] public DlnaOptions DlnaOptions { get; set; } public double DownMixAudioBoost { get; set; } @@ -213,10 +212,8 @@ namespace MediaBrowser.Model.Configuration public ChannelOptions ChannelOptions { get; set; } - [Obsolete] public ChapterOptions ChapterOptions { get; set; } - [Obsolete] public bool DefaultMetadataSettingsApplied { get; set; } /// diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index eeab8ee2e7..5c84b92af5 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -289,7 +289,7 @@ namespace MediaBrowser.ServerApplication DeleteDeprecatedModules(); MigrateModularConfigurations(); - ApplyDefaultXbmcSettings(); + ApplyDefaultMetadataSettings(); } private void MigrateModularConfigurations() @@ -316,7 +316,7 @@ namespace MediaBrowser.ServerApplication } } - private void ApplyDefaultXbmcSettings() + private void ApplyDefaultMetadataSettings() { if (!ServerConfigurationManager.Configuration.DefaultMetadataSettingsApplied) { diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs index 2d978781f7..a7015e41ff 100644 --- a/MediaBrowser.XbmcMetadata/EntryPoint.cs +++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs @@ -36,22 +36,39 @@ namespace MediaBrowser.XbmcMetadata void _libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e) { - if (e.UpdateReason == ItemUpdateType.ImageUpdate && e.Item is Person) + // TODO: Need a more accurate check here to see if xbmc metadata saving is enabled. + // This is probably good enough, but no guarantee + var userId = _config.GetNfoConfiguration().UserId; + if (string.IsNullOrWhiteSpace(userId)) { - var person = e.Item.Name; + return; + } - var items = _libraryManager.RootFolder - .GetRecursiveChildren(i => !i.IsFolder && i.People.Any(p => string.Equals(p.Name, person, StringComparison.OrdinalIgnoreCase))); + if (e.UpdateReason == ItemUpdateType.ImageUpdate) + { + var person = e.Item as Person; - foreach (var item in items) + if (person != null) { - SaveMetadataForItem(item, ItemUpdateType.MetadataEdit); + var items = _libraryManager.RootFolder.RecursiveChildren; + items = person.GetTaggedItems(items).ToList(); + + foreach (var item in items) + { + SaveMetadataForItem(item, ItemUpdateType.MetadataEdit); + } } } } void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e) { + var userId = _config.GetNfoConfiguration().UserId; + if (string.IsNullOrWhiteSpace(userId)) + { + return; + } + if (e.SaveReason == UserDataSaveReason.PlaybackFinished || e.SaveReason == UserDataSaveReason.TogglePlayed) { var item = e.Item as BaseItem; @@ -73,12 +90,6 @@ namespace MediaBrowser.XbmcMetadata private async void SaveMetadataForItem(BaseItem item, ItemUpdateType updateReason) { - var userId = _config.GetNfoConfiguration().UserId; - if (string.IsNullOrWhiteSpace(userId)) - { - return; - } - var locationType = item.LocationType; if (locationType == LocationType.Remote || locationType == LocationType.Virtual) diff --git a/MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs index 121514cdda..0f4d25dde4 100644 --- a/MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs @@ -95,20 +95,12 @@ namespace MediaBrowser.XbmcMetadata.Savers public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { - var locationType = item.LocationType; - if (locationType == LocationType.Remote || locationType == LocationType.Virtual) + if (!item.SupportsLocalMetadata) { return false; } - // If new metadata has been downloaded or metadata was manually edited, proceed - if ((updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload - || (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit) - { - return item is MusicAlbum; - } - - return false; + return item is MusicAlbum && updateType >= ItemUpdateType.MetadataDownload; } private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); diff --git a/MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs index f47785155b..937d702d34 100644 --- a/MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs @@ -85,20 +85,12 @@ namespace MediaBrowser.XbmcMetadata.Savers public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { - var locationType = item.LocationType; - if (locationType == LocationType.Remote || locationType == LocationType.Virtual) + if (!item.SupportsLocalMetadata) { return false; } - // If new metadata has been downloaded or metadata was manually edited, proceed - if ((updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload - || (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit) - { - return item is MusicArtist; - } - - return false; + return item is MusicArtist && updateType >= ItemUpdateType.MetadataDownload; } private void AddAlbums(IEnumerable albums, StringBuilder builder) diff --git a/MediaBrowser.XbmcMetadata/Savers/EpisodeXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/EpisodeXmlSaver.cs index a03eacdc47..1b5c24aad5 100644 --- a/MediaBrowser.XbmcMetadata/Savers/EpisodeXmlSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/EpisodeXmlSaver.cs @@ -130,20 +130,12 @@ namespace MediaBrowser.XbmcMetadata.Savers public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { - var locationType = item.LocationType; - if (locationType == LocationType.Remote || locationType == LocationType.Virtual) + if (!item.SupportsLocalMetadata) { return false; } - // If new metadata has been downloaded or metadata was manually edited, proceed - if ((updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload - || (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit) - { - return item is Episode; - } - - return false; + return item is Episode && updateType >= ItemUpdateType.MetadataDownload; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/MovieXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/MovieXmlSaver.cs index 586cefe653..fa2155e30a 100644 --- a/MediaBrowser.XbmcMetadata/Savers/MovieXmlSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/MovieXmlSaver.cs @@ -118,23 +118,17 @@ namespace MediaBrowser.XbmcMetadata.Savers public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { - var locationType = item.LocationType; - if (locationType == LocationType.Remote || locationType == LocationType.Virtual) + if (!item.SupportsLocalMetadata) { return false; } - // If new metadata has been downloaded or metadata was manually edited, proceed - if ((updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload - || (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit) - { - var video = item as Video; + var video = item as Video; - // Check parent for null to avoid running this against things like video backdrops - if (video != null && !(item is Episode) && !video.IsOwnedItem) - { - return true; - } + // Check parent for null to avoid running this against things like video backdrops + if (video != null && !(item is Episode) && !video.IsOwnedItem) + { + return updateType >= ItemUpdateType.MetadataDownload; } return false; diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs index 9de589e557..1b6c7a3401 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs @@ -71,20 +71,17 @@ namespace MediaBrowser.XbmcMetadata.Savers public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { - var locationType = item.LocationType; - if (locationType == LocationType.Remote || locationType == LocationType.Virtual) + if (!item.SupportsLocalMetadata) { return false; } - // If new metadata has been downloaded or metadata was manually edited, proceed - if ((updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload - || (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit) + if (!(item is Season)) { - return item is Season; + return false; } - return false; + return updateType >= ItemUpdateType.MetadataDownload || (updateType >= ItemUpdateType.MetadataImport && File.Exists(GetSavePath(item))); } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs index 9c99cc33d3..94d46f61d3 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs @@ -111,20 +111,12 @@ namespace MediaBrowser.XbmcMetadata.Savers public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { - var locationType = item.LocationType; - if (locationType == LocationType.Remote || locationType == LocationType.Virtual) + if (!item.SupportsLocalMetadata) { return false; } - // If new metadata has been downloaded or metadata was manually edited, proceed - if ((updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload - || (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit) - { - return item is Series; - } - - return false; + return item is Series && updateType >= ItemUpdateType.MetadataDownload; } } } -- cgit v1.2.3 From 8ae316a2f3333106921e7bc587bc990a8899c613 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 30 Jun 2014 13:40:46 -0400 Subject: fixes #859 - Support adaptive bitrate streaming --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 17 +++-- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 36 +---------- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 74 ++++++++++++++++------ .../Configuration/ServerConfiguration.cs | 6 +- .../MediaInfo/AudioImageProvider.cs | 28 +------- .../MediaInfo/FFProbeAudioInfo.cs | 2 +- .../Channels/ChannelConfigurations.cs | 29 +++++++++ .../Channels/ChannelDownloadScheduledTask.cs | 10 ++- .../Channels/ChannelManager.cs | 10 ++- .../MediaBrowser.Server.Implementations.csproj | 1 + MediaBrowser.ServerApplication/ApplicationHost.cs | 7 ++ 11 files changed, 122 insertions(+), 98 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 1b82349734..380ece2f2d 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1417,7 +1417,6 @@ namespace MediaBrowser.Api.Playback List mediaStreams = null; state.ItemType = item.GetType().Name; - state.ReadInputAtNativeFramerate = true; if (item is ILiveTvRecording) { @@ -1479,6 +1478,7 @@ namespace MediaBrowser.Api.Playback state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); mediaStreams = new List(); + state.ReadInputAtNativeFramerate = true; state.OutputAudioSync = "1000"; state.DeInterlace = true; state.InputVideoSync = "-1"; @@ -1489,13 +1489,13 @@ namespace MediaBrowser.Api.Playback } else if (item is IChannelMediaItem) { - var source = await GetChannelMediaInfo(request.Id, request.MediaSourceId, cancellationToken).ConfigureAwait(false); + var mediaSource = await GetChannelMediaInfo(request.Id, request.MediaSourceId, cancellationToken).ConfigureAwait(false); state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); - state.InputProtocol = source.Protocol; - state.MediaPath = source.Path; + state.InputProtocol = mediaSource.Protocol; + state.MediaPath = mediaSource.Path; state.RunTimeTicks = item.RunTimeTicks; - state.RemoteHttpHeaders = source.RequiredHttpHeaders; - mediaStreams = source.MediaStreams; + state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; + mediaStreams = mediaSource.MediaStreams; } else { @@ -1539,6 +1539,11 @@ namespace MediaBrowser.Api.Playback state.DeInterlace = true; } + if (state.InputProtocol == MediaProtocol.Rtmp) + { + state.ReadInputAtNativeFramerate = true; + } + var videoRequest = request as VideoStreamRequest; AttachMediaStreamInfo(state, mediaStreams, videoRequest, url); diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index e41a331be9..57c2244c7a 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -119,9 +119,8 @@ namespace MediaBrowser.Api.Playback.Hls } } - int audioBitrate; - int videoBitrate; - GetPlaylistBitrates(state, out audioBitrate, out videoBitrate); + var audioBitrate = state.OutputAudioBitrate ?? 0; + var videoBitrate = state.OutputVideoBitrate ?? 0; var appendBaselineStream = false; var baselineStreamBitrate = 64000; @@ -162,37 +161,6 @@ namespace MediaBrowser.Api.Playback.Hls return minimumSegmentCount; } - /// - /// Gets the playlist bitrates. - /// - /// The state. - /// The audio bitrate. - /// The video bitrate. - protected void GetPlaylistBitrates(StreamState state, out int audioBitrate, out int videoBitrate) - { - var audioBitrateParam = state.OutputAudioBitrate; - var videoBitrateParam = state.OutputVideoBitrate; - - if (!audioBitrateParam.HasValue) - { - if (state.AudioStream != null) - { - audioBitrateParam = state.AudioStream.BitRate; - } - } - - if (!videoBitrateParam.HasValue) - { - if (state.VideoStream != null) - { - videoBitrateParam = state.VideoStream.BitRate; - } - } - - audioBitrate = audioBitrateParam ?? 0; - videoBitrate = videoBitrateParam ?? 0; - } - private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, bool includeBaselineStream, int baselineStreamBitrate) { var builder = new StringBuilder(); diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 5913e81db8..b5b6849cef 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -304,45 +304,79 @@ namespace MediaBrowser.Api.Playback.Hls { var state = await GetState(request, CancellationToken.None).ConfigureAwait(false); - int audioBitrate; - int videoBitrate; - GetPlaylistBitrates(state, out audioBitrate, out videoBitrate); + var audioBitrate = state.OutputAudioBitrate ?? 0; + var videoBitrate = state.OutputVideoBitrate ?? 0; - var appendBaselineStream = false; - var baselineStreamBitrate = 64000; - - var hlsVideoRequest = state.VideoRequest as GetMasterHlsVideoStream; - if (hlsVideoRequest != null) - { - appendBaselineStream = hlsVideoRequest.AppendBaselineStream; - baselineStreamBitrate = hlsVideoRequest.BaselineStreamAudioBitRate ?? baselineStreamBitrate; - } - - var playlistText = GetMasterPlaylistFileText(videoBitrate + audioBitrate); + var playlistText = GetMasterPlaylistFileText(state, videoBitrate + audioBitrate); return ResultFactory.GetResult(playlistText, Common.Net.MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary()); } - private string GetMasterPlaylistFileText(int bitrate) + private string GetMasterPlaylistFileText(StreamState state, int totalBitrate) { var builder = new StringBuilder(); builder.AppendLine("#EXTM3U"); - // Pad a little to satisfy the apple hls validator - var paddedBitrate = Convert.ToInt32(bitrate * 1.05); - var queryStringIndex = Request.RawUrl.IndexOf('?'); var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex); // Main stream - builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture)); var playlistUrl = "main.m3u8" + queryString; - builder.AppendLine(playlistUrl); + AppendPlaylist(builder, playlistUrl, totalBitrate); + + if (state.VideoRequest.VideoBitRate.HasValue) + { + var requestedVideoBitrate = state.VideoRequest.VideoBitRate.Value; + + // By default, vary by just 200k + var variation = GetBitrateVariation(totalBitrate); + + var newBitrate = totalBitrate - variation; + AppendPlaylist(builder, playlistUrl.Replace(requestedVideoBitrate.ToString(UsCulture), (requestedVideoBitrate - variation).ToString(UsCulture)), newBitrate); + + newBitrate = totalBitrate - (2 * variation); + AppendPlaylist(builder, playlistUrl.Replace(requestedVideoBitrate.ToString(UsCulture), (requestedVideoBitrate - (2 * variation)).ToString(UsCulture)), newBitrate); + } return builder.ToString(); } + private void AppendPlaylist(StringBuilder builder, string url, int bitrate) + { + builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + bitrate.ToString(UsCulture)); + builder.AppendLine(url); + } + + private int GetBitrateVariation(int bitrate) + { + // By default, vary by just 200k + var variation = 200000; + + if (bitrate >= 10000000) + { + variation = 2000000; + } + else if (bitrate >= 5000000) + { + variation = 1500000; + } + else if (bitrate >= 3000000) + { + variation = 1000000; + } + else if (bitrate >= 2000000) + { + variation = 500000; + } + else if (bitrate >= 1000000) + { + variation = 300000; + } + + return variation; + } + public object Get(GetMainHlsVideoStream request) { var result = GetPlaylistAsync(request, "main").Result; diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index a5d19b5cbf..f7b888f824 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -1,5 +1,4 @@ -using System.Linq; -using MediaBrowser.Model.Weather; +using MediaBrowser.Model.Weather; using System; namespace MediaBrowser.Model.Configuration @@ -211,7 +210,6 @@ namespace MediaBrowser.Model.Configuration public string[] ManualLoginClients { get; set; } public ChannelOptions ChannelOptions { get; set; } - public ChapterOptions ChapterOptions { get; set; } public bool DefaultMetadataSettingsApplied { get; set; } @@ -274,8 +272,6 @@ namespace MediaBrowser.Model.Configuration SubtitleOptions = new SubtitleOptions(); - ChannelOptions = new ChannelOptions(); - LiveTvOptions = new LiveTvOptions(); TvFileOrganizationOptions = new TvFileOrganizationOptions(); } diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index b2ca97f55c..9188a22814 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -6,7 +6,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -24,40 +23,17 @@ namespace MediaBrowser.Providers.MediaInfo { private readonly ConcurrentDictionary _locks = new ConcurrentDictionary(); - private readonly IIsoManager _isoManager; private readonly IMediaEncoder _mediaEncoder; private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; - public AudioImageProvider(IIsoManager isoManager, IMediaEncoder mediaEncoder, IServerConfigurationManager config, IFileSystem fileSystem) + public AudioImageProvider(IMediaEncoder mediaEncoder, IServerConfigurationManager config, IFileSystem fileSystem) { - _isoManager = isoManager; _mediaEncoder = mediaEncoder; _config = config; _fileSystem = fileSystem; } - /// - /// The null mount task result - /// - protected readonly Task NullMountTaskResult = Task.FromResult(null); - - /// - /// Mounts the iso if needed. - /// - /// The item. - /// The cancellation token. - /// Task{IIsoMount}. - protected Task MountIsoIfNeeded(Video item, CancellationToken cancellationToken) - { - if (item.VideoType == VideoType.Iso) - { - return _isoManager.Mount(item.Path, cancellationToken); - } - - return NullMountTaskResult; - } - public IEnumerable GetSupportedImages(IHasImages item) { return new List { ImageType.Primary }; @@ -156,7 +132,7 @@ namespace MediaBrowser.Providers.MediaInfo public bool Supports(IHasImages item) { - return item.LocationType == LocationType.FileSystem && item is Audio; + return item is Audio; } public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 0f2ed1642f..a856d5dba3 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -98,7 +98,7 @@ namespace MediaBrowser.Providers.MediaInfo audio.FormatName = mediaInfo.Format; audio.TotalBitrate = mediaInfo.TotalBitrate; - audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.Video); + audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.EmbeddedImage); if (data.streams != null) { diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs b/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs new file mode 100644 index 0000000000..9dfb0404e0 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs @@ -0,0 +1,29 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Configuration; +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.Channels +{ + public static class ChannelConfigurationExtension + { + public static ChannelOptions GetChannelsConfiguration(this IConfigurationManager manager) + { + return manager.GetConfiguration("channels"); + } + } + + public class ChannelConfigurationFactory : IConfigurationFactory + { + public IEnumerable GetConfigurations() + { + return new List + { + new ConfigurationStore + { + Key = "channels", + ConfigurationType = typeof (ChannelOptions) + } + }; + } + } +} diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs index ce5c41f890..d219ab0276 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs @@ -146,9 +146,11 @@ namespace MediaBrowser.Server.Implementations.Channels { var numComplete = 0; + var options = _config.GetChannelsConfiguration(); + foreach (var item in result.Items) { - if (_config.Configuration.ChannelOptions.DownloadingChannels.Contains(item.ChannelId)) + if (options.DownloadingChannels.Contains(item.ChannelId)) { try { @@ -282,12 +284,14 @@ namespace MediaBrowser.Server.Implementations.Channels private void CleanChannelContent(CancellationToken cancellationToken) { - if (!_config.Configuration.ChannelOptions.MaxDownloadAge.HasValue) + var options = _config.GetChannelsConfiguration(); + + if (!options.MaxDownloadAge.HasValue) { return; } - var minDateModified = DateTime.UtcNow.AddDays(0 - _config.Configuration.ChannelOptions.MaxDownloadAge.Value); + var minDateModified = DateTime.UtcNow.AddDays(0 - options.MaxDownloadAge.Value); var path = _manager.ChannelDownloadPath; diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index 188a26c604..c6dd807585 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -77,9 +77,11 @@ namespace MediaBrowser.Server.Implementations.Channels { get { - if (!string.IsNullOrWhiteSpace(_config.Configuration.ChannelOptions.DownloadPath)) + var options = _config.GetChannelsConfiguration(); + + if (!string.IsNullOrWhiteSpace(options.DownloadPath)) { - return _config.Configuration.ChannelOptions.DownloadPath; + return options.DownloadPath; } return Path.Combine(_config.ApplicationPaths.ProgramDataPath, "channels"); @@ -374,7 +376,9 @@ namespace MediaBrowser.Server.Implementations.Channels { var list = channelMediaSources.ToList(); - var width = _config.Configuration.ChannelOptions.PreferredStreamingWidth; + var options = _config.GetChannelsConfiguration(); + + var width = options.PreferredStreamingWidth; if (width.HasValue) { diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 7410f63778..3401078518 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -101,6 +101,7 @@ Properties\SharedVersion.cs + diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 96aa9c9d59..87f18e4cba 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -310,6 +310,13 @@ namespace MediaBrowser.ServerApplication saveConfig = true; } + if (ServerConfigurationManager.Configuration.ChannelOptions != null) + { + ServerConfigurationManager.SaveConfiguration("channels", ServerConfigurationManager.Configuration.ChannelOptions); + ServerConfigurationManager.Configuration.ChannelOptions = null; + saveConfig = true; + } + if (saveConfig) { ServerConfigurationManager.SaveConfiguration(); -- cgit v1.2.3 From c273f5fd9c33415a1fa985222e43c9c02f3d36e5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 30 Jun 2014 15:24:35 -0400 Subject: fixes #860 - Add options to display channels directly within user views --- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 5 +++-- MediaBrowser.Controller/Channels/Channel.cs | 2 +- MediaBrowser.Model/Configuration/UserConfiguration.cs | 3 +++ .../Library/UserViewManager.cs | 11 +++++++++-- .../Localization/Server/server.json | 4 +++- 5 files changed, 19 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index b5b6849cef..bde2c56943 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -335,8 +335,9 @@ namespace MediaBrowser.Api.Playback.Hls var newBitrate = totalBitrate - variation; AppendPlaylist(builder, playlistUrl.Replace(requestedVideoBitrate.ToString(UsCulture), (requestedVideoBitrate - variation).ToString(UsCulture)), newBitrate); - newBitrate = totalBitrate - (2 * variation); - AppendPlaylist(builder, playlistUrl.Replace(requestedVideoBitrate.ToString(UsCulture), (requestedVideoBitrate - (2 * variation)).ToString(UsCulture)), newBitrate); + variation *= 2; + newBitrate = totalBitrate - variation; + AppendPlaylist(builder, playlistUrl.Replace(requestedVideoBitrate.ToString(UsCulture), (requestedVideoBitrate - variation).ToString(UsCulture)), newBitrate); } return builder.ToString(); diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs index 3d9d0d381d..df38259b42 100644 --- a/MediaBrowser.Controller/Channels/Channel.cs +++ b/MediaBrowser.Controller/Channels/Channel.cs @@ -4,7 +4,7 @@ using System.Linq; namespace MediaBrowser.Controller.Channels { - public class Channel : BaseItem + public class Channel : Folder { public string OriginalChannelName { get; set; } diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 94a41bdda0..84ce2747a5 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -65,6 +65,8 @@ namespace MediaBrowser.Model.Configuration public string[] BlockedMediaFolders { get; set; } public string[] BlockedChannels { get; set; } + public string[] DisplayChannelsWithinViews { get; set; } + public string[] ExcludeFoldersFromGrouping { get; set; } public UnratedItem[] BlockUnratedItems { get; set; } @@ -85,6 +87,7 @@ namespace MediaBrowser.Model.Configuration EnableLiveTvAccess = true; BlockedMediaFolders = new string[] { }; + DisplayChannelsWithinViews = new string[] { }; BlockedChannels = new string[] { }; BlockUnratedItems = new UnratedItem[] { }; diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index fc4b9eb4ca..9ac82690b7 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -90,12 +90,19 @@ namespace MediaBrowser.Server.Implementations.Library { var channelResult = await _channelManager.GetChannels(new ChannelQuery { - Limit = 0, UserId = query.UserId }, cancellationToken).ConfigureAwait(false); - if (channelResult.TotalRecordCount > 0) + var channels = channelResult.Items; + + var embeddedChannels = channels + .Where(i => user.Configuration.DisplayChannelsWithinViews.Contains(i.Id)) + .ToList(); + + list.AddRange(embeddedChannels.Select(i => _channelManager.GetChannel(i.Id))); + + if (channels.Length > embeddedChannels.Count) { list.Add(await _channelManager.GetInternalChannelFolder(query.UserId, cancellationToken).ConfigureAwait(false)); } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 9063ebc4bb..4a3d93d1e0 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -846,5 +846,7 @@ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.", "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution", "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.", - "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution." + "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.", + "LabelGroupChannelsIntoViews": "Display the following channels within my views:", + "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view." } \ No newline at end of file -- cgit v1.2.3 From 43943657b7ea0c607f998c6397d3878e3fb05c5f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 1 Jul 2014 00:06:28 -0400 Subject: add additional view settings --- .../Collections/ICollectionManager.cs | 7 ++++ MediaBrowser.Controller/Entities/BaseItem.cs | 5 +++ MediaBrowser.Controller/Entities/Folder.cs | 5 ++- .../Configuration/NotificationOptions.cs | 10 ++--- .../Configuration/UserConfiguration.cs | 3 ++ MediaBrowser.Model/Dlna/DeviceProfile.cs | 10 ++--- MediaBrowser.Model/Dlna/StreamBuilder.cs | 43 ++++++++++++++++++---- MediaBrowser.Model/Dlna/StreamInfo.cs | 22 ++++++++--- MediaBrowser.Model/Extensions/StringHelper.cs | 11 ++++++ MediaBrowser.Model/Notifications/Notification.cs | 5 --- .../Collections/CollectionManager.cs | 11 ++++-- .../Collections/ManualCollectionsFolder.cs | 5 +++ .../Library/UserViewManager.cs | 17 +++++---- 13 files changed, 114 insertions(+), 40 deletions(-) (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs index b63c49f99a..fdb2a49755 100644 --- a/MediaBrowser.Controller/Collections/ICollectionManager.cs +++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs @@ -38,5 +38,12 @@ namespace MediaBrowser.Controller.Collections /// The user. /// IEnumerable{BaseItem}. IEnumerable CollapseItemsWithinBoxSets(IEnumerable items, User user); + + /// + /// Gets the collections folder. + /// + /// The user identifier. + /// Folder. + Folder GetCollectionsFolder(string userId); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index a2ff1b4fdf..524d7097ba 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -134,6 +134,11 @@ namespace MediaBrowser.Controller.Entities } } + public virtual bool IsHiddenFromUser(User user) + { + return false; + } + [IgnoreDataMember] public virtual bool IsOwnedItem { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index f503a5ff44..e54e72cd8d 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -809,7 +809,10 @@ namespace MediaBrowser.Controller.Entities { if (filter == null || filter(child)) { - list.Add(child); + if (!child.IsHiddenFromUser(user)) + { + list.Add(child); + } } if (recursive && child.IsFolder) diff --git a/MediaBrowser.Model/Configuration/NotificationOptions.cs b/MediaBrowser.Model/Configuration/NotificationOptions.cs index 5aac1652fc..dd523d9478 100644 --- a/MediaBrowser.Model/Configuration/NotificationOptions.cs +++ b/MediaBrowser.Model/Configuration/NotificationOptions.cs @@ -1,6 +1,4 @@ -using System; -using System.Linq; -using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Configuration { @@ -90,7 +88,7 @@ namespace MediaBrowser.Model.Configuration NotificationOption opt = GetOptions(notificationType); return opt == null || - !opt.DisabledServices.Contains(service, StringComparer.OrdinalIgnoreCase); + !ListHelper.ContainsIgnoreCase(opt.DisabledServices, service); } public bool IsEnabledToMonitorUser(string type, string userId) @@ -98,7 +96,7 @@ namespace MediaBrowser.Model.Configuration NotificationOption opt = GetOptions(type); return opt != null && opt.Enabled && - !opt.DisabledMonitorUsers.Contains(userId, StringComparer.OrdinalIgnoreCase); + !ListHelper.ContainsIgnoreCase(opt.DisabledMonitorUsers, userId); } public bool IsEnabledToSendToUser(string type, string userId, UserConfiguration userConfig) @@ -117,7 +115,7 @@ namespace MediaBrowser.Model.Configuration return true; } - return opt.SendToUsers.Contains(userId, StringComparer.OrdinalIgnoreCase); + return ListHelper.ContainsIgnoreCase(opt.SendToUsers, userId); } return false; diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 84ce2747a5..24a41863e9 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -72,6 +72,7 @@ namespace MediaBrowser.Model.Configuration public UnratedItem[] BlockUnratedItems { get; set; } public SubtitlePlaybackMode SubtitleMode { get; set; } + public bool DisplayCollectionsView { get; set; } /// /// Initializes a new instance of the class. @@ -92,6 +93,8 @@ namespace MediaBrowser.Model.Configuration BlockUnratedItems = new UnratedItem[] { }; ExcludeFoldersFromGrouping = new string[] { }; + + DisplayCollectionsView = true; } } } diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index 807e04427a..deaa307146 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -115,7 +115,7 @@ namespace MediaBrowser.Model.Dlna public TranscodingProfile GetAudioTranscodingProfile(string container, string audioCodec) { - container = (container ?? string.Empty).TrimStart('.'); + container = StringHelper.TrimStart((container ?? string.Empty), '.'); foreach (var i in TranscodingProfiles) { @@ -141,7 +141,7 @@ namespace MediaBrowser.Model.Dlna public TranscodingProfile GetVideoTranscodingProfile(string container, string audioCodec, string videoCodec) { - container = (container ?? string.Empty).TrimStart('.'); + container = StringHelper.TrimStart((container ?? string.Empty), '.'); foreach (var i in TranscodingProfiles) { @@ -172,7 +172,7 @@ namespace MediaBrowser.Model.Dlna public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate) { - container = (container ?? string.Empty).TrimStart('.'); + container = StringHelper.TrimStart((container ?? string.Empty), '.'); foreach (var i in ResponseProfiles) { @@ -217,7 +217,7 @@ namespace MediaBrowser.Model.Dlna public ResponseProfile GetImageMediaProfile(string container, int? width, int? height) { - container = (container ?? string.Empty).TrimStart('.'); + container = StringHelper.TrimStart((container ?? string.Empty), '.'); foreach (var i in ResponseProfiles) { @@ -270,7 +270,7 @@ namespace MediaBrowser.Model.Dlna TransportStreamTimestamp timestamp, bool? isAnamorphic) { - container = (container ?? string.Empty).TrimStart('.'); + container = StringHelper.TrimStart((container ?? string.Empty), '.'); foreach (var i in ResponseProfiles) { diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 877570844b..8aadd428f6 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -136,7 +136,12 @@ namespace MediaBrowser.Model.Dlna foreach (CodecProfile i in options.Profile.CodecProfiles) { if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec)) - conditions.AddRange(i.Conditions); + { + foreach (var c in i.Conditions) + { + conditions.Add(c); + } + } } int? audioChannels = audioStream.Channels; @@ -195,7 +200,12 @@ namespace MediaBrowser.Model.Dlna List audioTranscodingConditions = new List(); foreach (CodecProfile i in audioCodecProfiles) - audioTranscodingConditions.AddRange(i.Conditions); + { + foreach (var c in i.Conditions) + { + audioTranscodingConditions.Add(c); + } + } ApplyTranscodingConditions(playlistItem, audioTranscodingConditions); @@ -276,7 +286,10 @@ namespace MediaBrowser.Model.Dlna { if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec)) { - videoTranscodingConditions.AddRange(i.Conditions); + foreach (var c in i.Conditions) + { + videoTranscodingConditions.Add(c); + } break; } } @@ -287,7 +300,10 @@ namespace MediaBrowser.Model.Dlna { if (i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec)) { - audioTranscodingConditions.AddRange(i.Conditions); + foreach (var c in i.Conditions) + { + audioTranscodingConditions.Add(c); + } break; } } @@ -363,7 +379,10 @@ namespace MediaBrowser.Model.Dlna if (i.Type == DlnaProfileType.Video && ListHelper.ContainsIgnoreCase(i.GetContainers(), container)) { - conditions.AddRange(i.Conditions); + foreach (var c in i.Conditions) + { + conditions.Add(c); + } } } @@ -405,7 +424,12 @@ namespace MediaBrowser.Model.Dlna foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec)) - conditions.AddRange(i.Conditions); + { + foreach (var c in i.Conditions) + { + conditions.Add(c); + } + } } foreach (ProfileCondition i in conditions) @@ -429,7 +453,12 @@ namespace MediaBrowser.Model.Dlna foreach (CodecProfile i in profile.CodecProfiles) { if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec)) - conditions.AddRange(i.Conditions); + { + foreach (var c in i.Conditions) + { + conditions.Add(c); + } + } } foreach (ProfileCondition i in conditions) diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 8d507ae377..b8c256b25c 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -305,8 +305,14 @@ namespace MediaBrowser.Model.Dlna { int? totalBitrate = TargetTotalBitrate; + double totalSeconds = RunTimeTicks.Value; + // Convert to ms + totalSeconds /= 10000; + // Convert to seconds + totalSeconds /= 1000; + return totalBitrate.HasValue ? - Convert.ToInt64(totalBitrate.Value * TimeSpan.FromTicks(RunTimeTicks.Value).TotalSeconds) : + Convert.ToInt64(totalBitrate.Value * totalSeconds) : (long?)null; } @@ -375,11 +381,14 @@ namespace MediaBrowser.Model.Dlna Height = videoStream.Height.Value }; + double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null; + double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null; + ImageSize newSize = DrawingUtils.Resize(size, null, null, - MaxWidth, - MaxHeight); + maxWidth, + maxHeight); return Convert.ToInt32(newSize.Width); } @@ -402,11 +411,14 @@ namespace MediaBrowser.Model.Dlna Height = videoStream.Height.Value }; + double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null; + double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null; + ImageSize newSize = DrawingUtils.Resize(size, null, null, - MaxWidth, - MaxHeight); + maxWidth, + maxHeight); return Convert.ToInt32(newSize.Height); } diff --git a/MediaBrowser.Model/Extensions/StringHelper.cs b/MediaBrowser.Model/Extensions/StringHelper.cs index 1c086655ff..2eae56cd4f 100644 --- a/MediaBrowser.Model/Extensions/StringHelper.cs +++ b/MediaBrowser.Model/Extensions/StringHelper.cs @@ -59,5 +59,16 @@ namespace MediaBrowser.Model.Extensions { return val.ToString(CultureInfo.InvariantCulture); } + + /// + /// Trims the start. + /// + /// The string. + /// The c. + /// System.String. + public static string TrimStart(string str, char c) + { + return str.TrimStart(c); + } } } diff --git a/MediaBrowser.Model/Notifications/Notification.cs b/MediaBrowser.Model/Notifications/Notification.cs index 731c3d3035..5439b838d6 100644 --- a/MediaBrowser.Model/Notifications/Notification.cs +++ b/MediaBrowser.Model/Notifications/Notification.cs @@ -19,10 +19,5 @@ namespace MediaBrowser.Model.Notifications public string Url { get; set; } public NotificationLevel Level { get; set; } - - public Notification() - { - Date = DateTime.UtcNow; - } } } diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs index a69f9e94bd..d9323573d4 100644 --- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs +++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs @@ -4,13 +4,13 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MoreLinq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MoreLinq; namespace MediaBrowser.Server.Implementations.Collections { @@ -27,6 +27,12 @@ namespace MediaBrowser.Server.Implementations.Collections _iLibraryMonitor = iLibraryMonitor; } + public Folder GetCollectionsFolder(string userId) + { + return _libraryManager.RootFolder.Children.Concat(_libraryManager.RootFolder.GetHiddenChildren()).OfType() + .FirstOrDefault(); + } + public async Task CreateCollection(CollectionCreationOptions options) { var name = options.Name; @@ -104,8 +110,7 @@ namespace MediaBrowser.Server.Implementations.Collections } } - return _libraryManager.RootFolder.Children.OfType().FirstOrDefault() ?? - _libraryManager.RootFolder.GetHiddenChildren().OfType().FirstOrDefault(); + return GetCollectionsFolder(string.Empty); } public async Task AddToCollection(Guid collectionId, IEnumerable ids) diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs index c58b9181ba..03479d838f 100644 --- a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs +++ b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs @@ -28,6 +28,11 @@ namespace MediaBrowser.Server.Implementations.Collections } } + public override bool IsHiddenFromUser(User user) + { + return true; + } + public override string CollectionType { get { return Model.Entities.CollectionType.BoxSets; } diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 9ac82690b7..24e4f0ef44 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -62,28 +62,29 @@ namespace MediaBrowser.Server.Implementations.Library if (recursiveChildren.OfType().Any()) { - list.Add(await GetUserView(CollectionType.TvShows, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(CollectionType.TvShows, user, string.Empty, cancellationToken).ConfigureAwait(false)); } if (recursiveChildren.OfType().Any() || recursiveChildren.OfType().Any()) { - list.Add(await GetUserView(CollectionType.Music, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(CollectionType.Music, user, string.Empty, cancellationToken).ConfigureAwait(false)); } if (recursiveChildren.OfType().Any()) { - list.Add(await GetUserView(CollectionType.Movies, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(CollectionType.Movies, user, string.Empty, cancellationToken).ConfigureAwait(false)); } if (recursiveChildren.OfType().Any()) { - list.Add(await GetUserView(CollectionType.Games, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(CollectionType.Games, user, string.Empty, cancellationToken).ConfigureAwait(false)); } - if (recursiveChildren.OfType().Any()) + if (user.Configuration.DisplayCollectionsView || + recursiveChildren.OfType().Any()) { - list.Add(await GetUserView(CollectionType.BoxSets, user, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(CollectionType.BoxSets, user, "zzz_" + CollectionType.BoxSets, cancellationToken).ConfigureAwait(false)); } if (query.IncludeExternalContent) @@ -116,11 +117,11 @@ namespace MediaBrowser.Server.Implementations.Library return list.OrderBy(i => i.SortName); } - private Task GetUserView(string type, User user, CancellationToken cancellationToken) + private Task GetUserView(string type, User user, string sortName, CancellationToken cancellationToken) { var name = _localizationManager.GetLocalizedString("ViewType" + type); - return _libraryManager.GetNamedView(name, type, string.Empty, cancellationToken); + return _libraryManager.GetNamedView(name, type, sortName, cancellationToken); } } } -- cgit v1.2.3 From 3bef6ead9cec4c33d43b6348ae4fc33c9b70316a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 1 Jul 2014 17:13:32 -0400 Subject: #514 - Support HLS seeking --- MediaBrowser.Api/BaseApiService.cs | 9 ++-- .../DefaultTheme/DefaultThemeService.cs | 2 +- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 63 ++++++++++++++++------ MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 42 +++------------ MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 13 ++++- MediaBrowser.Api/SearchService.cs | 4 +- MediaBrowser.Api/SimilarItemsHelper.cs | 4 +- MediaBrowser.Api/UserLibrary/UserLibraryService.cs | 3 +- MediaBrowser.Controller/Entities/Folder.cs | 27 +--------- MediaBrowser.Controller/Entities/UserView.cs | 12 +++-- MediaBrowser.Model/ApiClient/IApiClient.cs | 7 +++ .../Configuration/UserConfiguration.cs | 2 - MediaBrowser.Model/Dto/StudioDto.cs | 9 +++- .../Dto/DtoService.cs | 7 ++- .../Library/SearchEngine.cs | 2 +- .../Library/UserViewManager.cs | 5 +- 16 files changed, 110 insertions(+), 101 deletions(-) (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 569e125302..f1d5962139 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -159,7 +159,7 @@ namespace MediaBrowser.Api return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager)); } - protected IList GetAllLibraryItems(Guid? userId, IUserManager userManager, ILibraryManager libraryManager, string parentId = null) + protected IEnumerable GetAllLibraryItems(Guid? userId, IUserManager userManager, ILibraryManager libraryManager, string parentId = null) { if (!string.IsNullOrEmpty(parentId)) { @@ -169,7 +169,7 @@ namespace MediaBrowser.Api { var user = userManager.GetUserById(userId.Value); - return folder.GetRecursiveChildren(user).ToList(); + return folder.GetRecursiveChildren(user); } return folder.GetRecursiveChildren(); @@ -178,7 +178,7 @@ namespace MediaBrowser.Api { var user = userManager.GetUserById(userId.Value); - return userManager.GetUserById(userId.Value).RootFolder.GetRecursiveChildren(user, null); + return userManager.GetUserById(userId.Value).RootFolder.GetRecursiveChildren(user); } return libraryManager.RootFolder.GetRecursiveChildren(); @@ -239,7 +239,8 @@ namespace MediaBrowser.Api return name; } - return libraryManager.RootFolder.GetRecursiveChildren(i => i is Game) + return libraryManager.RootFolder.GetRecursiveChildren() + .OfType() .SelectMany(i => i.Genres) .Distinct(StringComparer.OrdinalIgnoreCase) .FirstOrDefault(i => diff --git a/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs b/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs index 6acecd342d..8bc867a2e7 100644 --- a/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs +++ b/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs @@ -381,7 +381,7 @@ namespace MediaBrowser.Api.DefaultTheme var currentUser1 = user; var ownedEpisodes = series - .SelectMany(i => i.GetRecursiveChildren(currentUser1, j => j.LocationType != LocationType.Virtual)) + .SelectMany(i => i.GetRecursiveChildren(currentUser1).Where(j => j.LocationType != LocationType.Virtual)) .OfType() .ToList(); diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 57c2244c7a..fa78fa0205 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -59,10 +59,11 @@ namespace MediaBrowser.Api.Playback.Hls /// Processes the request. /// /// The request. + /// if set to true [is live]. /// System.Object. - protected object ProcessRequest(StreamRequest request) + protected object ProcessRequest(StreamRequest request, bool isLive) { - return ProcessRequestAsync(request).Result; + return ProcessRequestAsync(request, isLive).Result; } private static readonly SemaphoreSlim FfmpegStartLock = new SemaphoreSlim(1, 1); @@ -70,13 +71,12 @@ namespace MediaBrowser.Api.Playback.Hls /// Processes the request async. /// /// The request. + /// if set to true [is live]. /// Task{System.Object}. - /// - /// A video bitrate is required + /// A video bitrate is required /// or - /// An audio bitrate is required - /// - private async Task ProcessRequestAsync(StreamRequest request) + /// An audio bitrate is required + private async Task ProcessRequestAsync(StreamRequest request, bool isLive) { var cancellationTokenSource = new CancellationTokenSource(); @@ -110,7 +110,8 @@ namespace MediaBrowser.Api.Playback.Hls throw; } - await WaitForMinimumSegmentCount(playlist, GetSegmentWait(), cancellationTokenSource.Token).ConfigureAwait(false); + var waitCount = isLive ? 1 : GetSegmentWait(); + await WaitForMinimumSegmentCount(playlist, waitCount, cancellationTokenSource.Token).ConfigureAwait(false); } } finally @@ -119,6 +120,22 @@ namespace MediaBrowser.Api.Playback.Hls } } + if (isLive) + { + //var file = request.PlaylistId + Path.GetExtension(Request.PathInfo); + + //file = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, file); + + try + { + return ResultFactory.GetStaticFileResult(Request, playlist, FileShare.ReadWrite); + } + finally + { + ApiEntryPoint.Instance.OnTranscodeEndRequest(playlist, TranscodingJobType.Hls); + } + } + var audioBitrate = state.OutputAudioBitrate ?? 0; var videoBitrate = state.OutputVideoBitrate ?? 0; @@ -188,16 +205,18 @@ namespace MediaBrowser.Api.Playback.Hls protected async Task WaitForMinimumSegmentCount(string playlist, int segmentCount, CancellationToken cancellationToken) { - var count = 0; + Logger.Debug("Waiting for {0} segments in {1}", segmentCount, playlist); - // Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written - using (var fileStream = FileSystem.GetFileStream(playlist, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) + while (true) { - using (var reader = new StreamReader(fileStream)) + // Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written + using (var fileStream = FileSystem.GetFileStream(playlist, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { - while (true) + using (var reader = new StreamReader(fileStream)) { - if (!reader.EndOfStream) + var count = 0; + + while (!reader.EndOfStream) { var line = await reader.ReadLineAsync().ConfigureAwait(false); @@ -206,11 +225,12 @@ namespace MediaBrowser.Api.Playback.Hls count++; if (count >= segmentCount) { + Logger.Debug("Finished waiting for {0} segments in {1}", segmentCount, playlist); return; } } } - await Task.Delay(25, cancellationToken).ConfigureAwait(false); + await Task.Delay(100, cancellationToken).ConfigureAwait(false); } } } @@ -229,7 +249,7 @@ namespace MediaBrowser.Api.Playback.Hls var itsOffsetMs = hlsVideoRequest == null ? 0 - : ((GetHlsVideoStream)state.VideoRequest).TimeStampOffsetMs; + : hlsVideoRequest.TimeStampOffsetMs; var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds.ToString(UsCulture)); @@ -240,7 +260,15 @@ namespace MediaBrowser.Api.Playback.Hls // If isEncoding is true we're actually starting ffmpeg var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0"; - var args = string.Format("{0} {1} -i {2} -map_metadata -1 -threads {3} {4} {5} -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"", + var baseUrlParam = string.Empty; + + if (state.Request is GetLiveHlsStream) + { + baseUrlParam = string.Format(" -hls_base_url \"{0}/\"", + "hls/" + Path.GetFileNameWithoutExtension(outputPath)); + } + + var args = string.Format("{0} {1} -i {2} -map_metadata -1 -threads {3} {4} {5} -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9}{10} -y \"{11}\"", itsOffset, inputModifier, GetInputArgument(state), @@ -251,6 +279,7 @@ namespace MediaBrowser.Api.Playback.Hls state.SegmentLength.ToString(UsCulture), startNumberParam, state.HlsListSize.ToString(UsCulture), + baseUrlParam, outputPath ).Trim(); diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index bde2c56943..5bb6106860 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -22,11 +22,6 @@ namespace MediaBrowser.Api.Playback.Hls [Api(Description = "Gets a video stream using HTTP live streaming.")] public class GetMasterHlsVideoStream : VideoStreamRequest { - [ApiMember(Name = "BaselineStreamAudioBitRate", Description = "Optional. Specify the audio bitrate for the baseline stream.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] - public int? BaselineStreamAudioBitRate { get; set; } - - [ApiMember(Name = "AppendBaselineStream", Description = "Optional. Whether or not to include a baseline audio-only stream in the master playlist.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] - public bool AppendBaselineStream { get; set; } } [Route("/Videos/{Id}/main.m3u8", "GET")] @@ -35,12 +30,6 @@ namespace MediaBrowser.Api.Playback.Hls { } - [Route("/Videos/{Id}/baseline.m3u8", "GET")] - [Api(Description = "Gets a video stream using HTTP live streaming.")] - public class GetBaselineHlsVideoStream : VideoStreamRequest - { - } - /// /// Class GetHlsVideoSegment /// @@ -73,16 +62,11 @@ namespace MediaBrowser.Api.Playback.Hls public object Get(GetDynamicHlsVideoSegment request) { - if (string.Equals("baseline", request.PlaylistId, StringComparison.OrdinalIgnoreCase)) - { - return GetDynamicSegment(request, false).Result; - } - - return GetDynamicSegment(request, true).Result; + return GetDynamicSegment(request).Result; } private static readonly SemaphoreSlim FfmpegStartLock = new SemaphoreSlim(1, 1); - private async Task GetDynamicSegment(GetDynamicHlsVideoSegment request, bool isMain) + private async Task GetDynamicSegment(GetDynamicHlsVideoSegment request) { if ((request.StartTimeTicks ?? 0) > 0) { @@ -322,7 +306,9 @@ namespace MediaBrowser.Api.Playback.Hls var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex); // Main stream - var playlistUrl = "main.m3u8" + queryString; + var playlistUrl = (state.RunTimeTicks ?? 0) > 0 ? "main.m3u8" : "live.m3u8"; + playlistUrl += queryString; + AppendPlaylist(builder, playlistUrl, totalBitrate); if (state.VideoRequest.VideoBitRate.HasValue) @@ -385,13 +371,6 @@ namespace MediaBrowser.Api.Playback.Hls return result; } - public object Get(GetBaselineHlsVideoStream request) - { - var result = GetPlaylistAsync(request, "baseline").Result; - - return result; - } - private async Task GetPlaylistAsync(VideoStreamRequest request, string name) { var state = await GetState(request, CancellationToken.None).ConfigureAwait(false); @@ -506,14 +485,6 @@ namespace MediaBrowser.Api.Playback.Hls /// System.String. protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding) { - var hlsVideoRequest = state.VideoRequest as GetHlsVideoStream; - - var itsOffsetMs = hlsVideoRequest == null - ? 0 - : ((GetHlsVideoStream)state.VideoRequest).TimeStampOffsetMs; - - var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds.ToString(UsCulture)); - var threads = GetNumberOfThreads(state, false); var inputModifier = GetInputModifier(state); @@ -521,8 +492,7 @@ namespace MediaBrowser.Api.Playback.Hls // If isEncoding is true we're actually starting ffmpeg var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0"; - var args = string.Format("{0} {1} -i {2} -map_metadata -1 -threads {3} {4} {5} -flags -global_header {6} -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"", - itsOffset, + var args = string.Format("{0} -i {1} -map_metadata -1 -threads {2} {3} {4} -flags -global_header {5} -hls_time {6} -start_number {7} -hls_list_size {8} -y \"{9}\"", inputModifier, GetInputArgument(state), threads, diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 1a925378bb..28c0219fce 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -32,6 +32,12 @@ namespace MediaBrowser.Api.Playback.Hls public int TimeStampOffsetMs { get; set; } } + [Route("/Videos/{Id}/live.m3u8", "GET")] + [Api(Description = "Gets a video stream using HTTP live streaming.")] + public class GetLiveHlsStream : VideoStreamRequest + { + } + /// /// Class GetHlsVideoSegment /// @@ -105,7 +111,12 @@ namespace MediaBrowser.Api.Playback.Hls /// System.Object. public object Get(GetHlsVideoStream request) { - return ProcessRequest(request); + return ProcessRequest(request, false); + } + + public object Get(GetLiveHlsStream request) + { + return ProcessRequest(request, true); } /// diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs index 9fcbe39eba..e72edcc982 100644 --- a/MediaBrowser.Api/SearchService.cs +++ b/MediaBrowser.Api/SearchService.cs @@ -192,14 +192,14 @@ namespace MediaBrowser.Api { result.Series = season.Series.Name; - result.EpisodeCount = season.GetRecursiveChildren(i => i is Episode).Count; + result.EpisodeCount = season.GetRecursiveChildren().Count(i => i is Episode); } var series = item as Series; if (series != null) { - result.EpisodeCount = series.GetRecursiveChildren(i => i is Episode).Count; + result.EpisodeCount = series.GetRecursiveChildren().Count(i => i is Episode); } var album = item as MusicAlbum; diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index 660b55f309..2da29928b2 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -78,8 +78,8 @@ namespace MediaBrowser.Api var fields = request.GetItemFields().ToList(); var inputItems = user == null - ? libraryManager.RootFolder.GetRecursiveChildren(i => i.Id != item.Id) - : user.RootFolder.GetRecursiveChildren(user, i => i.Id != item.Id); + ? libraryManager.RootFolder.GetRecursiveChildren().Where(i => i.Id != item.Id) + : user.RootFolder.GetRecursiveChildren(user).Where(i => i.Id != item.Id); var items = GetSimilaritems(item, inputItems.Where(includeInSearch), getSimilarityScore) .ToList(); diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index 96bbd6dffb..a1625d0520 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -541,7 +541,8 @@ namespace MediaBrowser.Api.UserLibrary if (series != null) { var dtos = series - .GetRecursiveChildren(i => i is Episode && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0) + .GetRecursiveChildren() + .Where(i => i is Episode && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0) .OrderBy(i => { if (i.PremiereDate.HasValue) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index c712d50afa..52c414ae8e 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -856,19 +856,6 @@ namespace MediaBrowser.Controller.Entities /// IEnumerable{BaseItem}. /// public IEnumerable GetRecursiveChildren(User user, bool includeLinkedChildren = true) - { - return GetRecursiveChildren(user, null, includeLinkedChildren); - } - - /// - /// Gets the recursive children. - /// - /// The user. - /// The filter. - /// if set to true [include linked children]. - /// IList{BaseItem}. - /// - public IList GetRecursiveChildren(User user, Func filter, bool includeLinkedChildren = true) { if (user == null) { @@ -877,7 +864,7 @@ namespace MediaBrowser.Controller.Entities var list = new List(); - var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true, filter); + var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true, null); return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list; } @@ -887,20 +874,10 @@ namespace MediaBrowser.Controller.Entities /// /// IList{BaseItem}. public IList GetRecursiveChildren() - { - return GetRecursiveChildren(i => true); - } - - /// - /// Gets the recursive children. - /// - /// The filter. - /// IEnumerable{BaseItem}. - public IList GetRecursiveChildren(Func filter) { var list = new List(); - AddChildrenToList(list, true, filter); + AddChildrenToList(list, true, null); return list; } diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index ce188554cd..86099fdc01 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -18,11 +18,17 @@ namespace MediaBrowser.Controller.Entities switch (ViewType) { case CollectionType.Games: - return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)).OfType(); + return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)) + .OfType(); case CollectionType.BoxSets: - return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)).OfType(); + return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)) + .OfType(); case CollectionType.TvShows: - return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)).OfType(); + return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)) + .OfType(); + case CollectionType.Trailers: + return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)) + .OfType(); default: return mediaFolders.SelectMany(i => i.GetChildren(user, includeLinkedChildren)); } diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 4f008571ce..33c6f980ce 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -217,6 +217,7 @@ namespace MediaBrowser.Model.ApiClient /// Gets the additional parts. /// /// The item identifier. + /// The user identifier. /// Task{BaseItemDto[]}. Task GetAdditionalParts(string itemId, string userId); @@ -241,6 +242,12 @@ namespace MediaBrowser.Model.ApiClient /// Task{SessionInfoDto[]}. Task GetClientSessionsAsync(SessionQuery query); + /// + /// Gets the client session asynchronous. + /// + /// Task{SessionInfoDto}. + Task GetCurrentSessionAsync(); + /// /// Gets the item counts async. /// diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 24a41863e9..0834452fbc 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -93,8 +93,6 @@ namespace MediaBrowser.Model.Configuration BlockUnratedItems = new UnratedItem[] { }; ExcludeFoldersFromGrouping = new string[] { }; - - DisplayCollectionsView = true; } } } diff --git a/MediaBrowser.Model/Dto/StudioDto.cs b/MediaBrowser.Model/Dto/StudioDto.cs index 4f21784fda..a0027cc4e2 100644 --- a/MediaBrowser.Model/Dto/StudioDto.cs +++ b/MediaBrowser.Model/Dto/StudioDto.cs @@ -1,5 +1,4 @@ -using System; -using System.ComponentModel; +using System.ComponentModel; using System.Diagnostics; using System.Runtime.Serialization; @@ -17,6 +16,12 @@ namespace MediaBrowser.Model.Dto /// The name. public string Name { get; set; } + /// + /// Gets or sets the identifier. + /// + /// The identifier. + public string Id { get; set; } + /// /// Gets or sets the primary image tag. /// diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 7f63dac332..73216ca33c 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -328,7 +328,8 @@ namespace MediaBrowser.Server.Implementations.Dto if (!string.IsNullOrEmpty(item.Album)) { var parentAlbum = _libraryManager.RootFolder - .GetRecursiveChildren(i => i is MusicAlbum) + .GetRecursiveChildren() + .Where(i => i is MusicAlbum) .FirstOrDefault(i => string.Equals(i.Name, item.Album, StringComparison.OrdinalIgnoreCase)); if (parentAlbum != null) @@ -539,6 +540,7 @@ namespace MediaBrowser.Server.Implementations.Dto if (dictionary.TryGetValue(studio, out entity)) { + studioDto.Id = entity.Id.ToString("N"); studioDto.PrimaryImageTag = GetImageCacheTag(entity, ImageType.Primary); } @@ -1248,7 +1250,8 @@ namespace MediaBrowser.Server.Implementations.Dto } else { - children = folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual); + children = folder.GetRecursiveChildren(user) + .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual); } // Loop through each recursive child diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 4c65fad682..6faa72b818 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -41,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Library { var user = _userManager.GetUserById(new Guid(query.UserId)); - inputItems = user.RootFolder.GetRecursiveChildren(user, null); + inputItems = user.RootFolder.GetRecursiveChildren(user, true); } diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 24e4f0ef44..dd2978b17b 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Querying; namespace MediaBrowser.Server.Implementations.Library { @@ -84,7 +85,7 @@ namespace MediaBrowser.Server.Implementations.Library if (user.Configuration.DisplayCollectionsView || recursiveChildren.OfType().Any()) { - list.Add(await GetUserView(CollectionType.BoxSets, user, "zzz_" + CollectionType.BoxSets, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(CollectionType.BoxSets, user, CollectionType.BoxSets, cancellationToken).ConfigureAwait(false)); } if (query.IncludeExternalContent) @@ -114,7 +115,7 @@ namespace MediaBrowser.Server.Implementations.Library } } - return list.OrderBy(i => i.SortName); + return _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).Cast(); } private Task GetUserView(string type, User user, string sortName, CancellationToken cancellationToken) -- cgit v1.2.3 From 59dc591f66c20b6417aa2baa9503a154585386f9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 2 Jul 2014 14:34:08 -0400 Subject: update to jquery mobile 1.4.3 --- MediaBrowser.Api/ApiEntryPoint.cs | 60 ++- .../DefaultTheme/DefaultThemeService.cs | 2 + MediaBrowser.Api/Dlna/DlnaService.cs | 2 + MediaBrowser.Api/ItemLookupService.cs | 2 + MediaBrowser.Api/ItemRefreshService.cs | 2 + MediaBrowser.Api/ItemUpdateService.cs | 6 +- MediaBrowser.Api/Library/ChapterService.cs | 2 + .../Library/FileOrganizationService.cs | 2 + .../Library/LibraryStructureService.cs | 28 +- MediaBrowser.Api/Library/SubtitleService.cs | 2 + MediaBrowser.Api/LiveTv/LiveTvService.cs | 2 + MediaBrowser.Api/LocalizationService.cs | 2 + MediaBrowser.Api/Movies/CollectionService.cs | 2 + MediaBrowser.Api/Movies/MoviesService.cs | 2 + MediaBrowser.Api/Movies/TrailersService.cs | 2 + MediaBrowser.Api/Music/AlbumsService.cs | 3 +- MediaBrowser.Api/Music/InstantMixService.cs | 2 + MediaBrowser.Api/PackageReviewService.cs | 2 + MediaBrowser.Api/PackageService.cs | 2 + MediaBrowser.Api/Playback/BaseStreamingService.cs | 7 - MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 12 +- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 10 +- MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs | 4 +- MediaBrowser.Api/PluginService.cs | 2 + .../ScheduledTasks/ScheduledTaskService.cs | 2 + MediaBrowser.Api/SearchService.cs | 2 + MediaBrowser.Api/TvShowsService.cs | 2 + MediaBrowser.Api/UserLibrary/ArtistsService.cs | 2 + MediaBrowser.Api/UserLibrary/GameGenresService.cs | 2 + MediaBrowser.Api/UserLibrary/GenresService.cs | 2 + MediaBrowser.Api/UserLibrary/ItemsService.cs | 2 + MediaBrowser.Api/UserLibrary/MusicGenresService.cs | 2 + MediaBrowser.Api/UserLibrary/PersonsService.cs | 2 + MediaBrowser.Api/UserLibrary/StudiosService.cs | 2 + MediaBrowser.Api/UserLibrary/UserLibraryService.cs | 2 + MediaBrowser.Api/UserLibrary/YearsService.cs | 2 + MediaBrowser.Api/UserService.cs | 63 +--- MediaBrowser.Api/VideosService.cs | 2 + MediaBrowser.Controller/Library/IUserManager.cs | 4 +- MediaBrowser.Controller/Net/AuthorizationInfo.cs | 5 + MediaBrowser.Controller/Session/ISessionManager.cs | 13 +- .../MediaBrowser.Model.Portable.csproj | 24 +- .../MediaBrowser.Model.net35.csproj | 24 +- .../Configuration/NotificationOption.cs | 54 --- .../Configuration/NotificationOptions.cs | 124 ------- .../Configuration/NotificationType.cs | 23 -- MediaBrowser.Model/Configuration/SendToUserType.cs | 9 - .../Configuration/ServerConfiguration.cs | 8 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 8 +- .../Notifications/NotificationOption.cs | 56 +++ .../Notifications/NotificationOptions.cs | 125 +++++++ .../Notifications/NotificationType.cs | 23 ++ MediaBrowser.Model/Notifications/SendToUserType.cs | 9 + MediaBrowser.Model/Updates/PackageVersionInfo.cs | 32 +- MediaBrowser.Model/Users/AuthenticationResult.cs | 6 + .../HttpServer/Security/AuthService.cs | 25 +- .../HttpServer/Security/AuthorizationContext.cs | 3 +- .../Library/UserManager.cs | 11 +- .../LiveTv/LiveTvManager.cs | 125 ++++--- .../Localization/JavaScript/javascript.json | 18 +- .../MediaBrowser.Server.Implementations.csproj | 1 + .../NotificationConfigurationFactory.cs | 21 ++ .../Notifications/NotificationManager.cs | 16 +- .../Session/SessionManager.cs | 31 +- MediaBrowser.ServerApplication/ApplicationHost.cs | 7 + MediaBrowser.WebDashboard/Api/DashboardService.cs | 4 +- .../MediaBrowser.WebDashboard.csproj | 409 +++++++++++---------- 67 files changed, 828 insertions(+), 641 deletions(-) delete mode 100644 MediaBrowser.Model/Configuration/NotificationOption.cs delete mode 100644 MediaBrowser.Model/Configuration/NotificationOptions.cs delete mode 100644 MediaBrowser.Model/Configuration/NotificationType.cs delete mode 100644 MediaBrowser.Model/Configuration/SendToUserType.cs create mode 100644 MediaBrowser.Model/Notifications/NotificationOption.cs create mode 100644 MediaBrowser.Model/Notifications/NotificationOptions.cs create mode 100644 MediaBrowser.Model/Notifications/NotificationType.cs create mode 100644 MediaBrowser.Model/Notifications/SendToUserType.cs create mode 100644 MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 2177f90c2f..8e6ca44014 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -37,6 +37,8 @@ namespace MediaBrowser.Api private readonly ISessionManager _sessionManager; + public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1,1); + /// /// Initializes a new instance of the class. /// @@ -301,8 +303,9 @@ namespace MediaBrowser.Api /// /// The device id. /// The delete mode. + /// if set to true [acquire lock]. /// sourcePath - internal void KillTranscodingJobs(string deviceId, FileDeleteMode deleteMode) + internal async Task KillTranscodingJobs(string deviceId, FileDeleteMode deleteMode, bool acquireLock) { if (string.IsNullOrEmpty(deviceId)) { @@ -318,9 +321,29 @@ namespace MediaBrowser.Api jobs.AddRange(_activeTranscodingJobs.Where(i => string.Equals(deviceId, i.DeviceId, StringComparison.OrdinalIgnoreCase))); } - foreach (var job in jobs) + if (jobs.Count == 0) + { + return; + } + + if (acquireLock) { - KillTranscodingJob(job, deleteMode); + await TranscodingStartLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); + } + + try + { + foreach (var job in jobs) + { + KillTranscodingJob(job, deleteMode); + } + } + finally + { + if (acquireLock) + { + TranscodingStartLock.Release(); + } } } @@ -328,10 +351,11 @@ namespace MediaBrowser.Api /// Kills the transcoding jobs. /// /// The device identifier. - /// The output path. + /// The type. /// The delete mode. + /// if set to true [acquire lock]. /// deviceId - internal void KillTranscodingJobs(string deviceId, string outputPath, FileDeleteMode deleteMode) + internal async Task KillTranscodingJobs(string deviceId, TranscodingJobType type, FileDeleteMode deleteMode, bool acquireLock) { if (string.IsNullOrEmpty(deviceId)) { @@ -344,12 +368,32 @@ namespace MediaBrowser.Api { // This is really only needed for HLS. // Progressive streams can stop on their own reliably - jobs.AddRange(_activeTranscodingJobs.Where(i => string.Equals(deviceId, i.DeviceId, StringComparison.OrdinalIgnoreCase) && string.Equals(outputPath, i.Path, StringComparison.OrdinalIgnoreCase))); + jobs.AddRange(_activeTranscodingJobs.Where(i => string.Equals(deviceId, i.DeviceId, StringComparison.OrdinalIgnoreCase) && i.Type == type)); } - foreach (var job in jobs) + if (jobs.Count == 0) { - KillTranscodingJob(job, deleteMode); + return; + } + + if (acquireLock) + { + await TranscodingStartLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); + } + + try + { + foreach (var job in jobs) + { + KillTranscodingJob(job, deleteMode); + } + } + finally + { + if (acquireLock) + { + TranscodingStartLock.Release(); + } } } diff --git a/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs b/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs index 8bc867a2e7..21ba47bd4d 100644 --- a/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs +++ b/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; @@ -86,6 +87,7 @@ namespace MediaBrowser.Api.DefaultTheme public Guid UserId { get; set; } } + [Authenticated] public class DefaultThemeService : BaseApiService { private readonly IUserManager _userManager; diff --git a/MediaBrowser.Api/Dlna/DlnaService.cs b/MediaBrowser.Api/Dlna/DlnaService.cs index 9e6ca3aea9..fec6d698ae 100644 --- a/MediaBrowser.Api/Dlna/DlnaService.cs +++ b/MediaBrowser.Api/Dlna/DlnaService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Dlna; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using ServiceStack; using System.Collections.Generic; @@ -42,6 +43,7 @@ namespace MediaBrowser.Api.Dlna { } + [Authenticated] public class DlnaService : BaseApiService { private readonly IDlnaManager _dlnaManager; diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index e68aa73f6a..35b1b53851 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; @@ -104,6 +105,7 @@ namespace MediaBrowser.Api public string Id { get; set; } } + [Authenticated] public class ItemLookupService : BaseApiService { private readonly IProviderManager _providerManager; diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index 0094282c8a..b95e18a0d9 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using ServiceStack; using System; @@ -30,6 +31,7 @@ namespace MediaBrowser.Api public string Id { get; set; } } + [Authenticated] public class ItemRefreshService : BaseApiService { private readonly ILibraryManager _libraryManager; diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index ad7da8e3c5..db6c6ce53e 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -1,11 +1,12 @@ -using System.Collections.Generic; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dto; using ServiceStack; using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -19,6 +20,7 @@ namespace MediaBrowser.Api public string ItemId { get; set; } } + [Authenticated] public class ItemUpdateService : BaseApiService { private readonly ILibraryManager _libraryManager; diff --git a/MediaBrowser.Api/Library/ChapterService.cs b/MediaBrowser.Api/Library/ChapterService.cs index 72ffa3fca6..6b8dd18f10 100644 --- a/MediaBrowser.Api/Library/ChapterService.cs +++ b/MediaBrowser.Api/Library/ChapterService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Chapters; +using MediaBrowser.Controller.Net; using ServiceStack; using System.Linq; @@ -9,6 +10,7 @@ namespace MediaBrowser.Api.Library { } + [Authenticated] public class ChapterService : BaseApiService { private readonly IChapterManager _chapterManager; diff --git a/MediaBrowser.Api/Library/FileOrganizationService.cs b/MediaBrowser.Api/Library/FileOrganizationService.cs index 01531a7ae6..adf6a522b3 100644 --- a/MediaBrowser.Api/Library/FileOrganizationService.cs +++ b/MediaBrowser.Api/Library/FileOrganizationService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.FileOrganization; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.Querying; using ServiceStack; @@ -78,6 +79,7 @@ namespace MediaBrowser.Api.Library public bool RememberCorrection { get; set; } } + [Authenticated] public class FileOrganizationService : BaseApiService { private readonly IFileOrganizationService _iFileOrganizationService; diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index 947da29fea..c3ef587685 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using ServiceStack; @@ -130,36 +131,11 @@ namespace MediaBrowser.Api.Library /// true if [refresh library]; otherwise, false. public bool RefreshLibrary { get; set; } } - - [Route("/Library/Downloaded", "POST")] - public class ReportContentDownloaded : IReturnVoid - { - [ApiMember(Name = "Path", Description = "The path being downloaded to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Path { get; set; } - - [ApiMember(Name = "ImageUrl", Description = "Optional thumbnail image url of the content.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string ImageUrl { get; set; } - - [ApiMember(Name = "Name", Description = "The name of the content.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Name { get; set; } - } - - [Route("/Library/Downloading", "POST")] - public class ReportContentDownloading : IReturnVoid - { - [ApiMember(Name = "Path", Description = "The path being downloaded to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Path { get; set; } - - [ApiMember(Name = "ImageUrl", Description = "Optional thumbnail image url of the content.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string ImageUrl { get; set; } - - [ApiMember(Name = "Name", Description = "The name of the content.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Name { get; set; } - } /// /// Class LibraryStructureService /// + [Authenticated] public class LibraryStructureService : BaseApiService { /// diff --git a/MediaBrowser.Api/Library/SubtitleService.cs b/MediaBrowser.Api/Library/SubtitleService.cs index 62c7ac7c0a..4fc3e00c08 100644 --- a/MediaBrowser.Api/Library/SubtitleService.cs +++ b/MediaBrowser.Api/Library/SubtitleService.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Subtitles; using MediaBrowser.Model.Entities; @@ -86,6 +87,7 @@ namespace MediaBrowser.Api.Library public string Id { get; set; } } + [Authenticated] public class SubtitleService : BaseApiService { private readonly ILibraryManager _libraryManager; diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index de01628f84..497f2d0a35 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -1,5 +1,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; @@ -267,6 +268,7 @@ namespace MediaBrowser.Api.LiveTv public string UserId { get; set; } } + [Authenticated] public class LiveTvService : BaseApiService { private readonly ILiveTvManager _liveTvManager; diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs index d3c47dfa1e..5696d8df75 100644 --- a/MediaBrowser.Api/LocalizationService.cs +++ b/MediaBrowser.Api/LocalizationService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Localization; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using ServiceStack; @@ -42,6 +43,7 @@ namespace MediaBrowser.Api /// /// Class CulturesService /// + [Authenticated] public class LocalizationService : BaseApiService { /// diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs index b9e3888fda..19e47eb857 100644 --- a/MediaBrowser.Api/Movies/CollectionService.cs +++ b/MediaBrowser.Api/Movies/CollectionService.cs @@ -1,5 +1,6 @@ using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Querying; using ServiceStack; using System; @@ -45,6 +46,7 @@ namespace MediaBrowser.Api.Movies public Guid Id { get; set; } } + [Authenticated] public class CollectionService : BaseApiService { private readonly ICollectionManager _collectionManager; diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index db02ed4280..f0bf22c5e1 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -64,6 +65,7 @@ namespace MediaBrowser.Api.Movies /// /// Class MoviesService /// + [Authenticated] public class MoviesService : BaseApiService { /// diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs index 05e6a95774..b0ee6b6d57 100644 --- a/MediaBrowser.Api/Movies/TrailersService.cs +++ b/MediaBrowser.Api/Movies/TrailersService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using ServiceStack; @@ -18,6 +19,7 @@ namespace MediaBrowser.Api.Movies /// /// Class TrailersService /// + [Authenticated] public class TrailersService : BaseApiService { /// diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs index 0732c951a8..34a933dee3 100644 --- a/MediaBrowser.Api/Music/AlbumsService.cs +++ b/MediaBrowser.Api/Music/AlbumsService.cs @@ -2,10 +2,10 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using ServiceStack; using System; -using System.Collections.Generic; using System.Linq; namespace MediaBrowser.Api.Music @@ -15,6 +15,7 @@ namespace MediaBrowser.Api.Music { } + [Authenticated] public class AlbumsService : BaseApiService { /// diff --git a/MediaBrowser.Api/Music/InstantMixService.cs b/MediaBrowser.Api/Music/InstantMixService.cs index f50c87f47a..ff029d5b52 100644 --- a/MediaBrowser.Api/Music/InstantMixService.cs +++ b/MediaBrowser.Api/Music/InstantMixService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Querying; using ServiceStack; using System.Collections.Generic; @@ -33,6 +34,7 @@ namespace MediaBrowser.Api.Music public string Name { get; set; } } + [Authenticated] public class InstantMixService : BaseApiService { private readonly IUserManager _userManager; diff --git a/MediaBrowser.Api/PackageReviewService.cs b/MediaBrowser.Api/PackageReviewService.cs index 94ff1b62e2..112a2c5cea 100644 --- a/MediaBrowser.Api/PackageReviewService.cs +++ b/MediaBrowser.Api/PackageReviewService.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Constants; using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Serialization; using ServiceStack; @@ -96,6 +97,7 @@ namespace MediaBrowser.Api } + [Authenticated] public class PackageReviewService : BaseApiService { private readonly IHttpClient _httpClient; diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs index b54b05fcf7..84b42baa38 100644 --- a/MediaBrowser.Api/PackageService.cs +++ b/MediaBrowser.Api/PackageService.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Updates; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Updates; using ServiceStack; using System; @@ -121,6 +122,7 @@ namespace MediaBrowser.Api /// /// Class PackageService /// + [Authenticated] public class PackageService : BaseApiService { private readonly IInstallationManager _installationManager; diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 9ff482a1ab..75e13f92c2 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -13,7 +13,6 @@ using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Library; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.MediaInfo; using System; @@ -1955,12 +1954,6 @@ namespace MediaBrowser.Api.Playback /// The video request. private void EnforceResolutionLimit(StreamState state, VideoStreamRequest videoRequest) { - // If enabled, allow whatever the client asks for - if (ServerConfigurationManager.Configuration.AllowVideoUpscaling) - { - return; - } - // Switch the incoming params to be ceilings rather than fixed values videoRequest.MaxWidth = videoRequest.MaxWidth ?? videoRequest.Width; videoRequest.MaxHeight = videoRequest.MaxHeight ?? videoRequest.Height; diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index fa78fa0205..8a65e2b565 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -66,7 +66,6 @@ namespace MediaBrowser.Api.Playback.Hls return ProcessRequestAsync(request, isLive).Result; } - private static readonly SemaphoreSlim FfmpegStartLock = new SemaphoreSlim(1, 1); /// /// Processes the request async. /// @@ -82,6 +81,11 @@ namespace MediaBrowser.Api.Playback.Hls var state = await GetState(request, cancellationTokenSource.Token).ConfigureAwait(false); + if (isLive) + { + state.Request.StartTimeTicks = null; + } + var playlist = state.OutputFilePath; if (File.Exists(playlist)) @@ -90,7 +94,7 @@ namespace MediaBrowser.Api.Playback.Hls } else { - await FfmpegStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); + await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { if (File.Exists(playlist)) @@ -99,6 +103,8 @@ namespace MediaBrowser.Api.Playback.Hls } else { + await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, FileDeleteMode.All, false).ConfigureAwait(false); + // If the playlist doesn't already exist, startup ffmpeg try { @@ -116,7 +122,7 @@ namespace MediaBrowser.Api.Playback.Hls } finally { - FfmpegStartLock.Release(); + ApiEntryPoint.Instance.TranscodingStartLock.Release(); } } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 5bb6106860..0af336c55b 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -65,7 +65,6 @@ namespace MediaBrowser.Api.Playback.Hls return GetDynamicSegment(request).Result; } - private static readonly SemaphoreSlim FfmpegStartLock = new SemaphoreSlim(1, 1); private async Task GetDynamicSegment(GetDynamicHlsVideoSegment request) { if ((request.StartTimeTicks ?? 0) > 0) @@ -90,7 +89,7 @@ namespace MediaBrowser.Api.Playback.Hls return await GetSegmentResult(playlistPath, segmentPath, index, cancellationToken).ConfigureAwait(false); } - await FfmpegStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); + await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { if (File.Exists(segmentPath)) @@ -107,10 +106,11 @@ namespace MediaBrowser.Api.Playback.Hls // If the playlist doesn't already exist, startup ffmpeg try { + // TODO: Delete files from other jobs, but not this one + await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, FileDeleteMode.None, false).ConfigureAwait(false); + if (currentTranscodingIndex.HasValue) { - ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, playlistPath, FileDeleteMode.None); - DeleteLastFile(playlistPath, 0); } @@ -131,7 +131,7 @@ namespace MediaBrowser.Api.Playback.Hls } finally { - FfmpegStartLock.Release(); + ApiEntryPoint.Instance.TranscodingStartLock.Release(); } Logger.Info("waiting for {0}", segmentPath); diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index f31671b1a1..3848cb2de0 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -74,7 +74,9 @@ namespace MediaBrowser.Api.Playback.Hls public void Delete(StopEncodingProcess request) { - ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, FileDeleteMode.All); + var task = ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, FileDeleteMode.All, true); + + Task.WaitAll(task); } /// diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index 31463dc3f4..29cc7baf89 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Security; using MediaBrowser.Common.Updates; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; @@ -100,6 +101,7 @@ namespace MediaBrowser.Api /// /// Class PluginsService /// + [Authenticated] public class PluginService : BaseApiService { /// diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs index aaf14ce715..483133c102 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Tasks; using ServiceStack; using ServiceStack.Text.Controller; @@ -78,6 +79,7 @@ namespace MediaBrowser.Api.ScheduledTasks /// /// Class ScheduledTasksService /// + [Authenticated] public class ScheduledTaskService : BaseApiService { /// diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs index e72edcc982..a6fcaf4381 100644 --- a/MediaBrowser.Api/SearchService.cs +++ b/MediaBrowser.Api/SearchService.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Search; using ServiceStack; @@ -79,6 +80,7 @@ namespace MediaBrowser.Api /// /// Class SearchService /// + [Authenticated] public class SearchService : BaseApiService { /// diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 6776cbf172..c32e672160 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; @@ -175,6 +176,7 @@ namespace MediaBrowser.Api /// /// Class TvShowsService /// + [Authenticated] public class TvShowsService : BaseApiService { /// diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs index 13027d30b5..07015ecae2 100644 --- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs +++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; @@ -46,6 +47,7 @@ namespace MediaBrowser.Api.UserLibrary /// /// Class ArtistsService /// + [Authenticated] public class ArtistsService : BaseItemsByNameService { /// diff --git a/MediaBrowser.Api/UserLibrary/GameGenresService.cs b/MediaBrowser.Api/UserLibrary/GameGenresService.cs index b1379ad5d6..49e979e551 100644 --- a/MediaBrowser.Api/UserLibrary/GameGenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GameGenresService.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -41,6 +42,7 @@ namespace MediaBrowser.Api.UserLibrary public Guid? UserId { get; set; } } + [Authenticated] public class GameGenresService : BaseItemsByNameService { public GameGenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService) diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs index 68f0e21edc..c8c45c1bb3 100644 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GenresService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; @@ -46,6 +47,7 @@ namespace MediaBrowser.Api.UserLibrary /// /// Class GenresService /// + [Authenticated] public class GenresService : BaseItemsByNameService { public GenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService) diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index c926c16ff2..ba07571bf2 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; @@ -246,6 +247,7 @@ namespace MediaBrowser.Api.UserLibrary /// /// Class ItemsService /// + [Authenticated] public class ItemsService : BaseApiService { /// diff --git a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs index 538b165751..f50f0a0bd4 100644 --- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs +++ b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; @@ -41,6 +42,7 @@ namespace MediaBrowser.Api.UserLibrary public Guid? UserId { get; set; } } + [Authenticated] public class MusicGenresService : BaseItemsByNameService { public MusicGenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService) diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs index 962effdeda..cf9959e535 100644 --- a/MediaBrowser.Api/UserLibrary/PersonsService.cs +++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; @@ -51,6 +52,7 @@ namespace MediaBrowser.Api.UserLibrary /// /// Class PersonsService /// + [Authenticated] public class PersonsService : BaseItemsByNameService { /// diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs index 4c38ba0d1f..2024d779b7 100644 --- a/MediaBrowser.Api/UserLibrary/StudiosService.cs +++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; @@ -43,6 +44,7 @@ namespace MediaBrowser.Api.UserLibrary /// /// Class StudiosService /// + [Authenticated] public class StudiosService : BaseItemsByNameService { public StudiosService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService) diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index da12a9e3d2..d1767e7fd9 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -424,6 +425,7 @@ namespace MediaBrowser.Api.UserLibrary /// /// Class UserLibraryService /// + [Authenticated] public class UserLibraryService : BaseApiService { /// diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs index 4dda045c06..2b300f9003 100644 --- a/MediaBrowser.Api/UserLibrary/YearsService.cs +++ b/MediaBrowser.Api/UserLibrary/YearsService.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; @@ -43,6 +44,7 @@ namespace MediaBrowser.Api.UserLibrary /// /// Class YearsService /// + [Authenticated] public class YearsService : BaseItemsByNameService { public YearsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService) diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 764a281024..64d1fcb34c 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -268,28 +268,6 @@ namespace MediaBrowser.Api /// /// The request. public object Post(AuthenticateUser request) - { - // No response needed. Will throw an exception on failure. - var result = AuthenticateUser(request).Result; - - return result; - } - - public object Post(AuthenticateUserByName request) - { - var user = _userManager.Users.FirstOrDefault(i => string.Equals(request.Username, i.Name, StringComparison.OrdinalIgnoreCase)); - - if (user == null) - { - throw new ArgumentException(string.Format("User {0} not found.", request.Username)); - } - - var result = AuthenticateUser(new AuthenticateUser { Id = user.Id, Password = request.Password }).Result; - - return ToOptimizedResult(result); - } - - private async Task AuthenticateUser(AuthenticateUser request) { var user = _userManager.GetUserById(request.Id); @@ -298,38 +276,21 @@ namespace MediaBrowser.Api throw new ResourceNotFoundException("User not found"); } - var auth = AuthorizationContext.GetAuthorizationInfo(Request); - - // Login in the old way if the header is missing - if (string.IsNullOrEmpty(auth.Client) || - string.IsNullOrEmpty(auth.Device) || - string.IsNullOrEmpty(auth.DeviceId) || - string.IsNullOrEmpty(auth.Version)) + return Post(new AuthenticateUserByName { - var success = await _userManager.AuthenticateUser(user, request.Password).ConfigureAwait(false); - - if (!success) - { - // Unauthorized - throw new UnauthorizedAccessException("Invalid user or password entered."); - } - - return new AuthenticationResult - { - User = _dtoService.GetUserDto(user) - }; - } + Username = user.Name, + Password = request.Password + }); + } - var session = await _sessionMananger.AuthenticateNewSession(user, request.Password, auth.Client, auth.Version, - auth.DeviceId, auth.Device, Request.RemoteIp).ConfigureAwait(false); + public object Post(AuthenticateUserByName request) + { + var auth = AuthorizationContext.GetAuthorizationInfo(Request); - var result = new AuthenticationResult - { - User = _dtoService.GetUserDto(user), - SessionInfo = _sessionMananger.GetSessionInfoDto(session) - }; + var result = _sessionMananger.AuthenticateNewSession(request.Username, request.Password, auth.Client, auth.Version, + auth.DeviceId, auth.Device, Request.RemoteIp).Result; - return result; + return ToOptimizedResult(result); } /// @@ -353,7 +314,7 @@ namespace MediaBrowser.Api } else { - var success = _userManager.AuthenticateUser(user, request.CurrentPassword).Result; + var success = _userManager.AuthenticateUser(user.Name, request.CurrentPassword).Result; if (!success) { diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs index f62e37f798..2407a1a391 100644 --- a/MediaBrowser.Api/VideosService.cs +++ b/MediaBrowser.Api/VideosService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Querying; using ServiceStack; @@ -41,6 +42,7 @@ namespace MediaBrowser.Api public string Ids { get; set; } } + [Authenticated] public class VideosService : BaseApiService { private readonly ILibraryManager _libraryManager; diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index 010caa2337..0da5f92728 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -50,11 +50,11 @@ namespace MediaBrowser.Controller.Library /// /// Authenticates a User and returns a result indicating whether or not it succeeded /// - /// The user. + /// The username. /// The password. /// Task{System.Boolean}. /// user - Task AuthenticateUser(User user, string password); + Task AuthenticateUser(string username, string password); /// /// Refreshes metadata for each user diff --git a/MediaBrowser.Controller/Net/AuthorizationInfo.cs b/MediaBrowser.Controller/Net/AuthorizationInfo.cs index e609204d69..d7dcb60f0e 100644 --- a/MediaBrowser.Controller/Net/AuthorizationInfo.cs +++ b/MediaBrowser.Controller/Net/AuthorizationInfo.cs @@ -28,5 +28,10 @@ namespace MediaBrowser.Controller.Net /// /// The version. public string Version { get; set; } + /// + /// Gets or sets the token. + /// + /// The token. + public string Token { get; set; } } } diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 74ad1b7ee6..6d3a9d20cf 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Session; +using MediaBrowser.Model.Users; using System; using System.Collections.Generic; using System.Threading; @@ -206,11 +207,11 @@ namespace MediaBrowser.Controller.Session /// The session identifier. /// The item. void ReportNowViewingItem(string sessionId, BaseItemInfo item); - + /// /// Authenticates the new session. /// - /// The user. + /// The username. /// The password. /// Type of the client. /// The application version. @@ -218,7 +219,7 @@ namespace MediaBrowser.Controller.Session /// Name of the device. /// The remote end point. /// Task{SessionInfo}. - Task AuthenticateNewSession(User user, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint); + Task AuthenticateNewSession(string username, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint); /// /// Reports the capabilities. @@ -248,5 +249,11 @@ namespace MediaBrowser.Controller.Session /// The version. /// SessionInfo. SessionInfo GetSession(string deviceId, string client, string version); + + /// + /// Validates the security token. + /// + /// The token. + void ValidateSecurityToken(string token); } } \ No newline at end of file diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 2d19d335d2..0ed49d5f89 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -137,21 +137,9 @@ Configuration\MetadataPluginType.cs - - Configuration\NotificationOption.cs - - - Configuration\NotificationOptions.cs - - - Configuration\NotificationType.cs - Configuration\PathSubstitution.cs - - Configuration\SendToUserType.cs - Configuration\ServerConfiguration.cs @@ -638,6 +626,12 @@ Notifications\NotificationLevel.cs + + Notifications\NotificationOption.cs + + + Notifications\NotificationOptions.cs + Notifications\NotificationQuery.cs @@ -653,9 +647,15 @@ Notifications\NotificationsSummary.cs + + Notifications\NotificationType.cs + Notifications\NotificationTypeInfo.cs + + Notifications\SendToUserType.cs + Plugins\BasePluginConfiguration.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index c0c886c8a2..12c87ca97a 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -124,21 +124,9 @@ Configuration\MetadataPluginType.cs - - Configuration\NotificationOption.cs - - - Configuration\NotificationOptions.cs - - - Configuration\NotificationType.cs - Configuration\PathSubstitution.cs - - Configuration\SendToUserType.cs - Configuration\ServerConfiguration.cs @@ -619,6 +607,12 @@ Notifications\NotificationLevel.cs + + Notifications\NotificationOption.cs + + + Notifications\NotificationOptions.cs + Notifications\NotificationQuery.cs @@ -634,9 +628,15 @@ Notifications\NotificationsSummary.cs + + Notifications\NotificationType.cs + Notifications\NotificationTypeInfo.cs + + Notifications\SendToUserType.cs + Plugins\BasePluginConfiguration.cs diff --git a/MediaBrowser.Model/Configuration/NotificationOption.cs b/MediaBrowser.Model/Configuration/NotificationOption.cs deleted file mode 100644 index 5fcf3550c9..0000000000 --- a/MediaBrowser.Model/Configuration/NotificationOption.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace MediaBrowser.Model.Configuration -{ - public class NotificationOption - { - public string Type { get; set; } - - /// - /// User Ids to not monitor (it's opt out) - /// - public string[] DisabledMonitorUsers { get; set; } - - /// - /// User Ids to send to (if SendToUserMode == Custom) - /// - public string[] SendToUsers { get; set; } - - /// - /// Gets or sets a value indicating whether this is enabled. - /// - /// true if enabled; otherwise, false. - public bool Enabled { get; set; } - - /// - /// Gets or sets the title format string. - /// - /// The title format string. - public string Title { get; set; } - - /// - /// Gets or sets the description. - /// - /// The description. - public string Description { get; set; } - - /// - /// Gets or sets the disabled services. - /// - /// The disabled services. - public string[] DisabledServices { get; set; } - - /// - /// Gets or sets the send to user mode. - /// - /// The send to user mode. - public SendToUserType SendToUserMode { get; set; } - - public NotificationOption() - { - DisabledServices = new string[] { }; - DisabledMonitorUsers = new string[] { }; - SendToUsers = new string[] { }; - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/NotificationOptions.cs b/MediaBrowser.Model/Configuration/NotificationOptions.cs deleted file mode 100644 index dd523d9478..0000000000 --- a/MediaBrowser.Model/Configuration/NotificationOptions.cs +++ /dev/null @@ -1,124 +0,0 @@ -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Model.Configuration -{ - public class NotificationOptions - { - public NotificationOption[] Options { get; set; } - - public NotificationOptions() - { - Options = new[] - { - new NotificationOption - { - Type = NotificationType.TaskFailed.ToString(), - Enabled = true, - SendToUserMode = SendToUserType.Admins - }, - new NotificationOption - { - Type = NotificationType.ServerRestartRequired.ToString(), - Enabled = true, - SendToUserMode = SendToUserType.Admins - }, - new NotificationOption - { - Type = NotificationType.ApplicationUpdateAvailable.ToString(), - Enabled = true, - SendToUserMode = SendToUserType.Admins - }, - new NotificationOption - { - Type = NotificationType.ApplicationUpdateInstalled.ToString(), - Enabled = true, - SendToUserMode = SendToUserType.Admins - }, - new NotificationOption - { - Type = NotificationType.PluginUpdateInstalled.ToString(), - Enabled = true, - SendToUserMode = SendToUserType.Admins - }, - new NotificationOption - { - Type = NotificationType.PluginUninstalled.ToString(), - Enabled = true, - SendToUserMode = SendToUserType.Admins - }, - new NotificationOption - { - Type = NotificationType.InstallationFailed.ToString(), - Enabled = true, - SendToUserMode = SendToUserType.Admins - }, - new NotificationOption - { - Type = NotificationType.PluginInstalled.ToString(), - Enabled = true, - SendToUserMode = SendToUserType.Admins - }, - new NotificationOption - { - Type = NotificationType.PluginError.ToString(), - Enabled = true, - SendToUserMode = SendToUserType.Admins - } - }; - } - - public NotificationOption GetOptions(string type) - { - foreach (NotificationOption i in Options) - { - if (StringHelper.EqualsIgnoreCase(type, i.Type)) return i; - } - return null; - } - - public bool IsEnabled(string type) - { - NotificationOption opt = GetOptions(type); - - return opt != null && opt.Enabled; - } - - public bool IsServiceEnabled(string service, string notificationType) - { - NotificationOption opt = GetOptions(notificationType); - - return opt == null || - !ListHelper.ContainsIgnoreCase(opt.DisabledServices, service); - } - - public bool IsEnabledToMonitorUser(string type, string userId) - { - NotificationOption opt = GetOptions(type); - - return opt != null && opt.Enabled && - !ListHelper.ContainsIgnoreCase(opt.DisabledMonitorUsers, userId); - } - - public bool IsEnabledToSendToUser(string type, string userId, UserConfiguration userConfig) - { - NotificationOption opt = GetOptions(type); - - if (opt != null && opt.Enabled) - { - if (opt.SendToUserMode == SendToUserType.All) - { - return true; - } - - if (opt.SendToUserMode == SendToUserType.Admins && userConfig.IsAdministrator) - { - return true; - } - - return ListHelper.ContainsIgnoreCase(opt.SendToUsers, userId); - } - - return false; - } - } -} diff --git a/MediaBrowser.Model/Configuration/NotificationType.cs b/MediaBrowser.Model/Configuration/NotificationType.cs deleted file mode 100644 index d8043b0e14..0000000000 --- a/MediaBrowser.Model/Configuration/NotificationType.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace MediaBrowser.Model.Configuration -{ - public enum NotificationType - { - ApplicationUpdateAvailable, - ApplicationUpdateInstalled, - AudioPlayback, - GamePlayback, - VideoPlayback, - AudioPlaybackStopped, - GamePlaybackStopped, - VideoPlaybackStopped, - InstallationFailed, - PluginError, - PluginInstalled, - PluginUpdateInstalled, - PluginUninstalled, - NewLibraryContent, - NewLibraryContentMultiple, - ServerRestartRequired, - TaskFailed - } -} \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/SendToUserType.cs b/MediaBrowser.Model/Configuration/SendToUserType.cs deleted file mode 100644 index a2eac4c2d9..0000000000 --- a/MediaBrowser.Model/Configuration/SendToUserType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace MediaBrowser.Model.Configuration -{ - public enum SendToUserType - { - All = 0, - Admins = 1, - Custom = 2 - } -} \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index f7b888f824..36c353479f 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Weather; +using MediaBrowser.Model.Notifications; +using MediaBrowser.Model.Weather; using System; namespace MediaBrowser.Model.Configuration @@ -178,8 +179,6 @@ namespace MediaBrowser.Model.Configuration /// The encoding quality. public EncodingQuality MediaEncodingQuality { get; set; } - public bool AllowVideoUpscaling { get; set; } - public MetadataOptions[] MetadataOptions { get; set; } public bool EnableDebugEncodingLogging { get; set; } @@ -268,10 +267,7 @@ namespace MediaBrowser.Model.Configuration new MetadataOptions(0, 1280) {ItemType = "Season"} }; - NotificationOptions = new NotificationOptions(); - SubtitleOptions = new SubtitleOptions(); - LiveTvOptions = new LiveTvOptions(); TvFileOrganizationOptions = new TvFileOrganizationOptions(); } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index d2b0a8caf3..d758f2f394 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -88,11 +88,11 @@ - - - + + + - + diff --git a/MediaBrowser.Model/Notifications/NotificationOption.cs b/MediaBrowser.Model/Notifications/NotificationOption.cs new file mode 100644 index 0000000000..09f7072dd3 --- /dev/null +++ b/MediaBrowser.Model/Notifications/NotificationOption.cs @@ -0,0 +1,56 @@ +using MediaBrowser.Model.Configuration; + +namespace MediaBrowser.Model.Notifications +{ + public class NotificationOption + { + public string Type { get; set; } + + /// + /// User Ids to not monitor (it's opt out) + /// + public string[] DisabledMonitorUsers { get; set; } + + /// + /// User Ids to send to (if SendToUserMode == Custom) + /// + public string[] SendToUsers { get; set; } + + /// + /// Gets or sets a value indicating whether this is enabled. + /// + /// true if enabled; otherwise, false. + public bool Enabled { get; set; } + + /// + /// Gets or sets the title format string. + /// + /// The title format string. + public string Title { get; set; } + + /// + /// Gets or sets the description. + /// + /// The description. + public string Description { get; set; } + + /// + /// Gets or sets the disabled services. + /// + /// The disabled services. + public string[] DisabledServices { get; set; } + + /// + /// Gets or sets the send to user mode. + /// + /// The send to user mode. + public SendToUserType SendToUserMode { get; set; } + + public NotificationOption() + { + DisabledServices = new string[] { }; + DisabledMonitorUsers = new string[] { }; + SendToUsers = new string[] { }; + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Notifications/NotificationOptions.cs b/MediaBrowser.Model/Notifications/NotificationOptions.cs new file mode 100644 index 0000000000..7d80f31774 --- /dev/null +++ b/MediaBrowser.Model/Notifications/NotificationOptions.cs @@ -0,0 +1,125 @@ +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Extensions; + +namespace MediaBrowser.Model.Notifications +{ + public class NotificationOptions + { + public NotificationOption[] Options { get; set; } + + public NotificationOptions() + { + Options = new[] + { + new NotificationOption + { + Type = NotificationType.TaskFailed.ToString(), + Enabled = true, + SendToUserMode = SendToUserType.Admins + }, + new NotificationOption + { + Type = NotificationType.ServerRestartRequired.ToString(), + Enabled = true, + SendToUserMode = SendToUserType.Admins + }, + new NotificationOption + { + Type = NotificationType.ApplicationUpdateAvailable.ToString(), + Enabled = true, + SendToUserMode = SendToUserType.Admins + }, + new NotificationOption + { + Type = NotificationType.ApplicationUpdateInstalled.ToString(), + Enabled = true, + SendToUserMode = SendToUserType.Admins + }, + new NotificationOption + { + Type = NotificationType.PluginUpdateInstalled.ToString(), + Enabled = true, + SendToUserMode = SendToUserType.Admins + }, + new NotificationOption + { + Type = NotificationType.PluginUninstalled.ToString(), + Enabled = true, + SendToUserMode = SendToUserType.Admins + }, + new NotificationOption + { + Type = NotificationType.InstallationFailed.ToString(), + Enabled = true, + SendToUserMode = SendToUserType.Admins + }, + new NotificationOption + { + Type = NotificationType.PluginInstalled.ToString(), + Enabled = true, + SendToUserMode = SendToUserType.Admins + }, + new NotificationOption + { + Type = NotificationType.PluginError.ToString(), + Enabled = true, + SendToUserMode = SendToUserType.Admins + } + }; + } + + public NotificationOption GetOptions(string type) + { + foreach (NotificationOption i in Options) + { + if (StringHelper.EqualsIgnoreCase(type, i.Type)) return i; + } + return null; + } + + public bool IsEnabled(string type) + { + NotificationOption opt = GetOptions(type); + + return opt != null && opt.Enabled; + } + + public bool IsServiceEnabled(string service, string notificationType) + { + NotificationOption opt = GetOptions(notificationType); + + return opt == null || + !ListHelper.ContainsIgnoreCase(opt.DisabledServices, service); + } + + public bool IsEnabledToMonitorUser(string type, string userId) + { + NotificationOption opt = GetOptions(type); + + return opt != null && opt.Enabled && + !ListHelper.ContainsIgnoreCase(opt.DisabledMonitorUsers, userId); + } + + public bool IsEnabledToSendToUser(string type, string userId, UserConfiguration userConfig) + { + NotificationOption opt = GetOptions(type); + + if (opt != null && opt.Enabled) + { + if (opt.SendToUserMode == SendToUserType.All) + { + return true; + } + + if (opt.SendToUserMode == SendToUserType.Admins && userConfig.IsAdministrator) + { + return true; + } + + return ListHelper.ContainsIgnoreCase(opt.SendToUsers, userId); + } + + return false; + } + } +} diff --git a/MediaBrowser.Model/Notifications/NotificationType.cs b/MediaBrowser.Model/Notifications/NotificationType.cs new file mode 100644 index 0000000000..34e4d32b53 --- /dev/null +++ b/MediaBrowser.Model/Notifications/NotificationType.cs @@ -0,0 +1,23 @@ +namespace MediaBrowser.Model.Notifications +{ + public enum NotificationType + { + ApplicationUpdateAvailable, + ApplicationUpdateInstalled, + AudioPlayback, + GamePlayback, + VideoPlayback, + AudioPlaybackStopped, + GamePlaybackStopped, + VideoPlaybackStopped, + InstallationFailed, + PluginError, + PluginInstalled, + PluginUpdateInstalled, + PluginUninstalled, + NewLibraryContent, + NewLibraryContentMultiple, + ServerRestartRequired, + TaskFailed + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Notifications/SendToUserType.cs b/MediaBrowser.Model/Notifications/SendToUserType.cs new file mode 100644 index 0000000000..1998d3102f --- /dev/null +++ b/MediaBrowser.Model/Notifications/SendToUserType.cs @@ -0,0 +1,9 @@ +namespace MediaBrowser.Model.Notifications +{ + public enum SendToUserType + { + All = 0, + Admins = 1, + Custom = 2 + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs index de8f4e8b86..b9bf6e7fe6 100644 --- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs +++ b/MediaBrowser.Model/Updates/PackageVersionInfo.cs @@ -1,4 +1,6 @@ - +using System; +using System.Runtime.Serialization; + namespace MediaBrowser.Model.Updates { /// @@ -24,6 +26,32 @@ namespace MediaBrowser.Model.Updates /// The version STR. public string versionStr { get; set; } + /// + /// The _version + /// + private Version _version; + /// + /// Gets or sets the version. + /// Had to make this an interpreted property since Protobuf can't handle Version + /// + /// The version. + [IgnoreDataMember] + public Version version + { + get { return _version ?? (_version = new Version(ValueOrDefault(versionStr, "0.0.0.1"))); } + } + + /// + /// Values the or default. + /// + /// The STR. + /// The def. + /// System.String. + private static string ValueOrDefault(string str, string def) + { + return string.IsNullOrEmpty(str) ? def : str; + } + /// /// Gets or sets the classification. /// @@ -60,4 +88,4 @@ namespace MediaBrowser.Model.Updates /// The target filename. public string targetFilename { get; set; } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Model/Users/AuthenticationResult.cs b/MediaBrowser.Model/Users/AuthenticationResult.cs index 998aaa3a7f..8046e83c7f 100644 --- a/MediaBrowser.Model/Users/AuthenticationResult.cs +++ b/MediaBrowser.Model/Users/AuthenticationResult.cs @@ -16,5 +16,11 @@ namespace MediaBrowser.Model.Users /// /// The session information. public SessionInfoDto SessionInfo { get; set; } + + /// + /// Gets or sets the authentication token. + /// + /// The authentication token. + public string AuthenticationToken { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs index 1a7f9db283..c29a7d14e3 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs @@ -51,13 +51,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security private void ValidateUser(IRequest req) { - User user = null; - //This code is executed before the service var auth = AuthorizationContext.GetAuthorizationInfo(req); - if (auth != null) + if (string.IsNullOrWhiteSpace(auth.Token)) { + // Legacy + // TODO: Deprecate this in Oct 2014 + + User user = null; + if (!string.IsNullOrWhiteSpace(auth.UserId)) { var userId = auth.UserId; @@ -65,22 +68,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security user = UserManager.GetUserById(new Guid(userId)); } - string deviceId = auth.DeviceId; - string device = auth.Device; - string client = auth.Client; - string version = auth.Version; - - if (!string.IsNullOrEmpty(client) && !string.IsNullOrEmpty(deviceId) && !string.IsNullOrEmpty(device) && !string.IsNullOrEmpty(version)) + if (user == null || user.Configuration.IsDisabled) { - var remoteEndPoint = req.RemoteIp; - - SessionManager.LogSessionActivity(client, version, deviceId, device, remoteEndPoint, user); + throw new UnauthorizedAccessException("Unauthorized access."); } } - - if (user == null || user.Configuration.IsDisabled) + else { - throw new UnauthorizedAccessException("Unauthorized access."); + SessionManager.ValidateSecurityToken(auth.Token); } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 6ea77f2518..77343ab4ef 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -42,7 +42,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security Device = device, DeviceId = deviceId, UserId = userId, - Version = version + Version = version, + Token = httpReq.Headers["X-AUTH-TOKEN"] }; } diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index f9d7479cea..1e0bbc39bc 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -121,17 +121,20 @@ namespace MediaBrowser.Server.Implementations.Library /// /// Authenticates a User and returns a result indicating whether or not it succeeded /// - /// The user. + /// The username. /// The password. /// Task{System.Boolean}. /// user - public async Task AuthenticateUser(User user, string password) + /// + public async Task AuthenticateUser(string username, string password) { - if (user == null) + if (string.IsNullOrWhiteSpace(username)) { - throw new ArgumentNullException("user"); + throw new ArgumentNullException("username"); } + var user = Users.First(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase)); + if (user.Configuration.IsDisabled) { throw new UnauthorizedAccessException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name)); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 467bedcf13..ad1ddba881 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -49,8 +49,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly List _services = new List(); - private readonly ConcurrentDictionary _openStreams = - new ConcurrentDictionary(); + private readonly ConcurrentDictionary _openStreams = + new ConcurrentDictionary(); private List _channelIdList = new List(); private Dictionary _programs = new Dictionary(); @@ -291,66 +291,69 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); public async Task GetRecordingStream(string id, CancellationToken cancellationToken) + { + return await GetLiveStream(id, false, cancellationToken).ConfigureAwait(false); + } + + public async Task GetChannelStream(string id, CancellationToken cancellationToken) + { + return await GetLiveStream(id, true, cancellationToken).ConfigureAwait(false); + } + + private async Task GetLiveStream(string id, bool isChannel, CancellationToken cancellationToken) { await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try { - var service = ActiveService; - - var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); - - var recording = recordings.First(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id)); - - var result = await service.GetRecordingStream(recording.Id, cancellationToken).ConfigureAwait(false); - - Sanitize(result); + // Avoid implicitly captured closure + var itemId = id; - _logger.Debug("Live stream info: " + _json.SerializeToString(result)); + var stream = _openStreams + .Where(i => string.Equals(i.Value.ItemId, itemId) && isChannel == i.Value.IsChannel) + .Take(1) + .Select(i => i.Value) + .FirstOrDefault(); - if (!string.IsNullOrEmpty(result.Id)) + if (stream != null) { - _openStreams.AddOrUpdate(result.Id, result, (key, info) => result); + stream.ConsumerCount++; + _logger.Debug("Returning existing live tv stream"); + return stream.Info; } - return result; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting recording stream", ex); - - throw; - } - finally - { - _liveStreamSemaphore.Release(); - } - } - - public async Task GetChannelStream(string id, CancellationToken cancellationToken) - { - await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { var service = ActiveService; + LiveStreamInfo info; - var channel = GetInternalChannel(id); - - _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId); + if (isChannel) + { + var channel = GetInternalChannel(id); + _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId); - var result = await service.GetChannelStream(channel.ExternalId, cancellationToken).ConfigureAwait(false); + info = await service.GetChannelStream(channel.ExternalId, cancellationToken).ConfigureAwait(false); + } + else + { + var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); + var recording = recordings.First(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id)); - Sanitize(result); + _logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, recording.Id); + info = await service.GetRecordingStream(recording.Id, cancellationToken).ConfigureAwait(false); + } - _logger.Debug("Live stream info: " + _json.SerializeToString(result)); + Sanitize(info); - if (!string.IsNullOrEmpty(result.Id)) + var data = new LiveStreamData { - _openStreams.AddOrUpdate(result.Id, result, (key, info) => result); - } + Info = info, + ConsumerCount = 1, + IsChannel = isChannel, + ItemId = id + }; - return result; + _openStreams.AddOrUpdate(info.Id, data, (key, i) => data); + + return info; } catch (Exception ex) { @@ -1597,20 +1600,38 @@ namespace MediaBrowser.Server.Implementations.LiveTv }; } + class LiveStreamData + { + internal LiveStreamInfo Info; + internal int ConsumerCount; + internal string ItemId; + internal bool IsChannel; + } + public async Task CloseLiveStream(string id, CancellationToken cancellationToken) { await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - var service = ActiveService; - - _logger.Info("Closing live stream from {0}, stream Id: {1}", service.Name, id); - try { - await service.CloseLiveStream(id, cancellationToken).ConfigureAwait(false); + var service = ActiveService; + + LiveStreamData data; + if (_openStreams.TryGetValue(id, out data)) + { + if (data.ConsumerCount > 1) + { + data.ConsumerCount--; + _logger.Info("Decrementing live stream client count."); + return; + } - LiveStreamInfo removed; - _openStreams.TryRemove(id, out removed); + } + _openStreams.TryRemove(id, out data); + + _logger.Info("Closing live stream from {0}, stream Id: {1}", service.Name, id); + + await service.CloseLiveStream(id, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { @@ -1662,7 +1683,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { foreach (var stream in _openStreams.Values.ToList()) { - var task = CloseLiveStream(stream.Id, CancellationToken.None); + var task = CloseLiveStream(stream.Info.Id, CancellationToken.None); Task.WaitAll(task); } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index b3280dac7c..41555fe82e 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -201,5 +201,21 @@ "ButtonOpenInNewTab": "Open in new tab", "ButtonShuffle": "Shuffle", "ButtonInstantMix": "Instant mix", - "ButtonResume": "Resume" + "ButtonResume": "Resume", + "HeaderScenes": "Scenes", + "HeaderAudioTracks": "Audio Tracks", + "LabelUnknownLanguage": "Unknown language", + "HeaderSubtitles": "Subtitles", + "HeaderVideoQuality": "Video Quality", + "MessageErrorPlayingVideo": "There was an error playing the video.", + "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.", + "ButtonHome": "Home", + "ButtonDashboard": "Dashboard", + "ButtonReports": "Reports", + "ButtonMetadataManager": "Metadata Manager", + "HeaderTime": "Time", + "HeaderName": "Name", + "HeaderAlbum": "Album", + "HeaderAlbumArtist": "Album Artist", + "HeaderArtist": "Artist" } \ 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 10e27bc304..a909929ae0 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -200,6 +200,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs new file mode 100644 index 0000000000..a336eba0ed --- /dev/null +++ b/MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs @@ -0,0 +1,21 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Notifications; +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.Notifications +{ + public class NotificationConfigurationFactory : IConfigurationFactory + { + public IEnumerable GetConfigurations() + { + return new List + { + new ConfigurationStore + { + Key = "notifications", + ConfigurationType = typeof (NotificationOptions) + } + }; + } + } +} diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs index 416b29e86b..964e2cd243 100644 --- a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs +++ b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -30,13 +31,18 @@ namespace MediaBrowser.Server.Implementations.Notifications _logger = logManager.GetLogger(GetType().Name); } + private NotificationOptions GetConfiguration() + { + return _config.GetConfiguration("notifications"); + } + public Task SendNotification(NotificationRequest request, CancellationToken cancellationToken) { var notificationType = request.NotificationType; var options = string.IsNullOrWhiteSpace(notificationType) ? null : - _config.Configuration.NotificationOptions.GetOptions(notificationType); + GetConfiguration().GetOptions(notificationType); var users = GetUserIds(request, options) .Except(request.ExcludeUserIds) @@ -223,7 +229,7 @@ namespace MediaBrowser.Server.Implementations.Notifications private bool IsEnabled(INotificationService service, string notificationType) { return string.IsNullOrEmpty(notificationType) || - _config.Configuration.NotificationOptions.IsServiceEnabled(service.Name, notificationType); + GetConfiguration().IsServiceEnabled(service.Name, notificationType); } public void AddParts(IEnumerable services, IEnumerable notificationTypeFactories) @@ -248,9 +254,11 @@ namespace MediaBrowser.Server.Implementations.Notifications }).SelectMany(i => i).ToList(); + var config = GetConfiguration(); + foreach (var i in list) { - i.Enabled = _config.Configuration.NotificationOptions.IsEnabled(i.Type); + i.Enabled = config.IsEnabled(i.Type); } return list; diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 4e2b3c7b78..2f6790a3e8 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -25,6 +25,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Users; namespace MediaBrowser.Server.Implementations.Session { @@ -1138,10 +1139,15 @@ namespace MediaBrowser.Server.Implementations.Session } } + public void ValidateSecurityToken(string token) + { + + } + /// /// Authenticates the new session. /// - /// The user. + /// The username. /// The password. /// Type of the client. /// The application version. @@ -1149,17 +1155,34 @@ namespace MediaBrowser.Server.Implementations.Session /// Name of the device. /// The remote end point. /// Task{SessionInfo}. + /// Invalid user or password entered. /// - public async Task AuthenticateNewSession(User user, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint) + public async Task AuthenticateNewSession(string username, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint) { - var result = await _userManager.AuthenticateUser(user, password).ConfigureAwait(false); + var result = await _userManager.AuthenticateUser(username, password).ConfigureAwait(false); if (!result) { throw new UnauthorizedAccessException("Invalid user or password entered."); } - return await LogSessionActivity(clientType, appVersion, deviceId, deviceName, remoteEndPoint, user).ConfigureAwait(false); + var user = _userManager.Users + .First(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase)); + + var session = await LogSessionActivity(clientType, + appVersion, + deviceId, + deviceName, + remoteEndPoint, + user) + .ConfigureAwait(false); + + return new AuthenticationResult + { + User = _dtoService.GetUserDto(user), + SessionInfo = GetSessionInfoDto(session), + AuthenticationToken = Guid.NewGuid().ToString("N") + }; } /// diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index e8fb7bfcbf..673a9f1519 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -318,6 +318,13 @@ namespace MediaBrowser.ServerApplication saveConfig = true; } + if (ServerConfigurationManager.Configuration.NotificationOptions != null) + { + ServerConfigurationManager.SaveConfiguration("notifications", ServerConfigurationManager.Configuration.NotificationOptions); + ServerConfigurationManager.Configuration.NotificationOptions = null; + saveConfig = true; + } + if (saveConfig) { ServerConfigurationManager.SaveConfiguration(); diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 80f864a326..3ccf26c375 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -403,7 +403,7 @@ namespace MediaBrowser.WebDashboard.Api var files = new[] { - "thirdparty/jquerymobile-1.4.2/jquery.mobile-1.4.2.min.css", + "thirdparty/jquerymobile-1.4.3/jquery.mobile-1.4.3.min.css", "css/all.css" + versionString }; @@ -449,7 +449,7 @@ namespace MediaBrowser.WebDashboard.Api // jQuery + jQuery mobile await AppendResource(memoryStream, "thirdparty/jquery-2.0.3.min.js", newLineBytes).ConfigureAwait(false); - await AppendResource(memoryStream, "thirdparty/jquerymobile-1.4.2/jquery.mobile-1.4.2.min.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/jquerymobile-1.4.3/jquery.mobile-1.4.3.min.js", newLineBytes).ConfigureAwait(false); await AppendLocalization(memoryStream).ConfigureAwait(false); await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index cbdae6d089..8f85fcb513 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -815,613 +815,613 @@ PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest @@ -2144,6 +2144,9 @@ PreserveNewest + + PreserveNewest + Designer -- cgit v1.2.3 From 7fa9b14f56eabbb06e38726879b3cddc47b8e8fb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 3 Jul 2014 22:22:57 -0400 Subject: fixes #762 - Marking unwatched doesn't update display --- MediaBrowser.Api/BrandingService.cs | 28 +++ MediaBrowser.Api/ConfigurationService.cs | 7 + MediaBrowser.Api/Images/ImageService.cs | 7 + MediaBrowser.Api/ItemRefreshService.cs | 22 ++- MediaBrowser.Api/Library/LibraryService.cs | 2 + MediaBrowser.Api/Library/SubtitleService.cs | 184 -------------------- MediaBrowser.Api/MediaBrowser.Api.csproj | 4 +- MediaBrowser.Api/NotificationsService.cs | 2 + MediaBrowser.Api/SessionsService.cs | 12 +- MediaBrowser.Api/Subtitles/SubtitleService.cs | 189 +++++++++++++++++++++ MediaBrowser.Api/SystemService.cs | 70 +++++++- MediaBrowser.Api/UserLibrary/UserLibraryService.cs | 10 +- MediaBrowser.Api/UserService.cs | 4 + .../WebSocket/LogFileWebSocketListener.cs | 149 ---------------- MediaBrowser.Common/Net/MimeTypes.cs | 4 + MediaBrowser.Controller/Dto/IDtoService.cs | 7 - MediaBrowser.Controller/Entities/BaseItem.cs | 15 ++ MediaBrowser.Controller/Entities/Folder.cs | 80 ++++++++- MediaBrowser.Controller/Entities/IHasUserData.cs | 18 +- MediaBrowser.Controller/Entities/TV/Episode.cs | 2 +- MediaBrowser.Controller/Entities/UserRootFolder.cs | 6 + MediaBrowser.Controller/Entities/UserView.cs | 2 +- .../Library/IUserDataManager.cs | 9 + MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs | 4 +- .../Providers/MetadataRefreshOptions.cs | 39 +++-- MediaBrowser.Controller/Session/ISessionManager.cs | 8 +- .../MediaBrowser.Model.Portable.csproj | 6 + .../MediaBrowser.Model.net35.csproj | 6 + MediaBrowser.Model/Branding/BrandingOptions.cs | 12 ++ .../Configuration/ServerConfiguration.cs | 3 - .../Configuration/XbmcMetadataOptions.cs | 3 + MediaBrowser.Model/Dto/UserItemDataDto.cs | 16 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 + .../Notifications/NotificationRequest.cs | 3 +- MediaBrowser.Model/Session/SessionInfoDto.cs | 32 +--- MediaBrowser.Model/System/LogFile.cs | 31 ++++ MediaBrowser.Providers/Manager/ImageSaver.cs | 28 ++- .../MediaInfo/FFProbeVideoInfo.cs | 4 +- .../Branding/BrandingConfigurationFactory.cs | 21 +++ .../Dto/DtoService.cs | 52 +++--- .../EntryPoints/UserDataChangeNotifier.cs | 45 +++-- .../HttpServer/HttpListenerHost.cs | 26 +-- .../HttpServer/Security/AuthorizationContext.cs | 9 +- .../Library/UserDataManager.cs | 37 ++++ .../LiveTv/LiveTvDtoService.cs | 11 +- .../LiveTv/LiveTvManager.cs | 6 +- .../Localization/Server/server.json | 17 +- .../MediaBrowser.Server.Implementations.csproj | 1 + .../Notifications/NotificationManager.cs | 5 +- .../Session/SessionManager.cs | 27 ++- .../Sorting/AirTimeComparer.cs | 33 +++- MediaBrowser.ServerApplication/ApplicationHost.cs | 2 +- .../Native/BrowserLauncher.cs | 12 -- MediaBrowser.ServerApplication/ServerNotifyIcon.cs | 15 -- MediaBrowser.WebDashboard/Api/DashboardService.cs | 3 +- .../MediaBrowser.WebDashboard.csproj | 22 +-- 56 files changed, 821 insertions(+), 553 deletions(-) create mode 100644 MediaBrowser.Api/BrandingService.cs delete mode 100644 MediaBrowser.Api/Library/SubtitleService.cs create mode 100644 MediaBrowser.Api/Subtitles/SubtitleService.cs delete mode 100644 MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs create mode 100644 MediaBrowser.Model/Branding/BrandingOptions.cs create mode 100644 MediaBrowser.Model/System/LogFile.cs create mode 100644 MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/BrandingService.cs b/MediaBrowser.Api/BrandingService.cs new file mode 100644 index 0000000000..4b49b411a8 --- /dev/null +++ b/MediaBrowser.Api/BrandingService.cs @@ -0,0 +1,28 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Branding; +using ServiceStack; + +namespace MediaBrowser.Api +{ + [Route("/Branding/Configuration", "GET", Summary = "Gets branding configuration")] + public class GetBrandingOptions : IReturn + { + } + + public class BrandingService : BaseApiService + { + private readonly IConfigurationManager _config; + + public BrandingService(IConfigurationManager config) + { + _config = config; + } + + public object Get(GetBrandingOptions request) + { + var result = _config.GetConfiguration("branding"); + + return ToOptimizedResult(result); + } + } +} diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs index 39fcc50d8f..291deb3b01 100644 --- a/MediaBrowser.Api/ConfigurationService.cs +++ b/MediaBrowser.Api/ConfigurationService.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Serialization; @@ -27,6 +28,7 @@ namespace MediaBrowser.Api } [Route("/System/Configuration/{Key}", "GET", Summary = "Gets a named configuration")] + [Authenticated] public class GetNamedConfiguration { [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] @@ -37,11 +39,13 @@ namespace MediaBrowser.Api /// Class UpdateConfiguration /// [Route("/System/Configuration", "POST", Summary = "Updates application configuration")] + [Authenticated] public class UpdateConfiguration : ServerConfiguration, IReturnVoid { } [Route("/System/Configuration/{Key}", "POST", Summary = "Updates named configuration")] + [Authenticated] public class UpdateNamedConfiguration : IReturnVoid, IRequiresRequestStream { [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] @@ -51,18 +55,21 @@ namespace MediaBrowser.Api } [Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")] + [Authenticated] public class GetDefaultMetadataOptions : IReturn { } [Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")] + [Authenticated] public class GetMetadataPlugins : IReturn> { } [Route("/System/Configuration/VideoImageExtraction", "POST", Summary = "Updates image extraction for all types")] + [Authenticated] public class UpdateVideoImageExtraction : IReturnVoid { public bool Enabled { get; set; } diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 4f8c348bb8..deaefe019a 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Drawing; @@ -26,6 +27,7 @@ namespace MediaBrowser.Api.Images /// [Route("/Items/{Id}/Images", "GET")] [Api(Description = "Gets information about an item's images")] + [Authenticated] public class GetItemImageInfos : IReturn> { /// @@ -56,6 +58,7 @@ namespace MediaBrowser.Api.Images /// [Route("/Items/{Id}/Images/{Type}/{Index}/Index", "POST")] [Api(Description = "Updates the index for an item image")] + [Authenticated] public class UpdateItemImageIndex : IReturnVoid { /// @@ -137,6 +140,7 @@ namespace MediaBrowser.Api.Images [Route("/Items/{Id}/Images/{Type}", "DELETE")] [Route("/Items/{Id}/Images/{Type}/{Index}", "DELETE")] [Api(Description = "Deletes an item image")] + [Authenticated] public class DeleteItemImage : DeleteImageRequest, IReturnVoid { /// @@ -153,6 +157,7 @@ namespace MediaBrowser.Api.Images [Route("/Users/{Id}/Images/{Type}", "DELETE")] [Route("/Users/{Id}/Images/{Type}/{Index}", "DELETE")] [Api(Description = "Deletes a user image")] + [Authenticated] public class DeleteUserImage : DeleteImageRequest, IReturnVoid { /// @@ -169,6 +174,7 @@ namespace MediaBrowser.Api.Images [Route("/Users/{Id}/Images/{Type}", "POST")] [Route("/Users/{Id}/Images/{Type}/{Index}", "POST")] [Api(Description = "Posts a user image")] + [Authenticated] public class PostUserImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid { /// @@ -191,6 +197,7 @@ namespace MediaBrowser.Api.Images [Route("/Items/{Id}/Images/{Type}", "POST")] [Route("/Items/{Id}/Images/{Type}/{Index}", "POST")] [Api(Description = "Posts an item image")] + [Authenticated] public class PostItemImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid { /// diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index b95e18a0d9..993b69601c 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -13,10 +13,16 @@ namespace MediaBrowser.Api { public class BaseRefreshRequest : IReturnVoid { - [ApiMember(Name = "Forced", Description = "Indicates if a normal or forced refresh should occur.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")] - public bool Forced { get; set; } + [ApiMember(Name = "MetadataRefreshMode", Description = "Specifies the metadata refresh mode", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")] + public MetadataRefreshMode MetadataRefreshMode { get; set; } - [ApiMember(Name = "ReplaceAllImages", Description = "Determines if images should be replaced during the refresh.", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")] + [ApiMember(Name = "ImageRefreshMode", Description = "Specifies the image refresh mode", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")] + public ImageRefreshMode ImageRefreshMode { get; set; } + + [ApiMember(Name = "ReplaceAllMetadata", Description = "Determines if metadata should be replaced. Only applicable if mode is FullRefresh", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")] + public bool ReplaceAllMetadata { get; set; } + + [ApiMember(Name = "ReplaceAllImages", Description = "Determines if images should be replaced. Only applicable if mode is FullRefresh", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")] public bool ReplaceAllImages { get; set; } } @@ -93,7 +99,7 @@ namespace MediaBrowser.Api private async Task RefreshItem(RefreshItem request, BaseItem item) { var options = GetRefreshOptions(request); - + try { await item.RefreshMetadata(options, CancellationToken.None).ConfigureAwait(false); @@ -148,10 +154,10 @@ namespace MediaBrowser.Api { return new MetadataRefreshOptions { - MetadataRefreshMode = MetadataRefreshMode.FullRefresh, - ImageRefreshMode = ImageRefreshMode.FullRefresh, - ReplaceAllMetadata = request.Forced, - ReplaceAllImages = request.ReplaceAllImages + MetadataRefreshMode = request.MetadataRefreshMode, + ImageRefreshMode = request.ImageRefreshMode, + ReplaceAllImages = request.ReplaceAllImages, + ReplaceAllMetadata = request.ReplaceAllMetadata }; } } diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 77a714755d..10aa231265 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; @@ -226,6 +227,7 @@ namespace MediaBrowser.Api.Library /// /// Class LibraryService /// + [Authenticated] public class LibraryService : BaseApiService { /// diff --git a/MediaBrowser.Api/Library/SubtitleService.cs b/MediaBrowser.Api/Library/SubtitleService.cs deleted file mode 100644 index 4fc3e00c08..0000000000 --- a/MediaBrowser.Api/Library/SubtitleService.cs +++ /dev/null @@ -1,184 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Subtitles; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Providers; -using ServiceStack; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Api.Library -{ - [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/Stream.{Format}", "GET", Summary = "Gets subtitles in a specified format (vtt).")] - public class GetSubtitle - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - - [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string MediaSourceId { get; set; } - - [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")] - public int Index { get; set; } - - [ApiMember(Name = "Format", Description = "Format", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Format { get; set; } - - [ApiMember(Name = "StartPositionTicks", Description = "StartPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public long StartPositionTicks { get; set; } - } - - [Route("/Videos/{Id}/Subtitles/{Index}", "DELETE", Summary = "Deletes an external subtitle file")] - public class DeleteSubtitle - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] - public string Id { get; set; } - - [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "DELETE")] - public int Index { get; set; } - } - - [Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")] - public class SearchRemoteSubtitles : IReturn> - { - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - - [ApiMember(Name = "Language", Description = "Language", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Language { get; set; } - } - - [Route("/Items/{Id}/RemoteSearch/Subtitles/Providers", "GET")] - public class GetSubtitleProviders : IReturn> - { - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - [Route("/Items/{Id}/RemoteSearch/Subtitles/{SubtitleId}", "POST")] - public class DownloadRemoteSubtitles : IReturnVoid - { - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - [ApiMember(Name = "SubtitleId", Description = "SubtitleId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string SubtitleId { get; set; } - } - - [Route("/Providers/Subtitles/Subtitles/{Id}", "GET")] - public class GetRemoteSubtitles : IReturnVoid - { - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - - [Authenticated] - public class SubtitleService : BaseApiService - { - private readonly ILibraryManager _libraryManager; - private readonly ISubtitleManager _subtitleManager; - private readonly ISubtitleEncoder _subtitleEncoder; - - public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder) - { - _libraryManager = libraryManager; - _subtitleManager = subtitleManager; - _subtitleEncoder = subtitleEncoder; - } - - public object Get(SearchRemoteSubtitles request) - { - var video = (Video)_libraryManager.GetItemById(request.Id); - - var response = _subtitleManager.SearchSubtitles(video, request.Language, CancellationToken.None).Result; - - return ToOptimizedResult(response); - } - public object Get(GetSubtitle request) - { - if (string.IsNullOrEmpty(request.Format)) - { - var item = (Video)_libraryManager.GetItemById(new Guid(request.Id)); - - var mediaSource = item.GetMediaSources(false) - .First(i => string.Equals(i.Id, request.MediaSourceId ?? request.Id)); - - var subtitleStream = mediaSource.MediaStreams - .First(i => i.Type == MediaStreamType.Subtitle && i.Index == request.Index); - - return ToStaticFileResult(subtitleStream.Path); - } - - var stream = GetSubtitles(request).Result; - - return ResultFactory.GetResult(stream, Common.Net.MimeTypes.GetMimeType("file." + request.Format)); - } - - private async Task GetSubtitles(GetSubtitle request) - { - return await _subtitleEncoder.GetSubtitles(request.Id, - request.MediaSourceId, - request.Index, - request.Format, - request.StartPositionTicks, - CancellationToken.None).ConfigureAwait(false); - } - - public void Delete(DeleteSubtitle request) - { - var task = _subtitleManager.DeleteSubtitles(request.Id, request.Index); - - Task.WaitAll(task); - } - - public object Get(GetSubtitleProviders request) - { - var result = _subtitleManager.GetProviders(request.Id); - - return ToOptimizedResult(result); - } - - public object Get(GetRemoteSubtitles request) - { - var result = _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).Result; - - return ResultFactory.GetResult(result.Stream, Common.Net.MimeTypes.GetMimeType("file." + result.Format)); - } - - public void Post(DownloadRemoteSubtitles request) - { - var video = (Video)_libraryManager.GetItemById(request.Id); - - Task.Run(async () => - { - try - { - await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None) - .ConfigureAwait(false); - - await video.RefreshMetadata(new MetadataRefreshOptions(), CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.ErrorException("Error downloading subtitles", ex); - } - - }); - } - } -} diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index a68966b335..ca2887d19c 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -65,11 +65,12 @@ Properties\SharedVersion.cs + - + @@ -139,7 +140,6 @@ - diff --git a/MediaBrowser.Api/NotificationsService.cs b/MediaBrowser.Api/NotificationsService.cs index 28edb61dd9..51a0801060 100644 --- a/MediaBrowser.Api/NotificationsService.cs +++ b/MediaBrowser.Api/NotificationsService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Notifications; using MediaBrowser.Model.Notifications; using ServiceStack; @@ -82,6 +83,7 @@ namespace MediaBrowser.Api public string Ids { get; set; } } + [Authenticated] public class NotificationsService : BaseApiService { private readonly INotificationsRepository _notificationsRepo; diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs index 00c307a18b..f4651601b0 100644 --- a/MediaBrowser.Api/SessionsService.cs +++ b/MediaBrowser.Api/SessionsService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Session; using ServiceStack; @@ -14,6 +15,7 @@ namespace MediaBrowser.Api /// Class GetSessions /// [Route("/Sessions", "GET", Summary = "Gets a list of sessions")] + [Authenticated] public class GetSessions : IReturn> { [ApiMember(Name = "ControllableByUserId", Description = "Optional. Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] @@ -27,6 +29,7 @@ namespace MediaBrowser.Api /// Class DisplayContent /// [Route("/Sessions/{Id}/Viewing", "POST", Summary = "Instructs a session to browse to an item or view")] + [Authenticated] public class DisplayContent : IReturnVoid { /// @@ -59,6 +62,7 @@ namespace MediaBrowser.Api } [Route("/Sessions/{Id}/Playing", "POST", Summary = "Instructs a session to play an item")] + [Authenticated] public class Play : IReturnVoid { /// @@ -91,6 +95,7 @@ namespace MediaBrowser.Api } [Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")] + [Authenticated] public class SendPlaystateCommand : IReturnVoid { /// @@ -115,6 +120,7 @@ namespace MediaBrowser.Api } [Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")] + [Authenticated] public class SendSystemCommand : IReturnVoid { /// @@ -133,6 +139,7 @@ namespace MediaBrowser.Api } [Route("/Sessions/{Id}/Command/{Command}", "POST", Summary = "Issues a system command to a client")] + [Authenticated] public class SendGeneralCommand : IReturnVoid { /// @@ -151,6 +158,7 @@ namespace MediaBrowser.Api } [Route("/Sessions/{Id}/Command", "POST", Summary = "Issues a system command to a client")] + [Authenticated] public class SendFullGeneralCommand : GeneralCommand, IReturnVoid { /// @@ -162,6 +170,7 @@ namespace MediaBrowser.Api } [Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")] + [Authenticated] public class SendMessageCommand : IReturnVoid { /// @@ -182,6 +191,7 @@ namespace MediaBrowser.Api } [Route("/Sessions/{Id}/Users/{UserId}", "POST", Summary = "Adds an additional user to a session")] + [Authenticated] public class AddUserToSession : IReturnVoid { [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] @@ -192,6 +202,7 @@ namespace MediaBrowser.Api } [Route("/Sessions/{Id}/Users/{UserId}", "DELETE", Summary = "Removes an additional user from a session")] + [Authenticated] public class RemoveUserFromSession : IReturnVoid { [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] @@ -202,7 +213,6 @@ namespace MediaBrowser.Api } [Route("/Sessions/Capabilities", "POST", Summary = "Updates capabilities for a device")] - [Route("/Sessions/{Id}/Capabilities", "POST", Summary = "Updates capabilities for a device")] public class PostCapabilities : IReturnVoid { /// diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs new file mode 100644 index 0000000000..3e692cb22f --- /dev/null +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -0,0 +1,189 @@ +using System.IO; +using System.Linq; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Subtitles; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using ServiceStack; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Subtitles +{ + [Route("/Videos/{Id}/Subtitles/{Index}", "DELETE", Summary = "Deletes an external subtitle file")] + [Authenticated] + public class DeleteSubtitle + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] + public string Id { get; set; } + + [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "DELETE")] + public int Index { get; set; } + } + + [Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")] + [Authenticated] + public class SearchRemoteSubtitles : IReturn> + { + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + + [ApiMember(Name = "Language", Description = "Language", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Language { get; set; } + } + + [Route("/Items/{Id}/RemoteSearch/Subtitles/Providers", "GET")] + [Authenticated] + public class GetSubtitleProviders : IReturn> + { + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/Items/{Id}/RemoteSearch/Subtitles/{SubtitleId}", "POST")] + [Authenticated] + public class DownloadRemoteSubtitles : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + [ApiMember(Name = "SubtitleId", Description = "SubtitleId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string SubtitleId { get; set; } + } + + [Route("/Providers/Subtitles/Subtitles/{Id}", "GET")] + [Authenticated] + public class GetRemoteSubtitles : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/Stream.{Format}", "GET", Summary = "Gets subtitles in a specified format (vtt).")] + public class GetSubtitle + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + + [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string MediaSourceId { get; set; } + + [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")] + public int Index { get; set; } + + [ApiMember(Name = "Format", Description = "Format", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Format { get; set; } + + [ApiMember(Name = "StartPositionTicks", Description = "StartPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public long StartPositionTicks { get; set; } + } + + public class SubtitleService : BaseApiService + { + private readonly ILibraryManager _libraryManager; + private readonly ISubtitleManager _subtitleManager; + private readonly ISubtitleEncoder _subtitleEncoder; + + public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder) + { + _libraryManager = libraryManager; + _subtitleManager = subtitleManager; + _subtitleEncoder = subtitleEncoder; + } + + public object Get(GetSubtitle request) + { + if (string.IsNullOrEmpty(request.Format)) + { + var item = (Video)_libraryManager.GetItemById(new Guid(request.Id)); + + var mediaSource = item.GetMediaSources(false) + .First(i => string.Equals(i.Id, request.MediaSourceId ?? request.Id)); + + var subtitleStream = mediaSource.MediaStreams + .First(i => i.Type == MediaStreamType.Subtitle && i.Index == request.Index); + + return ToStaticFileResult(subtitleStream.Path); + } + + var stream = GetSubtitles(request).Result; + + return ResultFactory.GetResult(stream, Common.Net.MimeTypes.GetMimeType("file." + request.Format)); + } + + private async Task GetSubtitles(GetSubtitle request) + { + return await _subtitleEncoder.GetSubtitles(request.Id, + request.MediaSourceId, + request.Index, + request.Format, + request.StartPositionTicks, + CancellationToken.None).ConfigureAwait(false); + } + + public object Get(SearchRemoteSubtitles request) + { + var video = (Video)_libraryManager.GetItemById(request.Id); + + var response = _subtitleManager.SearchSubtitles(video, request.Language, CancellationToken.None).Result; + + return ToOptimizedResult(response); + } + + public void Delete(DeleteSubtitle request) + { + var task = _subtitleManager.DeleteSubtitles(request.Id, request.Index); + + Task.WaitAll(task); + } + + public object Get(GetSubtitleProviders request) + { + var result = _subtitleManager.GetProviders(request.Id); + + return ToOptimizedResult(result); + } + + public object Get(GetRemoteSubtitles request) + { + var result = _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).Result; + + return ResultFactory.GetResult(result.Stream, Common.Net.MimeTypes.GetMimeType("file." + result.Format)); + } + + public void Post(DownloadRemoteSubtitles request) + { + var video = (Video)_libraryManager.GetItemById(request.Id); + + Task.Run(async () => + { + try + { + await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None) + .ConfigureAwait(false); + + await video.RefreshMetadata(new MetadataRefreshOptions(), CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + Logger.ErrorException("Error downloading subtitles", ex); + } + + }); + } + } +} diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs index 2f0741434a..6f2e83a796 100644 --- a/MediaBrowser.Api/SystemService.cs +++ b/MediaBrowser.Api/SystemService.cs @@ -1,6 +1,12 @@ -using MediaBrowser.Controller; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Net; using MediaBrowser.Model.System; using ServiceStack; +using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Threading.Tasks; namespace MediaBrowser.Api @@ -18,15 +24,30 @@ namespace MediaBrowser.Api /// Class RestartApplication /// [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")] + [Authenticated] public class RestartApplication { } [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")] + [Authenticated] public class ShutdownApplication { } + [Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")] + [Authenticated] + public class GetServerLogs : IReturn> + { + } + + [Route("/System/Logs/Log", "GET", Summary = "Gets a log file")] + public class GetLogFile + { + [ApiMember(Name = "Name", Description = "The log file name.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string Name { get; set; } + } + /// /// Class SystemInfoService /// @@ -36,16 +57,59 @@ namespace MediaBrowser.Api /// The _app host /// private readonly IServerApplicationHost _appHost; - + private readonly IApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; /// /// Initializes a new instance of the class. /// /// The app host. /// jsonSerializer - public SystemService(IServerApplicationHost appHost) + public SystemService(IServerApplicationHost appHost, IApplicationPaths appPaths, IFileSystem fileSystem) { _appHost = appHost; + _appPaths = appPaths; + _fileSystem = fileSystem; + } + + public object Get(GetServerLogs request) + { + List files; + + try + { + files = new DirectoryInfo(_appPaths.LogDirectoryPath) + .EnumerateFiles("*", SearchOption.AllDirectories) + .Where(i => string.Equals(i.Extension, ".txt", System.StringComparison.OrdinalIgnoreCase)) + .ToList(); + } + catch (DirectoryNotFoundException) + { + files = new List(); + } + + var result = files.Select(i => new LogFile + { + DateCreated = _fileSystem.GetCreationTimeUtc(i), + DateModified = _fileSystem.GetLastWriteTimeUtc(i), + Name = i.Name, + Size = i.Length + + }).OrderByDescending(i => i.DateModified) + .ThenByDescending(i => i.DateCreated) + .ThenBy(i => i.Name) + .ToList(); + + return ToOptimizedResult(result); + } + + public object Get(GetLogFile request) + { + var file = new DirectoryInfo(_appPaths.LogDirectoryPath) + .EnumerateFiles("*", SearchOption.AllDirectories) + .First(i => string.Equals(i.Name, request.Name, System.StringComparison.OrdinalIgnoreCase)); + + return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite); } /// diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index d1767e7fd9..55cdc8681e 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -717,9 +717,7 @@ namespace MediaBrowser.Api.UserLibrary await _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None).ConfigureAwait(false); - data = _userDataRepository.GetUserData(user.Id, key); - - return _dtoService.GetUserItemDataDto(data); + return _userDataRepository.GetUserDataDto(item, user); } /// @@ -766,9 +764,7 @@ namespace MediaBrowser.Api.UserLibrary await _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None).ConfigureAwait(false); - data = _userDataRepository.GetUserData(user.Id, key); - - return _dtoService.GetUserItemDataDto(data); + return _userDataRepository.GetUserDataDto(item, user); } /// @@ -936,7 +932,7 @@ namespace MediaBrowser.Api.UserLibrary await item.MarkUnplayed(user, _userDataRepository).ConfigureAwait(false); } - return _dtoService.GetUserItemDataDto(_userDataRepository.GetUserData(user.Id, item.GetUserDataKey())); + return _userDataRepository.GetUserDataDto(item, user); } } } diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 64d1fcb34c..cda489c94a 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -51,6 +51,7 @@ namespace MediaBrowser.Api /// Class DeleteUser /// [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")] + [Authenticated] public class DeleteUser : IReturnVoid { /// @@ -107,6 +108,7 @@ namespace MediaBrowser.Api /// Class UpdateUserPassword /// [Route("/Users/{Id}/Password", "POST", Summary = "Updates a user's password")] + [Authenticated] public class UpdateUserPassword : IReturnVoid { /// @@ -138,6 +140,7 @@ namespace MediaBrowser.Api /// Class UpdateUser /// [Route("/Users/{Id}", "POST", Summary = "Updates a user")] + [Authenticated] public class UpdateUser : UserDto, IReturnVoid { } @@ -146,6 +149,7 @@ namespace MediaBrowser.Api /// Class CreateUser /// [Route("/Users", "POST", Summary = "Creates a user")] + [Authenticated] public class CreateUser : UserDto, IReturn { } diff --git a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs deleted file mode 100644 index 46dabb0420..0000000000 --- a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs +++ /dev/null @@ -1,149 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.Api.WebSocket -{ - /// - /// Class ScheduledTasksWebSocketListener - /// - public class LogFileWebSocketListener : BasePeriodicWebSocketListener, LogFileWebSocketState> - { - /// - /// Gets the name. - /// - /// The name. - protected override string Name - { - get { return "LogFile"; } - } - - /// - /// The _kernel - /// - private readonly ILogManager _logManager; - private readonly IFileSystem _fileSystem; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The log manager. - public LogFileWebSocketListener(ILogger logger, ILogManager logManager, IFileSystem fileSystem) - : base(logger) - { - _logManager = logManager; - _fileSystem = fileSystem; - _logManager.LoggerLoaded += kernel_LoggerLoaded; - } - - /// - /// Gets the data to send. - /// - /// The state. - /// IEnumerable{System.String}. - protected override async Task> GetDataToSend(LogFileWebSocketState state) - { - if (!string.Equals(_logManager.LogFilePath, state.LastLogFilePath)) - { - state.LastLogFilePath = _logManager.LogFilePath; - state.StartLine = 0; - } - - var lines = await GetLogLines(state.LastLogFilePath, state.StartLine, _fileSystem).ConfigureAwait(false); - - state.StartLine += lines.Count; - - return lines; - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected override void Dispose(bool dispose) - { - if (dispose) - { - _logManager.LoggerLoaded -= kernel_LoggerLoaded; - } - base.Dispose(dispose); - } - - /// - /// Handles the LoggerLoaded event of the kernel control. - /// - /// The source of the event. - /// The instance containing the event data. - void kernel_LoggerLoaded(object sender, EventArgs e) - { - // Reset the startline for each connection whenever the logger reloads - lock (ActiveConnections) - { - foreach (var connection in ActiveConnections) - { - connection.Item4.StartLine = 0; - } - } - } - - /// - /// Gets the log lines. - /// - /// The log file path. - /// The start line. - /// Task{IEnumerable{System.String}}. - internal static async Task> GetLogLines(string logFilePath, int startLine, IFileSystem fileSystem) - { - var lines = new List(); - - using (var fs = fileSystem.GetFileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) - { - using (var reader = new StreamReader(fs)) - { - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - - if (line.IndexOf("Info -", StringComparison.OrdinalIgnoreCase) != -1 || - line.IndexOf("Warn -", StringComparison.OrdinalIgnoreCase) != -1 || - line.IndexOf("Error -", StringComparison.OrdinalIgnoreCase) != -1) - { - lines.Add(line); - } - } - } - } - - if (startLine > 0) - { - lines = lines.Skip(startLine).ToList(); - } - - return lines; - } - } - - /// - /// Class LogFileWebSocketState - /// - public class LogFileWebSocketState : WebSocketListenerState - { - /// - /// Gets or sets the last log file path. - /// - /// The last log file path. - public string LastLogFilePath { get; set; } - /// - /// Gets or sets the start line. - /// - /// The start line. - public int StartLine { get; set; } - } -} diff --git a/MediaBrowser.Common/Net/MimeTypes.cs b/MediaBrowser.Common/Net/MimeTypes.cs index 0cc4fc6b4d..dcac5e7ba6 100644 --- a/MediaBrowser.Common/Net/MimeTypes.cs +++ b/MediaBrowser.Common/Net/MimeTypes.cs @@ -199,6 +199,10 @@ namespace MediaBrowser.Common.Net { return "application/x-javascript"; } + if (ext.Equals(".map", StringComparison.OrdinalIgnoreCase)) + { + return "application/x-javascript"; + } if (ext.Equals(".woff", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index f9d7cc21af..0d0555dc0d 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -25,13 +25,6 @@ namespace MediaBrowser.Controller.Dto /// System.String. string GetDtoId(BaseItem item); - /// - /// Gets the user item data dto. - /// - /// The data. - /// UserItemDataDto. - UserItemDataDto GetUserItemDataDto(UserItemData data); - /// /// Attaches the primary image aspect ratio. /// diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 524d7097ba..0428347310 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Library; using MediaBrowser.Model.Logging; @@ -1571,5 +1572,19 @@ namespace MediaBrowser.Controller.Entities return path; } + + public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user) + { + if (RunTimeTicks.HasValue) + { + double pct = RunTimeTicks.Value; + + if (pct > 0) + { + pct = userData.PlaybackPositionTicks / pct; + dto.PlayedPercentage = 100 * pct; + } + } + } } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 584091b130..b886cef193 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MoreLinq; using System; @@ -769,6 +770,11 @@ namespace MediaBrowser.Controller.Entities /// IEnumerable{BaseItem}. /// public virtual IEnumerable GetChildren(User user, bool includeLinkedChildren) + { + return GetChildren(user, includeLinkedChildren, false); + } + + internal IEnumerable GetChildren(User user, bool includeLinkedChildren, bool includeHidden) { if (user == null) { @@ -780,7 +786,7 @@ namespace MediaBrowser.Controller.Entities var list = new List(); - var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, false); + var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, includeHidden, false); return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list; } @@ -796,9 +802,10 @@ namespace MediaBrowser.Controller.Entities /// The user. /// if set to true [include linked children]. /// The list. + /// if set to true [include hidden]. /// if set to true [recursive]. /// true if XXXX, false otherwise - private bool AddChildrenToList(User user, bool includeLinkedChildren, List list, bool recursive) + private bool AddChildrenToList(User user, bool includeLinkedChildren, List list, bool includeHidden, bool recursive) { var hasLinkedChildren = false; @@ -806,7 +813,7 @@ namespace MediaBrowser.Controller.Entities { if (child.IsVisible(user)) { - if (!child.IsHiddenFromUser(user)) + if (includeHidden || !child.IsHiddenFromUser(user)) { list.Add(child); } @@ -815,7 +822,7 @@ namespace MediaBrowser.Controller.Entities { var folder = (Folder)child; - if (folder.AddChildrenToList(user, includeLinkedChildren, list, true)) + if (folder.AddChildrenToList(user, includeLinkedChildren, list, includeHidden, true)) { hasLinkedChildren = true; } @@ -855,7 +862,7 @@ namespace MediaBrowser.Controller.Entities var list = new List(); - var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true); + var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, false, true); return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list; } @@ -1069,5 +1076,68 @@ namespace MediaBrowser.Controller.Entities return GetRecursiveChildren(user).Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual) .All(i => i.IsUnplayed(user)); } + + public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user) + { + var recursiveItemCount = 0; + var unplayed = 0; + + double totalPercentPlayed = 0; + + IEnumerable children; + var folder = this; + + var season = folder as Season; + + if (season != null) + { + children = season.GetEpisodes(user).Where(i => i.LocationType != LocationType.Virtual); + } + else + { + children = folder.GetRecursiveChildren(user) + .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual); + } + + // Loop through each recursive child + foreach (var child in children) + { + recursiveItemCount++; + + var isUnplayed = true; + + var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey()); + + // Incrememt totalPercentPlayed + if (itemUserData != null) + { + if (itemUserData.Played) + { + totalPercentPlayed += 100; + + isUnplayed = false; + } + else if (itemUserData.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0) + { + double itemPercent = itemUserData.PlaybackPositionTicks; + itemPercent /= child.RunTimeTicks.Value; + totalPercentPlayed += itemPercent; + } + } + + if (isUnplayed) + { + unplayed++; + } + } + + dto.UnplayedItemCount = unplayed; + + if (recursiveItemCount > 0) + { + dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount; + dto.Played = dto.PlayedPercentage.Value >= 100; + } + } } } diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs index 780181a61d..d576d90c45 100644 --- a/MediaBrowser.Controller/Entities/IHasUserData.cs +++ b/MediaBrowser.Controller/Entities/IHasUserData.cs @@ -1,4 +1,6 @@ - +using MediaBrowser.Model.Dto; +using System; + namespace MediaBrowser.Controller.Entities { /// @@ -6,10 +8,24 @@ namespace MediaBrowser.Controller.Entities /// public interface IHasUserData { + /// + /// Gets or sets the identifier. + /// + /// The identifier. + Guid Id { get; set; } + /// /// Gets the user data key. /// /// System.String. string GetUserDataKey(); + + /// + /// Fills the user data dto values. + /// + /// The dto. + /// The user data. + /// The user. + void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user); } } diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index b9630a66f4..847183fd00 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.Controller.Entities.TV { get { - return FindParent(); + return Season; } } diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index e5a8135c2d..6404e71ec6 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dto; using System; using System.Collections.Generic; using System.Linq; @@ -51,5 +52,10 @@ namespace MediaBrowser.Controller.Entities LibraryManager.RegisterItem(item); } } + + public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user) + { + // Nothing meaninful here and will only waste resources + } } } diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 86099fdc01..619a497f5f 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -44,7 +44,7 @@ namespace MediaBrowser.Controller.Entities var excludeFolderIds = user.Configuration.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).ToList(); return user.RootFolder - .GetChildren(user, true) + .GetChildren(user, true, true) .OfType() .Where(i => !excludeFolderIds.Contains(i.Id) && !IsExcludedFromGrouping(i)); } diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index 2bec9e3deb..9db91e7f22 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using System; using System.Threading; @@ -34,5 +35,13 @@ namespace MediaBrowser.Controller.Library /// The key. /// Task{UserItemData}. UserItemData GetUserData(Guid userId, string key); + + /// + /// Gets the user data dto. + /// + /// The item. + /// The user. + /// UserItemDataDto. + UserItemDataDto GetUserDataDto(IHasUserData item, User user); } } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs index 23610351e7..ba1cb30436 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Controller.LiveTv { - public interface ILiveTvRecording : IHasImages, IHasMediaSources + public interface ILiveTvRecording : IHasImages, IHasMediaSources, IHasUserData { string ServiceName { get; set; } @@ -20,8 +20,6 @@ namespace MediaBrowser.Controller.LiveTv string GetClientTypeName(); - string GetUserDataKey(); - bool IsParentalAllowed(User user); Task RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken); diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index 692d6db909..7f1ddbce9b 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -1,6 +1,6 @@ -using System; +using MediaBrowser.Model.Entities; +using System; using System.Collections.Generic; -using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers { @@ -18,6 +18,11 @@ namespace MediaBrowser.Controller.Providers /// [Obsolete] public bool ForceSave { get; set; } + + public MetadataRefreshOptions() + { + MetadataRefreshMode = MetadataRefreshMode.Default; + } } public class ImageRefreshOptions @@ -38,48 +43,54 @@ namespace MediaBrowser.Controller.Providers public bool IsReplacingImage(ImageType type) { - return ReplaceAllImages || ReplaceImages.Contains(type); + return ImageRefreshMode == ImageRefreshMode.FullRefresh && + (ReplaceAllImages || ReplaceImages.Contains(type)); } } public enum MetadataRefreshMode { /// - /// Providers will be executed based on default rules + /// The none /// - EnsureMetadata = 0, + None = 0, /// - /// No providers will be executed + /// The validation only /// - None = 1, + ValidationOnly = 1, /// - /// All providers will be executed to search for new metadata + /// Providers will be executed based on default rules /// - FullRefresh = 2, + Default = 2, /// - /// The validation only + /// All providers will be executed to search for new metadata /// - ValidationOnly = 3 + FullRefresh = 3 } public enum ImageRefreshMode { + /// + /// The none + /// + None = 0, + /// /// The default /// - Default = 0, + Default = 1, /// /// Existing images will be validated /// - ValidationOnly = 1, + ValidationOnly = 2, /// /// All providers will be executed to search for new metadata /// - FullRefresh = 2 + FullRefresh = 3 } } diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 6d3a9d20cf..7b20621827 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -219,7 +219,13 @@ namespace MediaBrowser.Controller.Session /// Name of the device. /// The remote end point. /// Task{SessionInfo}. - Task AuthenticateNewSession(string username, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint); + Task AuthenticateNewSession(string username, + string password, + string clientType, + string appVersion, + string deviceId, + string deviceName, + string remoteEndPoint); /// /// Reports the capabilities. diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 0ed49d5f89..91c1508fc1 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -77,6 +77,9 @@ ApiClient\SessionUpdatesEventArgs.cs + + Branding\BrandingOptions.cs + Channels\ChannelFeatures.cs @@ -815,6 +818,9 @@ Session\UserDataChangeInfo.cs + + System\LogFile.cs + System\SystemInfo.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 12c87ca97a..782e8524db 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -64,6 +64,9 @@ ApiClient\SessionUpdatesEventArgs.cs + + Branding\BrandingOptions.cs + Channels\ChannelFeatures.cs @@ -796,6 +799,9 @@ Session\UserDataChangeInfo.cs + + System\LogFile.cs + System\SystemInfo.cs diff --git a/MediaBrowser.Model/Branding/BrandingOptions.cs b/MediaBrowser.Model/Branding/BrandingOptions.cs new file mode 100644 index 0000000000..737cb5c48f --- /dev/null +++ b/MediaBrowser.Model/Branding/BrandingOptions.cs @@ -0,0 +1,12 @@ + +namespace MediaBrowser.Model.Branding +{ + public class BrandingOptions + { + /// + /// Gets or sets the login disclaimer. + /// + /// The login disclaimer. + public string LoginDisclaimer { get; set; } + } +} diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 36c353479f..49b731341a 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -158,9 +158,6 @@ namespace MediaBrowser.Model.Configuration public bool EnableTmdbUpdates { get; set; } public bool EnableFanArtUpdates { get; set; } - public bool RequireMobileManualLogin { get; set; } - public bool RequireNonMobileManualLogin { get; set; } - /// /// Gets or sets the image saving convention. /// diff --git a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs index db8b69951a..86eb40b975 100644 --- a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs +++ b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs @@ -10,12 +10,15 @@ namespace MediaBrowser.Model.Configuration public bool SaveImagePathsInNfo { get; set; } public bool EnablePathSubstitution { get; set; } + public bool EnableExtraThumbsDuplication { get; set; } + public XbmcMetadataOptions() { ReleaseDateFormat = "yyyy-MM-dd"; SaveImagePathsInNfo = true; EnablePathSubstitution = true; + EnableExtraThumbsDuplication = true; } } } diff --git a/MediaBrowser.Model/Dto/UserItemDataDto.cs b/MediaBrowser.Model/Dto/UserItemDataDto.cs index 26b0e9d9e8..6ee9f19163 100644 --- a/MediaBrowser.Model/Dto/UserItemDataDto.cs +++ b/MediaBrowser.Model/Dto/UserItemDataDto.cs @@ -1,6 +1,6 @@ -using System; +using MediaBrowser.Model.Extensions; +using System; using System.ComponentModel; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Dto { @@ -15,6 +15,18 @@ namespace MediaBrowser.Model.Dto /// The rating. public double? Rating { get; set; } + /// + /// Gets or sets the played percentage. + /// + /// The played percentage. + public double? PlayedPercentage { get; set; } + + /// + /// Gets or sets the unplayed item count. + /// + /// The unplayed item count. + public int? UnplayedItemCount { get; set; } + /// /// Gets or sets the playback position ticks. /// diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index d758f2f394..4d4ca8e20c 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -65,6 +65,7 @@ + @@ -294,6 +295,7 @@ + diff --git a/MediaBrowser.Model/Notifications/NotificationRequest.cs b/MediaBrowser.Model/Notifications/NotificationRequest.cs index f511d41a97..6e9368f441 100644 --- a/MediaBrowser.Model/Notifications/NotificationRequest.cs +++ b/MediaBrowser.Model/Notifications/NotificationRequest.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Model.Configuration; -using System; +using System; using System.Collections.Generic; namespace MediaBrowser.Model.Notifications diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs index 40723eff83..98df3efe55 100644 --- a/MediaBrowser.Model/Session/SessionInfoDto.cs +++ b/MediaBrowser.Model/Session/SessionInfoDto.cs @@ -1,32 +1,20 @@ using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Extensions; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Session { [DebuggerDisplay("Client = {Client}, Username = {UserName}")] public class SessionInfoDto : IHasPropertyChangedEvent { - /// - /// Gets or sets a value indicating whether this instance can seek. - /// - /// true if this instance can seek; otherwise, false. - public bool CanSeek { get; set; } - /// /// Gets or sets the supported commands. /// /// The supported commands. public List SupportedCommands { get; set; } - - /// - /// Gets or sets the remote end point. - /// - /// The remote end point. - public string RemoteEndPoint { get; set; } /// /// Gets or sets the queueable media types. @@ -99,18 +87,6 @@ namespace MediaBrowser.Model.Session /// /// The name of the device. public string DeviceName { get; set; } - - /// - /// Gets or sets a value indicating whether this instance is paused. - /// - /// true if this instance is paused; otherwise, false. - public bool IsPaused { get; set; } - - /// - /// Gets or sets a value indicating whether this instance is muted. - /// - /// true if this instance is muted; otherwise, false. - public bool IsMuted { get; set; } /// /// Gets or sets the now playing item. @@ -118,12 +94,6 @@ namespace MediaBrowser.Model.Session /// The now playing item. public BaseItemInfo NowPlayingItem { get; set; } - /// - /// Gets or sets the now playing position ticks. - /// - /// The now playing position ticks. - public long? NowPlayingPositionTicks { get; set; } - /// /// Gets or sets the device id. /// diff --git a/MediaBrowser.Model/System/LogFile.cs b/MediaBrowser.Model/System/LogFile.cs new file mode 100644 index 0000000000..ba409c5423 --- /dev/null +++ b/MediaBrowser.Model/System/LogFile.cs @@ -0,0 +1,31 @@ +using System; + +namespace MediaBrowser.Model.System +{ + public class LogFile + { + /// + /// Gets or sets the date created. + /// + /// The date created. + public DateTime DateCreated { get; set; } + + /// + /// Gets or sets the date modified. + /// + /// The date modified. + public DateTime DateModified { get; set; } + + /// + /// Gets or sets the size. + /// + /// The size. + public long Size { get; set; } + + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; set; } + } +} diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 12af93dbd1..1b2e9fa6d6 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.IO; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -441,11 +442,16 @@ namespace MediaBrowser.Providers.Manager var extraFanartFilename = GetBackdropSaveFilename(item.GetImages(ImageType.Backdrop), "fanart", "fanart", outputIndex); - return new[] - { - Path.Combine(item.ContainingFolderPath, "extrafanart", extraFanartFilename + extension), - Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(UsCulture) + extension) - }; + var list = new List + { + Path.Combine(item.ContainingFolderPath, "extrafanart", extraFanartFilename + extension) + }; + + if (EnableExtraThumbsDuplication) + { + list.Add(Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(UsCulture) + extension)); + } + return list.ToArray(); } if (type == ImageType.Primary) @@ -528,6 +534,16 @@ namespace MediaBrowser.Providers.Manager return new[] { GetStandardSavePath(item, type, imageIndex, mimeType, true) }; } + private bool EnableExtraThumbsDuplication + { + get + { + var config = _config.GetConfiguration("xbmcmetadata"); + + return config.EnableExtraThumbsDuplication; + } + } + /// /// Gets the save path for item in mixed folder. /// diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 92b4616e71..57a40741f5 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -234,7 +234,7 @@ namespace MediaBrowser.Providers.MediaInfo await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false); if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || - options.MetadataRefreshMode == MetadataRefreshMode.EnsureMetadata) + options.MetadataRefreshMode == MetadataRefreshMode.Default) { try { @@ -460,7 +460,7 @@ namespace MediaBrowser.Providers.MediaInfo var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, currentStreams.Count, options.DirectoryService, false).ToList(); - var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.EnsureMetadata || + var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh; if (enableSubtitleDownloading && (_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles && diff --git a/MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs b/MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs new file mode 100644 index 0000000000..d6cd3424b1 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs @@ -0,0 +1,21 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Branding; +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.Branding +{ + public class BrandingConfigurationFactory : IConfigurationFactory + { + public IEnumerable GetConfigurations() + { + return new[] + { + new ConfigurationStore + { + ConfigurationType = typeof(BrandingOptions), + Key = "branding" + } + }; + } + } +} diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 73216ca33c..62ff9f6879 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -212,6 +212,12 @@ namespace MediaBrowser.Server.Implementations.Dto { if (item.IsFolder) { + var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey()); + + // Skip the user data manager because we've already looped through the recursive tree and don't want to do it twice + // TODO: Improve in future + dto.UserData = GetUserItemDataDto(userData); + var folder = (Folder)item; dto.ChildCount = GetChildCount(folder, user); @@ -220,15 +226,15 @@ namespace MediaBrowser.Server.Implementations.Dto { SetSpecialCounts(folder, user, dto, fields); } - } - var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey()); - - dto.UserData = GetUserItemDataDto(userData); + dto.UserData.Played = dto.PlayedPercentage.HasValue && dto.PlayedPercentage.Value >= 100; + dto.UserData.PlayedPercentage = dto.PlayedPercentage; + dto.UserData.UnplayedItemCount = dto.RecursiveUnplayedItemCount; + } - if (item.IsFolder) + else { - dto.UserData.Played = dto.PlayedPercentage.HasValue && dto.PlayedPercentage.Value >= 100; + dto.UserData = _userDataRepository.GetUserDataDto(item, user); } dto.PlayAccess = item.GetPlayAccess(user); @@ -1110,16 +1116,17 @@ namespace MediaBrowser.Server.Implementations.Dto if (episode != null) { - series = item.FindParent(); + series = episode.Series; - dto.SeriesId = GetDtoId(series); - dto.SeriesName = series.Name; - dto.AirTime = series.AirTime; - dto.SeriesStudio = series.Studios.FirstOrDefault(); - - dto.SeriesThumbImageTag = GetImageCacheTag(series, ImageType.Thumb); - - dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary); + if (series != null) + { + dto.SeriesId = GetDtoId(series); + dto.SeriesName = series.Name; + dto.AirTime = series.AirTime; + dto.SeriesStudio = series.Studios.FirstOrDefault(); + dto.SeriesThumbImageTag = GetImageCacheTag(series, ImageType.Thumb); + dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary); + } } // Add SeasonInfo @@ -1127,14 +1134,17 @@ namespace MediaBrowser.Server.Implementations.Dto if (season != null) { - series = item.FindParent(); + series = season.Series; - dto.SeriesId = GetDtoId(series); - dto.SeriesName = series.Name; - dto.AirTime = series.AirTime; - dto.SeriesStudio = series.Studios.FirstOrDefault(); + if (series != null) + { + dto.SeriesId = GetDtoId(series); + dto.SeriesName = series.Name; + dto.AirTime = series.AirTime; + dto.SeriesStudio = series.Studios.FirstOrDefault(); - dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary); + dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary); + } } var game = item as Game; diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs index d7186aa211..c31f462150 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -1,10 +1,11 @@ -using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Session; +using MoreLinq; using System; using System.Collections.Generic; using System.Linq; @@ -17,21 +18,21 @@ namespace MediaBrowser.Server.Implementations.EntryPoints { private readonly ISessionManager _sessionManager; private readonly ILogger _logger; - private readonly IDtoService _dtoService; private readonly IUserDataManager _userDataManager; + private readonly IUserManager _userManager; private readonly object _syncLock = new object(); private Timer UpdateTimer { get; set; } private const int UpdateDuration = 500; - private readonly Dictionary> _changedKeys = new Dictionary>(); + private readonly Dictionary> _changedItems = new Dictionary>(); - public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, IDtoService dtoService, ILogger logger) + public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager) { _userDataManager = userDataManager; _sessionManager = sessionManager; - _dtoService = dtoService; _logger = logger; + _userManager = userManager; } public void Run() @@ -58,15 +59,28 @@ namespace MediaBrowser.Server.Implementations.EntryPoints UpdateTimer.Change(UpdateDuration, Timeout.Infinite); } - List keys; + List keys; - if (!_changedKeys.TryGetValue(e.UserId, out keys)) + if (!_changedItems.TryGetValue(e.UserId, out keys)) { - keys = new List(); - _changedKeys[e.UserId] = keys; + keys = new List(); + _changedItems[e.UserId] = keys; } - keys.Add(e.Key); + keys.Add(e.Item); + + var baseItem = e.Item as BaseItem; + + // Go up one level for indicators + if (baseItem != null) + { + var parent = baseItem.Parent; + + if (parent != null) + { + keys.Add(parent); + } + } } } @@ -75,8 +89,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints lock (_syncLock) { // Remove dupes in case some were saved multiple times - var changes = _changedKeys.ToList(); - _changedKeys.Clear(); + var changes = _changedItems.ToList(); + _changedItems.Clear(); SendNotifications(changes, CancellationToken.None); @@ -88,7 +102,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints } } - private async Task SendNotifications(IEnumerable>> changes, CancellationToken cancellationToken) + private async Task SendNotifications(IEnumerable>> changes, CancellationToken cancellationToken) { foreach (var pair in changes) { @@ -99,8 +113,11 @@ namespace MediaBrowser.Server.Implementations.EntryPoints if (userSessions.Count > 0) { + var user = _userManager.GetUserById(userId); + var dtoList = pair.Value - .Select(i => _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(userId, i))) + .DistinctBy(i => i.Id) + .Select(i => _userDataManager.GetUserDataDto(i, user)) .ToList(); var info = new UserDataChangeInfo diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 833dfc5e45..cfcbb077e9 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -363,19 +363,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer { try { - var errorResponse = new ErrorResponse - { - ResponseStatus = new ResponseStatus - { - ErrorCode = ex.GetType().GetOperationName(), - Message = ex.Message, - StackTrace = ex.StackTrace, - } - }; - var operationName = context.Request.GetOperationName(); var httpReq = GetRequest(context, operationName); var httpRes = httpReq.Response; + + if (httpRes.IsClosed) + { + return; + } + var contentType = httpReq.ResponseContentType; var serializer = HostContext.ContentTypes.GetResponseSerializer(contentType); @@ -398,6 +394,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer httpRes.ContentType = contentType; + var errorResponse = new ErrorResponse + { + ResponseStatus = new ResponseStatus + { + ErrorCode = ex.GetType().GetOperationName(), + Message = ex.Message, + StackTrace = ex.StackTrace, + } + }; + serializer(httpReq, errorResponse, httpRes); httpRes.Close(); diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 77343ab4ef..94be37e956 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -36,6 +36,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security auth.TryGetValue("Version", out version); } + var token = httpReq.Headers["X-MediaBrowser-Token"]; + + if (string.IsNullOrWhiteSpace(token)) + { + token = httpReq.QueryString["api_key"]; + } + return new AuthorizationInfo { Client = client, @@ -43,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security DeviceId = deviceId, UserId = userId, Version = version, - Token = httpReq.Headers["X-AUTH-TOKEN"] + Token = token }; } diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs index 79f1265116..d3030f31f9 100644 --- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; @@ -125,5 +126,41 @@ namespace MediaBrowser.Server.Implementations.Library { return userId + key; } + + public UserItemDataDto GetUserDataDto(IHasUserData item, User user) + { + var userData = GetUserData(user.Id, item.GetUserDataKey()); + var dto = GetUserItemDataDto(userData); + + item.FillUserDataDtoValues(dto, userData, user); + + return dto; + } + + /// + /// Converts a UserItemData to a DTOUserItemData + /// + /// The data. + /// DtoUserItemData. + /// + private UserItemDataDto GetUserItemDataDto(UserItemData data) + { + if (data == null) + { + throw new ArgumentNullException("data"); + } + + return new UserItemDataDto + { + IsFavorite = data.IsFavorite, + Likes = data.Likes, + PlaybackPositionTicks = data.PlaybackPositionTicks, + PlayCount = data.PlayCount, + Rating = data.Rating, + Played = data.Played, + LastPlayedDate = data.LastPlayedDate, + Key = data.Key + }; + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index 412b2e7bd0..9c69e656d7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -4,7 +4,6 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; @@ -23,15 +22,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly IUserDataManager _userDataManager; private readonly IDtoService _dtoService; - private readonly IItemRepository _itemRepo; - public LiveTvDtoService(IDtoService dtoService, IUserDataManager userDataManager, IImageProcessor imageProcessor, ILogger logger, IItemRepository itemRepo) + public LiveTvDtoService(IDtoService dtoService, IUserDataManager userDataManager, IImageProcessor imageProcessor, ILogger logger) { _dtoService = dtoService; _userDataManager = userDataManager; _imageProcessor = imageProcessor; _logger = logger; - _itemRepo = itemRepo; } public TimerInfoDto GetTimerInfoDto(TimerInfo info, ILiveTvService service, LiveTvProgram program, LiveTvChannel channel) @@ -249,7 +246,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (user != null) { - dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, recording.GetUserDataKey())); + dto.UserData = _userDataManager.GetUserDataDto(recording, user); dto.PlayAccess = recording.GetPlayAccess(user); } @@ -322,7 +319,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (user != null) { - dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, info.GetUserDataKey())); + dto.UserData = _userDataManager.GetUserDataDto(info, user); dto.PlayAccess = info.GetPlayAccess(user); } @@ -401,7 +398,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (user != null) { - dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, item.GetUserDataKey())); + dto.UserData = _userDataManager.GetUserDataDto(item, user); dto.PlayAccess = item.GetPlayAccess(user); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index ad1ddba881..09793f4fc7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -40,7 +40,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly IUserDataManager _userDataManager; private readonly ILibraryManager _libraryManager; private readonly ITaskManager _taskManager; - private readonly IJsonSerializer _json; private readonly IDtoService _dtoService; private readonly ILocalizationManager _localization; @@ -58,7 +57,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly SemaphoreSlim _refreshSemaphore = new SemaphoreSlim(1, 1); - public LiveTvManager(IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, IJsonSerializer json, ILocalizationManager localization) + public LiveTvManager(IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization) { _config = config; _fileSystem = fileSystem; @@ -67,12 +66,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv _userManager = userManager; _libraryManager = libraryManager; _taskManager = taskManager; - _json = json; _localization = localization; _dtoService = dtoService; _userDataManager = userDataManager; - _tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger, _itemRepo); + _tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger); } /// diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 3bd0df0eb5..d6d4bbc516 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -258,11 +258,11 @@ "LabelCachePath": "Cache path:", "LabelCachePathHelp": "This folder contains server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", - "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder.", + "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", "TabTV": "TV", "TabGames": "Games", @@ -284,7 +284,7 @@ "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.", - "OptionImageSavingCompatible": "Compatible - Media Browser/Plex/Xbmc", + "OptionImageSavingCompatible": "Compatible - Media Browser/Xbmc/Plex", "OptionImageSavingStandard": "Standard - MB2", "ButtonSignIn": "Sign In", "TitleSignIn": "Sign In", @@ -849,5 +849,14 @@ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.", "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", - "LabelDisplayCollectionsView": "Display a Collections view to show movie collections" + "LabelDisplayCollectionsView": "Display a Collections view to show movie collections", + "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", + "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.", + "TabServices": "Services", + "TabLogs": "Logs", + "HeaderServerLogFiles": "Server log files:", + "TabBranding": "Branding", + "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.", + "LabelLoginDisclaimer": "Login disclaimer:", + "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page." } \ 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 a909929ae0..1d201e0690 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -101,6 +101,7 @@ Properties\SharedVersion.cs + diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs index 964e2cd243..b832f3a06b 100644 --- a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs +++ b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs @@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Notifications; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Notifications; using System; @@ -93,7 +92,9 @@ namespace MediaBrowser.Server.Implementations.Notifications if (options != null && !string.IsNullOrWhiteSpace(request.NotificationType)) { - return _userManager.Users.Where(i => _config.Configuration.NotificationOptions.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Configuration)) + var config = GetConfiguration(); + + return _userManager.Users.Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Configuration)) .Select(i => i.Id.ToString("N")); } diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 2f6790a3e8..2d85a3aa7f 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -1,4 +1,6 @@ -using MediaBrowser.Common.Events; +using System.Security.Cryptography; +using System.Text; +using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; @@ -1185,6 +1187,24 @@ namespace MediaBrowser.Server.Implementations.Session }; } + private bool IsLocal(string remoteEndpoint) + { + if (string.IsNullOrWhiteSpace(remoteEndpoint)) + { + throw new ArgumentNullException("remoteEndpoint"); + } + + // Private address space: + // http://en.wikipedia.org/wiki/Private_network + + return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 || + remoteEndpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) || + remoteEndpoint.StartsWith("192.", StringComparison.OrdinalIgnoreCase) || + remoteEndpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase) || + remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) || + remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase); + } + /// /// Reports the capabilities. /// @@ -1283,15 +1303,10 @@ namespace MediaBrowser.Server.Implementations.Session DeviceName = session.DeviceName, Id = session.Id, LastActivityDate = session.LastActivityDate, - NowPlayingPositionTicks = session.PlayState.PositionTicks, - IsPaused = session.PlayState.IsPaused, - IsMuted = session.PlayState.IsMuted, NowViewingItem = session.NowViewingItem, ApplicationVersion = session.ApplicationVersion, - CanSeek = session.PlayState.CanSeek, QueueableMediaTypes = session.QueueableMediaTypes, PlayableMediaTypes = session.PlayableMediaTypes, - RemoteEndPoint = session.RemoteEndPoint, AdditionalUsers = session.AdditionalUsers, SupportedCommands = session.SupportedCommands, UserName = session.UserName, diff --git a/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs index 46c3df07b7..7e6a252cdc 100644 --- a/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs @@ -26,13 +26,36 @@ namespace MediaBrowser.Server.Implementations.Sorting /// System.String. private DateTime GetValue(BaseItem x) { - var series = (x as Series) ?? x.FindParent(); + var series = x as Series; - DateTime result; - if (series != null && DateTime.TryParse(series.AirTime, out result)) + if (series == null) { - return result; - } + var season = x as Season; + + if (season != null) + { + series = season.Series; + } + else + { + var episode = x as Episode; + + if (episode != null) + { + series = episode.Series; + } + } + } + + if (series != null) + { + DateTime result; + if (DateTime.TryParse(series.AirTime, out result)) + { + return result; + } + } + return DateTime.MinValue; } diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 673a9f1519..91e92e21c5 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -654,7 +654,7 @@ namespace MediaBrowser.ServerApplication var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor); RegisterSingleInstance(collectionManager); - LiveTvManager = new LiveTvManager(ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, JsonSerializer, LocalizationManager); + LiveTvManager = new LiveTvManager(ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager); RegisterSingleInstance(LiveTvManager); UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, FileSystemManager, UserManager, ChannelManager, LiveTvManager); diff --git a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs index 4ba98e9b69..c2c64ea4d4 100644 --- a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs +++ b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs @@ -86,18 +86,6 @@ namespace MediaBrowser.ServerApplication.Native appHost.WebApplicationName + "/swagger-ui/index.html", logger); } - /// - /// Opens the standard API documentation. - /// - /// The configuration manager. - /// The app host. - /// The logger. - public static void OpenStandardApiDocumentation(IServerConfigurationManager configurationManager, IServerApplicationHost appHost, ILogger logger) - { - OpenUrl("http://localhost:" + configurationManager.Configuration.HttpServerPortNumber + "/" + - appHost.WebApplicationName + "/metadata", logger); - } - /// /// Opens the URL. /// diff --git a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs index f5f9434e7d..47a4be8e36 100644 --- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs +++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs @@ -29,7 +29,6 @@ namespace MediaBrowser.ServerApplication private System.Windows.Forms.ToolStripMenuItem cmdLogWindow; private System.Windows.Forms.ToolStripMenuItem cmdCommunity; private System.Windows.Forms.ToolStripMenuItem cmdApiDocs; - private System.Windows.Forms.ToolStripMenuItem cmdStandardDocs; private System.Windows.Forms.ToolStripMenuItem cmdSwagger; private System.Windows.Forms.ToolStripMenuItem cmdGtihub; @@ -90,7 +89,6 @@ namespace MediaBrowser.ServerApplication cmdConfigure = new System.Windows.Forms.ToolStripMenuItem(); cmdBrowse = new System.Windows.Forms.ToolStripMenuItem(); cmdApiDocs = new System.Windows.Forms.ToolStripMenuItem(); - cmdStandardDocs = new System.Windows.Forms.ToolStripMenuItem(); cmdSwagger = new System.Windows.Forms.ToolStripMenuItem(); cmdGtihub = new System.Windows.Forms.ToolStripMenuItem(); @@ -169,17 +167,11 @@ namespace MediaBrowser.ServerApplication // cmdApiDocs // cmdApiDocs.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - cmdStandardDocs, cmdSwagger, cmdGtihub}); cmdApiDocs.Name = "cmdApiDocs"; cmdApiDocs.Size = new System.Drawing.Size(208, 22); // - // cmdStandardDocs - // - cmdStandardDocs.Name = "cmdStandardDocs"; - cmdStandardDocs.Size = new System.Drawing.Size(136, 22); - // // cmdSwagger // cmdSwagger.Name = "cmdSwagger"; @@ -199,7 +191,6 @@ namespace MediaBrowser.ServerApplication cmdLibraryExplorer.Click += cmdLibraryExplorer_Click; cmdSwagger.Click += cmdSwagger_Click; - cmdStandardDocs.Click += cmdStandardDocs_Click; cmdGtihub.Click += cmdGtihub_Click; LoadLogWindow(null, EventArgs.Empty); @@ -224,7 +215,6 @@ namespace MediaBrowser.ServerApplication cmdCommunity.Text = _localization.GetLocalizedString("LabelVisitCommunity"); cmdGtihub.Text = _localization.GetLocalizedString("LabelGithubWiki"); cmdSwagger.Text = _localization.GetLocalizedString("LabelSwagger"); - cmdStandardDocs.Text = _localization.GetLocalizedString("LabelStandard"); cmdApiDocs.Text = _localization.GetLocalizedString("LabelViewApiDocumentation"); cmdBrowse.Text = _localization.GetLocalizedString("LabelBrowseLibrary"); cmdConfigure.Text = _localization.GetLocalizedString("LabelConfigureMediaBrowser"); @@ -346,11 +336,6 @@ namespace MediaBrowser.ServerApplication BrowserLauncher.OpenGithub(_logger); } - void cmdStandardDocs_Click(object sender, EventArgs e) - { - BrowserLauncher.OpenStandardApiDocumentation(_configurationManager, _appHost, _logger); - } - void cmdSwagger_Click(object sender, EventArgs e) { BrowserLauncher.OpenSwagger(_configurationManager, _appHost, _logger); diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 3ccf26c375..36adae71c7 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -521,6 +521,7 @@ namespace MediaBrowser.WebDashboard.Api "mediacontroller.js", "chromecast.js", "backdrops.js", + "branding.js", "mediaplayer.js", "mediaplayer-video.js", @@ -529,7 +530,6 @@ namespace MediaBrowser.WebDashboard.Api "ratingdialog.js", "aboutpage.js", - "allusersettings.js", "alphapicker.js", "addpluginpage.js", "advancedconfigurationpage.js", @@ -537,7 +537,6 @@ namespace MediaBrowser.WebDashboard.Api "advancedserversettings.js", "metadataadvanced.js", "appsplayback.js", - "appsweather.js", "autoorganizetv.js", "autoorganizelog.js", "channels.js", diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 8f85fcb513..0099daaf19 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -98,6 +98,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -392,9 +395,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -617,6 +617,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -1499,9 +1502,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -1748,11 +1748,6 @@ PreserveNewest - - - PreserveNewest - - PreserveNewest @@ -1814,11 +1809,6 @@ PreserveNewest - - - PreserveNewest - - PreserveNewest -- cgit v1.2.3 From c02e917f5657db4bd76fc6ca17c535fc441c641c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 7 Jul 2014 21:41:03 -0400 Subject: completed auth database --- MediaBrowser.Api/ApiEntryPoint.cs | 34 +-- MediaBrowser.Api/ConfigurationService.cs | 1 + MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 9 +- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 3 +- MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs | 2 +- MediaBrowser.Api/SessionsService.cs | 18 +- MediaBrowser.Api/SystemService.cs | 1 + MediaBrowser.Api/UserService.cs | 32 +- .../Channels/ChannelItemInfo.cs | 13 +- .../Collections/CollectionEvents.cs | 37 +++ .../Collections/ICollectionManager.cs | 15 + MediaBrowser.Controller/Dto/IDtoService.cs | 7 + .../MediaBrowser.Controller.csproj | 4 + .../Providers/IMetadataProvider.cs | 1 + .../Security/AuthenticationInfo.cs | 61 ++++ .../Security/AuthenticationInfoQuery.cs | 42 +++ .../Security/IAuthenticationRepository.cs | 39 +++ MediaBrowser.Controller/Session/ISessionManager.cs | 25 +- MediaBrowser.Controller/Session/SessionInfo.cs | 2 +- MediaBrowser.LocalMetadata/BaseXmlProvider.cs | 10 +- MediaBrowser.Model/ApiClient/IApiClient.cs | 19 +- .../Configuration/ServerConfiguration.cs | 2 + MediaBrowser.Model/Users/AuthenticationResult.cs | 2 +- MediaBrowser.Providers/Manager/MetadataService.cs | 1 - MediaBrowser.Providers/Manager/ProviderUtils.cs | 2 +- .../TV/MovieDbEpisodeImageProvider.cs | 2 +- .../Channels/ChannelManager.cs | 3 +- .../Collections/CollectionManager.cs | 57 +++- .../HttpServer/Security/AuthService.cs | 48 +-- .../MediaBrowser.Server.Implementations.csproj | 1 + .../SqliteFileOrganizationRepository.cs | 2 +- .../Security/AuthenticationRepository.cs | 338 +++++++++++++++++++++ .../Session/SessionManager.cs | 159 +++++++++- MediaBrowser.ServerApplication/ApplicationHost.cs | 20 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 2 +- .../Providers/BaseNfoProvider.cs | 10 +- MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs | 13 +- .../Savers/XmlSaverHelpers.cs | 22 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 41 files changed, 933 insertions(+), 136 deletions(-) create mode 100644 MediaBrowser.Controller/Collections/CollectionEvents.cs create mode 100644 MediaBrowser.Controller/Security/AuthenticationInfo.cs create mode 100644 MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs create mode 100644 MediaBrowser.Controller/Security/IAuthenticationRepository.cs create mode 100644 MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 8e6ca44014..f255339bc3 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Api private readonly ISessionManager _sessionManager; - public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1,1); + public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1, 1); /// /// Initializes a new instance of the class. @@ -102,7 +102,7 @@ namespace MediaBrowser.Api { var jobCount = _activeTranscodingJobs.Count; - Parallel.ForEach(_activeTranscodingJobs.ToList(), j => KillTranscodingJob(j, FileDeleteMode.All)); + Parallel.ForEach(_activeTranscodingJobs.ToList(), j => KillTranscodingJob(j, path => true)); // Try to allow for some time to kill the ffmpeg processes and delete the partial stream files if (jobCount > 0) @@ -295,17 +295,18 @@ namespace MediaBrowser.Api { var job = (TranscodingJob)state; - KillTranscodingJob(job, FileDeleteMode.All); + KillTranscodingJob(job, path => true); } /// /// Kills the single transcoding job. /// /// The device id. - /// The delete mode. + /// The delete. /// if set to true [acquire lock]. + /// Task. /// sourcePath - internal async Task KillTranscodingJobs(string deviceId, FileDeleteMode deleteMode, bool acquireLock) + internal async Task KillTranscodingJobs(string deviceId, Func delete, bool acquireLock) { if (string.IsNullOrEmpty(deviceId)) { @@ -330,12 +331,12 @@ namespace MediaBrowser.Api { await TranscodingStartLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); } - + try { foreach (var job in jobs) { - KillTranscodingJob(job, deleteMode); + KillTranscodingJob(job, delete); } } finally @@ -352,10 +353,11 @@ namespace MediaBrowser.Api /// /// The device identifier. /// The type. - /// The delete mode. + /// The delete. /// if set to true [acquire lock]. + /// Task. /// deviceId - internal async Task KillTranscodingJobs(string deviceId, TranscodingJobType type, FileDeleteMode deleteMode, bool acquireLock) + internal async Task KillTranscodingJobs(string deviceId, TranscodingJobType type, Func delete, bool acquireLock) { if (string.IsNullOrEmpty(deviceId)) { @@ -385,7 +387,7 @@ namespace MediaBrowser.Api { foreach (var job in jobs) { - KillTranscodingJob(job, deleteMode); + KillTranscodingJob(job, delete); } } finally @@ -401,8 +403,8 @@ namespace MediaBrowser.Api /// Kills the transcoding job. /// /// The job. - /// The delete mode. - private void KillTranscodingJob(TranscodingJob job, FileDeleteMode deleteMode) + /// The delete. + private void KillTranscodingJob(TranscodingJob job, Func delete) { lock (_activeTranscodingJobs) { @@ -454,7 +456,7 @@ namespace MediaBrowser.Api } } - if (deleteMode == FileDeleteMode.All) + if (delete(job.Path)) { DeletePartialStreamFiles(job.Path, job.Type, 0, 1500); } @@ -593,10 +595,4 @@ namespace MediaBrowser.Api /// Hls } - - public enum FileDeleteMode - { - None, - All - } } diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs index e628c5f7af..6710461ad9 100644 --- a/MediaBrowser.Api/ConfigurationService.cs +++ b/MediaBrowser.Api/ConfigurationService.cs @@ -18,6 +18,7 @@ namespace MediaBrowser.Api /// Class GetConfiguration /// [Route("/System/Configuration", "GET", Summary = "Gets application configuration")] + [Authenticated] public class GetConfiguration : IReturn { diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 8a65e2b565..8eff75533e 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -22,7 +22,8 @@ namespace MediaBrowser.Api.Playback.Hls /// public abstract class BaseHlsService : BaseStreamingService { - protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder) + protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder) + : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder) { } @@ -103,8 +104,8 @@ namespace MediaBrowser.Api.Playback.Hls } else { - await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, FileDeleteMode.All, false).ConfigureAwait(false); - + await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, p => true, false).ConfigureAwait(false); + // If the playlist doesn't already exist, startup ffmpeg try { @@ -252,7 +253,7 @@ namespace MediaBrowser.Api.Playback.Hls protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding) { var hlsVideoRequest = state.VideoRequest as GetHlsVideoStream; - + var itsOffsetMs = hlsVideoRequest == null ? 0 : hlsVideoRequest.TimeStampOffsetMs; diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 6c09f00a17..07aaf5f86c 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -127,8 +127,7 @@ namespace MediaBrowser.Api.Playback.Hls // If the playlist doesn't already exist, startup ffmpeg try { - // TODO: Delete files from other jobs, but not this one - await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, FileDeleteMode.None, false).ConfigureAwait(false); + await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, p => !string.Equals(p, playlistPath, StringComparison.OrdinalIgnoreCase), false).ConfigureAwait(false); if (currentTranscodingIndex.HasValue) { diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index 3848cb2de0..f283525885 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -74,7 +74,7 @@ namespace MediaBrowser.Api.Playback.Hls public void Delete(StopEncodingProcess request) { - var task = ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, FileDeleteMode.All, true); + var task = ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, path => true, true); Task.WaitAll(task); } diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs index f4651601b0..ed7db626f9 100644 --- a/MediaBrowser.Api/SessionsService.cs +++ b/MediaBrowser.Api/SessionsService.cs @@ -213,6 +213,7 @@ namespace MediaBrowser.Api } [Route("/Sessions/Capabilities", "POST", Summary = "Updates capabilities for a device")] + [Authenticated] public class PostCapabilities : IReturnVoid { /// @@ -235,6 +236,11 @@ namespace MediaBrowser.Api public bool SupportsMediaControl { get; set; } } + [Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")] + public class ReportSessionEnded : IReturnVoid + { + } + /// /// Class SessionsService /// @@ -246,16 +252,26 @@ namespace MediaBrowser.Api private readonly ISessionManager _sessionManager; private readonly IUserManager _userManager; + private readonly IAuthorizationContext _authContext; /// /// Initializes a new instance of the class. /// /// The session manager. /// The user manager. - public SessionsService(ISessionManager sessionManager, IUserManager userManager) + public SessionsService(ISessionManager sessionManager, IUserManager userManager, IAuthorizationContext authContext) { _sessionManager = sessionManager; _userManager = userManager; + _authContext = authContext; + } + + + public void Post(ReportSessionEnded request) + { + var auth = _authContext.GetAuthorizationInfo(Request); + + _sessionManager.Logout(auth.Token); } /// diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs index 6f2e83a796..f336736be8 100644 --- a/MediaBrowser.Api/SystemService.cs +++ b/MediaBrowser.Api/SystemService.cs @@ -15,6 +15,7 @@ namespace MediaBrowser.Api /// Class GetSystemInfo /// [Route("/System/Info", "GET", Summary = "Gets information about the server")] + [Authenticated] public class GetSystemInfo : IReturn { diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index cda489c94a..bcaf80d69c 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -4,7 +4,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Users; using ServiceStack; using ServiceStack.Text.Controller; @@ -19,6 +18,7 @@ namespace MediaBrowser.Api /// Class GetUsers /// [Route("/Users", "GET", Summary = "Gets a list of users")] + [Authenticated] public class GetUsers : IReturn> { [ApiMember(Name = "IsHidden", Description = "Optional filter by IsHidden=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] @@ -37,6 +37,7 @@ namespace MediaBrowser.Api /// Class GetUser /// [Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")] + [Authenticated] public class GetUser : IReturn { /// @@ -159,11 +160,6 @@ namespace MediaBrowser.Api /// public class UserService : BaseApiService, IHasAuthorization { - /// - /// The _XML serializer - /// - private readonly IXmlSerializer _xmlSerializer; - /// /// The _user manager /// @@ -176,19 +172,12 @@ namespace MediaBrowser.Api /// /// Initializes a new instance of the class. /// - /// The XML serializer. /// The user manager. /// The dto service. + /// The session mananger. /// xmlSerializer - public UserService(IXmlSerializer xmlSerializer, IUserManager userManager, IDtoService dtoService, ISessionManager sessionMananger) - : base() + public UserService(IUserManager userManager, IDtoService dtoService, ISessionManager sessionMananger) { - if (xmlSerializer == null) - { - throw new ArgumentNullException("xmlSerializer"); - } - - _xmlSerializer = xmlSerializer; _userManager = userManager; _dtoService = dtoService; _sessionMananger = sessionMananger; @@ -196,6 +185,11 @@ namespace MediaBrowser.Api public object Get(GetPublicUsers request) { + if (!Request.IsLocal && !_sessionMananger.IsLocal(Request.RemoteIp)) + { + return ToOptimizedResult(new List()); + } + return Get(new GetUsers { IsHidden = false, @@ -368,9 +362,15 @@ namespace MediaBrowser.Api { throw new ArgumentException("There must be at least one enabled user in the system."); } + + var revokeTask = _sessionMananger.RevokeUserTokens(user.Id.ToString("N")); + + Task.WaitAll(revokeTask); } - var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ? _userManager.UpdateUser(user) : _userManager.RenameUser(user, dtoUser.Name); + var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ? + _userManager.UpdateUser(user) : + _userManager.RenameUser(user, dtoUser.Name); Task.WaitAll(task); diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs index 707807bd5a..3c7df91c1c 100644 --- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs @@ -10,6 +10,8 @@ namespace MediaBrowser.Controller.Channels { public string Name { get; set; } + public string SeriesName { get; set; } + public string Id { get; set; } public ChannelItemType Type { get; set; } @@ -28,8 +30,6 @@ namespace MediaBrowser.Controller.Channels public long? RunTimeTicks { get; set; } - public bool IsInfiniteStream { get; set; } - public string ImageUrl { get; set; } public ChannelMediaType MediaType { get; set; } @@ -43,9 +43,14 @@ namespace MediaBrowser.Controller.Channels public int? ProductionYear { get; set; } public DateTime? DateCreated { get; set; } - + + public int? IndexNumber { get; set; } + public int? ParentIndexNumber { get; set; } + public List MediaSources { get; set; } - + + public bool IsInfiniteStream { get; set; } + public ChannelItemInfo() { MediaSources = new List(); diff --git a/MediaBrowser.Controller/Collections/CollectionEvents.cs b/MediaBrowser.Controller/Collections/CollectionEvents.cs new file mode 100644 index 0000000000..80f66a444a --- /dev/null +++ b/MediaBrowser.Controller/Collections/CollectionEvents.cs @@ -0,0 +1,37 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Collections +{ + public class CollectionCreatedEventArgs : EventArgs + { + /// + /// Gets or sets the collection. + /// + /// The collection. + public BoxSet Collection { get; set; } + + /// + /// Gets or sets the options. + /// + /// The options. + public CollectionCreationOptions Options { get; set; } + } + + public class CollectionModifiedEventArgs : EventArgs + { + /// + /// Gets or sets the collection. + /// + /// The collection. + public BoxSet Collection { get; set; } + + /// + /// Gets or sets the items changed. + /// + /// The items changed. + public List ItemsChanged { get; set; } + } +} diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs index fdb2a49755..9130f68d43 100644 --- a/MediaBrowser.Controller/Collections/ICollectionManager.cs +++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs @@ -8,6 +8,21 @@ namespace MediaBrowser.Controller.Collections { public interface ICollectionManager { + /// + /// Occurs when [collection created]. + /// + event EventHandler CollectionCreated; + + /// + /// Occurs when [items added to collection]. + /// + event EventHandler ItemsAddedToCollection; + + /// + /// Occurs when [items removed from collection]. + /// + event EventHandler ItemsRemovedFromCollection; + /// /// Creates the collection. /// diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index 0d0555dc0d..434e896dad 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -50,6 +50,13 @@ namespace MediaBrowser.Controller.Dto /// ChapterInfoDto. ChapterInfoDto GetChapterInfoDto(ChapterInfo chapterInfo, BaseItem item); + /// + /// Gets the user item data dto. + /// + /// The data. + /// UserItemDataDto. + UserItemDataDto GetUserItemDataDto(UserItemData data); + /// /// Gets the item by name dto. /// diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 4ad3033f9e..1c60ea8e68 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -95,6 +95,7 @@ + @@ -233,6 +234,9 @@ + + + diff --git a/MediaBrowser.Controller/Providers/IMetadataProvider.cs b/MediaBrowser.Controller/Providers/IMetadataProvider.cs index d33b2c9eb0..52cd6fceac 100644 --- a/MediaBrowser.Controller/Providers/IMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/IMetadataProvider.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Entities; +using System.Collections.Generic; namespace MediaBrowser.Controller.Providers { diff --git a/MediaBrowser.Controller/Security/AuthenticationInfo.cs b/MediaBrowser.Controller/Security/AuthenticationInfo.cs new file mode 100644 index 0000000000..dd5eec1f92 --- /dev/null +++ b/MediaBrowser.Controller/Security/AuthenticationInfo.cs @@ -0,0 +1,61 @@ +using System; + +namespace MediaBrowser.Controller.Security +{ + public class AuthenticationInfo + { + /// + /// Gets or sets the identifier. + /// + /// The identifier. + public string Id { get; set; } + + /// + /// Gets or sets the access token. + /// + /// The access token. + public string AccessToken { get; set; } + + /// + /// Gets or sets the device identifier. + /// + /// The device identifier. + public string DeviceId { get; set; } + + /// + /// Gets or sets the name of the application. + /// + /// The name of the application. + public string AppName { get; set; } + + /// + /// Gets or sets the name of the device. + /// + /// The name of the device. + public string DeviceName { get; set; } + + /// + /// Gets or sets the user identifier. + /// + /// The user identifier. + public string UserId { get; set; } + + /// + /// Gets or sets a value indicating whether this instance is active. + /// + /// true if this instance is active; otherwise, false. + public bool IsActive { get; set; } + + /// + /// Gets or sets the date created. + /// + /// The date created. + public DateTime DateCreated { get; set; } + + /// + /// Gets or sets the date revoked. + /// + /// The date revoked. + public DateTime? DateRevoked { get; set; } + } +} diff --git a/MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs b/MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs new file mode 100644 index 0000000000..3234b0350f --- /dev/null +++ b/MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs @@ -0,0 +1,42 @@ + +namespace MediaBrowser.Controller.Security +{ + public class AuthenticationInfoQuery + { + /// + /// Gets or sets the device identifier. + /// + /// The device identifier. + public string DeviceId { get; set; } + + /// + /// Gets or sets the user identifier. + /// + /// The user identifier. + public string UserId { get; set; } + + /// + /// Gets or sets the access token. + /// + /// The access token. + public string AccessToken { get; set; } + + /// + /// Gets or sets a value indicating whether this instance is active. + /// + /// null if [is active] contains no value, true if [is active]; otherwise, false. + public bool? IsActive { get; set; } + + /// + /// Gets or sets the start index. + /// + /// The start index. + public int? StartIndex { get; set; } + + /// + /// Gets or sets the limit. + /// + /// The limit. + public int? Limit { get; set; } + } +} diff --git a/MediaBrowser.Controller/Security/IAuthenticationRepository.cs b/MediaBrowser.Controller/Security/IAuthenticationRepository.cs new file mode 100644 index 0000000000..219b07028d --- /dev/null +++ b/MediaBrowser.Controller/Security/IAuthenticationRepository.cs @@ -0,0 +1,39 @@ +using MediaBrowser.Model.Querying; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Security +{ + public interface IAuthenticationRepository + { + /// + /// Creates the specified information. + /// + /// The information. + /// The cancellation token. + /// Task. + Task Create(AuthenticationInfo info, CancellationToken cancellationToken); + + /// + /// Updates the specified information. + /// + /// The information. + /// The cancellation token. + /// Task. + Task Update(AuthenticationInfo info, CancellationToken cancellationToken); + + /// + /// Gets the specified query. + /// + /// The query. + /// QueryResult{AuthenticationInfo}. + QueryResult Get(AuthenticationInfoQuery query); + + /// + /// Gets the specified identifier. + /// + /// The identifier. + /// AuthenticationInfo. + AuthenticationInfo Get(string id); + } +} diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 7b20621827..4b30c964c8 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -259,7 +259,28 @@ namespace MediaBrowser.Controller.Session /// /// Validates the security token. /// - /// The token. - void ValidateSecurityToken(string token); + /// The access token. + void ValidateSecurityToken(string accessToken); + + /// + /// Logouts the specified access token. + /// + /// The access token. + /// Task. + Task Logout(string accessToken); + + /// + /// Revokes the user tokens. + /// + /// The user identifier. + /// Task. + Task RevokeUserTokens(string userId); + + /// + /// Determines whether the specified remote endpoint is local. + /// + /// The remote endpoint. + /// true if the specified remote endpoint is local; otherwise, false. + bool IsLocal(string remoteEndpoint); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 6f27f6cb28..58d455955a 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -123,7 +123,7 @@ namespace MediaBrowser.Controller.Session public List SupportedCommands { get; set; } public TranscodingInfo TranscodingInfo { get; set; } - + /// /// Gets a value indicating whether this instance is active. /// diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs index cc9bc7bed7..62aec5ecbd 100644 --- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -1,11 +1,11 @@ -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Logging; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.LocalMetadata { diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 33c6f980ce..74a3314b72 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -246,7 +246,7 @@ namespace MediaBrowser.Model.ApiClient /// Gets the client session asynchronous. /// /// Task{SessionInfoDto}. - Task GetCurrentSessionAsync(); + Task GetCurrentSessionAsync(CancellationToken cancellationToken); /// /// Gets the item counts async. @@ -644,6 +644,13 @@ namespace MediaBrowser.Model.ApiClient /// Task. Task SetVolume(string sessionId, int volume); + /// + /// Stops the transcoding processes. + /// + /// The device identifier. + /// Task. + Task StopTranscodingProcesses(string deviceId); + /// /// Sets the index of the audio stream. /// @@ -984,7 +991,7 @@ namespace MediaBrowser.Model.ApiClient /// The query. /// The cancellation token. /// Task{LiveTvInfo}. - Task> GetLiveTvChannelsAsync(ChannelQuery query, CancellationToken cancellationToken); + Task> GetLiveTvChannelsAsync(LiveTvChannelQuery query, CancellationToken cancellationToken); /// /// Gets the live tv channel asynchronous. @@ -1187,5 +1194,13 @@ namespace MediaBrowser.Model.ApiClient /// The cancellation token. /// Task{QueryResult{BaseItemDto}}. Task> GetChannels(ChannelQuery query, CancellationToken cancellationToken); + + /// + /// Gets the latest channel items. + /// + /// The query. + /// The cancellation token. + /// Task{QueryResult{BaseItemDto}}. + Task> GetLatestChannelItems(AllChannelMediaQuery query, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 49b731341a..d9404ce29e 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -210,6 +210,8 @@ namespace MediaBrowser.Model.Configuration public bool DefaultMetadataSettingsApplied { get; set; } + public bool EnableTokenAuthentication { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.Model/Users/AuthenticationResult.cs b/MediaBrowser.Model/Users/AuthenticationResult.cs index 8046e83c7f..97fe2ea99e 100644 --- a/MediaBrowser.Model/Users/AuthenticationResult.cs +++ b/MediaBrowser.Model/Users/AuthenticationResult.cs @@ -21,6 +21,6 @@ namespace MediaBrowser.Model.Users /// Gets or sets the authentication token. /// /// The authentication token. - public string AuthenticationToken { get; set; } + public string AccessToken { get; set; } } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 95eca6ba0c..7feca2d349 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -8,7 +8,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index 2783fda6bc..f09890c40f 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -170,7 +170,7 @@ namespace MediaBrowser.Providers.Manager var key = id.Key; // Don't replace existing Id's. - if (!target.ProviderIds.ContainsKey(key)) + if (replaceData || !target.ProviderIds.ContainsKey(key)) { target.ProviderIds[key] = id.Value; } diff --git a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs index 7979711ec0..b3f62005b0 100644 --- a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs @@ -19,7 +19,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.TV { - public class MovieDbEpisodeImageProvider : IRemoteImageProvider, IHasOrder + public class MovieDbEpisodeImageProvider/* : IRemoteImageProvider, IHasOrder*/ { private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos"; private readonly IHttpClient _httpClient; diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index c6dd807585..d0ea64e0fc 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -1133,6 +1133,8 @@ namespace MediaBrowser.Server.Implementations.Channels item.CommunityRating = info.CommunityRating; item.OfficialRating = info.OfficialRating; item.Overview = info.Overview; + item.IndexNumber = info.IndexNumber; + item.ParentIndexNumber = info.ParentIndexNumber; item.People = info.People; item.PremiereDate = info.PremiereDate; item.ProductionYear = info.ProductionYear; @@ -1159,7 +1161,6 @@ namespace MediaBrowser.Server.Implementations.Channels if (channelMediaItem != null) { - channelMediaItem.IsInfiniteStream = info.IsInfiniteStream; channelMediaItem.ContentType = info.ContentType; channelMediaItem.ChannelMediaSources = info.MediaSources; diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs index 728b18bbf4..7bc7838c6f 100644 --- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs +++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs @@ -1,9 +1,11 @@ -using MediaBrowser.Common.IO; +using MediaBrowser.Common.Events; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Logging; using MoreLinq; using System; using System.Collections.Generic; @@ -19,12 +21,18 @@ namespace MediaBrowser.Server.Implementations.Collections private readonly ILibraryManager _libraryManager; private readonly IFileSystem _fileSystem; private readonly ILibraryMonitor _iLibraryMonitor; + private readonly ILogger _logger; - public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor) + public event EventHandler CollectionCreated; + public event EventHandler ItemsAddedToCollection; + public event EventHandler ItemsRemovedFromCollection; + + public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILogger logger) { _libraryManager = libraryManager; _fileSystem = fileSystem; _iLibraryMonitor = iLibraryMonitor; + _logger = logger; } public Folder GetCollectionsFolder(string userId) @@ -74,9 +82,16 @@ namespace MediaBrowser.Server.Implementations.Collections if (options.ItemIdList.Count > 0) { - await AddToCollection(collection.Id, options.ItemIdList); + await AddToCollection(collection.Id, options.ItemIdList, false); } + EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs + { + Collection = collection, + Options = options + + }, _logger); + return collection; } finally @@ -113,7 +128,12 @@ namespace MediaBrowser.Server.Implementations.Collections return GetCollectionsFolder(string.Empty); } - public async Task AddToCollection(Guid collectionId, IEnumerable ids) + public Task AddToCollection(Guid collectionId, IEnumerable ids) + { + return AddToCollection(collectionId, ids, true); + } + + private async Task AddToCollection(Guid collectionId, IEnumerable ids, bool fireEvent) { var collection = _libraryManager.GetItemById(collectionId) as BoxSet; @@ -123,6 +143,7 @@ namespace MediaBrowser.Server.Implementations.Collections } var list = new List(); + var itemList = new List(); var currentLinkedChildren = collection.GetLinkedChildren().ToList(); foreach (var itemId in ids) @@ -134,6 +155,8 @@ namespace MediaBrowser.Server.Implementations.Collections throw new ArgumentException("No item exists with the supplied Id"); } + itemList.Add(item); + if (currentLinkedChildren.Any(i => i.Id == itemId)) { throw new ArgumentException("Item already exists in collection"); @@ -165,6 +188,16 @@ namespace MediaBrowser.Server.Implementations.Collections await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false); + + if (fireEvent) + { + EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs + { + Collection = collection, + ItemsChanged = itemList + + }, _logger); + } } public async Task RemoveFromCollection(Guid collectionId, IEnumerable itemIds) @@ -177,6 +210,7 @@ namespace MediaBrowser.Server.Implementations.Collections } var list = new List(); + var itemList = new List(); foreach (var itemId in itemIds) { @@ -190,6 +224,12 @@ namespace MediaBrowser.Server.Implementations.Collections list.Add(child); var childItem = _libraryManager.GetItemById(itemId); + + if (childItem != null) + { + itemList.Add(childItem); + } + var supportsGrouping = childItem as ISupportsBoxSetGrouping; if (supportsGrouping != null) @@ -221,7 +261,7 @@ namespace MediaBrowser.Server.Implementations.Collections { File.Delete(file); } - + foreach (var child in list) { collection.LinkedChildren.Remove(child); @@ -238,6 +278,13 @@ namespace MediaBrowser.Server.Implementations.Collections await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false); + + EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs + { + Collection = collection, + ItemsChanged = itemList + + }, _logger); } public IEnumerable CollapseItemsWithinBoxSets(IEnumerable items, User user) diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs index c29a7d14e3..6894d7ac7e 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; @@ -13,9 +13,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security { public class AuthService : IAuthService { - public AuthService(IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext) + private readonly IServerConfigurationManager _config; + + public AuthService(IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config) { AuthorizationContext = authorizationContext; + _config = config; SessionManager = sessionManager; UserManager = userManager; } @@ -54,28 +57,30 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security //This code is executed before the service var auth = AuthorizationContext.GetAuthorizationInfo(req); - if (string.IsNullOrWhiteSpace(auth.Token)) + if (!string.IsNullOrWhiteSpace(auth.Token) || _config.Configuration.EnableTokenAuthentication) { - // Legacy - // TODO: Deprecate this in Oct 2014 - - User user = null; - - if (!string.IsNullOrWhiteSpace(auth.UserId)) - { - var userId = auth.UserId; + SessionManager.ValidateSecurityToken(auth.Token); + } - user = UserManager.GetUserById(new Guid(userId)); - } + var user = string.IsNullOrWhiteSpace(auth.UserId) + ? null + : UserManager.GetUserById(new Guid(auth.UserId)); - if (user == null || user.Configuration.IsDisabled) - { - throw new UnauthorizedAccessException("Unauthorized access."); - } + if (user != null && user.Configuration.IsDisabled) + { + throw new UnauthorizedAccessException("User account has been disabled."); } - else + + if (!string.IsNullOrWhiteSpace(auth.DeviceId) && + !string.IsNullOrWhiteSpace(auth.Client) && + !string.IsNullOrWhiteSpace(auth.Device)) { - SessionManager.ValidateSecurityToken(auth.Token); + SessionManager.LogSessionActivity(auth.Client, + auth.Version, + auth.DeviceId, + auth.Device, + req.RemoteIp, + user); } } @@ -108,11 +113,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security } } - private void LogRequest() - { - - } - protected bool DoHtmlRedirectIfConfigured(IRequest req, IResponse res, bool includeRedirectParam = false) { var htmlRedirect = this.HtmlRedirect ?? AuthenticateService.HtmlRedirect; diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 1d201e0690..859011f6ee 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -216,6 +216,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs index df32ac021b..5d5855bf8b 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs @@ -14,7 +14,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Persistence { - public class SqliteFileOrganizationRepository : IFileOrganizationRepository + public class SqliteFileOrganizationRepository : IFileOrganizationRepository, IDisposable { private IDbConnection _connection; diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs new file mode 100644 index 0000000000..5f225ddd47 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs @@ -0,0 +1,338 @@ +using MediaBrowser.Controller; +using MediaBrowser.Controller.Security; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Querying; +using MediaBrowser.Server.Implementations.Persistence; +using System; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Security +{ + public class AuthenticationRepository : IAuthenticationRepository + { + private IDbConnection _connection; + private readonly ILogger _logger; + private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); + private readonly IServerApplicationPaths _appPaths; + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + private IDbCommand _saveInfoCommand; + + public AuthenticationRepository(ILogger logger, IServerApplicationPaths appPaths) + { + _logger = logger; + _appPaths = appPaths; + } + + public async Task Initialize() + { + var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db"); + + _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); + + string[] queries = { + + "create table if not exists AccessTokens (Id GUID PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT, AppName TEXT, DeviceName TEXT, UserId TEXT, IsActive BIT, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)", + "create index if not exists idx_AccessTokens on AccessTokens(Id)", + + //pragmas + "pragma temp_store = memory", + + "pragma shrink_memory" + }; + + _connection.RunQueries(queries, _logger); + + PrepareStatements(); + } + + private void PrepareStatements() + { + _saveInfoCommand = _connection.CreateCommand(); + _saveInfoCommand.CommandText = "replace into AccessTokens (Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)"; + + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@Id"); + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AccessToken"); + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceId"); + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AppName"); + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceName"); + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@UserId"); + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@IsActive"); + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateCreated"); + _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateRevoked"); + } + + public Task Create(AuthenticationInfo info, CancellationToken cancellationToken) + { + info.Id = Guid.NewGuid().ToString("N"); + + return Update(info, cancellationToken); + } + + public async Task Update(AuthenticationInfo info, CancellationToken cancellationToken) + { + if (info == null) + { + throw new ArgumentNullException("info"); + } + + cancellationToken.ThrowIfCancellationRequested(); + + await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try + { + transaction = _connection.BeginTransaction(); + + var index = 0; + + _saveInfoCommand.GetParameter(index++).Value = new Guid(info.Id); + _saveInfoCommand.GetParameter(index++).Value = info.AccessToken; + _saveInfoCommand.GetParameter(index++).Value = info.DeviceId; + _saveInfoCommand.GetParameter(index++).Value = info.AppName; + _saveInfoCommand.GetParameter(index++).Value = info.DeviceName; + _saveInfoCommand.GetParameter(index++).Value = info.UserId; + _saveInfoCommand.GetParameter(index++).Value = info.IsActive; + _saveInfoCommand.GetParameter(index++).Value = info.DateCreated; + _saveInfoCommand.GetParameter(index++).Value = info.DateRevoked; + + _saveInfoCommand.Transaction = transaction; + + _saveInfoCommand.ExecuteNonQuery(); + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + catch (Exception e) + { + _logger.ErrorException("Failed to save record:", e); + + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + + _writeLock.Release(); + } + } + + private const string BaseSelectText = "select Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens"; + + public QueryResult Get(AuthenticationInfoQuery query) + { + if (query == null) + { + throw new ArgumentNullException("query"); + } + + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = BaseSelectText; + + var whereClauses = new List(); + + var startIndex = query.StartIndex ?? 0; + + if (startIndex > 0) + { + whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens ORDER BY DateCreated LIMIT {0})", + startIndex.ToString(_usCulture))); + } + + if (!string.IsNullOrWhiteSpace(query.AccessToken)) + { + whereClauses.Add("AccessToken=@AccessToken"); + cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken; + } + + if (!string.IsNullOrWhiteSpace(query.UserId)) + { + whereClauses.Add("UserId=@UserId"); + cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId; + } + + if (!string.IsNullOrWhiteSpace(query.DeviceId)) + { + whereClauses.Add("DeviceId=@DeviceId"); + cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId; + } + + if (query.IsActive.HasValue) + { + whereClauses.Add("IsActive=@IsActive"); + cmd.Parameters.Add(cmd, "@IsActive", DbType.Boolean).Value = query.IsActive.Value; + } + + if (whereClauses.Count > 0) + { + cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + } + + cmd.CommandText += " ORDER BY DateCreated"; + + if (query.Limit.HasValue) + { + cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); + } + + cmd.CommandText += "; select count (Id) from AccessTokens"; + + var list = new List(); + var count = 0; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + { + while (reader.Read()) + { + list.Add(Get(reader)); + } + + if (reader.NextResult() && reader.Read()) + { + count = reader.GetInt32(0); + } + } + + return new QueryResult() + { + Items = list.ToArray(), + TotalRecordCount = count + }; + } + } + + public AuthenticationInfo Get(string id) + { + if (string.IsNullOrEmpty(id)) + { + throw new ArgumentNullException("id"); + } + + var guid = new Guid(id); + + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = BaseSelectText + " where Id=@Id"; + + cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + { + if (reader.Read()) + { + return Get(reader); + } + } + } + + return null; + } + + private AuthenticationInfo Get(IDataReader reader) + { + var s = "select Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens"; + + var info = new AuthenticationInfo + { + Id = reader.GetGuid(0).ToString("N"), + AccessToken = reader.GetString(1) + }; + + if (!reader.IsDBNull(2)) + { + info.DeviceId = reader.GetString(2); + } + + if (!reader.IsDBNull(3)) + { + info.AppName = reader.GetString(3); + } + + if (!reader.IsDBNull(4)) + { + info.DeviceName = reader.GetString(4); + } + + if (!reader.IsDBNull(5)) + { + info.UserId = reader.GetString(5); + } + + info.IsActive = reader.GetBoolean(6); + info.DateCreated = reader.GetDateTime(7); + + if (!reader.IsDBNull(8)) + { + info.DateRevoked = reader.GetDateTime(8); + } + + return info; + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private readonly object _disposeLock = new object(); + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + try + { + lock (_disposeLock) + { + if (_connection != null) + { + if (_connection.IsOpen()) + { + _connection.Close(); + } + + _connection.Dispose(); + _connection = null; + } + } + } + catch (Exception ex) + { + _logger.ErrorException("Error disposing database", ex); + } + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 784719318f..c3d24c0de1 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -1,6 +1,4 @@ -using System.Security.Cryptography; -using System.Text; -using MediaBrowser.Common.Events; +using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; @@ -13,12 +11,14 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Library; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Session; +using MediaBrowser.Model.Users; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -27,7 +27,6 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Users; namespace MediaBrowser.Server.Implementations.Session { @@ -62,6 +61,8 @@ namespace MediaBrowser.Server.Implementations.Session private readonly IJsonSerializer _jsonSerializer; private readonly IServerApplicationHost _appHost; + private readonly IAuthenticationRepository _authRepo; + /// /// Gets or sets the configuration manager. /// @@ -104,7 +105,7 @@ namespace MediaBrowser.Server.Implementations.Session /// The logger. /// The user repository. /// The library manager. - public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient) + public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo) { _userDataRepository = userDataRepository; _configurationManager = configurationManager; @@ -119,6 +120,7 @@ namespace MediaBrowser.Server.Implementations.Session _jsonSerializer = jsonSerializer; _appHost = appHost; _httpClient = httpClient; + _authRepo = authRepo; } /// @@ -204,7 +206,12 @@ namespace MediaBrowser.Server.Implementations.Session /// Task. /// user /// - public async Task LogSessionActivity(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user) + public async Task LogSessionActivity(string clientType, + string appVersion, + string deviceId, + string deviceName, + string remoteEndPoint, + User user) { if (string.IsNullOrEmpty(clientType)) { @@ -1157,7 +1164,37 @@ namespace MediaBrowser.Server.Implementations.Session public void ValidateSecurityToken(string token) { + if (string.IsNullOrWhiteSpace(token)) + { + throw new UnauthorizedAccessException(); + } + var result = _authRepo.Get(new AuthenticationInfoQuery + { + AccessToken = token + }); + + var info = result.Items.FirstOrDefault(); + + if (info == null) + { + throw new UnauthorizedAccessException(); + } + + if (!info.IsActive) + { + throw new UnauthorizedAccessException("Access token has expired."); + } + + if (!string.IsNullOrWhiteSpace(info.UserId)) + { + var user = _userManager.GetUserById(new Guid(info.UserId)); + + if (user == null || user.Configuration.IsDisabled) + { + throw new UnauthorizedAccessException("User account has been disabled."); + } + } } /// @@ -1175,7 +1212,7 @@ namespace MediaBrowser.Server.Implementations.Session /// public async Task AuthenticateNewSession(string username, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint) { - var result = await _userManager.AuthenticateUser(username, password).ConfigureAwait(false); + var result = IsLocalhost(remoteEndPoint) || await _userManager.AuthenticateUser(username, password).ConfigureAwait(false); if (!result) { @@ -1185,6 +1222,8 @@ namespace MediaBrowser.Server.Implementations.Session var user = _userManager.Users .First(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase)); + var token = await GetAuthorizationToken(user.Id.ToString("N"), deviceId, clientType, deviceName).ConfigureAwait(false); + var session = await LogSessionActivity(clientType, appVersion, deviceId, @@ -1197,11 +1236,108 @@ namespace MediaBrowser.Server.Implementations.Session { User = _dtoService.GetUserDto(user), SessionInfo = GetSessionInfoDto(session), - AuthenticationToken = Guid.NewGuid().ToString("N") + AccessToken = token }; } - private bool IsLocal(string remoteEndpoint) + private async Task GetAuthorizationToken(string userId, string deviceId, string app, string deviceName) + { + var existing = _authRepo.Get(new AuthenticationInfoQuery + { + DeviceId = deviceId, + IsActive = true, + UserId = userId, + Limit = 1 + }); + + if (existing.Items.Length > 0) + { + _logger.Debug("Reissuing access token"); + return existing.Items[0].AccessToken; + } + + var newToken = new AuthenticationInfo + { + AppName = app, + DateCreated = DateTime.UtcNow, + DeviceId = deviceId, + DeviceName = deviceName, + UserId = userId, + IsActive = true, + AccessToken = Guid.NewGuid().ToString("N") + }; + + _logger.Debug("Creating new access token for user {0}", userId); + await _authRepo.Create(newToken, CancellationToken.None).ConfigureAwait(false); + + return newToken.AccessToken; + } + + public async Task Logout(string accessToken) + { + if (string.IsNullOrWhiteSpace(accessToken)) + { + throw new ArgumentNullException("accessToken"); + } + + var existing = _authRepo.Get(new AuthenticationInfoQuery + { + Limit = 1, + AccessToken = accessToken + + }).Items.FirstOrDefault(); + + if (existing != null) + { + existing.IsActive = false; + + await _authRepo.Update(existing, CancellationToken.None).ConfigureAwait(false); + + var sessions = Sessions + .Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase)) + .ToList(); + + foreach (var session in sessions) + { + try + { + ReportSessionEnded(session.Id); + } + catch (Exception ex) + { + _logger.ErrorException("Error reporting session ended", ex); + } + } + } + } + + public async Task RevokeUserTokens(string userId) + { + var existing = _authRepo.Get(new AuthenticationInfoQuery + { + IsActive = true, + UserId = userId + }); + + foreach (var info in existing.Items) + { + await Logout(info.AccessToken).ConfigureAwait(false); + } + } + + private bool IsLocalhost(string remoteEndpoint) + { + if (string.IsNullOrWhiteSpace(remoteEndpoint)) + { + throw new ArgumentNullException("remoteEndpoint"); + } + + return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 || + remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) || + remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase); + } + + public bool IsLocal(string remoteEndpoint) { if (string.IsNullOrWhiteSpace(remoteEndpoint)) { @@ -1211,12 +1347,11 @@ namespace MediaBrowser.Server.Implementations.Session // Private address space: // http://en.wikipedia.org/wiki/Private_network - return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 || + return IsLocalhost(remoteEndpoint) || remoteEndpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) || remoteEndpoint.StartsWith("192.", StringComparison.OrdinalIgnoreCase) || remoteEndpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase) || - remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) || - remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase); + remoteEndpoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase); } /// diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 91e92e21c5..ca04e580f3 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -210,6 +210,8 @@ namespace MediaBrowser.ServerApplication private IUserViewManager UserViewManager { get; set; } + private IAuthenticationRepository AuthenticationRepository { get; set; } + /// /// Initializes a new instance of the class. /// @@ -586,6 +588,9 @@ namespace MediaBrowser.ServerApplication FileOrganizationRepository = await GetFileOrganizationRepository().ConfigureAwait(false); RegisterSingleInstance(FileOrganizationRepository); + AuthenticationRepository = await GetAuthenticationRepository().ConfigureAwait(false); + RegisterSingleInstance(AuthenticationRepository); + UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer); RegisterSingleInstance(UserManager); @@ -625,7 +630,7 @@ namespace MediaBrowser.ServerApplication DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager); RegisterSingleInstance(DtoService); - SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient); + SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository); RegisterSingleInstance(SessionManager); var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer); @@ -651,7 +656,7 @@ namespace MediaBrowser.ServerApplication var connectionManager = new ConnectionManager(dlnaManager, ServerConfigurationManager, LogManager.GetLogger("UpnpConnectionManager"), HttpClient); RegisterSingleInstance(connectionManager); - var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor); + var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("CollectionManager")); RegisterSingleInstance(collectionManager); LiveTvManager = new LiveTvManager(ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager); @@ -678,7 +683,7 @@ namespace MediaBrowser.ServerApplication var authContext = new AuthorizationContext(); RegisterSingleInstance(authContext); RegisterSingleInstance(new SessionContext(UserManager, authContext, SessionManager)); - RegisterSingleInstance(new AuthService(UserManager, SessionManager, authContext)); + RegisterSingleInstance(new AuthService(UserManager, SessionManager, authContext, ServerConfigurationManager)); RegisterSingleInstance(new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder)); @@ -755,6 +760,15 @@ namespace MediaBrowser.ServerApplication return repo; } + private async Task GetAuthenticationRepository() + { + var repo = new AuthenticationRepository(LogManager.GetLogger("AuthenticationRepository"), ServerConfigurationManager.ApplicationPaths); + + await repo.Initialize().ConfigureAwait(false); + + return repo; + } + /// /// Configures the repositories. /// diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 0515148f02..49851f42a7 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// The cancellation token. private void Fetch(T item, string metadataFile, XmlReaderSettings settings, Encoding encoding, CancellationToken cancellationToken) { - using (var streamReader = new StreamReader(metadataFile, encoding)) + using (var streamReader = new StreamReader(metadataFile)) { // Use XmlReader for best performance using (var reader = XmlReader.Create(streamReader, settings)) diff --git a/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs index 65648e1d05..47371ea04b 100644 --- a/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs @@ -27,7 +27,7 @@ namespace MediaBrowser.XbmcMetadata.Providers var path = file.FullName; - await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + //await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); try { @@ -44,10 +44,10 @@ namespace MediaBrowser.XbmcMetadata.Providers { result.HasMetadata = false; } - finally - { - XmlProviderUtils.XmlParsingResourcePool.Release(); - } + //finally + //{ + // XmlProviderUtils.XmlParsingResourcePool.Release(); + //} return result; } diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs index 1b6c7a3401..a96b0636f2 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs @@ -1,15 +1,14 @@ -using System.Collections.Generic; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Security; using System.Text; using System.Threading; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; namespace MediaBrowser.XbmcMetadata.Savers { diff --git a/MediaBrowser.XbmcMetadata/Savers/XmlSaverHelpers.cs b/MediaBrowser.XbmcMetadata/Savers/XmlSaverHelpers.cs index 7f817f5912..7111a429ab 100644 --- a/MediaBrowser.XbmcMetadata/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.XbmcMetadata/Savers/XmlSaverHelpers.cs @@ -1,12 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Security; -using System.Text; -using System.Xml; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -18,6 +10,14 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.XbmcMetadata.Configuration; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Security; +using System.Text; +using System.Xml; namespace MediaBrowser.XbmcMetadata.Savers { @@ -392,9 +392,9 @@ namespace MediaBrowser.XbmcMetadata.Savers builder.Append("" + SecurityElement.Escape(person) + ""); } - if (writers.Count > 0) + foreach (var person in writers) { - builder.Append("" + SecurityElement.Escape(string.Join(" / ", writers.ToArray())) + ""); + builder.Append("" + SecurityElement.Escape(person) + ""); } var hasTrailer = item as IHasTrailers; diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 8c83ffabcd..f9e8c5aad8 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.412 + 3.0.414 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 88431b72cd..89aeff0a3d 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.412 + 3.0.414 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 73f764fd5e..1696ee347f 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.412 + 3.0.414 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - + -- cgit v1.2.3 From 59de5c0d14fbf0c09926e37dce0c2e6de69000dd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 11 Jul 2014 00:27:46 -0400 Subject: update translations --- MediaBrowser.Api/ConfigurationService.cs | 53 +++++++++++++++++++- MediaBrowser.Api/UserService.cs | 10 +++- .../Configuration/IServerConfigurationManager.cs | 6 +++ MediaBrowser.Controller/Entities/BaseItem.cs | 5 ++ MediaBrowser.Controller/Session/ISessionManager.cs | 2 +- MediaBrowser.Model/Configuration/ChapterOptions.cs | 4 -- .../Configuration/SubtitleOptions.cs | 1 + .../MediaInfo/FFProbeVideoInfo.cs | 2 +- .../Subtitles/OpenSubtitleDownloader.cs | 24 +++++++++ MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs | 10 ++-- .../Channels/ChannelManager.cs | 15 ++++-- .../Configuration/ServerConfigurationManager.cs | 57 +++++++++++++++++++++- .../HttpServer/Security/AuthService.cs | 2 +- .../Localization/JavaScript/ar.json | 17 ++++++- .../Localization/JavaScript/ca.json | 17 ++++++- .../Localization/JavaScript/cs.json | 17 ++++++- .../Localization/JavaScript/da.json | 17 ++++++- .../Localization/JavaScript/de.json | 21 ++++++-- .../Localization/JavaScript/el.json | 17 ++++++- .../Localization/JavaScript/en_GB.json | 17 ++++++- .../Localization/JavaScript/en_US.json | 17 ++++++- .../Localization/JavaScript/es_ES.json | 21 ++++++-- .../Localization/JavaScript/es_MX.json | 23 +++++++-- .../Localization/JavaScript/fr.json | 21 ++++++-- .../Localization/JavaScript/he.json | 17 ++++++- .../Localization/JavaScript/it.json | 21 ++++++-- .../Localization/JavaScript/kk.json | 21 ++++++-- .../Localization/JavaScript/ms.json | 17 ++++++- .../Localization/JavaScript/nb.json | 17 ++++++- .../Localization/JavaScript/nl.json | 21 ++++++-- .../Localization/JavaScript/pl.json | 17 ++++++- .../Localization/JavaScript/pt_BR.json | 21 ++++++-- .../Localization/JavaScript/pt_PT.json | 21 ++++++-- .../Localization/JavaScript/ru.json | 23 +++++++-- .../Localization/JavaScript/sv.json | 21 ++++++-- .../Localization/JavaScript/vi.json | 17 ++++++- .../Localization/JavaScript/zh_TW.json | 17 ++++++- .../Localization/Server/ar.json | 12 ++++- .../Localization/Server/ca.json | 12 ++++- .../Localization/Server/cs.json | 24 ++++++--- .../Localization/Server/da.json | 10 +++- .../Localization/Server/de.json | 18 +++++-- .../Localization/Server/el.json | 12 ++++- .../Localization/Server/en_GB.json | 12 ++++- .../Localization/Server/en_US.json | 12 ++++- .../Localization/Server/es_ES.json | 14 ++++-- .../Localization/Server/es_MX.json | 40 +++++++++------ .../Localization/Server/fr.json | 20 +++++--- .../Localization/Server/he.json | 16 ++++-- .../Localization/Server/it.json | 18 +++++-- .../Localization/Server/kk.json | 12 ++++- .../Localization/Server/ms.json | 12 ++++- .../Localization/Server/nb.json | 12 ++++- .../Localization/Server/nl.json | 14 ++++-- .../Localization/Server/pl.json | 12 ++++- .../Localization/Server/pt_BR.json | 10 +++- .../Localization/Server/pt_PT.json | 18 +++++-- .../Localization/Server/ru.json | 16 ++++-- .../Localization/Server/server.json | 13 ++++- .../Localization/Server/sv.json | 18 +++++-- .../Localization/Server/vi.json | 12 ++++- .../Localization/Server/zh_TW.json | 12 ++++- .../Session/SessionManager.cs | 13 +++-- MediaBrowser.ServerApplication/ApplicationHost.cs | 51 +------------------ MediaBrowser.WebDashboard/Api/DashboardService.cs | 4 +- .../MediaBrowser.WebDashboard.csproj | 24 +++------ 66 files changed, 888 insertions(+), 232 deletions(-) (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs index 6710461ad9..c83028bb2d 100644 --- a/MediaBrowser.Api/ConfigurationService.cs +++ b/MediaBrowser.Api/ConfigurationService.cs @@ -1,6 +1,8 @@ -using MediaBrowser.Common.Extensions; +using System; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; @@ -65,6 +67,13 @@ namespace MediaBrowser.Api } + [Route("/System/Configuration/MetadataPlugins/Autoset", "POST")] + [Authenticated] + public class AutoSetMetadataOptions : IReturnVoid + { + + } + public class ConfigurationService : BaseApiService { /// @@ -79,13 +88,15 @@ namespace MediaBrowser.Api private readonly IFileSystem _fileSystem; private readonly IProviderManager _providerManager; + private readonly ILibraryManager _libraryManager; - public ConfigurationService(IJsonSerializer jsonSerializer, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IProviderManager providerManager) + public ConfigurationService(IJsonSerializer jsonSerializer, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IProviderManager providerManager, ILibraryManager libraryManager) { _jsonSerializer = jsonSerializer; _configurationManager = configurationManager; _fileSystem = fileSystem; _providerManager = providerManager; + _libraryManager = libraryManager; } /// @@ -111,6 +122,44 @@ namespace MediaBrowser.Api return ToOptimizedResult(result); } + public void Post(AutoSetMetadataOptions request) + { + var service = AutoDetectMetadataService(); + + Logger.Info("Setting preferred metadata format to " + service); + + _configurationManager.SetPreferredMetadataService(service); + _configurationManager.SaveConfiguration(); + } + + private string AutoDetectMetadataService() + { + const string xbmc = "Xbmc Nfo"; + const string mb = "Media Browser Xml"; + + var paths = _libraryManager.GetDefaultVirtualFolders() + .SelectMany(i => i.Locations) + .Distinct(StringComparer.OrdinalIgnoreCase) + .Select(i => new DirectoryInfo(i)) + .ToList(); + + if (paths.Select(i => i.EnumerateFiles("*.xml", SearchOption.AllDirectories)) + .SelectMany(i => i) + .Any()) + { + return xbmc; + } + + if (paths.Select(i => i.EnumerateFiles("*.xml", SearchOption.AllDirectories)) + .SelectMany(i => i) + .Any(i => string.Equals(i.Name, "series.xml", StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, "movie.xml", StringComparison.OrdinalIgnoreCase))) + { + return mb; + } + + return xbmc; + } + /// /// Posts the specified configuraiton. /// diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index d5266038b7..0edd013df3 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -188,7 +188,11 @@ namespace MediaBrowser.Api public object Get(GetPublicUsers request) { - if (Request.IsLocal || !_config.Configuration.IsStartupWizardCompleted) + var authInfo = AuthorizationContext.GetAuthorizationInfo(Request); + var isDashboard = string.Equals(authInfo.Client, "Dashboard", StringComparison.OrdinalIgnoreCase); + + if ((Request.IsLocal && isDashboard) || + !_config.Configuration.IsStartupWizardCompleted) { return Get(new GetUsers { @@ -196,7 +200,8 @@ namespace MediaBrowser.Api }); } - if (_sessionMananger.IsLocal(Request.RemoteIp)) + // TODO: Add or is authenticated + if (_sessionMananger.IsInLocalNetwork(Request.RemoteIp)) { return Get(new GetUsers { @@ -205,6 +210,7 @@ namespace MediaBrowser.Api }); } + // Return empty when external return ToOptimizedResult(new List()); } diff --git a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs index 6a2343a009..c3d1796f99 100644 --- a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs +++ b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs @@ -26,5 +26,11 @@ namespace MediaBrowser.Controller.Configuration /// /// The configuration. ServerConfiguration Configuration { get; } + + /// + /// Sets the preferred metadata service. + /// + /// The service. + void SetPreferredMetadataService(string service); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index d89df5f12e..b891bcfb2a 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1526,6 +1526,11 @@ namespace MediaBrowser.Controller.Entities public virtual bool IsUnplayed(User user) { + if (user == null) + { + throw new ArgumentNullException("user"); + } + var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey()); return userdata == null || !userdata.Played; diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 4b30c964c8..88d0e9c1a1 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -281,6 +281,6 @@ namespace MediaBrowser.Controller.Session /// /// The remote endpoint. /// true if the specified remote endpoint is local; otherwise, false. - bool IsLocal(string remoteEndpoint); + bool IsInLocalNetwork(string remoteEndpoint); } } \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/ChapterOptions.cs b/MediaBrowser.Model/Configuration/ChapterOptions.cs index 8a059a0a4a..2e882ee611 100644 --- a/MediaBrowser.Model/Configuration/ChapterOptions.cs +++ b/MediaBrowser.Model/Configuration/ChapterOptions.cs @@ -14,10 +14,6 @@ public ChapterOptions() { - EnableMovieChapterImageExtraction = true; - EnableEpisodeChapterImageExtraction = false; - EnableOtherVideoChapterImageExtraction = false; - DownloadMovieChapters = true; DisabledFetchers = new string[] { }; diff --git a/MediaBrowser.Model/Configuration/SubtitleOptions.cs b/MediaBrowser.Model/Configuration/SubtitleOptions.cs index 96e04e5115..d50dba1b2e 100644 --- a/MediaBrowser.Model/Configuration/SubtitleOptions.cs +++ b/MediaBrowser.Model/Configuration/SubtitleOptions.cs @@ -10,6 +10,7 @@ namespace MediaBrowser.Model.Configuration public string OpenSubtitlesUsername { get; set; } public string OpenSubtitlesPasswordHash { get; set; } + public bool IsOpenSubtitleVipAccount { get; set; } public SubtitleOptions() { diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 57a40741f5..d46ddf7dcc 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -259,7 +259,7 @@ namespace MediaBrowser.Providers.MediaInfo { Chapters = chapters, Video = video, - ExtractImages = false, + ExtractImages = true, SaveChapters = false }, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs index 297f058672..c690fbd843 100644 --- a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs +++ b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs @@ -29,6 +29,15 @@ namespace MediaBrowser.Providers.Subtitles private readonly IServerConfigurationManager _config; private readonly IEncryptionManager _encryption; + private Timer _dailyTimer; + + // This is limited to 200 per day + private int _dailyDownloadCount; + + // It's 200 but this will be in-exact so buffer a little + // And the user may restart the server + private const int MaxDownloadsPerDay = 150; + public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption) { _logger = logManager.GetLogger(GetType().Name); @@ -37,6 +46,9 @@ namespace MediaBrowser.Providers.Subtitles _encryption = encryption; _config.ConfigurationUpdating += _config_ConfigurationUpdating; + + // Reset the count every 24 hours + _dailyTimer = new Timer(state => _dailyDownloadCount = 0, null, TimeSpan.FromHours(24), TimeSpan.FromHours(24)); } private const string PasswordHashPrefix = "h:"; @@ -100,6 +112,12 @@ namespace MediaBrowser.Providers.Subtitles throw new ArgumentNullException("id"); } + if (_dailyDownloadCount >= MaxDownloadsPerDay && + !_config.Configuration.SubtitleOptions.IsOpenSubtitleVipAccount) + { + throw new InvalidOperationException("Open Subtitle's daily download limit has been exceeded. Please try again tomorrow."); + } + var idParts = id.Split(new[] { '-' }, 3); var format = idParts[0]; @@ -272,6 +290,12 @@ namespace MediaBrowser.Providers.Subtitles public void Dispose() { _config.ConfigurationUpdating -= _config_ConfigurationUpdating; + + if (_dailyTimer != null) + { + _dailyTimer.Dispose(); + _dailyTimer = null; + } } } } diff --git a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs index ec02d3add9..0546701f39 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs @@ -165,7 +165,7 @@ namespace MediaBrowser.Providers.TV { cancellationToken.ThrowIfCancellationRequested(); - result.Item = await FetchMovieData(tmdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false); + result.Item = await FetchMovieData(tmdbId, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); result.HasMetadata = result.Item != null; } @@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.TV return result; } - private async Task FetchMovieData(string tmdbId, string language, string preferredCountryCode, CancellationToken cancellationToken) + private async Task FetchMovieData(string tmdbId, string language, CancellationToken cancellationToken) { string dataFilePath = null; RootObject seriesInfo = null; @@ -198,12 +198,12 @@ namespace MediaBrowser.Providers.TV var item = new Series(); - ProcessMainInfo(item, preferredCountryCode, seriesInfo); + ProcessMainInfo(item, seriesInfo); return item; } - private void ProcessMainInfo(Series series, string countryCode, RootObject seriesInfo) + private void ProcessMainInfo(Series series, RootObject seriesInfo) { series.Name = seriesInfo.name; series.SetProviderId(MetadataProviders.Tmdb, seriesInfo.id.ToString(_usCulture)); @@ -231,7 +231,7 @@ namespace MediaBrowser.Providers.TV } series.HomePageUrl = seriesInfo.homepage; - + series.RunTimeTicks = seriesInfo.episode_run_time.Select(i => TimeSpan.FromMinutes(i).Ticks).FirstOrDefault(); if (string.Equals(seriesInfo.status, "Ended", StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index 91bb1cbe61..c02ad177f3 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -384,11 +384,15 @@ namespace MediaBrowser.Server.Implementations.Channels { var val = width.Value; - return list + var res = list .OrderBy(i => i.Width.HasValue && i.Width.Value <= val) - .ThenBy(i => Math.Abs(i.Width ?? 0 - val)) + .ThenBy(i => Math.Abs((i.Width ?? 0) - val)) .ThenByDescending(i => i.Width ?? 0) - .ThenBy(list.IndexOf); + .ThenBy(list.IndexOf) + .ToList(); + + + return res; } return list @@ -533,6 +537,11 @@ namespace MediaBrowser.Server.Implementations.Channels ? null : _userManager.GetUserById(new Guid(query.UserId)); + if (!string.IsNullOrWhiteSpace(query.UserId) && user == null) + { + throw new ArgumentException("User not found."); + } + var channels = _channels; if (query.ChannelIds.Length > 0) diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index 59267e8569..404c333c2c 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -1,8 +1,13 @@ -using MediaBrowser.Common.Configuration; +using System.Linq; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; using MediaBrowser.Common.Implementations.Configuration; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Events; using MediaBrowser.Model.Logging; @@ -205,5 +210,55 @@ namespace MediaBrowser.Server.Implementations.Configuration } } } + + public void SetPreferredMetadataService(string service) + { + DisableMetadataService(typeof(Movie), Configuration, service); + DisableMetadataService(typeof(MusicAlbum), Configuration, service); + DisableMetadataService(typeof(MusicArtist), Configuration, service); + DisableMetadataService(typeof(Episode), Configuration, service); + DisableMetadataService(typeof(Season), Configuration, service); + DisableMetadataService(typeof(Series), Configuration, service); + DisableMetadataService(typeof(MusicVideo), Configuration, service); + DisableMetadataService(typeof(Trailer), Configuration, service); + DisableMetadataService(typeof(AdultVideo), Configuration, service); + DisableMetadataService(typeof(Video), Configuration, service); + } + + private void DisableMetadataService(Type type, ServerConfiguration config, string service) + { + var options = GetMetadataOptions(type, config); + + if (!options.DisabledMetadataSavers.Contains(service, StringComparer.OrdinalIgnoreCase)) + { + var list = options.DisabledMetadataSavers.ToList(); + + list.Add(service); + + options.DisabledMetadataSavers = list.ToArray(); + } + } + + private MetadataOptions GetMetadataOptions(Type type, ServerConfiguration config) + { + var options = config.MetadataOptions + .FirstOrDefault(i => string.Equals(i.ItemType, type.Name, StringComparison.OrdinalIgnoreCase)); + + if (options == null) + { + var list = config.MetadataOptions.ToList(); + + options = new MetadataOptions + { + ItemType = type.Name + }; + + list.Add(options); + + config.MetadataOptions = list.ToArray(); + } + + return options; + } } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs index 74ec325c62..2d7c798ade 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs @@ -49,7 +49,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security //ExecuteBasic(req, res, requestDto); //first check if session is authenticated //if (res.IsClosed) return; //AuthenticateAttribute already closed the request (ie auth failed) - //ValidateUser(req); + ValidateUser(req); } private void ValidateUser(IRequest req) diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json index 7e35d5d74a..294e293b7d 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Channels", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json index 5d06ba47e0..740d1f6e7b 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Channels", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json index 5fd59ee477..b9b3df10f1 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json @@ -215,5 +215,20 @@ "HeaderName": "N\u00e1zev", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Kan\u00e1ly", + "HeaderMediaFolders": "Slo\u017eky m\u00e9di\u00ed", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json index 1d3f195684..21ceabda5f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Kanaler", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json index 5b31baa337..546c8c1c44 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "Unbekannte Sprache", "ButtonMute": "Stumm", "ButtonUnmute": "Unmute", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "N\u00e4chster Track", "ButtonPause": "Pause", "ButtonPlay": "Abspielen", "ButtonEdit": "Bearbeiten", "ButtonQueue": "Warteschlange", "ButtonPlayTrailer": "Spiele Trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "Vorheriger Track", "LabelEnabled": "Aktivieren", "LabelDisabled": "Deaktivieren", "ButtonMoreInformation": "mehr Informationen", @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Kan\u00e4le", + "HeaderMediaFolders": "Medien Ordner", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json index 5305e1c881..4c441571d4 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Channels", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json index 8f1c2cc5af..a3f0038c74 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Channels", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json index ba55ada75e..9ae851d952 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Channels", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json index 1073d16cf2..55fbf236d9 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "Idioma desconocido", "ButtonMute": "Silencio", "ButtonUnmute": "Activar audio", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "Pista siguiente", "ButtonPause": "Pausa", "ButtonPlay": "Reproducir", "ButtonEdit": "Editar", "ButtonQueue": "En cola", "ButtonPlayTrailer": "Reproducir trailer", "ButtonPlaylist": "Lista de reproducci\u00f3n", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "Pista anterior", "LabelEnabled": "Activado", "LabelDisabled": "Desactivado", "ButtonMoreInformation": "M\u00e1s informaci\u00f3n", @@ -215,5 +215,20 @@ "HeaderName": "Nombre", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Artista del album", - "HeaderArtist": "Artista" + "HeaderArtist": "Artista", + "LabelAddedOnDate": "A\u00f1adido {0}", + "ButtonStart": "Inicio", + "HeaderChannels": "Canales", + "HeaderMediaFolders": "Carpetas de medios", + "HeaderBlockItemsWithNoRating": "Bloquear elementos sin informaci\u00f3n de clasificaci\u00f3n:", + "OptionBlockOthers": "Otros", + "OptionBlockTvShows": "Tv Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "M\u00fasica", + "OptionBlockMovies": "Pel\u00edculas", + "OptionBlockBooks": "Libros", + "OptionBlockGames": "Juegos", + "OptionBlockLiveTvPrograms": "Programas de TV en vivo", + "OptionBlockLiveTvChannels": "Canales de Tv en vivo", + "OptionBlockChannelContent": "Contenido de canales de Internet" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json index 1dbe5993cf..3f87eeaaed 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "Idioma Desconocido", "ButtonMute": "Mudo", "ButtonUnmute": "Quitar mudo", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "Pista Siguiente", "ButtonPause": "Pausar", "ButtonPlay": "Reproducir", "ButtonEdit": "Editar", "ButtonQueue": "A cola", "ButtonPlayTrailer": "Reproducir Avance", "ButtonPlaylist": "Lista de Reprod.", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "Pista Anterior", "LabelEnabled": "Habilitado", "LabelDisabled": "Deshabilitado", "ButtonMoreInformation": "Mas Informaci\u00f3n", @@ -143,7 +143,7 @@ "HeaderSelectChannelDownloadPath": "Selecciona una ruta para la descarga del canal", "HeaderSelectChannelDownloadPathHelp": "Navega o entra en la ruta usada para almacenar los archivos temporales del canal. La carpeta debe tener permisos de escritura.", "OptionNewCollection": "Nuevo...", - "ButtonAdd": "A\u00f1adir", + "ButtonAdd": "Agregar", "ButtonRemove": "Eliminar", "LabelChapterDownloaders": "Descargadores de Cap\u00edtulos:", "LabelChapterDownloadersHelp": "Habilite y califique sus descargadores de cap\u00edtulos preferidos en orden de prioridad. Los descargadores con menor prioridad s\u00f3lo seran utilizados para completar informaci\u00f3n faltante.", @@ -215,5 +215,20 @@ "HeaderName": "Nombre", "HeaderAlbum": "\u00c1lbum", "HeaderAlbumArtist": "Artista del \u00c1lbum", - "HeaderArtist": "Artista" + "HeaderArtist": "Artista", + "LabelAddedOnDate": "Agregado {0}", + "ButtonStart": "Iniciar", + "HeaderChannels": "Canales", + "HeaderMediaFolders": "Carpetas de Medios", + "HeaderBlockItemsWithNoRating": "Bloquear \u00edtems sin informaci\u00f3n de clasificaci\u00f3n", + "OptionBlockOthers": "Otros", + "OptionBlockTvShows": "Programas de TV", + "OptionBlockTrailers": "Avances", + "OptionBlockMusic": "M\u00fasica", + "OptionBlockMovies": "Pel\u00edculas", + "OptionBlockBooks": "Libros", + "OptionBlockGames": "Juegos", + "OptionBlockLiveTvPrograms": "Programas de TV en Vivo", + "OptionBlockLiveTvChannels": "Canales de TV en Vivo", + "OptionBlockChannelContent": "Contenido de Canales de Internet" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json index aaf35f77cf..7a020ab305 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "Langue inconnue", "ButtonMute": "Sourdine", "ButtonUnmute": "D\u00e9sactiver sourdine", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "Piste suivante", "ButtonPause": "Pause", "ButtonPlay": "Lire", "ButtonEdit": "Modifier", "ButtonQueue": "En file d'attente", "ButtonPlayTrailer": "Lire bande-annonce", "ButtonPlaylist": "Liste de lecture", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "Piste pr\u00e9c\u00e9dante", "LabelEnabled": "Activ\u00e9", "LabelDisabled": "D\u00e9sactiv\u00e9", "ButtonMoreInformation": "Plus d'information", @@ -215,5 +215,20 @@ "HeaderName": "Nom", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Cha\u00eenes", + "HeaderMediaFolders": "R\u00e9pertoires de m\u00e9dias", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json index 29e6dc70f5..59f4d83e9f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json @@ -215,5 +215,20 @@ "HeaderName": "\u05e9\u05dd", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "\u05e2\u05e8\u05d5\u05e6\u05d9\u05dd", + "HeaderMediaFolders": "\u05e1\u05e4\u05e8\u05d9\u05d5\u05ea \u05de\u05d3\u05d9\u05d4", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json index fcbe94376f..8ef22a7701 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "(linguaggio sconosciuto)", "ButtonMute": "Muto", "ButtonUnmute": "Togli muto", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "Prossimo", "ButtonPause": "Pausa", "ButtonPlay": "Riproduci", "ButtonEdit": "Modifica", "ButtonQueue": "In coda", "ButtonPlayTrailer": "Visualizza trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "Precedente", "LabelEnabled": "Abilitato", "LabelDisabled": "Disabilitato", "ButtonMoreInformation": "Maggiori informazioni", @@ -215,5 +215,20 @@ "HeaderName": "Nome", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Artista Album", - "HeaderArtist": "Artista" + "HeaderArtist": "Artista", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Canali", + "HeaderMediaFolders": "Cartelle dei media", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json index 36588f2ec0..22d1d91a36 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "\u0411\u0435\u043b\u0433\u0456\u0441\u0456\u0437 \u0442\u0456\u043b", "ButtonMute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u04e9\u0448\u0456\u0440\u0443", "ButtonUnmute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u049b\u043e\u0441\u0443", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0436\u043e\u043b\u0448\u044b\u049b", "ButtonPause": "\u04ae\u0437\u0456\u043b\u0456\u0441", "ButtonPlay": "\u041e\u0439\u043d\u0430\u0442\u0443", "ButtonEdit": "\u04e8\u04a3\u0434\u0435\u0443", "ButtonQueue": "\u041a\u0435\u0437\u0435\u043a", "ButtonPlayTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u0434\u0456 \u043e\u0439\u043d\u0430\u0442\u0443", "ButtonPlaylist": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "\u0410\u043b\u0434\u044b\u04a3\u0493\u044b \u0436\u043e\u043b\u0448\u044b\u049b", "LabelEnabled": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d", "LabelDisabled": "\u0410\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d", "ButtonMoreInformation": "\u041a\u04e9\u0431\u0456\u0440\u0435\u043a \u0430\u049b\u043f\u0430\u0440\u0430\u0442", @@ -215,5 +215,20 @@ "HeaderName": "\u0410\u0442\u044b", "HeaderAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c", "HeaderAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u0441\u044b", - "HeaderArtist": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b" + "HeaderArtist": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b", + "LabelAddedOnDate": "\u04ae\u0441\u0442\u0435\u043b\u0433\u0435\u043d\u0456 {0}", + "ButtonStart": "\u0411\u0430\u0441\u0442\u0430\u0443", + "HeaderChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440", + "HeaderMediaFolders": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b", + "HeaderBlockItemsWithNoRating": "\u0416\u0430\u0441\u0442\u044b\u049b \u0441\u0430\u043d\u0430\u0442\u044b \u0436\u043e\u049b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0434\u0456 \u049b\u04b1\u0440\u0441\u0430\u0443\u043b\u0430\u0443:", + "OptionBlockOthers": "\u0411\u0430\u0441\u049b\u0430\u043b\u0430\u0440", + "OptionBlockTvShows": "\u0421\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440", + "OptionBlockTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440", + "OptionBlockMusic": "\u041c\u0443\u0437\u044b\u043a\u0430", + "OptionBlockMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440", + "OptionBlockBooks": "\u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440", + "OptionBlockGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440", + "OptionBlockLiveTvPrograms": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414-\u0442\u0430\u0440\u0430\u0442\u044b\u043c\u0434\u0430\u0440", + "OptionBlockLiveTvChannels": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414-\u0430\u0440\u043d\u0430\u043b\u0430\u0440", + "OptionBlockChannelContent": "\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0430\u0440\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json index fa186607ac..b863a6c6e8 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Channels", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json index 7f9156ef52..acf1182f72 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Channels", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json index 5545b69d2e..e11fd37bec 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "Onbekende taal", "ButtonMute": "Dempen", "ButtonUnmute": "Dempen opheffen", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "Volgend nummer", "ButtonPause": "Pauze", "ButtonPlay": "Afspelen", "ButtonEdit": "Bewerken", "ButtonQueue": "Wachtrij", "ButtonPlayTrailer": "Trailer Afspelen", "ButtonPlaylist": "Afspeellijst", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "Vorig nummer", "LabelEnabled": "Ingeschakeld", "LabelDisabled": "Uitgeschakeld", "ButtonMoreInformation": "Meer informatie", @@ -215,5 +215,20 @@ "HeaderName": "Naam", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artiest", - "HeaderArtist": "Artiest" + "HeaderArtist": "Artiest", + "LabelAddedOnDate": "Toegevoegd {0}", + "ButtonStart": "Start", + "HeaderChannels": "Kanalen", + "HeaderMediaFolders": "Media Mappen", + "HeaderBlockItemsWithNoRating": "Blokkeren van onderdelen zonder classificatiegegevens:", + "OptionBlockOthers": "Overigen", + "OptionBlockTvShows": "TV Series", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Muziek", + "OptionBlockMovies": "Films", + "OptionBlockBooks": "Boeken", + "OptionBlockGames": "Spellen", + "OptionBlockLiveTvPrograms": "Live TV Programma's", + "OptionBlockLiveTvChannels": "Live TV Kanalen", + "OptionBlockChannelContent": "Internet kanaal Inhoud" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json index b29940c31b..729e20b316 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Channels", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json index 225172c813..16407aa48d 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "Idioma desconhecido", "ButtonMute": "Mudo", "ButtonUnmute": "Remover Mudo", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "Pr\u00f3xima faixa", "ButtonPause": "Pausar", "ButtonPlay": "Reproduzir", "ButtonEdit": "Editar", "ButtonQueue": "Fila", "ButtonPlayTrailer": "Reproduzir trailer", "ButtonPlaylist": "Lista reprodu\u00e7\u00e3o", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "Faixa anterior", "LabelEnabled": "Ativada", "LabelDisabled": "Desativada", "ButtonMoreInformation": "Mais informa\u00e7\u00f5es", @@ -215,5 +215,20 @@ "HeaderName": "Nome", "HeaderAlbum": "\u00c1lbum", "HeaderAlbumArtist": "Artista do \u00c1lbum", - "HeaderArtist": "Artista" + "HeaderArtist": "Artista", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Canais", + "HeaderMediaFolders": "Pastas de M\u00eddia", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json index 6adf54fbd9..9ca378a91f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "Unknown language", "ButtonMute": "Mute", "ButtonUnmute": "Unmute", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "Pr\u00f3xima Faixa", "ButtonPause": "Pausar", "ButtonPlay": "Reproduzir", "ButtonEdit": "Editar", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "Faixa Anterior", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -215,5 +215,20 @@ "HeaderName": "Nome", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Canais", + "HeaderMediaFolders": "Pastas Multim\u00e9dia", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json index 0d6bc9e83a..20eede5412 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json @@ -38,7 +38,7 @@ "LabelEpisode": "\u042d\u043f\u0438\u0437\u043e\u0434", "LabelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b", "LabelStopping": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e", - "ButtonStop": "\u0421\u0442\u043e\u043f", + "ButtonStop": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c", "LabelCancelled": "(\u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e)", "LabelFailed": "(\u043d\u0435\u0443\u0434\u0430\u0447\u043d\u043e)", "LabelAbortedByServerShutdown": "(\u041f\u0440\u0435\u0440\u0432\u0430\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430)", @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "\u041d\u0435\u043e\u043f\u043e\u0437\u043d\u0430\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a", "ButtonMute": "\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0432\u0443\u043a", "ButtonUnmute": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0432\u0443\u043a", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430", "ButtonPause": "\u041f\u0430\u0443\u0437\u0430", "ButtonPlay": "\u0412\u043e\u0441\u043f\u0440", "ButtonEdit": "\u041f\u0440\u0430\u0432\u0438\u0442\u044c", "ButtonQueue": "\u041e\u0447\u0435\u0440\u0435\u0434\u044c", "ButtonPlayTrailer": "\u0412\u043e\u0441\u043f\u0440 \u0442\u0440\u0435\u0439\u043b\u0435\u0440", "ButtonPlaylist": "\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430", "LabelEnabled": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u043e", "LabelDisabled": "\u0412\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043e", "ButtonMoreInformation": "\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f", @@ -215,5 +215,20 @@ "HeaderName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435", "HeaderAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c", "HeaderAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c", - "HeaderArtist": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c" + "HeaderArtist": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c", + "LabelAddedOnDate": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e {0}", + "ButtonStart": "\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c", + "HeaderChannels": "\u041a\u0430\u043d\u0430\u043b\u044b", + "HeaderMediaFolders": "\u041c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438", + "HeaderBlockItemsWithNoRating": "\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0431\u0435\u0437 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438:", + "OptionBlockOthers": "\u0414\u0440\u0443\u0433\u0438\u0435", + "OptionBlockTvShows": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b", + "OptionBlockTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b", + "OptionBlockMusic": "\u041c\u0443\u0437\u044b\u043a\u0430", + "OptionBlockMovies": "\u0424\u0438\u043b\u044c\u043c\u044b", + "OptionBlockBooks": "\u041a\u043d\u0438\u0433\u0438", + "OptionBlockGames": "\u0418\u0433\u0440\u044b", + "OptionBlockLiveTvPrograms": "\u042d\u0444\u0438\u0440\u043d\u044b\u0435 \u0442\u0435\u043b\u0435\u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438", + "OptionBlockLiveTvChannels": "\u042d\u0444\u0438\u0440\u043d\u044b\u0435 \u0422\u0412-\u043a\u0430\u043d\u0430\u043b\u044b", + "OptionBlockChannelContent": "\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043a\u0430\u043d\u0430\u043b\u043e\u0432" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json index 845621b100..153160c4aa 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json @@ -58,14 +58,14 @@ "LabelUnknownLanguage": "Ok\u00e4nt spr\u00e5k", "ButtonMute": "Tyst", "ButtonUnmute": "Muting av", - "ButtonNextTrack": "Next Track", + "ButtonNextTrack": "N\u00e4sta sp\u00e5r", "ButtonPause": "Paus", "ButtonPlay": "Spela upp", "ButtonEdit": "\u00c4ndra", "ButtonQueue": "K\u00f6", "ButtonPlayTrailer": "Spela upp trailer", "ButtonPlaylist": "Spellista", - "ButtonPreviousTrack": "Previous Track", + "ButtonPreviousTrack": "F\u00f6reg\u00e5ende sp\u00e5r", "LabelEnabled": "Aktiverad", "LabelDisabled": "Avaktiverad", "ButtonMoreInformation": "Mer information", @@ -215,5 +215,20 @@ "HeaderName": "Namn", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Albumartist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Kanaler", + "HeaderMediaFolders": "Mediamappar", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json index 8a10fdc558..7405894d47 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json @@ -215,5 +215,20 @@ "HeaderName": "T\u00ean", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "Channels", + "HeaderMediaFolders": "Media Folders", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json index abf7a395a9..1da78b98d0 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json @@ -215,5 +215,20 @@ "HeaderName": "Name", "HeaderAlbum": "Album", "HeaderAlbumArtist": "Album Artist", - "HeaderArtist": "Artist" + "HeaderArtist": "Artist", + "LabelAddedOnDate": "Added {0}", + "ButtonStart": "Start", + "HeaderChannels": "\u983b\u5ea6", + "HeaderMediaFolders": "\u5a92\u9ad4\u6587\u4ef6\u593e", + "HeaderBlockItemsWithNoRating": "Block items with no rating information:", + "OptionBlockOthers": "Others", + "OptionBlockTvShows": "TV Shows", + "OptionBlockTrailers": "Trailers", + "OptionBlockMusic": "Music", + "OptionBlockMovies": "Movies", + "OptionBlockBooks": "Books", + "OptionBlockGames": "Games", + "OptionBlockLiveTvPrograms": "Live TV Programs", + "OptionBlockLiveTvChannels": "Live TV Channels", + "OptionBlockChannelContent": "Internet Channel Content" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ar.json b/MediaBrowser.Server.Implementations/Localization/Server/ar.json index 53c3edfb16..ecb6abd641 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ar.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ar.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ca.json b/MediaBrowser.Server.Implementations/Localization/Server/ca.json index 65c50df853..35f607be11 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ca.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/cs.json b/MediaBrowser.Server.Implementations/Localization/Server/cs.json index 1f1bea554d..5d25ef870c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/cs.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/cs.json @@ -479,7 +479,7 @@ "HeaderProgram": "Program", "HeaderClients": "Klienti", "LabelCompleted": "Hotovo", - "LabelFailed": "Chyba", + "LabelFailed": "Failed", "LabelSkipped": "P\u0159esko\u010deno", "HeaderEpisodeOrganization": "Episode Organization", "LabelSeries": "Series:", @@ -490,7 +490,7 @@ "HeaderSupportTheTeam": "Podpo\u0159te t\u00edm Media Browser", "LabelSupportAmount": "Suma (USD)", "HeaderSupportTheTeamHelp": "Pomozte zajistit pokra\u010dov\u00e1n\u00ed v\u00fdvoje tohoto projektu t\u00edm, \u017ee daruje. \u010c\u00e1st v\u0161ech dar\u016f bude pou\u017eita na dal\u0161\u00ed bezplatn\u00e9 n\u00e1stroje na kter\u00fdch jsme z\u00e1visl\u00ed.", - "ButtonEnterSupporterKey": "Enter supporter key", + "ButtonEnterSupporterKey": "Vlo\u017ete kl\u00ed\u010d sponzora", "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.", "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.", "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.", @@ -529,7 +529,7 @@ "ButtonShutdown": "Vypnout", "ButtonUpdateNow": "Update Now", "PleaseUpdateManually": "Please shutdown the server and update manually.", - "NewServerVersionAvailable": "A new version of Media Browser Server is available!", + "NewServerVersionAvailable": "Je dostupn\u00e1 nov\u00e1 verze programu Media Browser!", "ServerUpToDate": "Media Browser Server is up to date", "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.", "LabelComponentsUpdated": "The following components have been installed or updated:", @@ -537,14 +537,14 @@ "LabelDownMixAudioScale": "Audio boost when downmixing:", "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.", "ButtonLinkKeys": "Link Keys", - "LabelOldSupporterKey": "Old supporter key", - "LabelNewSupporterKey": "New supporter key", + "LabelOldSupporterKey": "Star\u00fd kl\u00ed\u010d sponzora", + "LabelNewSupporterKey": "Nov\u00fd kl\u00ed\u010d sponzora", "HeaderMultipleKeyLinking": "Multiple Key Linking", "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.", - "LabelCurrentEmailAddress": "Current email address", + "LabelCurrentEmailAddress": "Aktu\u00e1ln\u00ed e-mailov\u00e1 adresa", "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.", "HeaderForgotKey": "Forgot Key", - "LabelEmailAddress": "Email address", + "LabelEmailAddress": "E-mailov\u00e1 adresa", "LabelSupporterEmailAddress": "The email address that was used to purchase the key.", "ButtonRetrieveKey": "Retrieve Key", "LabelSupporterKey": "Supporter Key (paste from email)", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/da.json b/MediaBrowser.Server.Implementations/Localization/Server/da.json index c5bf75c0ff..8f7bca7868 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/da.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/da.json @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/de.json b/MediaBrowser.Server.Implementations/Localization/Server/de.json index 151156fbf5..0338299860 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/de.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json @@ -479,10 +479,10 @@ "HeaderProgram": "Programm", "HeaderClients": "Clients", "LabelCompleted": "Fertiggestellt", - "LabelFailed": "Gescheitert", + "LabelFailed": "Failed", "LabelSkipped": "\u00dcbersprungen", "HeaderEpisodeOrganization": "Episodensortierung", - "LabelSeries": "Serien:", + "LabelSeries": "Series:", "LabelSeasonNumber": "Staffelnummer", "LabelEpisodeNumber": "Episodennummer", "LabelEndingEpisodeNumber": "Ending episode number", @@ -630,8 +630,8 @@ "ButtonScenes": "Szenen", "ButtonSubtitles": "Untertitel", "ButtonAudioTracks": "Audiospuren", - "ButtonPreviousTrack": "Vorheriger Track", - "ButtonNextTrack": "N\u00e4chster Track", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Stop", "ButtonPause": "Pause", "LabelGroupMoviesIntoCollections": "Gruppiere Filme in Collections", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/el.json b/MediaBrowser.Server.Implementations/Localization/Server/el.json index f590a2f64f..fb43d18778 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/el.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/el.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json index 051387ea95..202a376829 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json index 60557cdca8..764685deb3 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json b/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json index fbd39b960e..5a631a8d67 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json @@ -479,10 +479,10 @@ "HeaderProgram": "Programa", "HeaderClients": "Clientes", "LabelCompleted": "Completado", - "LabelFailed": "Err\u00f3neo", + "LabelFailed": "Error", "LabelSkipped": "Omitido", "HeaderEpisodeOrganization": "Organizaci\u00f3n de episodios", - "LabelSeries": "Serie:", + "LabelSeries": "Series:", "LabelSeasonNumber": "Temporada n\u00famero:", "LabelEpisodeNumber": "Episodio n\u00famero:", "LabelEndingEpisodeNumber": "N\u00famero episodio final:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login renuncia:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Donar autom\u00e1ticamente esta cantidad cada mes", - "LabelAutomaticallyDonateHelp": "Usted puede cancelar en cualquier momento desde su cuenta de PayPal." + "LabelAutomaticallyDonateHelp": "Usted puede cancelar en cualquier momento desde su cuenta de PayPal.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json index c8f3bcb05e..e5390cef5f 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json @@ -132,7 +132,7 @@ "OptionReleaseDate": "Fecha de Estreno", "OptionPlayCount": "N\u00famero de Reproducc.", "OptionDatePlayed": "Fecha de Reproducci\u00f3n", - "OptionDateAdded": "A\u00f1adido el", + "OptionDateAdded": "Agregardo el", "OptionAlbumArtist": "Artista del \u00c1lbum", "OptionArtist": "Artista", "OptionAlbum": "\u00c1lbum", @@ -234,7 +234,7 @@ "ButtonSelect": "Seleccionar", "ButtonSearch": "B\u00fasqueda", "ButtonGroupVersions": "Agrupar Versiones", - "ButtonAddToCollection": "Agregar a Colecci\u00f3n.", + "ButtonAddToCollection": "Agregar a Colecci\u00f3n", "PismoMessage": "Utilizando Pismo File Mount a trav\u00e9s de una licencia donada.", "TangibleSoftwareMessage": "Utilizando convertidores Java\/C# de Tangible Solutions por medio de una licencia donada.", "HeaderCredits": "Cr\u00e9ditos", @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "Al habilitarlo, se descargar\u00e1n autom\u00e1ticamente nuevas im\u00e1genes conforme son a\u00f1adidas a fanart.tv. Las Im\u00e1genes existentes no ser\u00e1n reemplazadas.", "LabelAutomaticUpdatesTmdbHelp": "Al habilitarlo, se descargar\u00e1n autom\u00e1ticamente nuevas im\u00e1genes conforme son a\u00f1adidas a TheMovieDB.org. Las im\u00e1genes existentes no ser\u00e1n reemplazadas.", "LabelAutomaticUpdatesTvdbHelp": "Al habilitarlo, se descargar\u00e1n autom\u00e1ticamente nuevas im\u00e1genes conforme son a\u00f1adidas a TheTVDB.com. Las im\u00e1genes existentes no ser\u00e1n reemplazadas.", - "ExtractChapterImagesHelp": "Extraer im\u00e1genes de cap\u00edtulos permite a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, intensivo en utilizaci\u00f3n del CPU y puede requerir varios gigabytes de espacio. Se ejecuta como una tarea nocturna, programada a las 4 de la ma\u00f1ana, aunque esto se puede configurar en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante las horas pico de uso.", + "ExtractChapterImagesHelp": "Extraer im\u00e1genes de cap\u00edtulos permite a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, intensivo en utilizaci\u00f3n del CPU y puede requerir varios gigabytes de espacio. Se ejecuta cuando se detectan nuevos videos, tambi\u00e9n como una tarea nocturna, programada a las 4:00 am. La programaci\u00f3n puede configurarse en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante horas pico de uso.", "LabelMetadataDownloadLanguage": "Lenguaje preferido para descargas:", "ButtonAutoScroll": "Auto-desplazamiento", "LabelImageSavingConvention": "Convenci\u00f3n de almacenamiento de im\u00e1genes:", @@ -353,9 +353,9 @@ "LabelMaxScreenshotsPerItem": "N\u00famero m\u00e1ximo de capturas de pantalla por \u00edtem:", "LabelMinBackdropDownloadWidth": "Anchura m\u00ednima de descarga de im\u00e1genes de fondo:", "LabelMinScreenshotDownloadWidth": "Anchura m\u00ednima de descarga de capturas de pantalla:", - "ButtonAddScheduledTaskTrigger": "A\u00f1adir Evento", - "HeaderAddScheduledTaskTrigger": "A\u00f1adir Evento", - "ButtonAdd": "A\u00f1adir", + "ButtonAddScheduledTaskTrigger": "Agregar Disparador de Tarea", + "HeaderAddScheduledTaskTrigger": "Agregar Disparador de Tarea", + "ButtonAdd": "Agregar", "LabelTriggerType": "Tipo de Evento:", "OptionDaily": "Diario", "OptionWeekly": "Semanal", @@ -406,7 +406,7 @@ "LabelFromHelp": "Ejemplo: D:\\Pel\u00edculas (en el servidor)", "LabelTo": "Hasta:", "LabelToHelp": "Ejemplo: \\\\MiServidor\\Pel\u00edculas (una ruta a la que los clientes pueden acceder)", - "ButtonAddPathSubstitution": "A\u00f1adir Ruta Alternativa", + "ButtonAddPathSubstitution": "Agregar Ruta Alternativa", "OptionSpecialEpisode": "Especiales", "OptionMissingEpisode": "Episodios Faltantes", "OptionUnairedEpisode": "Episodios no Emitidos", @@ -425,7 +425,7 @@ "OptionEnableDebugTranscodingLoggingHelp": "Esto crear\u00e1 archivos de bit\u00e1cora muy grandes y solo se recomienda cuando se requiera solucionar problemas.", "OptionUpscaling": "Permitir que los clientes solicitar v\u00eddeo de escala aumentada", "OptionUpscalingHelp": "En algunos casos esto resultar\u00e1 en una mejora de la calidad del video pero incrementar\u00e1 el uso del CPU.", - "EditCollectionItemsHelp": "A\u00f1adir o quitar pel\u00edculas, series, discos, libros o juegos que usted desee agrupar dentro de esta colecci\u00f3n.", + "EditCollectionItemsHelp": "Agregar o quitar pel\u00edculas, series, discos, libros o juegos que usted desee agrupar dentro de esta colecci\u00f3n.", "HeaderAddTitles": "Agregar T\u00edtulos", "LabelEnableDlnaPlayTo": "Habilitar \"Reproducir en\" por DLNA", "LabelEnableDlnaPlayToHelp": "Media Browser puede detectar dispositivos en su red y ofrecer la posibilidad de controlarlos remotamente.", @@ -587,8 +587,8 @@ "NotificationOptionGamePlaybackStopped": "Ejecuci\u00f3n de juego detenida", "NotificationOptionTaskFailed": "Falla de tarea programada", "NotificationOptionInstallationFailed": "Falla de instalaci\u00f3n", - "NotificationOptionNewLibraryContent": "Adici\u00f3n de nuevos contenidos", - "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido agregado (varios).", + "NotificationOptionNewLibraryContent": "Nuevo contenido agregado", + "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido agregado (varios)", "SendNotificationHelp": "Por defecto, las notificaciones son enviadas a la bandeja de entrada del panel de control. Navegue el cat\u00e1logo de complementos para instalar opciones de notificaci\u00f3n adicionales.", "NotificationOptionServerRestartRequired": "Reinicio del servidor requerido", "LabelNotificationEnabled": "Habilitar esta notificaci\u00f3n", @@ -630,8 +630,8 @@ "ButtonScenes": "Escenas", "ButtonSubtitles": "Subt\u00edtulos", "ButtonAudioTracks": "Pistas de audio", - "ButtonPreviousTrack": "Pista Anterior", - "ButtonNextTrack": "Pista Siguiente", + "ButtonPreviousTrack": "Pista anterior", + "ButtonNextTrack": "Pista siguiente", "ButtonStop": "Detener", "ButtonPause": "Pausar", "LabelGroupMoviesIntoCollections": "Agrupar pel\u00edculas en colecciones", @@ -702,8 +702,8 @@ "LabelSerialNumber": "N\u00famero de serie:", "LabelDeviceDescription": "Descripci\u00f3n del dispositivo", "HeaderIdentificationCriteriaHelp": "Capture, al menos, un criterio de identificaci\u00f3n.", - "HeaderDirectPlayProfileHelp": "A\u00f1ada perfiles de reproducci\u00f3n directa para indicar que formatos puede manejar el dispositivo de manera nativa.", - "HeaderTranscodingProfileHelp": "A\u00f1ada perfiles de transcodificaci\u00f3n para indicar que formatos deben ser usados cuando se requiera transcodificar.", + "HeaderDirectPlayProfileHelp": "Agregue perfiles de reproducci\u00f3n directa para indicar que formatos puede manejar el dispositivo de manera nativa.", + "HeaderTranscodingProfileHelp": "Agruegue perfiles de transcodificaci\u00f3n para indicar que formatos deben ser usados cuando se requiera transcodificar.", "HeaderResponseProfileHelp": "Los perfiles de respuesta proporcionan un medio para personalizar la informaci\u00f3n enviada a un dispositivo cuando se reproducen ciertos tipos de medios.", "LabelXDlnaCap": "X-DLNA cap:", "LabelXDlnaCapHelp": "Determina el contenido del elemento X_DLNACAP en el namespace urn:schemas-dlna-org:device-1-0.", @@ -824,7 +824,7 @@ "LabelProtocolInfoHelp": "El valor que ser\u00e1 utilizado cuando se responde a solicitudes GetProtocolInfo desde el dispositivo.", "TabXbmcMetadata": "Xbmc", "HeaderXbmcMetadataHelp": "Media Browser incluye soporte nativo para metadatos Nfo e im\u00e1genes de Xbmc. Para habilitar o deshabilitar metadatos de Xbmc, utilice la pesta\u00f1a Avanzado para configurar opciones para sus tipos de medios.", - "LabelXbmcMetadataUser": "A\u00f1adir usuario de monitoreo de datos a los nfo\u00b4s para:", + "LabelXbmcMetadataUser": "Agregar usuario de monitoreo de datos a los nfo\u00b4s para:", "LabelXbmcMetadataUserHelp": "Habilitar esto para mantener el monitoreo de datos en sincron\u00eda entre Media Browser y Xbmc.", "LabelXbmcMetadataDateFormat": "Formato de fecha de esteno:", "LabelXbmcMetadataDateFormatHelp": "Todas las fechas en los archivos nfo's ser\u00e1n le\u00eddas y escritas empleando este formato.", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Aviso de Inicio de Sesi\u00f3n:", "LabelLoginDisclaimerHelp": "Esto se mostrara al final de la pagina de inicio de sesi\u00f3n.", "LabelAutomaticallyDonate": "Donar autom\u00e1ticamente esta cantidad cada mes", - "LabelAutomaticallyDonateHelp": "Puedes cancelarlo en cualquier momento por medio de tu cuenta PayPal." + "LabelAutomaticallyDonateHelp": "Puedes cancelarlo en cualquier momento por medio de tu cuenta PayPal.", + "OptionList": "Lista", + "TabDashboard": "Panel de Control", + "TitleServer": "Servidor", + "LabelCache": "Cach\u00e9:", + "LabelLogs": "Bit\u00e1coras:", + "LabelMetadata": "Metadatos:", + "LabelImagesByName": "Im\u00e1genes por nombre:", + "LabelTranscodingTemporaryFiles": "Archivos temporales de transcodificaci\u00f3n:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fr.json b/MediaBrowser.Server.Implementations/Localization/Server/fr.json index 05b8f568d9..90a412bfc2 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json @@ -396,7 +396,7 @@ "HeaderCastCrew": "\u00c9quipe de tournage", "HeaderAdditionalParts": "Parties Additionelles", "ButtonSplitVersionsApart": "S\u00e9parer les versions", - "ButtonPlayTrailer": "Bande-annonce", + "ButtonPlayTrailer": "Trailer", "LabelMissing": "Manquant(s)", "LabelOffline": "Hors ligne", "PathSubstitutionHelp": "Les substitutions de chemins d'acc\u00e8s sont utilis\u00e9es pour faire correspondre un chemin d'acc\u00e8s du serveur \u00e0 un chemin d'acc\u00e8s accessible par les clients. En autorisant un acc\u00e8s direct aux m\u00e9dias du serveur, les clients pourront les lire directement du r\u00e9seau et \u00e9viter l'utilisation inutiles des ressources du serveur en demandant du transcodage.", @@ -479,10 +479,10 @@ "HeaderProgram": "Programme", "HeaderClients": "Clients", "LabelCompleted": "Compl\u00e9t\u00e9", - "LabelFailed": "\u00c9chec", + "LabelFailed": "Failed", "LabelSkipped": "Saut\u00e9", "HeaderEpisodeOrganization": "Organisation d'\u00e9pisodes", - "LabelSeries": "S\u00e9ries:", + "LabelSeries": "Series:", "LabelSeasonNumber": "Num\u00e9ro de saison", "LabelEpisodeNumber": "Num\u00e9ro d'\u00e9pisode", "LabelEndingEpisodeNumber": "Num\u00e9ro d'\u00e9pisode se terminant", @@ -630,8 +630,8 @@ "ButtonScenes": "Sc\u00e8nes", "ButtonSubtitles": "Sous-titres", "ButtonAudioTracks": "Piste audio", - "ButtonPreviousTrack": "Piste pr\u00e9c\u00e9dante", - "ButtonNextTrack": "Piste suivante", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Arr\u00eat", "ButtonPause": "Pause", "LabelGroupMoviesIntoCollections": "Grouper les films en collections", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/he.json b/MediaBrowser.Server.Implementations/Localization/Server/he.json index 55ed199e13..7ab9173aec 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/he.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/he.json @@ -396,7 +396,7 @@ "HeaderCastCrew": "\u05e9\u05d7\u05e7\u05e0\u05d9\u05dd \u05d5\u05e6\u05d5\u05d5\u05ea", "HeaderAdditionalParts": "\u05d7\u05dc\u05e7\u05d9\u05dd \u05e0\u05d5\u05e1\u05e4\u05d9\u05dd", "ButtonSplitVersionsApart": "\u05e4\u05e6\u05dc \u05d2\u05e8\u05e1\u05d0\u05d5\u05ea \u05d1\u05e0\u05e4\u05e8\u05d3", - "ButtonPlayTrailer": "\u05d8\u05e8\u05d9\u05d9\u05dc\u05e8\u05d9\u05dd", + "ButtonPlayTrailer": "Trailer", "LabelMissing": "\u05d7\u05e1\u05e8", "LabelOffline": "\u05dc\u05d0 \u05de\u05e7\u05d5\u05d5\u05df", "PathSubstitutionHelp": "\u05e0\u05ea\u05d9\u05d1\u05d9\u05dd \u05d7\u05dc\u05d5\u05e4\u05d9\u05d9\u05dd \u05d4\u05dd \u05dc\u05e6\u05d5\u05e8\u05da \u05de\u05d9\u05e4\u05d5\u05d9 \u05e0\u05ea\u05d9\u05d1\u05d9\u05dd \u05d1\u05e9\u05e8\u05ea \u05dc\u05e0\u05ea\u05d9\u05d1\u05d9\u05dd \u05e9\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d9\u05db\u05d5\u05dc\u05d9\u05dd \u05dc\u05d2\u05e9\u05ea \u05d0\u05dc\u05d9\u05d4\u05dd. \u05e2\u05dc \u05d9\u05d3\u05d9 \u05d4\u05e8\u05e9\u05d0\u05d4 \u05dc\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d2\u05d9\u05e9\u05d4 \u05d9\u05e9\u05d9\u05e8\u05d4 \u05dc\u05de\u05d3\u05d9\u05d4 \u05d1\u05e9\u05e8\u05ea \u05d0\u05dd \u05d9\u05db\u05d5\u05dc\u05d9\u05dd \u05dc\u05e0\u05d2\u05df \u05d0\u05ea \u05d4\u05e7\u05d1\u05e6\u05d9\u05dd \u05d9\u05e9\u05d9\u05e8\u05d5\u05ea \u05e2\u05dc \u05d2\u05d1\u05d9 \u05d4\u05e8\u05e9\u05ea \u05d5\u05dc\u05d4\u05d9\u05de\u05e0\u05e2 \u05de\u05e9\u05d9\u05de\u05d5\u05e9 \u05d1\u05de\u05e9\u05d0\u05d1\u05d9 \u05d4\u05e9\u05e8\u05ea \u05dc\u05e6\u05d5\u05e8\u05da \u05e7\u05d9\u05d3\u05d5\u05d3 \u05d5\u05e9\u05d9\u05d3\u05d5\u05e8.", @@ -479,10 +479,10 @@ "HeaderProgram": "\u05ea\u05d5\u05db\u05e0\u05d4", "HeaderClients": "\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd", "LabelCompleted": "\u05d4\u05d5\u05e9\u05dc\u05dd", - "LabelFailed": "\u05e0\u05db\u05e9\u05dc", + "LabelFailed": "Failed", "LabelSkipped": "\u05d3\u05d5\u05dc\u05d2", "HeaderEpisodeOrganization": "\u05d0\u05d9\u05e8\u05d2\u05d5\u05df \u05e4\u05e8\u05e7\u05d9\u05dd", - "LabelSeries": "\u05e1\u05d3\u05e8\u05d4:", + "LabelSeries": "Series:", "LabelSeasonNumber": "\u05de\u05e1\u05e4\u05e8 \u05e2\u05d5\u05e0\u05d4:", "LabelEpisodeNumber": "\u05de\u05e1\u05e4\u05e8 \u05e4\u05e8\u05e7:", "LabelEndingEpisodeNumber": "\u05de\u05e1\u05e4\u05e8 \u05e1\u05d9\u05d5\u05dd \u05e4\u05e8\u05e7:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/it.json b/MediaBrowser.Server.Implementations/Localization/Server/it.json index 591fe98b91..026772da57 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/it.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/it.json @@ -479,10 +479,10 @@ "HeaderProgram": "Programma", "HeaderClients": "Dispositivi", "LabelCompleted": "Completato", - "LabelFailed": "Fallito", + "LabelFailed": "Failed", "LabelSkipped": "Saltato", "HeaderEpisodeOrganization": "Organizzazione Episodi", - "LabelSeries": "Serie:", + "LabelSeries": "Series:", "LabelSeasonNumber": "Numero Stagione:", "LabelEpisodeNumber": "Numero Episodio:", "LabelEndingEpisodeNumber": "Ultimo Episodio Numero:", @@ -630,8 +630,8 @@ "ButtonScenes": "Scene", "ButtonSubtitles": "Sottotitoli", "ButtonAudioTracks": "Traccia Audio", - "ButtonPreviousTrack": "Precedente", - "ButtonNextTrack": "Prossimo", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Stop", "ButtonPause": "Pausa", "LabelGroupMoviesIntoCollections": "Raggruppa i film nelle collection", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "Questo verr\u00e0 visualizzato nella parte inferiore della pagina di accesso.", "LabelAutomaticallyDonate": "Donare automaticamente questo importo ogni mese", - "LabelAutomaticallyDonateHelp": "\u00c8 possibile annullare in qualsiasi momento tramite il vostro conto PayPal." + "LabelAutomaticallyDonateHelp": "\u00c8 possibile annullare in qualsiasi momento tramite il vostro conto PayPal.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/kk.json b/MediaBrowser.Server.Implementations/Localization/Server/kk.json index f7e73eb8fa..8ec25aea42 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/kk.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/kk.json @@ -795,7 +795,7 @@ "MessageLearnHowToCustomize": "\u041e\u0441\u044b \u0431\u0435\u0442\u0442\u0456 \u0436\u0435\u043a\u0435 \u043a\u04e9\u04a3\u0456\u043b\u0433\u0435 \u04b1\u043d\u0430\u0442\u0443 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u049b\u0430\u043b\u0430\u0439 \u0442\u0435\u04a3\u0448\u0435\u0443\u0456\u043d \u04af\u0439\u0440\u0435\u043d\u0456\u04a3\u0456\u0437. \u0422\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u04a3\u0456\u0437\u0434\u0456 \u049b\u0430\u0440\u0430\u0443 \u0436\u04d9\u043d\u0435 \u0436\u0430\u04a3\u0430\u0440\u0442\u0443 \u04af\u0448\u0456\u043d \u044d\u043a\u0440\u0430\u043d\u0434\u0430\u0493\u044b \u0436\u043e\u0493\u0430\u0440\u0493\u044b \u043e\u04a3 \u0431\u04b1\u0440\u044b\u0448\u044b\u043d\u0434\u0430\u0493\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u044b\u049b \u0431\u0435\u043b\u0433\u0456\u0448\u0435\u04a3\u0456\u0437\u0434\u0456 \u0431\u0430\u0441\u044b\u04a3\u044b\u0437.", "ButtonEditOtherUserPreferences": "\u041e\u0441\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043d \u04e9\u04a3\u0434\u0435\u0443.", "LabelChannelStreamQuality": "\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:", - "LabelChannelStreamQualityHelp": "\u04e8\u0442\u043a\u0456\u0437\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456 \u0442\u04e9\u043c\u0435\u043d \u043e\u0440\u0442\u0430\u043b\u0430\u0440\u0434\u0430, \u0441\u0430\u043f\u0430\u043d\u044b \u0448\u0435\u043a\u0442\u0435\u0443 \u0436\u0430\u0442\u044b\u049b \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u04af\u0448\u0456\u043d \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0433\u0435 \u043a\u04e9\u043c\u0435\u043a\u0442\u0435\u0441\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.", + "LabelChannelStreamQualityHelp": "\u04e8\u0442\u043a\u0456\u0437\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456 \u0442\u04e9\u043c\u0435\u043d \u043e\u0440\u0442\u0430\u0434\u0430, \u0441\u0430\u043f\u0430\u0441\u044b\u043d \u0448\u0435\u043a\u0442\u0435\u0443\u0456 \u0436\u0430\u0442\u044b\u049b\u0442\u0430\u0443 \u0430\u0493\u044b\u043d\u0434\u044b\u049b \u043e\u0439\u043d\u0430\u0442\u0443 \u04d9\u0441\u0435\u0440\u0456\u043d \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0443\u0456\u043d\u0435 \u043a\u04e9\u043c\u0435\u043a\u0442\u0435\u0441\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.", "OptionBestAvailableStreamQuality": "\u049a\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0435\u04a3 \u0436\u0430\u049b\u0441\u044b", "LabelEnableChannelContentDownloadingFor": "\u0411\u04b1\u043b \u04af\u0448\u0456\u043d \u0430\u0440\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u0434\u044b \u049b\u043e\u0441\u0443:", "LabelEnableChannelContentDownloadingForHelp": "\u041a\u0435\u0439\u0431\u0456\u0440 \u0430\u0440\u043d\u0430\u043b\u0430\u0440 \u049b\u0430\u0440\u0430\u0443\u0434\u044b\u04a3 \u0430\u043b\u0434\u044b\u043d\u0434\u0430 \u043c\u0430\u0437\u043c\u04af\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u0434\u044b \u049b\u043e\u043b\u0434\u0430\u0439\u0434\u044b. \u04e8\u0442\u043a\u0456\u0437\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456 \u0442\u04e9\u043c\u0435\u043d \u043e\u0440\u0442\u0430\u043b\u0430\u0440\u0434\u0430 \u0430\u0440\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0436\u04b1\u043c\u044b\u0441\u0442\u0430\u043d \u0431\u043e\u0441 \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043d\u044b \u049b\u043e\u0441\u044b\u04a3\u044b\u0437. \u041c\u0430\u0437\u043c\u04af\u043d \u0430\u0440\u043d\u0430 \u0436\u04af\u043a\u0442\u0435\u0443 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u0441\u044b \u0431\u04e9\u043b\u0456\u0433\u0456 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0436\u04af\u043a\u0442\u0435\u043b\u0435\u0434\u0456.", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "\u041a\u0456\u0440\u0433\u0435\u043d\u0434\u0435\u0433\u0456 \u0435\u0441\u043a\u0435\u0440\u0442\u0443:", "LabelLoginDisclaimerHelp": "\u0411\u04b1\u043b \u043a\u0456\u0440\u0443 \u0431\u0435\u0442\u0456\u043d\u0456\u04a3 \u0442\u04e9\u043c\u0435\u043d\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.", "LabelAutomaticallyDonate": "\u041e\u0441\u044b \u0441\u043e\u043c\u0430\u043d\u044b \u0430\u0439 \u0441\u0430\u0439\u044b\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0441\u044b\u0439\u043b\u0430\u0443", - "LabelAutomaticallyDonateHelp": "PayPal \u0435\u0441\u0435\u043f \u0448\u043e\u0442\u044b\u04a3\u044b\u0437 \u0430\u0440\u049b\u044b\u043b\u044b \u043a\u0435\u0437 \u043a\u0435\u043b\u0433\u0435\u043d \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0434\u043e\u0493\u0430\u0440\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u04a3\u0456\u0437 \u0431\u0430\u0440." + "LabelAutomaticallyDonateHelp": "PayPal \u0435\u0441\u0435\u043f \u0448\u043e\u0442\u044b\u04a3\u044b\u0437 \u0430\u0440\u049b\u044b\u043b\u044b \u043a\u0435\u0437 \u043a\u0435\u043b\u0433\u0435\u043d \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0434\u043e\u0493\u0430\u0440\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u04a3\u0456\u0437 \u0431\u0430\u0440.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ms.json b/MediaBrowser.Server.Implementations/Localization/Server/ms.json index b790d5660a..cbde8c27ce 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ms.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ms.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nb.json b/MediaBrowser.Server.Implementations/Localization/Server/nb.json index 394769b2a1..1bf329cd26 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/nb.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/nb.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nl.json b/MediaBrowser.Server.Implementations/Localization/Server/nl.json index 6c58426588..e7094e2888 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json @@ -630,8 +630,8 @@ "ButtonScenes": "Scenes", "ButtonSubtitles": "Ondertitels", "ButtonAudioTracks": "Audio tracks", - "ButtonPreviousTrack": "Vorig nummer", - "ButtonNextTrack": "Volgend nummer", + "ButtonPreviousTrack": "Vorige track", + "ButtonNextTrack": "Volgende track", "ButtonStop": "Stop", "ButtonPause": "Pauze", "LabelGroupMoviesIntoCollections": "Groepeer films in verzamelingen", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Aanmeld vrijwaring:", "LabelLoginDisclaimerHelp": "Dit wordt onderaan de login pagina weergegeven.", "LabelAutomaticallyDonate": "Doneer dit bedrag automatisch per maand", - "LabelAutomaticallyDonateHelp": "U kunt dit via uw PayPal account op elk moment annuleren." + "LabelAutomaticallyDonateHelp": "U kunt dit via uw PayPal account op elk moment annuleren.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pl.json b/MediaBrowser.Server.Implementations/Localization/Server/pl.json index b4d49e5b3b..aad8274bff 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pl.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pl.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json index 96c3429c96..ea1ed04008 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Aviso legal no login:", "LabelLoginDisclaimerHelp": "Isto ser\u00e1 exibido na parte inferior da p\u00e1gina de login.", "LabelAutomaticallyDonate": "Doar automaticamente esta quantidade a cada m\u00eas", - "LabelAutomaticallyDonateHelp": "Voc\u00ea pode cancelar a qualquer hora atrav\u00e9s de sua conta do PayPal." + "LabelAutomaticallyDonateHelp": "Voc\u00ea pode cancelar a qualquer hora atrav\u00e9s de sua conta do PayPal.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json index 87c24c117d..dfc818e7d2 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json @@ -479,10 +479,10 @@ "HeaderProgram": "Programa", "HeaderClients": "Clientes", "LabelCompleted": "Terminado", - "LabelFailed": "Falhou", + "LabelFailed": "Failed", "LabelSkipped": "Ignorado", "HeaderEpisodeOrganization": "Organiza\u00e7\u00e3o dos Epis\u00f3dios", - "LabelSeries": "S\u00e9rie:", + "LabelSeries": "Series:", "LabelSeasonNumber": "N\u00famero da temporada", "LabelEpisodeNumber": "N\u00famero do epis\u00f3dio", "LabelEndingEpisodeNumber": "N\u00famero do epis\u00f3dio final", @@ -630,8 +630,8 @@ "ButtonScenes": "Cenas", "ButtonSubtitles": "Legendas", "ButtonAudioTracks": "Faixas de \u00e1udio", - "ButtonPreviousTrack": "Faixa Anterior", - "ButtonNextTrack": "Pr\u00f3xima Faixa", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Parar", "ButtonPause": "Pausar", "LabelGroupMoviesIntoCollections": "Group movies into collections", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ru.json b/MediaBrowser.Server.Implementations/Localization/Server/ru.json index c1150bc2b3..eb58b98bce 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json @@ -479,7 +479,7 @@ "HeaderProgram": "\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430", "HeaderClients": "\u041a\u043b\u0438\u0435\u043d\u0442\u044b", "LabelCompleted": "\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e", - "LabelFailed": "\u041d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e", + "LabelFailed": "\u041d\u0435\u0443\u0434\u0430\u0447\u0430", "LabelSkipped": "\u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043e", "HeaderEpisodeOrganization": "\u0420\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043f\u0438\u0437\u043e\u0434\u0430", "LabelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b:", @@ -632,7 +632,7 @@ "ButtonAudioTracks": "\u0410\u0443\u0434\u0438\u043e\u0434\u043e\u0440\u043e\u0436\u043a\u0438", "ButtonPreviousTrack": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430", "ButtonNextTrack": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430", - "ButtonStop": "\u0421\u0442\u043e\u043f", + "ButtonStop": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c", "ButtonPause": "\u041f\u0430\u0443\u0437\u0430", "LabelGroupMoviesIntoCollections": "\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0438\u043b\u044c\u043c\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439", "LabelGroupMoviesIntoCollectionsHelp": "\u041f\u0440\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u0444\u0438\u043b\u044c\u043c\u043e\u0432, \u0444\u0438\u043b\u044c\u043c\u044b \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u043a\u0430\u043a \u0435\u0434\u0438\u043d\u044b\u0439 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442.", @@ -795,7 +795,7 @@ "MessageLearnHowToCustomize": "\u0423\u0437\u043d\u0430\u0439\u0442\u0435, \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c\u0443 \u0432\u043a\u0443\u0441\u0443. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0432\u0430\u0448\u0443 \u0430\u0432\u0430\u0442\u0430\u0440\u0443 \u0432 \u043f\u0440\u0430\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443 \u044d\u043a\u0440\u0430\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438.", "ButtonEditOtherUserPreferences": "\u041f\u0440\u0430\u0432\u0438\u0442\u044c \u043b\u0438\u0447\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.", "LabelChannelStreamQuality": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442:", - "LabelChannelStreamQualityHelp": "\u0412 \u0441\u0440\u0435\u0434\u0435 \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, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043b\u0430\u0432\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438.", + "LabelChannelStreamQualityHelp": "\u0412 \u0441\u0440\u0435\u0434\u0435 \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, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.", "OptionBestAvailableStreamQuality": "\u041d\u0430\u0438\u043b\u0443\u0447\u0448\u0435\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0435", "LabelEnableChannelContentDownloadingFor": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u0430 \u0434\u043b\u044f:", "LabelEnableChannelContentDownloadingForHelp": "\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043a\u0430\u043d\u0430\u043b\u0430\u043c\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043f\u0440\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435. \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 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432.", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "\u041e\u0433\u043e\u0432\u043e\u0440\u043a\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0432\u0445\u043e\u0434\u0430:", "LabelLoginDisclaimerHelp": "\u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u043d\u0438\u0436\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u0445\u043e\u0434\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.", "LabelAutomaticallyDonate": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u0430\u0440\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0443\u043c\u043c\u0443 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0441\u044f\u0446", - "LabelAutomaticallyDonateHelp": "\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u044e \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c PayPal." + "LabelAutomaticallyDonateHelp": "\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u044e \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c PayPal.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index e7e1685628..bc350bb38c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -861,5 +861,14 @@ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", - "OptionList": "List" + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:", + "HeaderLatestMusic": "Latest Music", + "HeaderBranding": "Branding" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sv.json b/MediaBrowser.Server.Implementations/Localization/Server/sv.json index c2e49294f1..8106294223 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/sv.json @@ -479,10 +479,10 @@ "HeaderProgram": "Program", "HeaderClients": "Klienter", "LabelCompleted": "Klar", - "LabelFailed": "Misslyckades", + "LabelFailed": "Failed", "LabelSkipped": "Hoppades \u00f6ver", "HeaderEpisodeOrganization": "Katalogisering av avsnitt", - "LabelSeries": "Serie:", + "LabelSeries": "Series:", "LabelSeasonNumber": "S\u00e4songsnummer:", "LabelEpisodeNumber": "Avsnittsnummer:", "LabelEndingEpisodeNumber": "Avslutande avsnittsnummer:", @@ -630,8 +630,8 @@ "ButtonScenes": "Scener", "ButtonSubtitles": "Undertexter", "ButtonAudioTracks": "Ljudsp\u00e5r", - "ButtonPreviousTrack": "F\u00f6reg\u00e5ende sp\u00e5r", - "ButtonNextTrack": "N\u00e4sta sp\u00e5r", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Stopp", "ButtonPause": "Paus", "LabelGroupMoviesIntoCollections": "Gruppera filmer i samlingsboxar", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Ansvarsbegr\u00e4nsning vid inloggning:", "LabelLoginDisclaimerHelp": "Detta visas l\u00e4ngst ned p\u00e5 inloggningssidan.", "LabelAutomaticallyDonate": "Donera automatiskt detta belopp varje m\u00e5nad", - "LabelAutomaticallyDonateHelp": "Du kan avbryta n\u00e4r som helst via ditt PayPal-konto." + "LabelAutomaticallyDonateHelp": "Du kan avbryta n\u00e4r som helst via ditt PayPal-konto.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/vi.json b/MediaBrowser.Server.Implementations/Localization/Server/vi.json index 269d7a8bc1..0da205c7b7 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/vi.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/vi.json @@ -279,7 +279,7 @@ "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", "LabelMetadataDownloadLanguage": "Preferred download language:", "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Image saving convention:", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json index 2868ad3d94..78c7689c35 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json @@ -396,7 +396,7 @@ "HeaderCastCrew": "\u62cd\u651d\u4eba\u54e1\u53ca\u6f14\u54e1", "HeaderAdditionalParts": "\u9644\u52a0\u90e8\u4efd", "ButtonSplitVersionsApart": "Split Versions Apart", - "ButtonPlayTrailer": "\u9810\u544a", + "ButtonPlayTrailer": "Trailer", "LabelMissing": "\u7f3a\u5c11", "LabelOffline": "\u96e2\u7dda", "PathSubstitutionHelp": "Path substitutions are used for mapping a path on the server to a path that clients are able to access. By allowing clients direct access to media on the server they may be able to play them directly over the network and avoid using server resources to stream and transcode them.", @@ -846,5 +846,13 @@ "LabelLoginDisclaimer": "Login disclaimer:", "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", "LabelAutomaticallyDonate": "Automatically donate this amount each month", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account." + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index c3d24c0de1..338bf89598 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -1210,9 +1210,16 @@ namespace MediaBrowser.Server.Implementations.Session /// Task{SessionInfo}. /// Invalid user or password entered. /// - public async Task AuthenticateNewSession(string username, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint) + public async Task AuthenticateNewSession(string username, + string password, + string clientType, + string appVersion, + string deviceId, + string deviceName, + string remoteEndPoint) { - var result = IsLocalhost(remoteEndPoint) || await _userManager.AuthenticateUser(username, password).ConfigureAwait(false); + var result = (IsLocalhost(remoteEndPoint) && string.Equals(clientType, "Dashboard", StringComparison.OrdinalIgnoreCase)) || + await _userManager.AuthenticateUser(username, password).ConfigureAwait(false); if (!result) { @@ -1337,7 +1344,7 @@ namespace MediaBrowser.Server.Implementations.Session remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase); } - public bool IsLocal(string remoteEndpoint) + public bool IsInLocalNetwork(string remoteEndpoint) { if (string.IsNullOrWhiteSpace(remoteEndpoint)) { diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 688c07639c..96e38b2d4e 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -17,9 +17,6 @@ using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.FileOrganization; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; @@ -45,7 +42,6 @@ using MediaBrowser.LocalMetadata.Providers; using MediaBrowser.MediaEncoding.BdInfo; using MediaBrowser.MediaEncoding.Encoder; using MediaBrowser.MediaEncoding.Subtitles; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; @@ -343,58 +339,13 @@ namespace MediaBrowser.ServerApplication ? "Xbmc Nfo" : "Media Browser Xml"; - DisableMetadataService(typeof(Movie), ServerConfigurationManager.Configuration, service); - DisableMetadataService(typeof(MusicAlbum), ServerConfigurationManager.Configuration, service); - DisableMetadataService(typeof(MusicArtist), ServerConfigurationManager.Configuration, service); - DisableMetadataService(typeof(Episode), ServerConfigurationManager.Configuration, service); - DisableMetadataService(typeof(Season), ServerConfigurationManager.Configuration, service); - DisableMetadataService(typeof(Series), ServerConfigurationManager.Configuration, service); - DisableMetadataService(typeof(MusicVideo), ServerConfigurationManager.Configuration, service); - DisableMetadataService(typeof(Trailer), ServerConfigurationManager.Configuration, service); - DisableMetadataService(typeof(AdultVideo), ServerConfigurationManager.Configuration, service); - DisableMetadataService(typeof(Video), ServerConfigurationManager.Configuration, service); + ServerConfigurationManager.SetPreferredMetadataService(service); } ServerConfigurationManager.Configuration.DefaultMetadataSettingsApplied = true; ServerConfigurationManager.SaveConfiguration(); } - private void DisableMetadataService(Type type, ServerConfiguration config, string service) - { - var options = GetMetadataOptions(type, config); - - if (!options.DisabledMetadataSavers.Contains(service, StringComparer.OrdinalIgnoreCase)) - { - var list = options.DisabledMetadataSavers.ToList(); - - list.Add(service); - - options.DisabledMetadataSavers = list.ToArray(); - } - } - - private MetadataOptions GetMetadataOptions(Type type, ServerConfiguration config) - { - var options = config.MetadataOptions - .FirstOrDefault(i => string.Equals(i.ItemType, type.Name, StringComparison.OrdinalIgnoreCase)); - - if (options == null) - { - var list = config.MetadataOptions.ToList(); - - options = new MetadataOptions - { - ItemType = type.Name - }; - - list.Add(options); - - config.MetadataOptions = list.ToArray(); - } - - return options; - } - private void DeleteDeprecatedModules() { try diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 36adae71c7..186cf9fe34 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -521,7 +521,6 @@ namespace MediaBrowser.WebDashboard.Api "mediacontroller.js", "chromecast.js", "backdrops.js", - "branding.js", "mediaplayer.js", "mediaplayer-video.js", @@ -544,7 +543,6 @@ namespace MediaBrowser.WebDashboard.Api "channelitems.js", "channelsettings.js", "dashboardgeneral.js", - "dashboardinfo.js", "dashboardpage.js", "directorybrowser.js", "dlnaprofile.js", @@ -627,6 +625,7 @@ namespace MediaBrowser.WebDashboard.Api "scheduledtaskpage.js", "scheduledtaskspage.js", "search.js", + "serversecurity.js", "songs.js", "supporterkeypage.js", "supporterpage.js", @@ -645,7 +644,6 @@ namespace MediaBrowser.WebDashboard.Api "userprofilespage.js", "userparentalcontrol.js", "wizardfinishpage.js", - "wizardimagesettings.js", "wizardservice.js", "wizardstartpage.js", "wizardsettings.js", diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 2906d1c34c..e08da4e004 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -98,9 +98,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -302,9 +299,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -620,9 +614,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -641,9 +632,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -794,6 +782,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -803,9 +794,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -815,6 +803,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -1442,9 +1433,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest -- cgit v1.2.3 From d7f3214b3251a210d784e86fcdcfdca9765e69b8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Jul 2014 17:03:57 -0400 Subject: move last fm providers to a plugin --- .../Channels/ChannelMediaInfo.cs | 2 + .../Configuration/UserConfiguration.cs | 1 + .../MediaBrowser.Providers.csproj | 4 - MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs | 5 + .../Music/AudioDbAlbumProvider.cs | 3 + .../Music/FanArtAlbumProvider.cs | 2 +- .../Music/FanArtArtistProvider.cs | 4 +- .../Music/LastFmImageProvider.cs | 164 ----------- .../Music/LastfmAlbumProvider.cs | 322 --------------------- .../Music/LastfmArtistProvider.cs | 160 ---------- MediaBrowser.Providers/Music/LastfmHelper.cs | 76 ----- .../Collections/ManualCollectionsFolder.cs | 2 +- .../Library/UserViewManager.cs | 4 +- 13 files changed, 17 insertions(+), 732 deletions(-) delete mode 100644 MediaBrowser.Providers/Music/LastFmImageProvider.cs delete mode 100644 MediaBrowser.Providers/Music/LastfmAlbumProvider.cs delete mode 100644 MediaBrowser.Providers/Music/LastfmArtistProvider.cs delete mode 100644 MediaBrowser.Providers/Music/LastfmHelper.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs index 64b4804148..f16fd11205 100644 --- a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs @@ -29,6 +29,8 @@ namespace MediaBrowser.Controller.Channels public MediaProtocol Protocol { get; set; } + public long? RunTimeTicks { get; set; } + public ChannelMediaInfo() { RequiredHttpHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 0834452fbc..1afc9a191c 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -93,6 +93,7 @@ namespace MediaBrowser.Model.Configuration BlockUnratedItems = new UnratedItem[] { }; ExcludeFoldersFromGrouping = new string[] { }; + DisplayCollectionsView = true; } } } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index fe22d4c99b..9a26101a1f 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -126,7 +126,6 @@ - @@ -138,11 +137,8 @@ - - - diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs b/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs index 49c7ebec8f..2044979e4e 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs @@ -12,6 +12,11 @@ namespace MediaBrowser.Providers.MediaInfo /// The result. public static void NormalizeFFProbeResult(InternalMediaInfoResult result) { + if (result == null) + { + throw new ArgumentNullException("result"); + } + if (result.format != null && result.format.tags != null) { result.format.tags = ConvertDictionaryToCaseInSensitive(result.format.tags); diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs index a9b3d8e115..ab9ac2331b 100644 --- a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; @@ -86,6 +87,8 @@ namespace MediaBrowser.Providers.Music item.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, result.strMusicBrainzArtistID); item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, result.strMusicBrainzID); + + item.Overview = (result.strDescriptionEN ?? string.Empty).StripHtml(); } public string Name diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs index ccab30bc6c..94d682f44b 100644 --- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs @@ -67,7 +67,7 @@ namespace MediaBrowser.Providers.Music if (!string.IsNullOrEmpty(artistMusicBrainzId)) { - await FanartArtistProvider.Current.EnsureMovieXml(artistMusicBrainzId, cancellationToken).ConfigureAwait(false); + await FanartArtistProvider.Current.EnsureArtistXml(artistMusicBrainzId, cancellationToken).ConfigureAwait(false); var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId); diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs index b9916dfbaa..a8df95fd1b 100644 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Providers.Music if (!String.IsNullOrEmpty(artistMusicBrainzId)) { - await EnsureMovieXml(artistMusicBrainzId, cancellationToken).ConfigureAwait(false); + await EnsureArtistXml(artistMusicBrainzId, cancellationToken).ConfigureAwait(false); var artistXmlPath = GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId); @@ -390,7 +390,7 @@ namespace MediaBrowser.Providers.Music } private readonly Task _cachedTask = Task.FromResult(true); - internal Task EnsureMovieXml(string musicBrainzId, CancellationToken cancellationToken) + internal Task EnsureArtistXml(string musicBrainzId, CancellationToken cancellationToken) { var xmlPath = GetArtistXmlPath(_config.ApplicationPaths, musicBrainzId); diff --git a/MediaBrowser.Providers/Music/LastFmImageProvider.cs b/MediaBrowser.Providers/Music/LastFmImageProvider.cs deleted file mode 100644 index b55a973516..0000000000 --- a/MediaBrowser.Providers/Music/LastFmImageProvider.cs +++ /dev/null @@ -1,164 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Providers; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers.Music -{ - public class LastfmImageProvider : IRemoteImageProvider, IHasOrder - { - private readonly IHttpClient _httpClient; - private readonly IServerConfigurationManager _config; - - public LastfmImageProvider(IHttpClient httpClient, IServerConfigurationManager config) - { - _httpClient = httpClient; - _config = config; - } - - public string Name - { - get { return ProviderName; } - } - - public static string ProviderName - { - get { return "last.fm"; } - } - - public bool Supports(IHasImages item) - { - return item is MusicAlbum || item is MusicArtist; - } - - public IEnumerable GetSupportedImages(IHasImages item) - { - return new List - { - ImageType.Primary - }; - } - - public Task> GetImages(IHasImages item, CancellationToken cancellationToken) - { - var list = new List(); - - RemoteImageInfo info = null; - - var musicBrainzId = item is MusicAlbum ? - item.GetProviderId(MetadataProviders.MusicBrainzAlbum) : - item.GetProviderId(MetadataProviders.MusicBrainzArtist); - - if (!string.IsNullOrEmpty(musicBrainzId)) - { - var cachePath = Path.Combine(_config.ApplicationPaths.CachePath, "lastfm", musicBrainzId, "image.txt"); - - try - { - var parts = File.ReadAllText(cachePath).Split('|'); - - info = GetInfo(parts.FirstOrDefault(), parts.LastOrDefault()); - } - catch (DirectoryNotFoundException) - { - } - catch (FileNotFoundException) - { - } - } - - if (info == null) - { - var musicBrainzReleaseGroupId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); - - if (!string.IsNullOrEmpty(musicBrainzReleaseGroupId)) - { - var cachePath = Path.Combine(_config.ApplicationPaths.CachePath, "lastfm", musicBrainzReleaseGroupId, "image.txt"); - - try - { - var parts = File.ReadAllText(cachePath).Split('|'); - - info = GetInfo(parts.FirstOrDefault(), parts.LastOrDefault()); - } - catch (DirectoryNotFoundException) - { - } - catch (FileNotFoundException) - { - } - } - } - - if (info != null) - { - list.Add(info); - } - - // The only info we have is size - return Task.FromResult>(list.OrderByDescending(i => i.Width ?? 0)); - } - - private RemoteImageInfo GetInfo(string url, string size) - { - if (string.IsNullOrEmpty(url)) - { - return null; - } - - var info = new RemoteImageInfo - { - ProviderName = Name, - Url = url, - Type = ImageType.Primary - }; - - if (string.Equals(size, "mega", StringComparison.OrdinalIgnoreCase)) - { - - } - else if (string.Equals(size, "extralarge", StringComparison.OrdinalIgnoreCase)) - { - - } - else if (string.Equals(size, "large", StringComparison.OrdinalIgnoreCase)) - { - - } - else if (string.Equals(size, "medium", StringComparison.OrdinalIgnoreCase)) - { - - } - - return info; - } - - public int Order - { - get - { - // After all others - return 3; - } - } - - public Task GetImageResponse(string url, CancellationToken cancellationToken) - { - return _httpClient.GetResponse(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url, - ResourcePool = LastfmArtistProvider.LastfmResourcePool - }); - } - } -} diff --git a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs deleted file mode 100644 index 8465397484..0000000000 --- a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs +++ /dev/null @@ -1,322 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; -using MoreLinq; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers.Music -{ - public class LastfmAlbumProvider : IRemoteMetadataProvider, IHasOrder - { - private readonly IJsonSerializer _json; - private readonly IHttpClient _httpClient; - - private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; - - public LastfmAlbumProvider(IHttpClient httpClient, IJsonSerializer json, IServerConfigurationManager config, ILogger logger) - { - _httpClient = httpClient; - _json = json; - _config = config; - _logger = logger; - } - - public async Task> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken) - { - return new List(); - } - - public async Task> GetMetadata(AlbumInfo id, CancellationToken cancellationToken) - { - var result = new MetadataResult(); - - var lastFmData = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false); - - if (lastFmData != null && lastFmData.album != null) - { - result.HasMetadata = true; - result.Item = new MusicAlbum(); - ProcessAlbumData(result.Item, lastFmData.album); - } - - return result; - } - - private async Task GetAlbumResult(AlbumInfo item, CancellationToken cancellationToken) - { - // Try album release Id - var id = item.GetReleaseId(); - if (!string.IsNullOrEmpty(id)) - { - var result = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false); - - if (result != null && result.album != null) - { - return result; - } - } - - // Try album release group Id - id = item.GetReleaseGroupId(); - if (!string.IsNullOrEmpty(id)) - { - var result = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false); - - if (result != null && result.album != null) - { - return result; - } - } - - var albumArtist = item.GetAlbumArtist(); - // Get each song, distinct by the combination of AlbumArtist and Album - var songs = item.SongInfos.DistinctBy(i => (i.AlbumArtists.FirstOrDefault() ?? string.Empty) + (i.Album ?? string.Empty), StringComparer.OrdinalIgnoreCase).ToList(); - - foreach (var song in songs.Where(song => !string.IsNullOrEmpty(song.Album) && !string.IsNullOrEmpty(song.AlbumArtists.FirstOrDefault()))) - { - var result = await GetAlbumResult(song.AlbumArtists.FirstOrDefault(), song.Album, cancellationToken).ConfigureAwait(false); - - if (result != null && result.album != null) - { - return result; - } - } - - if (string.IsNullOrEmpty(albumArtist)) - { - return null; - } - - return await GetAlbumResult(albumArtist, item.Name, cancellationToken); - } - - private async Task GetAlbumResult(string artist, string album, CancellationToken cancellationToken) - { - // Get albu info using artist and album name - var url = LastfmArtistProvider.RootUrl + string.Format("method=album.getInfo&artist={0}&album={1}&api_key={2}&format=json", UrlEncode(artist), UrlEncode(album), LastfmArtistProvider.ApiKey); - - using (var json = await _httpClient.Get(new HttpRequestOptions - { - Url = url, - ResourcePool = LastfmArtistProvider.LastfmResourcePool, - CancellationToken = cancellationToken, - EnableHttpCompression = false - - }).ConfigureAwait(false)) - { - using (var reader = new StreamReader(json)) - { - var jsonText = await reader.ReadToEndAsync().ConfigureAwait(false); - - // Fix their bad json - jsonText = jsonText.Replace("\"#text\"", "\"url\""); - - return _json.DeserializeFromString(jsonText); - } - } - } - - private async Task GetAlbumResult(string musicbraizId, CancellationToken cancellationToken) - { - // Get albu info using artist and album name - var url = LastfmArtistProvider.RootUrl + string.Format("method=album.getInfo&mbid={0}&api_key={1}&format=json", musicbraizId, LastfmArtistProvider.ApiKey); - - using (var json = await _httpClient.Get(new HttpRequestOptions - { - Url = url, - ResourcePool = LastfmArtistProvider.LastfmResourcePool, - CancellationToken = cancellationToken, - EnableHttpCompression = false - - }).ConfigureAwait(false)) - { - return _json.DeserializeFromStream(json); - } - } - - private void ProcessAlbumData(MusicAlbum item, LastfmAlbum data) - { - var overview = data.wiki != null ? data.wiki.content : null; - - if (!item.LockedFields.Contains(MetadataFields.Overview)) - { - item.Overview = overview; - } - - // Only grab the date here if the album doesn't already have one, since id3 tags are preferred - DateTime release; - - if (DateTime.TryParse(data.releasedate, out release)) - { - // Lastfm sends back null as sometimes 1901, other times 0 - if (release.Year > 1901) - { - if (!item.PremiereDate.HasValue) - { - item.PremiereDate = release; - } - - if (!item.ProductionYear.HasValue) - { - item.ProductionYear = release.Year; - } - } - } - - string imageSize; - var url = LastfmHelper.GetImageUrl(data, out imageSize); - - var musicBrainzId = item.GetProviderId(MetadataProviders.MusicBrainzAlbum) ?? - item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); - - if (!string.IsNullOrEmpty(musicBrainzId) && !string.IsNullOrEmpty(url)) - { - LastfmHelper.SaveImageInfo(_config.ApplicationPaths, _logger, musicBrainzId, url, imageSize); - } - } - - /// - /// Encodes an URL. - /// - /// The name. - /// System.String. - private string UrlEncode(string name) - { - return WebUtility.UrlEncode(name); - } - - public string Name - { - get { return "last.fm"; } - } - - public int Order - { - get - { - // After fanart & audiodb - return 2; - } - } - - public Task GetImageResponse(string url, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - } - - #region Result Objects - - public class LastfmStats - { - public string listeners { get; set; } - public string playcount { get; set; } - } - - public class LastfmTag - { - public string name { get; set; } - public string url { get; set; } - } - - - public class LastfmTags - { - public List tag { get; set; } - } - - public class LastfmFormationInfo - { - public string yearfrom { get; set; } - public string yearto { get; set; } - } - - public class LastFmBio - { - public string published { get; set; } - public string summary { get; set; } - public string content { get; set; } - public string placeformed { get; set; } - public string yearformed { get; set; } - public List formationlist { get; set; } - } - - public class LastFmImage - { - public string url { get; set; } - public string size { get; set; } - } - - public class LastfmArtist : IHasLastFmImages - { - public string name { get; set; } - public string mbid { get; set; } - public string url { get; set; } - public string streamable { get; set; } - public string ontour { get; set; } - public LastfmStats stats { get; set; } - public List similar { get; set; } - public LastfmTags tags { get; set; } - public LastFmBio bio { get; set; } - public List image { get; set; } - } - - - public class LastfmAlbum : IHasLastFmImages - { - public string name { get; set; } - public string artist { get; set; } - public string id { get; set; } - public string mbid { get; set; } - public string releasedate { get; set; } - public int listeners { get; set; } - public int playcount { get; set; } - public LastfmTags toptags { get; set; } - public LastFmBio wiki { get; set; } - public List image { get; set; } - } - - public interface IHasLastFmImages - { - List image { get; set; } - } - - public class LastfmGetAlbumResult - { - public LastfmAlbum album { get; set; } - } - - public class LastfmGetArtistResult - { - public LastfmArtist artist { get; set; } - } - - public class Artistmatches - { - public List artist { get; set; } - } - - public class LastfmArtistSearchResult - { - public Artistmatches artistmatches { get; set; } - } - - public class LastfmArtistSearchResults - { - public LastfmArtistSearchResult results { get; set; } - } - - #endregion -} diff --git a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs deleted file mode 100644 index a2aa9d719e..0000000000 --- a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs +++ /dev/null @@ -1,160 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers.Music -{ - public class LastfmArtistProvider : IRemoteMetadataProvider, IHasOrder - { - private readonly IJsonSerializer _json; - private readonly IHttpClient _httpClient; - - internal static readonly SemaphoreSlim LastfmResourcePool = new SemaphoreSlim(4, 4); - - internal const string RootUrl = @"http://ws.audioscrobbler.com/2.0/?"; - internal static string ApiKey = "7b76553c3eb1d341d642755aecc40a33"; - - private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; - - public LastfmArtistProvider(IHttpClient httpClient, IJsonSerializer json, IServerConfigurationManager config, ILogger logger) - { - _httpClient = httpClient; - _json = json; - _config = config; - _logger = logger; - } - - public async Task> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken) - { - return new List(); - } - - public async Task> GetMetadata(ArtistInfo id, CancellationToken cancellationToken) - { - var result = new MetadataResult(); - - var musicBrainzId = id.GetMusicBrainzArtistId(); - - if (!String.IsNullOrWhiteSpace(musicBrainzId)) - { - cancellationToken.ThrowIfCancellationRequested(); - - result.Item = new MusicArtist(); - result.HasMetadata = true; - - await FetchLastfmData(result.Item, musicBrainzId, cancellationToken).ConfigureAwait(false); - } - - return result; - } - - protected async Task FetchLastfmData(MusicArtist item, string musicBrainzId, CancellationToken cancellationToken) - { - // Get artist info with provided id - var url = RootUrl + String.Format("method=artist.getInfo&mbid={0}&api_key={1}&format=json", UrlEncode(musicBrainzId), ApiKey); - - LastfmGetArtistResult result; - - using (var json = await _httpClient.Get(new HttpRequestOptions - { - Url = url, - ResourcePool = LastfmResourcePool, - CancellationToken = cancellationToken, - EnableHttpCompression = false - - }).ConfigureAwait(false)) - { - using (var reader = new StreamReader(json)) - { - var jsonText = await reader.ReadToEndAsync().ConfigureAwait(false); - - // Fix their bad json - jsonText = jsonText.Replace("\"#text\"", "\"url\""); - - result = _json.DeserializeFromString(jsonText); - } - } - - if (result != null && result.artist != null) - { - ProcessArtistData(item, result.artist, musicBrainzId); - } - } - - private void ProcessArtistData(MusicArtist artist, LastfmArtist data, string musicBrainzId) - { - var yearFormed = 0; - - if (data.bio != null) - { - Int32.TryParse(data.bio.yearformed, out yearFormed); - if (!artist.LockedFields.Contains(MetadataFields.Overview)) - { - artist.Overview = (data.bio.content ?? string.Empty).StripHtml(); - } - if (!string.IsNullOrEmpty(data.bio.placeformed) && !artist.LockedFields.Contains(MetadataFields.ProductionLocations)) - { - artist.AddProductionLocation(data.bio.placeformed); - } - } - - if (yearFormed > 0) - { - artist.PremiereDate = new DateTime(yearFormed, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - artist.ProductionYear = yearFormed; - } - - string imageSize; - var url = LastfmHelper.GetImageUrl(data, out imageSize); - - if (!string.IsNullOrEmpty(musicBrainzId) && !string.IsNullOrEmpty(url)) - { - LastfmHelper.SaveImageInfo(_config.ApplicationPaths, _logger, musicBrainzId, url, imageSize); - } - } - - /// - /// Encodes an URL. - /// - /// The name. - /// System.String. - private string UrlEncode(string name) - { - return WebUtility.UrlEncode(name); - } - - public string Name - { - get { return "last.fm"; } - } - - public int Order - { - get - { - // After fanart & audiodb - return 2; - } - } - - public Task GetImageResponse(string url, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - } -} diff --git a/MediaBrowser.Providers/Music/LastfmHelper.cs b/MediaBrowser.Providers/Music/LastfmHelper.cs deleted file mode 100644 index 7c83cec6b4..0000000000 --- a/MediaBrowser.Providers/Music/LastfmHelper.cs +++ /dev/null @@ -1,76 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Providers.Music -{ - public static class LastfmHelper - { - public static string GetImageUrl(IHasLastFmImages data, out string size) - { - size = null; - - if (data.image == null) - { - return null; - } - - var validImages = data.image - .Where(i => !string.IsNullOrWhiteSpace(i.url)) - .ToList(); - - var img = validImages - .FirstOrDefault(i => string.Equals(i.size, "mega", StringComparison.OrdinalIgnoreCase)) ?? - data.image.FirstOrDefault(i => string.Equals(i.size, "extralarge", StringComparison.OrdinalIgnoreCase)) ?? - data.image.FirstOrDefault(i => string.Equals(i.size, "large", StringComparison.OrdinalIgnoreCase)) ?? - data.image.FirstOrDefault(i => string.Equals(i.size, "medium", StringComparison.OrdinalIgnoreCase)) ?? - data.image.FirstOrDefault(); - - if (img != null) - { - size = img.size; - return img.url; - } - - return null; - } - - public static void SaveImageInfo(IApplicationPaths appPaths, ILogger logger, string musicBrainzId, string url, string size) - { - if (appPaths == null) - { - throw new ArgumentNullException("appPaths"); - } - if (string.IsNullOrEmpty(musicBrainzId)) - { - throw new ArgumentNullException("musicBrainzId"); - } - if (string.IsNullOrEmpty(url)) - { - throw new ArgumentNullException("url"); - } - - var cachePath = Path.Combine(appPaths.CachePath, "lastfm", musicBrainzId, "image.txt"); - - try - { - if (string.IsNullOrEmpty(url)) - { - File.Delete(cachePath); - } - else - { - Directory.CreateDirectory(Path.GetDirectoryName(cachePath)); - File.WriteAllText(cachePath, url + "|" + size); - } - } - catch (IOException ex) - { - // Don't fail if this is unable to write - logger.ErrorException("Error saving to {0}", ex, cachePath); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs index 07c86ed314..aaa02c7209 100644 --- a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs +++ b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Server.Implementations.Collections public override bool IsHiddenFromUser(User user) { - return true; + return !user.Configuration.DisplayCollectionsView; } public override string CollectionType diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index dd2978b17b..73afa22e38 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -10,12 +10,12 @@ using MediaBrowser.Controller.Localization; using MediaBrowser.Model.Channels; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Library; +using MediaBrowser.Model.Querying; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Querying; namespace MediaBrowser.Server.Implementations.Library { @@ -82,7 +82,7 @@ namespace MediaBrowser.Server.Implementations.Library list.Add(await GetUserView(CollectionType.Games, user, string.Empty, cancellationToken).ConfigureAwait(false)); } - if (user.Configuration.DisplayCollectionsView || + if (user.Configuration.DisplayCollectionsView && recursiveChildren.OfType().Any()) { list.Add(await GetUserView(CollectionType.BoxSets, user, CollectionType.BoxSets, cancellationToken).ConfigureAwait(false)); -- cgit v1.2.3 From 9c252f3e50e1396009eb3e35163e013036c3af77 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Jul 2014 20:57:32 -0400 Subject: fix multi-part folder rips --- MediaBrowser.Controller/Entities/Video.cs | 2 +- .../Configuration/ServerConfiguration.cs | 57 ++++++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 4d50e61aeb..5685edc815 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -326,7 +326,7 @@ namespace MediaBrowser.Controller.Entities { if ((i.Attributes & FileAttributes.Directory) == FileAttributes.Directory) { - return !string.Equals(i.FullName, path, StringComparison.OrdinalIgnoreCase) && EntityResolutionHelper.IsMultiPartFolder(i.FullName) && EntityResolutionHelper.IsMultiPartFile(i.Name); + return !string.Equals(i.FullName, path, StringComparison.OrdinalIgnoreCase) && EntityResolutionHelper.IsMultiPartFolder(i.FullName); } return false; diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index d9404ce29e..064ac234f3 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Notifications; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Notifications; using MediaBrowser.Model.Weather; using System; @@ -261,8 +262,58 @@ namespace MediaBrowser.Model.Configuration MetadataOptions = new[] { new MetadataOptions(1, 1280) {ItemType = "Book"}, - new MetadataOptions(1, 1280) {ItemType = "MusicAlbum"}, - new MetadataOptions(1, 1280) {ItemType = "MusicArtist"}, + + new MetadataOptions(1, 1280) + { + ItemType = "MusicAlbum", + ImageOptions = new [] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Disc + } + } + }, + + new MetadataOptions(1, 1280) + { + ItemType = "MusicArtist", + ImageOptions = new [] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default + // They do look great, but most artists won't have them, which means a banner view isn't really possible + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + }, + + // Don't download this by default + // Generally not used + new ImageOption + { + Limit = 0, + Type = ImageType.Art + } + } + }, + new MetadataOptions(0, 1280) {ItemType = "Season"} }; -- cgit v1.2.3 From ea559a6e274c2067cda780ba81bc5237c9e2ebf7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 18 Jul 2014 18:14:59 -0400 Subject: create http listener abstraction --- MediaBrowser.Common/Net/IServerManager.cs | 3 +- MediaBrowser.Controller/Net/IHttpServer.cs | 6 - .../Configuration/ServerConfiguration.cs | 7 - .../HttpServer/HttpListenerHost.cs | 226 +++-------------- .../HttpServer/IHttpListener.cs | 42 +++ .../HttpServer/NetListener/HttpListenerServer.cs | 281 +++++++++++++++++++++ .../MediaBrowser.Server.Implementations.csproj | 5 + .../ServerManager/ServerManager.cs | 7 +- MediaBrowser.ServerApplication/ApplicationHost.cs | 4 +- 9 files changed, 367 insertions(+), 214 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs create mode 100644 MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Common/Net/IServerManager.cs b/MediaBrowser.Common/Net/IServerManager.cs index f81c99ac65..7c14f98ce9 100644 --- a/MediaBrowser.Common/Net/IServerManager.cs +++ b/MediaBrowser.Common/Net/IServerManager.cs @@ -26,8 +26,7 @@ namespace MediaBrowser.Common.Net /// Starts this instance. /// /// The URL prefixes. - /// if set to true [enable HTTP logging]. - void Start(IEnumerable urlPrefixes, bool enableHttpLogging); + void Start(IEnumerable urlPrefixes); /// /// Starts the web socket server. diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs index 20f07c74de..9a3cc6cb5d 100644 --- a/MediaBrowser.Controller/Net/IHttpServer.cs +++ b/MediaBrowser.Controller/Net/IHttpServer.cs @@ -38,12 +38,6 @@ namespace MediaBrowser.Controller.Net /// void Stop(); - /// - /// Gets or sets a value indicating whether [enable HTTP request logging]. - /// - /// true if [enable HTTP request logging]; otherwise, false. - bool EnableHttpRequestLogging { get; set; } - /// /// Occurs when [web socket connected]. /// diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 064ac234f3..904c7bcddf 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -22,12 +22,6 @@ namespace MediaBrowser.Model.Configuration /// The weather unit. public WeatherUnits WeatherUnit { get; set; } - /// - /// Gets or sets a value indicating whether [enable HTTP level logging]. - /// - /// true if [enable HTTP level logging]; otherwise, false. - public bool EnableHttpLevelLogging { get; set; } - /// /// Gets or sets a value indicating whether [enable u pn p]. /// @@ -223,7 +217,6 @@ namespace MediaBrowser.Model.Configuration ImageSavingConvention = ImageSavingConvention.Compatible; HttpServerPortNumber = 8096; LegacyWebSocketPortNumber = 8945; - EnableHttpLevelLogging = true; EnableDashboardResponseCaching = true; EnableAutomaticRestart = true; diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 3401491828..68b69cdf02 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -5,6 +5,7 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.HttpServer.NetListener; using ServiceStack; using ServiceStack.Api.Swagger; using ServiceStack.Host; @@ -34,14 +35,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer private readonly List _restServices = new List(); - private HttpListener Listener { get; set; } - protected bool IsStarted = false; + private IHttpListener _listener; - private readonly AutoResetEvent _listenForNextRequest = new AutoResetEvent(false); private readonly SmartThreadPool _threadPoolManager; + private const int IdleTimeout = 300; - private const int IdleTimeout = 300; - private readonly ContainerAdapter _containerAdapter; private readonly ConcurrentDictionary _localEndPoints = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); @@ -53,7 +51,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// The local end points. public IEnumerable LocalEndPoints { - get { return _localEndPoints.Keys.ToList(); } + get { return _listener == null ? new List() : _listener.LocalEndPoints; } } public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, string serviceName, string handlerPath, string defaultRedirectPath, params Assembly[] assembliesWithServices) @@ -148,120 +146,32 @@ namespace MediaBrowser.Server.Implementations.HttpServer public override ServiceStackHost Start(string listeningAtUrlBase) { - StartListener(Listen); + StartListener(); return this; } /// /// Starts the Web Service /// - private void StartListener(WaitCallback listenCallback) + private void StartListener() { - // *** Already running - just leave it in place - if (IsStarted) - return; - - if (Listener == null) - Listener = new HttpListener(); - HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First()); - foreach (var prefix in UrlPrefixes) - { - _logger.Info("Adding HttpListener prefix " + prefix); - Listener.Prefixes.Add(prefix); - } - - IsStarted = true; - _logger.Info("Starting HttpListner"); - Listener.Start(); - _logger.Info("HttpListener started"); - - ThreadPool.QueueUserWorkItem(listenCallback); - } - - private bool IsListening - { - get { return this.IsStarted && this.Listener != null && this.Listener.IsListening; } - } - - // Loop here to begin processing of new requests. - private void Listen(object state) - { - while (IsListening) - { - if (Listener == null) return; - - try - { - Listener.BeginGetContext(ListenerCallback, Listener); - _listenForNextRequest.WaitOne(); - } - catch (Exception ex) - { - _logger.Error("Listen()", ex); - return; - } - if (Listener == null) return; - } - } - - // Handle the processing of a request in here. - private void ListenerCallback(IAsyncResult asyncResult) - { - var listener = asyncResult.AsyncState as HttpListener; - HttpListenerContext context; - - if (listener == null) return; - var isListening = listener.IsListening; - - try - { - if (!isListening) - { - _logger.Debug("Ignoring ListenerCallback() as HttpListener is no longer listening"); return; - } - // The EndGetContext() method, as with all Begin/End asynchronous methods in the .NET Framework, - // blocks until there is a request to be processed or some type of data is available. - context = listener.EndGetContext(asyncResult); - } - catch (Exception ex) + _listener = new HttpListenerServer(_logger, _threadPoolManager) { - // You will get an exception when httpListener.Stop() is called - // because there will be a thread stopped waiting on the .EndGetContext() - // method, and again, that is just the way most Begin/End asynchronous - // methods of the .NET Framework work. - var errMsg = ex + ": " + IsListening; - _logger.Warn(errMsg); - return; - } - finally - { - // Once we know we have a request (or exception), we signal the other thread - // so that it calls the BeginGetContext() (or possibly exits if we're not - // listening any more) method to start handling the next incoming request - // while we continue to process this request on a different thread. - _listenForNextRequest.Set(); - } + WebSocketHandler = WebSocketHandler, + ErrorHandler = ErrorHandler, + RequestHandler = RequestHandler + }; - _threadPoolManager.QueueWorkItem(() => InitTask(context)); + _listener.Start(UrlPrefixes); } - public virtual void InitTask(HttpListenerContext context) + private void WebSocketHandler(WebSocketConnectEventArgs args) { - try - { - var task = this.ProcessRequestAsync(context); - task.ContinueWith(x => HandleError(x.Exception, context), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent); - - if (task.Status == TaskStatus.Created) - { - task.RunSynchronously(); - } - } - catch (Exception ex) + if (WebSocketConnected != null) { - HandleError(ex, context); + WebSocketConnected(this, args); } } @@ -280,43 +190,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer _localEndPoints.GetOrAdd(address, address); } - if (EnableHttpRequestLogging) - { - LoggerUtils.LogRequest(_logger, request); - } - } - - /// - /// Processes the web socket request. - /// - /// The CTX. - /// Task. - private async Task ProcessWebSocketRequest(HttpListenerContext ctx) - { -#if !__MonoCS__ - try - { - var webSocketContext = await ctx.AcceptWebSocketAsync(null).ConfigureAwait(false); - if (WebSocketConnected != null) - { - WebSocketConnected(this, new WebSocketConnectEventArgs { WebSocket = new NativeWebSocket(webSocketContext.WebSocket, _logger), Endpoint = ctx.Request.RemoteEndPoint.ToString() }); - } - } - catch (Exception ex) - { - _logger.ErrorException("AcceptWebSocketAsync error", ex); - ctx.Response.StatusCode = 500; - ctx.Response.Close(); - } -#endif + LoggerUtils.LogRequest(_logger, request); } - private void HandleError(Exception ex, HttpListenerContext context) + private void ErrorHandler(Exception ex, IRequest httpReq) { try { - var operationName = context.Request.GetOperationName(); - var httpReq = GetRequest(context, operationName); var httpRes = httpReq.Response; if (httpRes.IsClosed) @@ -366,84 +246,54 @@ namespace MediaBrowser.Server.Implementations.HttpServer } } - private static ListenerRequest GetRequest(HttpListenerContext httpContext, string operationName) - { - var req = new ListenerRequest(httpContext, operationName, RequestAttributes.None); - req.RequestAttributes = req.GetAttributes(); - - return req; - } - /// /// Shut down the Web Service /// public void Stop() { - if (Listener != null) + if (_listener != null) { - foreach (var prefix in UrlPrefixes) - { - Listener.Prefixes.Remove(prefix); - } - - Listener.Close(); + _listener.Stop(); } } /// /// Overridable method that can be used to implement a custom hnandler /// - /// - protected Task ProcessRequestAsync(HttpListenerContext context) + /// The HTTP req. + /// Task. + protected Task RequestHandler(IHttpRequest httpReq, Uri url) { - var request = context.Request; - - LogHttpRequest(request); + var date = DateTime.Now; - if (request.IsWebSocketRequest) - { - return ProcessWebSocketRequest(context); - } + var httpRes = httpReq.Response; - var localPath = request.Url.LocalPath; + var operationName = httpReq.OperationName; + var localPath = url.LocalPath; if (string.Equals(localPath, "/" + HandlerPath + "/", StringComparison.OrdinalIgnoreCase)) { - context.Response.Redirect(DefaultRedirectPath); - context.Response.Close(); + httpRes.RedirectToUrl(DefaultRedirectPath); return Task.FromResult(true); } if (string.Equals(localPath, "/" + HandlerPath, StringComparison.OrdinalIgnoreCase)) { - context.Response.Redirect(HandlerPath + "/" + DefaultRedirectPath); - context.Response.Close(); + httpRes.RedirectToUrl(HandlerPath + "/" + DefaultRedirectPath); return Task.FromResult(true); } if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase)) { - context.Response.Redirect(HandlerPath + "/" + DefaultRedirectPath); - context.Response.Close(); + httpRes.RedirectToUrl(HandlerPath + "/" + DefaultRedirectPath); return Task.FromResult(true); } if (string.IsNullOrEmpty(localPath)) { - context.Response.Redirect("/" + HandlerPath + "/" + DefaultRedirectPath); - context.Response.Close(); + httpRes.RedirectToUrl("/" + HandlerPath + "/" + DefaultRedirectPath); return Task.FromResult(true); } - var date = DateTime.Now; - - if (string.IsNullOrEmpty(context.Request.RawUrl)) - return ((object)null).AsTaskResult(); - - var operationName = context.Request.GetOperationName(); - - var httpReq = GetRequest(context, operationName); - var httpRes = httpReq.Response; var handler = HttpHandlerFactory.GetHandler(httpReq); - var url = request.Url.ToString(); var remoteIp = httpReq.RemoteIp; var serviceStackHandler = handler as IServiceStackHandler; @@ -461,15 +311,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer //Matches Exceptions handled in HttpListenerBase.InitTask() var statusCode = httpRes.StatusCode; + var urlString = url.ToString(); task.ContinueWith(x => { var duration = DateTime.Now - date; - if (EnableHttpRequestLogging) - { - LoggerUtils.LogResponse(_logger, statusCode, url, remoteIp, duration); - } + LoggerUtils.LogResponse(_logger, statusCode, urlString, remoteIp, duration); }, TaskContinuationOptions.None); @@ -480,12 +328,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer .AsTaskException(); } - /// - /// Gets or sets a value indicating whether [enable HTTP request logging]. - /// - /// true if [enable HTTP request logging]; otherwise, false. - public bool EnableHttpRequestLogging { get; set; } - /// /// Adds the rest handlers. /// @@ -530,8 +372,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer if (disposing) { - _threadPoolManager.Dispose(); - + _threadPoolManager.Dispose(); + Stop(); } diff --git a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs new file mode 100644 index 0000000000..1d80a263c0 --- /dev/null +++ b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using MediaBrowser.Common.Net; +using ServiceStack.Web; +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.HttpServer +{ + public interface IHttpListener : IDisposable + { + IEnumerable LocalEndPoints { get; } + + /// + /// Gets or sets the error handler. + /// + /// The error handler. + Action ErrorHandler { get; set; } + + /// + /// Gets or sets the request handler. + /// + /// The request handler. + Func RequestHandler { get; set; } + + /// + /// Gets or sets the web socket handler. + /// + /// The web socket handler. + Action WebSocketHandler { get; set; } + + /// + /// Starts this instance. + /// + /// The URL prefixes. + void Start(IEnumerable urlPrefixes); + + /// + /// Stops this instance. + /// + void Stop(); + } +} diff --git a/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs new file mode 100644 index 0000000000..51f0554d73 --- /dev/null +++ b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs @@ -0,0 +1,281 @@ +using Amib.Threading; +using MediaBrowser.Common.Net; +using MediaBrowser.Model.Logging; +using ServiceStack; +using ServiceStack.Host.HttpListener; +using ServiceStack.Web; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.HttpServer.NetListener +{ + public class HttpListenerServer : IHttpListener + { + private readonly ILogger _logger; + private HttpListener _listener; + private readonly AutoResetEvent _listenForNextRequest = new AutoResetEvent(false); + private readonly SmartThreadPool _threadPoolManager; + + public System.Action ErrorHandler { get; set; } + public Action WebSocketHandler { get; set; } + public System.Func RequestHandler { get; set; } + + private readonly ConcurrentDictionary _localEndPoints = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + + public HttpListenerServer(ILogger logger, SmartThreadPool threadPoolManager) + { + _logger = logger; + + _threadPoolManager = threadPoolManager; + } + + /// + /// Gets the local end points. + /// + /// The local end points. + public IEnumerable LocalEndPoints + { + get { return _localEndPoints.Keys.ToList(); } + } + + private List UrlPrefixes { get; set; } + + public void Start(IEnumerable urlPrefixes) + { + UrlPrefixes = urlPrefixes.ToList(); + + if (_listener == null) + _listener = new System.Net.HttpListener(); + + //HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First()); + + foreach (var prefix in UrlPrefixes) + { + _logger.Info("Adding HttpListener prefix " + prefix); + _listener.Prefixes.Add(prefix); + } + + _listener.Start(); + + ThreadPool.QueueUserWorkItem(Listen); + } + + private bool IsListening + { + get { return _listener != null && _listener.IsListening; } + } + + // Loop here to begin processing of new requests. + private void Listen(object state) + { + while (IsListening) + { + if (_listener == null) return; + + try + { + _listener.BeginGetContext(ListenerCallback, _listener); + _listenForNextRequest.WaitOne(); + } + catch (Exception ex) + { + _logger.Error("Listen()", ex); + return; + } + if (_listener == null) return; + } + } + + // Handle the processing of a request in here. + private void ListenerCallback(IAsyncResult asyncResult) + { + var listener = asyncResult.AsyncState as HttpListener; + HttpListenerContext context; + + if (listener == null) return; + var isListening = listener.IsListening; + + try + { + if (!isListening) + { + _logger.Debug("Ignoring ListenerCallback() as HttpListener is no longer listening"); return; + } + // The EndGetContext() method, as with all Begin/End asynchronous methods in the .NET Framework, + // blocks until there is a request to be processed or some type of data is available. + context = listener.EndGetContext(asyncResult); + } + catch (Exception ex) + { + // You will get an exception when httpListener.Stop() is called + // because there will be a thread stopped waiting on the .EndGetContext() + // method, and again, that is just the way most Begin/End asynchronous + // methods of the .NET Framework work. + var errMsg = ex + ": " + IsListening; + _logger.Warn(errMsg); + return; + } + finally + { + // Once we know we have a request (or exception), we signal the other thread + // so that it calls the BeginGetContext() (or possibly exits if we're not + // listening any more) method to start handling the next incoming request + // while we continue to process this request on a different thread. + _listenForNextRequest.Set(); + } + + _threadPoolManager.QueueWorkItem(() => InitTask(context)); + } + + public virtual void InitTask(HttpListenerContext context) + { + try + { + var task = this.ProcessRequestAsync(context); + task.ContinueWith(x => HandleError(x.Exception, context), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent); + + if (task.Status == TaskStatus.Created) + { + task.RunSynchronously(); + } + } + catch (Exception ex) + { + HandleError(ex, context); + } + } + + protected Task ProcessRequestAsync(HttpListenerContext context) + { + var request = context.Request; + + LogHttpRequest(request); + + if (request.IsWebSocketRequest) + { + return ProcessWebSocketRequest(context); + } + + if (string.IsNullOrEmpty(context.Request.RawUrl)) + return ((object)null).AsTaskResult(); + + var operationName = context.Request.GetOperationName(); + + var httpReq = GetRequest(context, operationName); + + return RequestHandler(httpReq, request.Url); + } + + /// + /// Processes the web socket request. + /// + /// The CTX. + /// Task. + private async Task ProcessWebSocketRequest(HttpListenerContext ctx) + { +#if !__MonoCS__ + try + { + var webSocketContext = await ctx.AcceptWebSocketAsync(null).ConfigureAwait(false); + + if (WebSocketHandler != null) + { + WebSocketHandler(new WebSocketConnectEventArgs + { + WebSocket = new NativeWebSocket(webSocketContext.WebSocket, _logger), + Endpoint = ctx.Request.RemoteEndPoint.ToString() + }); + } + } + catch (Exception ex) + { + _logger.ErrorException("AcceptWebSocketAsync error", ex); + ctx.Response.StatusCode = 500; + ctx.Response.Close(); + } +#endif + } + + private void HandleError(Exception ex, HttpListenerContext context) + { + var operationName = context.Request.GetOperationName(); + var httpReq = GetRequest(context, operationName); + + if (ErrorHandler != null) + { + ErrorHandler(ex, httpReq); + } + } + + private static ListenerRequest GetRequest(HttpListenerContext httpContext, string operationName) + { + var req = new ListenerRequest(httpContext, operationName, RequestAttributes.None); + req.RequestAttributes = req.GetAttributes(); + + return req; + } + + /// + /// Logs the HTTP request. + /// + /// The request. + private void LogHttpRequest(HttpListenerRequest request) + { + var endpoint = request.LocalEndPoint; + + if (endpoint != null) + { + var address = endpoint.ToString(); + + _localEndPoints.GetOrAdd(address, address); + } + + LoggerUtils.LogRequest(_logger, request); + } + + public void Stop() + { + if (_listener != null) + { + foreach (var prefix in UrlPrefixes) + { + _listener.Prefixes.Remove(prefix); + } + + _listener.Close(); + } + } + + public void Dispose() + { + Dispose(true); + } + + private bool _disposed; + private readonly object _disposeLock = new object(); + protected virtual void Dispose(bool disposing) + { + if (_disposed) return; + + lock (_disposeLock) + { + if (_disposed) return; + + if (disposing) + { + _threadPoolManager.Dispose(); + + Stop(); + } + + //release unmanaged resources here... + _disposed = true; + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 8d4eec29e0..c24e9574f7 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -96,6 +96,9 @@ ..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll + + ..\ThirdParty\WebsocketSharp\websocket-sharp.dll + @@ -134,6 +137,8 @@ + + diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs index e66b87b0c8..5931d7718f 100644 --- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs +++ b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs @@ -123,9 +123,9 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// /// Starts this instance. /// - public void Start(IEnumerable urlPrefixes, bool enableHttpLogging) + public void Start(IEnumerable urlPrefixes) { - ReloadHttpServer(urlPrefixes, enableHttpLogging); + ReloadHttpServer(urlPrefixes); } public void StartWebSocketServer() @@ -152,14 +152,13 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// /// Restarts the Http Server, or starts it if not currently running /// - private void ReloadHttpServer(IEnumerable urlPrefixes, bool enableHttpLogging) + private void ReloadHttpServer(IEnumerable urlPrefixes) { _logger.Info("Loading Http Server"); try { HttpServer = _applicationHost.Resolve(); - HttpServer.EnableHttpRequestLogging = enableHttpLogging; HttpServer.StartServer(urlPrefixes); } catch (SocketException ex) diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 60d1c92b42..da7f8631b0 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -851,7 +851,7 @@ namespace MediaBrowser.ServerApplication { try { - ServerManager.Start(HttpServerUrlPrefixes, ServerConfigurationManager.Configuration.EnableHttpLevelLogging); + ServerManager.Start(HttpServerUrlPrefixes); } catch (Exception ex) { @@ -881,8 +881,6 @@ namespace MediaBrowser.ServerApplication { base.OnConfigurationUpdated(sender, e); - HttpServer.EnableHttpRequestLogging = ServerConfigurationManager.Configuration.EnableHttpLevelLogging; - if (!HttpServer.UrlPrefixes.SequenceEqual(HttpServerUrlPrefixes, StringComparer.OrdinalIgnoreCase)) { NotifyPendingRestart(); -- cgit v1.2.3 From ce20066bc0e2c7ba1634200cdee6ac339d4dfb60 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 20 Jul 2014 00:46:29 -0400 Subject: update translations --- MediaBrowser.Api/ItemRefreshService.cs | 3 +- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 5 + .../BaseApplicationHost.cs | 48 +- .../ScheduledTasks/Tasks/ReloadLoggerFileTask.cs | 2 +- MediaBrowser.Common/Net/IWebSocket.cs | 14 +- MediaBrowser.Common/Net/IWebSocketConnection.cs | 5 +- MediaBrowser.Controller/Library/TVUtils.cs | 8 +- .../Configuration/ServerConfiguration.cs | 7 - .../HttpServer/HttpListenerHost.cs | 2 +- .../HttpServer/NativeWebSocket.cs | 21 +- .../HttpServer/SocketSharp/SharpWebSocket.cs | 24 +- .../Library/Resolvers/TV/SeriesResolver.cs | 8 +- .../Localization/JavaScript/ar.json | 10 +- .../Localization/JavaScript/ca.json | 10 +- .../Localization/JavaScript/cs.json | 8 +- .../Localization/JavaScript/da.json | 10 +- .../Localization/JavaScript/de.json | 6 +- .../Localization/JavaScript/el.json | 10 +- .../Localization/JavaScript/en_GB.json | 10 +- .../Localization/JavaScript/en_US.json | 10 +- .../Localization/JavaScript/es.json | 6 +- .../Localization/JavaScript/es_MX.json | 138 +- .../Localization/JavaScript/fr.json | 6 +- .../Localization/JavaScript/he.json | 10 +- .../Localization/JavaScript/it.json | 42 +- .../Localization/JavaScript/javascript.json | 53 +- .../Localization/JavaScript/kk.json | 6 +- .../Localization/JavaScript/ms.json | 10 +- .../Localization/JavaScript/nb.json | 10 +- .../Localization/JavaScript/nl.json | 18 +- .../Localization/JavaScript/pl.json | 10 +- .../Localization/JavaScript/pt_BR.json | 6 +- .../Localization/JavaScript/pt_PT.json | 6 +- .../Localization/JavaScript/ru.json | 10 +- .../Localization/JavaScript/sv.json | 6 +- .../Localization/JavaScript/vi.json | 10 +- .../Localization/JavaScript/zh_TW.json | 10 +- .../Localization/Server/ar.json | 22 +- .../Localization/Server/ca.json | 22 +- .../Localization/Server/cs.json | 18 +- .../Localization/Server/da.json | 16 +- .../Localization/Server/de.json | 24 +- .../Localization/Server/el.json | 22 +- .../Localization/Server/en_GB.json | 22 +- .../Localization/Server/en_US.json | 22 +- .../Localization/Server/es.json | 20 +- .../Localization/Server/es_MX.json | 30 +- .../Localization/Server/fr.json | 26 +- .../Localization/Server/he.json | 18 +- .../Localization/Server/it.json | 58 +- .../Localization/Server/kk.json | 16 +- .../Localization/Server/ko.json | 22 +- .../Localization/Server/ms.json | 22 +- .../Localization/Server/nb.json | 22 +- .../Localization/Server/nl.json | 58 +- .../Localization/Server/pl.json | 22 +- .../Localization/Server/pt_BR.json | 20 +- .../Localization/Server/pt_PT.json | 22 +- .../Localization/Server/ru.json | 34 +- .../Localization/Server/server.json | 1793 ++++++++++---------- .../Localization/Server/sv.json | 24 +- .../Localization/Server/vi.json | 20 +- .../Localization/Server/zh_TW.json | 16 +- .../ServerManager/ServerManager.cs | 7 +- .../ServerManager/WebSocketConnection.cs | 54 +- MediaBrowser.ServerApplication/ApplicationHost.cs | 22 +- MediaBrowser.ServerApplication/MainStartup.cs | 8 +- .../Native/RegisterServer.bat | 6 - .../Native/ServerAuthorization.cs | 8 +- .../Providers/MovieDbProviderTests.cs | 7 - MediaBrowser.Tests/Resolvers/TvUtilTests.cs | 2 +- MediaBrowser.WebDashboard/Api/DashboardService.cs | 4 +- .../MediaBrowser.WebDashboard.csproj | 15 +- 73 files changed, 1762 insertions(+), 1360 deletions(-) (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index 993b69601c..768e9a4a82 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -157,7 +157,8 @@ namespace MediaBrowser.Api MetadataRefreshMode = request.MetadataRefreshMode, ImageRefreshMode = request.ImageRefreshMode, ReplaceAllImages = request.ReplaceAllImages, - ReplaceAllMetadata = request.ReplaceAllMetadata + ReplaceAllMetadata = request.ReplaceAllMetadata, + ForceSave = true }; } } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index a098d26daa..f01d8ddf4b 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -65,6 +65,11 @@ namespace MediaBrowser.Api.Playback.Hls throw new ArgumentException("Video codec copy is not allowed here."); } + if (string.IsNullOrEmpty(request.MediaSourceId)) + { + throw new ArgumentException("MediaSourceId is required"); + } + var result = GetAsync(request).Result; return result; diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index 178b840a87..850309465e 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -211,6 +211,8 @@ namespace MediaBrowser.Common.Implementations JsonSerializer = CreateJsonSerializer(); Logger = LogManager.GetLogger("App"); + OnLoggerLoaded(true); + LogManager.LoggerLoaded += (s, e) => OnLoggerLoaded(false); IsFirstRun = !ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted; progress.Report(2); @@ -219,16 +221,11 @@ namespace MediaBrowser.Common.Implementations ? LogSeverity.Debug : LogSeverity.Info; - // Put the app config in the log for troubleshooting purposes - Logger.LogMultiline("Application Configuration:", LogSeverity.Info, new StringBuilder(JsonSerializer.SerializeToString(ConfigurationManager.CommonConfiguration))); - progress.Report(3); DiscoverTypes(); progress.Report(14); - Logger.Info("Version {0} initializing", ApplicationVersion); - SetHttpLimit(); progress.Report(15); @@ -245,6 +242,47 @@ namespace MediaBrowser.Common.Implementations progress.Report(100); } + protected virtual void OnLoggerLoaded(bool isFirstLoad) + { + Logger.Info("Application version: {0}", ApplicationVersion); + + if (!isFirstLoad) + { + LogEnvironmentInfo(Logger, ApplicationPaths); + } + + // Put the app config in the log for troubleshooting purposes + Logger.LogMultiline("Application configuration:", LogSeverity.Info, new StringBuilder(JsonSerializer.SerializeToString(ConfigurationManager.CommonConfiguration))); + + if (Plugins != null) + { + var pluginBuilder = new StringBuilder(); + + foreach (var plugin in Plugins) + { + pluginBuilder.AppendLine(string.Format("{0} {1}", plugin.Name, plugin.Version)); + } + + Logger.LogMultiline("Plugins:", LogSeverity.Info, pluginBuilder); + } + } + + public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths) + { + logger.Info("Command line: {0}", string.Join(" ", Environment.GetCommandLineArgs())); + + logger.Info("Server: {0}", Environment.MachineName); + logger.Info("Operating system: {0}", Environment.OSVersion.ToString()); + logger.Info("Processor count: {0}", Environment.ProcessorCount); + logger.Info("64-Bit OS: {0}", Environment.Is64BitOperatingSystem); + logger.Info("64-Bit Process: {0}", Environment.Is64BitProcess); + logger.Info("Program data path: {0}", appPaths.ProgramDataPath); + + logger.Info("Application Path: {0}", appPaths.ApplicationPath); + + logger.Info("*** When reporting issues please include the entire log file. ***".ToUpper()); + } + protected virtual IJsonSerializer CreateJsonSerializer() { return new JsonSerializer(); diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs index 78f60632fa..38b6b4ad68 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks public bool IsHidden { - get { return true; } + get { return false; } } public bool IsEnabled diff --git a/MediaBrowser.Common/Net/IWebSocket.cs b/MediaBrowser.Common/Net/IWebSocket.cs index 05f7975bca..b31a953192 100644 --- a/MediaBrowser.Common/Net/IWebSocket.cs +++ b/MediaBrowser.Common/Net/IWebSocket.cs @@ -32,15 +32,23 @@ namespace MediaBrowser.Common.Net /// /// The on receive. Action OnReceive { get; set; } - + /// /// Sends the async. /// /// The bytes. - /// The type. /// if set to true [end of message]. /// The cancellation token. /// Task. - Task SendAsync(byte[] bytes, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken); + Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken); + + /// + /// Sends the asynchronous. + /// + /// The text. + /// if set to true [end of message]. + /// The cancellation token. + /// Task. + Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Common/Net/IWebSocketConnection.cs b/MediaBrowser.Common/Net/IWebSocketConnection.cs index 9f9dfaeca3..b7715e20b9 100644 --- a/MediaBrowser.Common/Net/IWebSocketConnection.cs +++ b/MediaBrowser.Common/Net/IWebSocketConnection.cs @@ -63,11 +63,10 @@ namespace MediaBrowser.Common.Net /// /// Sends a message asynchronously. /// - /// The buffer. - /// The type. + /// The text. /// The cancellation token. /// Task. /// buffer - Task SendAsync(byte[] buffer, WebSocketMessageType type, CancellationToken cancellationToken); + Task SendAsync(string text, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index 88eadda005..af0ff8319e 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -200,7 +200,9 @@ namespace MediaBrowser.Controller.Library /// Determines whether [is series folder] [the specified path]. /// /// The path. + /// if set to true [consider seasonless series]. /// The file system children. + /// The directory service. /// true if [is series folder] [the specified path]; otherwise, false. public static bool IsSeriesFolder(string path, bool considerSeasonlessSeries, IEnumerable fileSystemChildren, IDirectoryService directoryService) { @@ -227,8 +229,10 @@ namespace MediaBrowser.Controller.Library { return true; } - - nonSeriesFolders++; + if (!EntityResolutionHelper.IgnoreFolders.Contains(child.Name, StringComparer.OrdinalIgnoreCase)) + { + nonSeriesFolders++; + } if (nonSeriesFolders >= 3) { diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 904c7bcddf..3448a2905f 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -34,12 +34,6 @@ namespace MediaBrowser.Model.Configuration /// The HTTP server port number. public int HttpServerPortNumber { get; set; } - /// - /// Gets or sets the legacy web socket port number. - /// - /// The legacy web socket port number. - public int LegacyWebSocketPortNumber { get; set; } - /// /// Gets or sets a value indicating whether [enable internet providers]. /// @@ -216,7 +210,6 @@ namespace MediaBrowser.Model.Configuration MediaEncodingQuality = EncodingQuality.Auto; ImageSavingConvention = ImageSavingConvention.Compatible; HttpServerPortNumber = 8096; - LegacyWebSocketPortNumber = 8945; EnableDashboardResponseCaching = true; EnableAutomaticRestart = true; diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 62a43751db..f530564eaa 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -157,7 +157,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First()); _listener = NativeWebSocket.IsSupported - ? _listener = new HttpListenerServer(_logger, _threadPoolManager) + ? _listener = new WebSocketSharpListener(_logger, _threadPoolManager) : _listener = new WebSocketSharpListener(_logger, _threadPoolManager); _listener.WebSocketHandler = WebSocketHandler; diff --git a/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs b/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs index f89cdac47c..c7669fecb5 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Events; +using System.Text; +using MediaBrowser.Common.Events; using MediaBrowser.Common.Net; using MediaBrowser.Model.Logging; using System; @@ -36,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// The socket. /// The logger. /// socket - public NativeWebSocket(System.Net.WebSockets.WebSocket socket, ILogger logger) + public NativeWebSocket(WebSocket socket, ILogger logger) { if (socket == null) { @@ -155,6 +156,22 @@ namespace MediaBrowser.Server.Implementations.HttpServer return WebSocket.SendAsync(new ArraySegment(bytes), nativeType, true, linkedTokenSource.Token); } + public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken) + { + var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationTokenSource.Token); + + return WebSocket.SendAsync(new ArraySegment(bytes), System.Net.WebSockets.WebSocketMessageType.Binary, true, linkedTokenSource.Token); + } + + public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken) + { + var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationTokenSource.Token); + + var bytes = Encoding.UTF8.GetBytes(text); + + return WebSocket.SendAsync(new ArraySegment(bytes), System.Net.WebSockets.WebSocketMessageType.Text, true, linkedTokenSource.Token); + } + /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs index 4127892409..7ff3a12478 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs @@ -96,22 +96,30 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp /// Sends the async. /// /// The bytes. - /// The type. /// if set to true [end of message]. /// The cancellation token. /// Task. - public Task SendAsync(byte[] bytes, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken) + public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken) { - System.Net.WebSockets.WebSocketMessageType nativeType; + var completionSource = new TaskCompletionSource(); - if (!Enum.TryParse(type.ToString(), true, out nativeType)) - { - _logger.Warn("Unrecognized WebSocketMessageType: {0}", type.ToString()); - } + WebSocket.SendAsync(bytes, res => completionSource.TrySetResult(true)); + + return completionSource.Task; + } + /// + /// Sends the asynchronous. + /// + /// The text. + /// if set to true [end of message]. + /// The cancellation token. + /// Task. + public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken) + { var completionSource = new TaskCompletionSource(); - WebSocket.SendAsync(Encoding.UTF8.GetString(bytes), res => completionSource.TrySetResult(true)); + WebSocket.SendAsync(text, res => completionSource.TrySetResult(true)); return completionSource.Task; } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 6b376d3b46..a756dc7944 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -67,14 +67,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV { return null; } - - // Without these movies that have the name season in them could cause the parent folder to be resolved as a series - if (filename.IndexOf("[tmdbid=", StringComparison.OrdinalIgnoreCase) != -1) - { - return null; - } - if (args.ContainsMetaFileByName("series.xml") || filename.IndexOf("[tvdbid=", StringComparison.OrdinalIgnoreCase) != -1 || TVUtils.IsSeriesFolder(args.Path, collectionType == CollectionType.TvShows, args.FileSystemChildren, args.DirectoryService)) + if (TVUtils.IsSeriesFolder(args.Path, collectionType == CollectionType.TvShows, args.FileSystemChildren, args.DirectoryService)) { return new Series(); } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json index eb1334c10d..1192bafb77 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Select", + "ButtonNew": "New" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json index f317188931..37a5735e4b 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Select", + "ButtonNew": "New" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json index a7f7141754..92f352ca62 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json @@ -58,7 +58,7 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "P\u0159ehr\u00e1t", "ButtonEdit": "Upravit", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Titulky", "ButtonScenes": "Sc\u00e9ny", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Vybrat", + "ButtonNew": "Nov\u00e9" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json index 2b70bf74ed..988b036509 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Afspil", "ButtonEdit": "Rediger", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Undertekster", "ButtonScenes": "Scener", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "V\u00e6lg", + "ButtonNew": "Ny" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json index be4cf1bbfa..58b273c266 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Untertitel", "ButtonScenes": "Szenen", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Ausw\u00e4hlen", + "ButtonNew": "Neu" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json index a033dcbc9e..9ad65edbda 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Select", + "ButtonNew": "New" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json index 59dbb63e68..03694cad0a 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Select", + "ButtonNew": "New" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json index a0fc056bc4..bfd93b7950 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Select", + "ButtonNew": "New" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json index 5c199c8ea1..05647f10d5 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subt\u00edtulos", "ButtonScenes": "Escenas", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Seleccionar", + "ButtonNew": "Nuevo" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json index 1ca3aa56d7..62ecc25789 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json @@ -233,85 +233,89 @@ "ButtonRevoke": "Revocar", "MessageConfirmRevokeApiKey": "\u00bfEst\u00e1 seguro de querer revocar esta llave de API?", "HeaderConfirmRevokeApiKey": "Revocar llave de API", - "ValueContainer": "Container: {0}", - "ValueAudioCodec": "Audio Codec: {0}", - "ValueVideoCodec": "Video Codec: {0}", - "ValueCodec": "Codec: {0}", - "ValueConditions": "Conditions: {0}", - "LabelAll": "All", - "HeaderDeleteImage": "Delete Image", - "MessageFileNotFound": "File not found.", - "MessageFileReadError": "An error occurred reading this file.", - "ButtonNextPage": "Next Page", - "ButtonPreviousPage": "Previous Page", - "ButtonMoveLeft": "Move left", - "ButtonMoveRight": "Move right", - "ButtonBrowseOnlineImages": "Browse online images", - "HeaderDeleteItem": "Delete Item", - "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?", - "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.", - "MessageValueNotCorrect": "The value entered is not correct. Please try again.", - "MessageItemSaved": "Item saved.", + "ValueContainer": "Contenedor: {0}", + "ValueAudioCodec": "C\u00f3dec de Audio: {0}", + "ValueVideoCodec": "C\u00f3dec de Video: {0}", + "ValueCodec": "C\u00f3dec: {0}", + "ValueConditions": "Condiciones: {0}", + "LabelAll": "Todos", + "HeaderDeleteImage": "Eliminar Im\u00e1gen", + "MessageFileNotFound": "Archivo no encontrado.", + "MessageFileReadError": "Ha ocurrido un error al leer este archivo.", + "ButtonNextPage": "P\u00e1gina Siguiente", + "ButtonPreviousPage": "P\u00e1gina Anterior", + "ButtonMoveLeft": "Mover a la izquierda", + "ButtonMoveRight": "Mover a la derecha", + "ButtonBrowseOnlineImages": "Navegar por im\u00e1genes en l\u00ednea", + "HeaderDeleteItem": "Eliminar \u00cdtem", + "ConfirmDeleteItem": "\u00bfEsta seguro de querer eleiminar este \u00edtem de su biblioteca?", + "MessagePleaseEnterNameOrId": "Por favor ingrese un nombre o id externo.", + "MessageValueNotCorrect": "El valor ingresado no es correcto. Intente nuevamente por favor.", + "MessageItemSaved": "\u00cdtem guardado.", "OptionEnded": "Finalizado", "OptionContinuing": "Continuando", "OptionOff": "No", "OptionOn": "Si", - "HeaderFields": "Fields", - "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.", - "HeaderLiveTV": "Live TV", - "MissingLocalTrailer": "Missing local trailer.", - "MissingPrimaryImage": "Missing primary image.", - "MissingBackdropImage": "Missing backdrop image.", - "MissingLogoImage": "Missing logo image.", - "MissingEpisode": "Missing episode.", - "OptionScreenshots": "Screenshots", - "OptionBackdrops": "Backdrops", - "OptionImages": "Images", - "OptionKeywords": "Keywords", - "OptionTags": "Tags", - "OptionStudios": "Studios", - "OptionName": "Name", - "OptionOverview": "Overview", - "OptionGenres": "Genres", + "HeaderFields": "Campos", + "HeaderFieldsHelp": "Deslice un campo hacia \"apagado\" para bloquearlo y evitar que sus datos sean modificados.", + "HeaderLiveTV": "TV en Vivo", + "MissingLocalTrailer": "Falta avance local.", + "MissingPrimaryImage": "Falta im\u00e1gen primaria.", + "MissingBackdropImage": "Falta im\u00e1gen de fondo.", + "MissingLogoImage": "Falta im\u00e1gen de logo.", + "MissingEpisode": "Falta episodio.", + "OptionScreenshots": "Capuras de Pantalla", + "OptionBackdrops": "Fondos", + "OptionImages": "Im\u00e1genes", + "OptionKeywords": "Palabras clave", + "OptionTags": "Etiquetas", + "OptionStudios": "Estudios", + "OptionName": "Nombre", + "OptionOverview": "Sinopsis", + "OptionGenres": "G\u00e9neros", "OptionParentalRating": "Clasificaci\u00f3n Parental", - "OptionPeople": "People", + "OptionPeople": "Personas", "OptionRuntime": "Duraci\u00f3n", - "OptionProductionLocations": "Production Locations", - "OptionBirthLocation": "Birth Location", + "OptionProductionLocations": "Lugares de Producci\u00f3n", + "OptionBirthLocation": "Lugar de Nacimiento", "LabelAllChannels": "Todos los canales", - "LabelLiveProgram": "LIVE", - "LabelNewProgram": "NEW", - "LabelPremiereProgram": "PREMIERE", - "HeaderChangeFolderType": "Change Folder Type", - "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.", - "HeaderAlert": "Alert", - "MessagePleaseRestart": "Please restart to finish updating.", + "LabelLiveProgram": "EN VIVO", + "LabelNewProgram": "NUEVO", + "LabelPremiereProgram": "ESTRENO", + "HeaderChangeFolderType": "Cambiar tipo de carpeta", + "HeaderChangeFolderTypeHelp": "Para cambiar el tipo de carpeta, por favor elimine y reconstruya la colecci\u00f3n con el nuevo tipo.", + "HeaderAlert": "Alerta", + "MessagePleaseRestart": "Por favor reinicie para finalizar la actualizaci\u00f3n.", "ButtonRestart": "Reiniciar", - "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.", - "ButtonHide": "Hide", - "MessageSettingsSaved": "Settings saved.", - "ButtonSignOut": "Sign Out", - "ButtonMyProfile": "My Profile", - "ButtonMyPreferences": "My Preferences", - "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.", - "LabelInstallingPackage": "Installing {0}", - "LabelPackageInstallCompleted": "{0} installation completed.", - "LabelPackageInstallFailed": "{0} installation failed.", - "LabelPackageInstallCancelled": "{0} installation cancelled.", + "MessagePleaseRefreshPage": "Por favor actualice esta p\u00e1gina para recibir nuevas actualizaciones desde el servidor.", + "ButtonHide": "Ocultar", + "MessageSettingsSaved": "Configuraciones guardadas", + "ButtonSignOut": "Cerrar Sesi\u00f3n", + "ButtonMyProfile": "Mi Perf\u00edl", + "ButtonMyPreferences": "Mis Preferencias", + "MessageBrowserDoesNotSupportWebSockets": "Este navegador no soporta sockets web. Para una mejor experiencia, pruebe con un navegador m\u00e1s nuevo como Chrome, Firefox, IE10+, Safari (iOS) u Opera.", + "LabelInstallingPackage": "Instalando {0}", + "LabelPackageInstallCompleted": "{0} instalaci\u00f3n completada.", + "LabelPackageInstallFailed": "{0} instalaci\u00f3n fallida.", + "LabelPackageInstallCancelled": "{0} instalaci\u00f3n cancelada.", "TabServer": "Servidor", - "TabUsers": "Users", - "TabLibrary": "Library", + "TabUsers": "Usuarios", + "TabLibrary": "Biblioteca", "TabMetadata": "Metadatos", "TabDLNA": "DLNA", - "TabLiveTV": "Live TV", - "TabAutoOrganize": "Auto-Organize", - "TabPlugins": "Plugins", + "TabLiveTV": "TV en Vivo", + "TabAutoOrganize": "Auto-Organizar", + "TabPlugins": "Complementos", "TabAdvanced": "Avanzado", - "TabHelp": "Help", - "TabScheduledTasks": "Scheduled Tasks", - "ButtonFullscreen": "Fullscreen", - "ButtonAudioTracks": "Audio Tracks", + "TabHelp": "Ayuda", + "TabScheduledTasks": "Tareas Programadas", + "ButtonFullscreen": "Pantalla completa", + "ButtonAudioTracks": "Pistas de Sonido", "ButtonSubtitles": "Subt\u00edtulos", "ButtonScenes": "Escenas", - "ButtonQuality": "Quality" + "ButtonQuality": "Calidad", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Seleccionar", + "ButtonNew": "Nuevo" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json index 0919afc7d7..e0b199b12f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Sous-titres", "ButtonScenes": "Sc\u00e8nes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "S\u00e9lectionner", + "ButtonNew": "Nouveau" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json index 6310881f20..2cb25ef9b6 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "\u05e0\u05d2\u05df", "ButtonEdit": "\u05e2\u05e8\u05d5\u05da", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "\u05d1\u05d7\u05e8", + "ButtonNew": "\u05d7\u05d3\u05e9" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json index 96e71a9717..1963f249af 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json @@ -216,31 +216,31 @@ "HeaderAlbumArtist": "Artista Album", "HeaderArtist": "Artista", "LabelAddedOnDate": "Added {0}", - "ButtonStart": "Start", + "ButtonStart": "Avvio", "HeaderChannels": "Canali", "HeaderMediaFolders": "Cartelle dei media", - "HeaderBlockItemsWithNoRating": "Block items with no rating information:", - "OptionBlockOthers": "Others", - "OptionBlockTvShows": "TV Shows", - "OptionBlockTrailers": "Trailers", - "OptionBlockMusic": "Music", - "OptionBlockMovies": "Movies", - "OptionBlockBooks": "Books", - "OptionBlockGames": "Games", - "OptionBlockLiveTvPrograms": "Live TV Programs", - "OptionBlockLiveTvChannels": "Live TV Channels", - "OptionBlockChannelContent": "Internet Channel Content", - "ButtonRevoke": "Revoke", - "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.", - "HeaderConfirmRevokeApiKey": "Revoke Api Key", + "HeaderBlockItemsWithNoRating": "Blocca gli elementi senza informazioni di valutazione", + "OptionBlockOthers": "Altri", + "OptionBlockTvShows": "Serie TV", + "OptionBlockTrailers": "Trailer", + "OptionBlockMusic": "Musica", + "OptionBlockMovies": "Film", + "OptionBlockBooks": "Libri", + "OptionBlockGames": "Giochi", + "OptionBlockLiveTvPrograms": "Programmi TV in onda", + "OptionBlockLiveTvChannels": "Canali TV in onda", + "OptionBlockChannelContent": "Contenuto di Canali Internet", + "ButtonRevoke": "Revocare", + "MessageConfirmRevokeApiKey": "Sei sicuro che desideri revocare le chiavi api? La connessione dell'applicazione con Media Browser sar\u00e0 improvvisamente terminata.", + "HeaderConfirmRevokeApiKey": "Revocare Chiave Api", "ValueContainer": "Container: {0}", "ValueAudioCodec": "Audio Codec: {0}", "ValueVideoCodec": "Video Codec: {0}", "ValueCodec": "Codec: {0}", "ValueConditions": "Conditions: {0}", - "LabelAll": "All", - "HeaderDeleteImage": "Delete Image", - "MessageFileNotFound": "File not found.", + "LabelAll": "Tutti", + "HeaderDeleteImage": "Cancella Immagine", + "MessageFileNotFound": "File non trovato.", "MessageFileReadError": "An error occurred reading this file.", "ButtonNextPage": "Next Page", "ButtonPreviousPage": "Previous Page", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Sottotitoli", "ButtonScenes": "Scene", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Seleziona", + "ButtonNew": "Nuovo" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index 187bcb59f0..0b6e7c9c5c 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -296,29 +296,32 @@ "MessageSettingsSaved": "Settings saved.", "ButtonSignOut": "Sign Out", "ButtonMyProfile": "My Profile", - "ButtonMyPreferences": "My Preferences", - "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.", - "LabelInstallingPackage": "Installing {0}", - "LabelPackageInstallCompleted": "{0} installation completed.", - "LabelPackageInstallFailed": "{0} installation failed.", - "LabelPackageInstallCancelled": "{0} installation cancelled.", - "TabServer": "Server", - "TabUsers": "Users", - "TabLibrary": "Library", - "TabMetadata": "Metadata", - "TabDLNA": "DLNA", - "TabLiveTV": "Live TV", - "TabAutoOrganize": "Auto-Organize", - "TabPlugins": "Plugins", - "TabAdvanced": "Advanced", - "TabHelp": "Help", - "TabScheduledTasks": "Scheduled Tasks", - "ButtonFullscreen": "Fullscreen", - "ButtonMute": "Mute", - "ButtonUnmute": "Unmute", - "ButtonAudioTracks": "Audio Tracks", - "ButtonSubtitles": "Subtitles", - "ButtonScenes": "Scenes", - "ButtonQuality": "Quality", - "HeaderNotifications": "Notifications" + "ButtonMyPreferences": "My Preferences", + "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.", + "LabelInstallingPackage": "Installing {0}", + "LabelPackageInstallCompleted": "{0} installation completed.", + "LabelPackageInstallFailed": "{0} installation failed.", + "LabelPackageInstallCancelled": "{0} installation cancelled.", + "TabServer": "Server", + "TabUsers": "Users", + "TabLibrary": "Library", + "TabMetadata": "Metadata", + "TabDLNA": "DLNA", + "TabLiveTV": "Live TV", + "TabAutoOrganize": "Auto-Organize", + "TabPlugins": "Plugins", + "TabAdvanced": "Advanced", + "TabHelp": "Help", + "TabScheduledTasks": "Scheduled Tasks", + "ButtonFullscreen": "Fullscreen", + "ButtonMute": "Mute", + "ButtonUnmute": "Unmute", + "ButtonAudioTracks": "Audio Tracks", + "ButtonSubtitles": "Subtitles", + "ButtonScenes": "Scenes", + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Select", + "ButtonNew": "New" } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json index a15a128782..113389a11f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json @@ -313,5 +313,9 @@ "ButtonAudioTracks": "\u0414\u044b\u0431\u044b\u0441 \u0436\u043e\u043b\u0448\u044b\u0493\u044b", "ButtonSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440", "ButtonScenes": "\u0421\u0430\u0445\u043d\u0430\u043b\u0430\u0440", - "ButtonQuality": "\u0421\u0430\u043f\u0430" + "ButtonQuality": "\u0421\u0430\u043f\u0430", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "\u0411\u04e9\u043b\u0435\u043a\u0442\u0435\u0443", + "ButtonNew": "\u0416\u0430\u0441\u0430\u0443" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json index 30a6b8e261..3ed0c8735c 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Select", + "ButtonNew": "New" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json index 6f726759dd..c1700fe519 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Select", + "ButtonNew": "New" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json index 3f0d010842..10275847da 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json @@ -20,11 +20,11 @@ "OptionRelease": "Offici\u00eble Release", "OptionBeta": "Beta", "OptionDev": "Dev (Instabiel)", - "UninstallPluginHeader": "Plug-in de\u00efnstalleren", + "UninstallPluginHeader": "Invoegtoepassing de\u00efnstalleren", "UninstallPluginConfirmation": "Weet u zeker dat u {0} wilt de\u00efnstalleren?", - "NoPluginConfigurationMessage": "Deze plug-in heeft niets in te stellen", - "NoPluginsInstalledMessage": "U heeft geen plug-ins ge\u00efnstalleerd", - "BrowsePluginCatalogMessage": "Bekijk de Plug-in catalogus voor beschikbare plug-ins.", + "NoPluginConfigurationMessage": "Deze Invoegtoepassing heeft niets in te stellen", + "NoPluginsInstalledMessage": "U heeft geen Invoegtoepassingen ge\u00efnstalleerd", + "BrowsePluginCatalogMessage": "Bekijk de Invoegtoepassings catalogus voor beschikbare Invoegtoepassingen.", "MessageKeyEmailedTo": "Sleutel gemaild naar {0}.", "MessageKeysLinked": "Sleutels gekoppeld.", "HeaderConfirmation": "Bevestiging", @@ -45,7 +45,7 @@ "HeaderDeleteTaskTrigger": "Verwijderen Taak Trigger", "HeaderTaskTriggers": "Taak Triggers", "MessageDeleteTaskTrigger": "Weet u zeker dat u deze taak trigger wilt verwijderen?", - "MessageNoPluginsInstalled": "U heeft geen plug-ins ge\u00efnstalleerd.", + "MessageNoPluginsInstalled": "U heeft geen Invoegtoepassingen ge\u00efnstalleerd.", "LabelVersionInstalled": "{0} ge\u00efnstalleerd", "LabelNumberReviews": "{0} Recensies", "LabelFree": "Gratis", @@ -305,7 +305,7 @@ "TabDLNA": "DLNA", "TabLiveTV": "Live TV", "TabAutoOrganize": "Automatisch-Organiseren", - "TabPlugins": "Plugins", + "TabPlugins": "Invoegtoepassingen", "TabAdvanced": "Geavanceerd", "TabHelp": "Hulp", "TabScheduledTasks": "Geplande taken", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Ondertitels", "ButtonScenes": "Scenes", - "ButtonQuality": "Kwaliteit" + "ButtonQuality": "Kwaliteit", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Selecteer", + "ButtonNew": "Nieuw" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json index b97935ddeb..3375c1a1d8 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Select", + "ButtonNew": "New" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json index 367e971d8f..aac6a2c05a 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Faixas de \u00c1udio", "ButtonSubtitles": "Legendas", "ButtonScenes": "Cenas", - "ButtonQuality": "Qualidade" + "ButtonQuality": "Qualidade", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Selecionar", + "ButtonNew": "Nova" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json index c7f7c0f69f..eb3740b84c 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Legendas", "ButtonScenes": "Cenas", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "Selecionar", + "ButtonNew": "Novo" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json index a7d6690f04..ea32fb9329 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json @@ -68,7 +68,7 @@ "ButtonPreviousTrack": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430", "LabelEnabled": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u043e", "LabelDisabled": "\u0412\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043e", - "ButtonMoreInformation": "\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f", + "ButtonMoreInformation": "\u0415\u0449\u0451 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f", "LabelNoUnreadNotifications": "\u041d\u0435\u0442 \u043d\u0435\u043f\u0440\u043e\u0447\u0442\u0451\u043d\u043d\u044b\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.", "ButtonViewNotifications": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f", "ButtonMarkTheseRead": "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0430\u043a \u043f\u0440\u043e\u0447\u0442\u0451\u043d\u043d\u044b\u0435", @@ -207,7 +207,7 @@ "MessageErrorPlayingVideo": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u0432\u0438\u0434\u0435\u043e.", "MessageEnsureOpenTuner": "\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0442\u0430\u043c \u043e\u0442\u043a\u0440\u044b\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0442\u044e\u043d\u0435\u0440.", "ButtonHome": "\u0413\u043b\u0430\u0432\u043d\u0430\u044f", - "ButtonDashboard": "\u041f\u0430\u043d\u0435\u043b\u044c \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430", + "ButtonDashboard": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c", "ButtonReports": "\u041e\u0442\u0447\u0451\u0442\u044b", "ButtonMetadataManager": "\u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445", "HeaderTime": "\u0412\u0440\u0435\u043c\u044f", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "\u0410\u0443\u0434\u0438\u043e \u0434\u043e\u0440\u043e\u0436\u043a\u0438", "ButtonSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b", "ButtonScenes": "\u0421\u0446\u0435\u043d\u044b", - "ButtonQuality": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e" + "ButtonQuality": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c", + "ButtonNew": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json index a0ee4fdaf7..421a0dea9a 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Undertexter", "ButtonScenes": "Scener", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "V\u00e4lj", + "ButtonNew": "Nytillkommet" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json index b9b21645b1..0f93d06956 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "Play", "ButtonEdit": "Edit", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "L\u1ef1a ch\u1ecdn", + "ButtonNew": "M\u1edbi" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json index 5408f0b915..fe7d379946 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json @@ -58,14 +58,14 @@ "ButtonMute": "Mute", "ButtonUnmute": "Unmute", "ButtonStop": "Stop", - "ButtonNextTrack": "Next track", + "ButtonNextTrack": "Next Track", "ButtonPause": "Pause", "ButtonPlay": "\u64ad\u653e", "ButtonEdit": "\u7de8\u8f2f", "ButtonQueue": "Queue", "ButtonPlayTrailer": "Play trailer", "ButtonPlaylist": "Playlist", - "ButtonPreviousTrack": "Previous track", + "ButtonPreviousTrack": "Previous Track", "LabelEnabled": "Enabled", "LabelDisabled": "Disabled", "ButtonMoreInformation": "More Information", @@ -313,5 +313,9 @@ "ButtonAudioTracks": "Audio Tracks", "ButtonSubtitles": "Subtitles", "ButtonScenes": "Scenes", - "ButtonQuality": "Quality" + "ButtonQuality": "Quality", + "HeaderNotifications": "Notifications", + "HeaderSelectPlayer": "Select Player:", + "ButtonSelect": "\u9078\u64c7", + "ButtonNew": "\u5275\u5efa" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ar.json b/MediaBrowser.Server.Implementations/Localization/Server/ar.json index 59438e2b5e..df4178c6a4 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ar.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ar.json @@ -190,7 +190,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Continuing", "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "Sunday", "OptionMonday": "Monday", "OptionTuesday": "Tuesday", @@ -198,7 +198,8 @@ "OptionThursday": "Thursday", "OptionFriday": "Friday", "OptionSaturday": "Saturday", - "HeaderManagement": "Management:", + "HeaderManagement": "Management", + "LabelManagement": "Management:", "OptionMissingImdbId": "Missing IMDb Id", "OptionMissingTvdbId": "Missing TheTVDB Id", "OptionMissingOverview": "Missing Overview", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "Select Directory", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ca.json b/MediaBrowser.Server.Implementations/Localization/Server/ca.json index 1de1534e7a..461e56f49e 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ca.json @@ -190,7 +190,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Continuing", "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "Sunday", "OptionMonday": "Monday", "OptionTuesday": "Tuesday", @@ -198,7 +198,8 @@ "OptionThursday": "Thursday", "OptionFriday": "Friday", "OptionSaturday": "Saturday", - "HeaderManagement": "Management:", + "HeaderManagement": "Management", + "LabelManagement": "Management:", "OptionMissingImdbId": "Missing IMDb Id", "OptionMissingTvdbId": "Missing TheTVDB Id", "OptionMissingOverview": "Missing Overview", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "Select Directory", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/cs.json b/MediaBrowser.Server.Implementations/Localization/Server/cs.json index 507045cbbf..d6cdfe0285 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/cs.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/cs.json @@ -199,6 +199,7 @@ "OptionFriday": "P\u00e1tek", "OptionSaturday": "Sobota", "HeaderManagement": "Management:", + "LabelManagement": "Management:", "OptionMissingImdbId": "Chyb\u011bj\u00edc\u00ed IMDb Id", "OptionMissingTvdbId": "Chyb\u011bj\u00edc\u00ed TheTVDB Id", "OptionMissingOverview": "Chyb\u011bj\u00edc\u00ed p\u0159ehled", @@ -479,7 +480,7 @@ "HeaderProgram": "Program", "HeaderClients": "Klienti", "LabelCompleted": "Hotovo", - "LabelFailed": "Chyba", + "LabelFailed": "Failed", "LabelSkipped": "P\u0159esko\u010deno", "HeaderEpisodeOrganization": "Organizace epizod", "LabelSeries": "Series:", @@ -629,8 +630,8 @@ "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Sc\u00e9ny", "ButtonSubtitles": "Titulky", - "ButtonAudioTracks": "Audio stopy", - "ButtonPreviousTrack": "P\u0159edchod\u00ed stopa", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", "ButtonNextTrack": "Next track", "ButtonStop": "Stop", "ButtonPause": "Pause", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/da.json b/MediaBrowser.Server.Implementations/Localization/Server/da.json index 55c296948c..8db9c68f89 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/da.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/da.json @@ -199,6 +199,7 @@ "OptionFriday": "Fredag", "OptionSaturday": "L\u00f8rdag", "HeaderManagement": "Ledelse:", + "LabelManagement": "Management:", "OptionMissingImdbId": "Manglende IMDB Id", "OptionMissingTvdbId": "Manglende TheTVDB Id", "OptionMissingOverview": "Manglende Overblik", @@ -626,10 +627,10 @@ "TabNowPlaying": "Spiler nu", "TabNavigation": "Navigation", "TabControls": "Controls", - "ButtonFullscreen": "Skift til fuldsk\u00e6rm", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Scener", "ButtonSubtitles": "Undertekster", - "ButtonAudioTracks": "Lyd filer", + "ButtonAudioTracks": "Audio tracks", "ButtonPreviousTrack": "Previous track", "ButtonNextTrack": "Next track", "ButtonStop": "Stop", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/de.json b/MediaBrowser.Server.Implementations/Localization/Server/de.json index cfb0924d22..90c4c9e529 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/de.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json @@ -199,6 +199,7 @@ "OptionFriday": "Freitag", "OptionSaturday": "Samstag", "HeaderManagement": "Verwaltung:", + "LabelManagement": "Management:", "OptionMissingImdbId": "Fehlende IMDb Id", "OptionMissingTvdbId": "Fehlende TheTVDB Id", "OptionMissingOverview": "Fehlende \u00dcbersicht", @@ -479,10 +480,10 @@ "HeaderProgram": "Programm", "HeaderClients": "Clients", "LabelCompleted": "Fertiggestellt", - "LabelFailed": "Gescheitert", + "LabelFailed": "Failed", "LabelSkipped": "\u00dcbersprungen", "HeaderEpisodeOrganization": "Episodensortierung", - "LabelSeries": "Serien:", + "LabelSeries": "Series:", "LabelSeasonNumber": "Staffelnummer", "LabelEpisodeNumber": "Episodennummer", "LabelEndingEpisodeNumber": "Ending episode number", @@ -626,12 +627,12 @@ "TabNowPlaying": "Aktuelle Wiedergabe", "TabNavigation": "Navigation", "TabControls": "Controls", - "ButtonFullscreen": "Schalte Vollbild um", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Szenen", "ButtonSubtitles": "Untertitel", - "ButtonAudioTracks": "Audiospuren", - "ButtonPreviousTrack": "Vorheriger Track", - "ButtonNextTrack": "N\u00e4chster Track", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Stop", "ButtonPause": "Pause", "LabelGroupMoviesIntoCollections": "Gruppiere Filme in Collections", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/el.json b/MediaBrowser.Server.Implementations/Localization/Server/el.json index b6c94c512f..b778dc4154 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/el.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/el.json @@ -190,7 +190,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Continuing", "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "Sunday", "OptionMonday": "Monday", "OptionTuesday": "Tuesday", @@ -198,7 +198,8 @@ "OptionThursday": "Thursday", "OptionFriday": "Friday", "OptionSaturday": "Saturday", - "HeaderManagement": "Management:", + "HeaderManagement": "Management", + "LabelManagement": "Management:", "OptionMissingImdbId": "Missing IMDb Id", "OptionMissingTvdbId": "Missing TheTVDB Id", "OptionMissingOverview": "Missing Overview", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "Select Directory", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json index 48a5cc0049..6538111571 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json @@ -190,7 +190,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Continuing", "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "Sunday", "OptionMonday": "Monday", "OptionTuesday": "Tuesday", @@ -198,7 +198,8 @@ "OptionThursday": "Thursday", "OptionFriday": "Friday", "OptionSaturday": "Saturday", - "HeaderManagement": "Management:", + "HeaderManagement": "Management", + "LabelManagement": "Management:", "OptionMissingImdbId": "Missing IMDb Id", "OptionMissingTvdbId": "Missing TheTVDB Id", "OptionMissingOverview": "Missing Overview", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "Select Directory", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json index 16700e356d..f315798ec9 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json @@ -190,7 +190,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Continuing", "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "Sunday", "OptionMonday": "Monday", "OptionTuesday": "Tuesday", @@ -198,7 +198,8 @@ "OptionThursday": "Thursday", "OptionFriday": "Friday", "OptionSaturday": "Saturday", - "HeaderManagement": "Management:", + "HeaderManagement": "Management", + "LabelManagement": "Management:", "OptionMissingImdbId": "Missing IMDb Id", "OptionMissingTvdbId": "Missing TheTVDB Id", "OptionMissingOverview": "Missing Overview", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "Select Directory", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es.json b/MediaBrowser.Server.Implementations/Localization/Server/es.json index 45b3b5c781..18e44a03cf 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es.json @@ -199,6 +199,7 @@ "OptionFriday": "Viernes", "OptionSaturday": "S\u00e1bado", "HeaderManagement": "Administraci\u00f3n", + "LabelManagement": "Management:", "OptionMissingImdbId": "Falta IMDb Id", "OptionMissingTvdbId": "Falta TheTVDB Id", "OptionMissingOverview": "Falta argumento", @@ -479,10 +480,10 @@ "HeaderProgram": "Programa", "HeaderClients": "Clientes", "LabelCompleted": "Completado", - "LabelFailed": "Err\u00f3neo", + "LabelFailed": "Error", "LabelSkipped": "Omitido", "HeaderEpisodeOrganization": "Organizaci\u00f3n de episodios", - "LabelSeries": "Serie:", + "LabelSeries": "Series:", "LabelSeasonNumber": "Temporada n\u00famero:", "LabelEpisodeNumber": "Episodio n\u00famero:", "LabelEndingEpisodeNumber": "N\u00famero episodio final:", @@ -626,10 +627,10 @@ "TabNowPlaying": "Reproduciendo ahora", "TabNavigation": "Navegaci\u00f3n", "TabControls": "Controles", - "ButtonFullscreen": "Pantalla completa", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Escenas", "ButtonSubtitles": "Subt\u00edtulos", - "ButtonAudioTracks": "Pistas de audio", + "ButtonAudioTracks": "Audio tracks", "ButtonPreviousTrack": "Pista anterior", "ButtonNextTrack": "Pista siguiente", "ButtonStop": "Detener", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json index 733e377065..55439632f5 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json @@ -199,6 +199,7 @@ "OptionFriday": "Viernes", "OptionSaturday": "S\u00e1bado", "HeaderManagement": "Administraci\u00f3n:", + "LabelManagement": "Management:", "OptionMissingImdbId": "Falta Id de IMDb", "OptionMissingTvdbId": "Falta Id de TheTVDB", "OptionMissingOverview": "Falta Sinopsis", @@ -626,12 +627,12 @@ "TabNowPlaying": "Reproduci\u00e9ndo Ahora", "TabNavigation": "Navegaci\u00f3n", "TabControls": "Controles", - "ButtonFullscreen": "Alternar pantalla completa", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Escenas", "ButtonSubtitles": "Subt\u00edtulos", - "ButtonAudioTracks": "Pistas de audio", - "ButtonPreviousTrack": "Pista Anterior", - "ButtonNextTrack": "Pista Siguiente", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Pista anterior", + "ButtonNextTrack": "Pista siguiente", "ButtonStop": "Detener", "ButtonPause": "Pausar", "LabelGroupMoviesIntoCollections": "Agrupar pel\u00edculas en colecciones", @@ -868,11 +869,20 @@ "LabelAppName": "Nombre del App", "LabelAppNameExample": "Ejemplo: Sickbeard, NzbDrone", "HeaderNewApiKeyHelp": "Otorgar a la aplicaci\u00f3n persmiso para comunicarse con Media Browser.", - "HeaderHttpHeaders": "Http Headers", - "HeaderIdentificationHeader": "Identification Header", - "LabelValue": "Value:", - "LabelMatchType": "Match type:", - "OptionEquals": "Equals", + "HeaderHttpHeaders": "Encabezados Http", + "HeaderIdentificationHeader": "Encabezado de Identificaci\u00f3n", + "LabelValue": "Valor:", + "LabelMatchType": "Tipo de Coincidencia:", + "OptionEquals": "Igual a", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Subcadena", + "TabView": "Vista", + "TabSort": "Ordenaci\u00f3n", + "TabFilter": "Filtro", + "ButtonView": "Vista", + "LabelPageSize": "Tama\u00f1o de Pantalla:", + "LabelView": "Vista:", + "TabUsers": "Usuarios", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fr.json b/MediaBrowser.Server.Implementations/Localization/Server/fr.json index ccfccea6ae..fc02a9e8ca 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json @@ -199,6 +199,7 @@ "OptionFriday": "Vendredi", "OptionSaturday": "Samedi", "HeaderManagement": "Gestion:", + "LabelManagement": "Management:", "OptionMissingImdbId": "ID IMDb manquant:", "OptionMissingTvdbId": "ID TVDB manquant:", "OptionMissingOverview": "R\u00e9sum\u00e9 manquant", @@ -396,7 +397,7 @@ "HeaderCastCrew": "\u00c9quipe de tournage", "HeaderAdditionalParts": "Parties Additionelles", "ButtonSplitVersionsApart": "S\u00e9parer les versions", - "ButtonPlayTrailer": "Bande-annonce", + "ButtonPlayTrailer": "Trailer", "LabelMissing": "Manquant(s)", "LabelOffline": "Hors ligne", "PathSubstitutionHelp": "Les substitutions de chemins d'acc\u00e8s sont utilis\u00e9es pour faire correspondre un chemin d'acc\u00e8s du serveur \u00e0 un chemin d'acc\u00e8s accessible par les clients. En autorisant un acc\u00e8s direct aux m\u00e9dias du serveur, les clients pourront les lire directement du r\u00e9seau et \u00e9viter l'utilisation inutiles des ressources du serveur en demandant du transcodage.", @@ -479,10 +480,10 @@ "HeaderProgram": "Programme", "HeaderClients": "Clients", "LabelCompleted": "Compl\u00e9t\u00e9", - "LabelFailed": "\u00c9chec", + "LabelFailed": "Failed", "LabelSkipped": "Saut\u00e9", "HeaderEpisodeOrganization": "Organisation d'\u00e9pisodes", - "LabelSeries": "S\u00e9ries:", + "LabelSeries": "Series:", "LabelSeasonNumber": "Num\u00e9ro de saison", "LabelEpisodeNumber": "Num\u00e9ro d'\u00e9pisode", "LabelEndingEpisodeNumber": "Num\u00e9ro d'\u00e9pisode se terminant", @@ -626,12 +627,12 @@ "TabNowPlaying": "En cours de lecture", "TabNavigation": "Navigation", "TabControls": "Contr\u00f4les", - "ButtonFullscreen": "Plein \u00e9cran", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Sc\u00e8nes", "ButtonSubtitles": "Sous-titres", - "ButtonAudioTracks": "Piste audio", - "ButtonPreviousTrack": "Piste pr\u00e9c\u00e9dante", - "ButtonNextTrack": "Piste suivante", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Arr\u00eat", "ButtonPause": "Pause", "LabelGroupMoviesIntoCollections": "Grouper les films en collections", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/he.json b/MediaBrowser.Server.Implementations/Localization/Server/he.json index 473b2523fc..effeb0ad60 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/he.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/he.json @@ -199,6 +199,7 @@ "OptionFriday": "\u05e9\u05d9\u05e9\u05d9", "OptionSaturday": "\u05e9\u05d1\u05ea", "HeaderManagement": "\u05e0\u05d9\u05d4\u05d5\u05dc", + "LabelManagement": "Management:", "OptionMissingImdbId": "\u05d7\u05e1\u05e8 \u05de\u05d6\u05d4\u05d4 IMBb", "OptionMissingTvdbId": "\u05d7\u05e1\u05e8 \u05de\u05d6\u05d4\u05d4 TheTVDB", "OptionMissingOverview": "\u05d7\u05e1\u05e8\u05d4 \u05e1\u05e7\u05d9\u05e8\u05d4", @@ -396,7 +397,7 @@ "HeaderCastCrew": "\u05e9\u05d7\u05e7\u05e0\u05d9\u05dd \u05d5\u05e6\u05d5\u05d5\u05ea", "HeaderAdditionalParts": "\u05d7\u05dc\u05e7\u05d9\u05dd \u05e0\u05d5\u05e1\u05e4\u05d9\u05dd", "ButtonSplitVersionsApart": "\u05e4\u05e6\u05dc \u05d2\u05e8\u05e1\u05d0\u05d5\u05ea \u05d1\u05e0\u05e4\u05e8\u05d3", - "ButtonPlayTrailer": "\u05d8\u05e8\u05d9\u05d9\u05dc\u05e8\u05d9\u05dd", + "ButtonPlayTrailer": "Trailer", "LabelMissing": "\u05d7\u05e1\u05e8", "LabelOffline": "\u05dc\u05d0 \u05de\u05e7\u05d5\u05d5\u05df", "PathSubstitutionHelp": "\u05e0\u05ea\u05d9\u05d1\u05d9\u05dd \u05d7\u05dc\u05d5\u05e4\u05d9\u05d9\u05dd \u05d4\u05dd \u05dc\u05e6\u05d5\u05e8\u05da \u05de\u05d9\u05e4\u05d5\u05d9 \u05e0\u05ea\u05d9\u05d1\u05d9\u05dd \u05d1\u05e9\u05e8\u05ea \u05dc\u05e0\u05ea\u05d9\u05d1\u05d9\u05dd \u05e9\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d9\u05db\u05d5\u05dc\u05d9\u05dd \u05dc\u05d2\u05e9\u05ea \u05d0\u05dc\u05d9\u05d4\u05dd. \u05e2\u05dc \u05d9\u05d3\u05d9 \u05d4\u05e8\u05e9\u05d0\u05d4 \u05dc\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d2\u05d9\u05e9\u05d4 \u05d9\u05e9\u05d9\u05e8\u05d4 \u05dc\u05de\u05d3\u05d9\u05d4 \u05d1\u05e9\u05e8\u05ea \u05d0\u05dd \u05d9\u05db\u05d5\u05dc\u05d9\u05dd \u05dc\u05e0\u05d2\u05df \u05d0\u05ea \u05d4\u05e7\u05d1\u05e6\u05d9\u05dd \u05d9\u05e9\u05d9\u05e8\u05d5\u05ea \u05e2\u05dc \u05d2\u05d1\u05d9 \u05d4\u05e8\u05e9\u05ea \u05d5\u05dc\u05d4\u05d9\u05de\u05e0\u05e2 \u05de\u05e9\u05d9\u05de\u05d5\u05e9 \u05d1\u05de\u05e9\u05d0\u05d1\u05d9 \u05d4\u05e9\u05e8\u05ea \u05dc\u05e6\u05d5\u05e8\u05da \u05e7\u05d9\u05d3\u05d5\u05d3 \u05d5\u05e9\u05d9\u05d3\u05d5\u05e8.", @@ -479,10 +480,10 @@ "HeaderProgram": "\u05ea\u05d5\u05db\u05e0\u05d4", "HeaderClients": "\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd", "LabelCompleted": "\u05d4\u05d5\u05e9\u05dc\u05dd", - "LabelFailed": "\u05e0\u05db\u05e9\u05dc", + "LabelFailed": "Failed", "LabelSkipped": "\u05d3\u05d5\u05dc\u05d2", "HeaderEpisodeOrganization": "\u05d0\u05d9\u05e8\u05d2\u05d5\u05df \u05e4\u05e8\u05e7\u05d9\u05dd", - "LabelSeries": "\u05e1\u05d3\u05e8\u05d4:", + "LabelSeries": "Series:", "LabelSeasonNumber": "\u05de\u05e1\u05e4\u05e8 \u05e2\u05d5\u05e0\u05d4:", "LabelEpisodeNumber": "\u05de\u05e1\u05e4\u05e8 \u05e4\u05e8\u05e7:", "LabelEndingEpisodeNumber": "\u05de\u05e1\u05e4\u05e8 \u05e1\u05d9\u05d5\u05dd \u05e4\u05e8\u05e7:", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/it.json b/MediaBrowser.Server.Implementations/Localization/Server/it.json index 77d265bd48..2757333f1c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/it.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/it.json @@ -5,9 +5,9 @@ "LabelSwagger": "Swagger", "LabelStandard": "Standard", "LabelViewApiDocumentation": "Documentazione Api", - "LabelBrowseLibrary": "Apri Media Browser", + "LabelBrowseLibrary": "Esplora la libreria", "LabelConfigureMediaBrowser": "Configura Media Browser", - "LabelOpenLibraryViewer": "Esplora la Libreria", + "LabelOpenLibraryViewer": "Apri visualizzatore libreria", "LabelRestartServer": "Riavvia Server", "LabelShowLogWindow": "Mostra Finestra log", "LabelPrevious": "Precedente", @@ -199,6 +199,7 @@ "OptionFriday": "Venerdi", "OptionSaturday": "Sabato", "HeaderManagement": "Gestione:", + "LabelManagement": "Management:", "OptionMissingImdbId": "IMDB id mancante", "OptionMissingTvdbId": "TheTVDB Id mancante", "OptionMissingOverview": "Trama mancante", @@ -479,10 +480,10 @@ "HeaderProgram": "Programma", "HeaderClients": "Dispositivi", "LabelCompleted": "Completato", - "LabelFailed": "Fallito", + "LabelFailed": "Failed", "LabelSkipped": "Saltato", "HeaderEpisodeOrganization": "Organizzazione Episodi", - "LabelSeries": "Serie:", + "LabelSeries": "Series:", "LabelSeasonNumber": "Numero Stagione:", "LabelEpisodeNumber": "Numero Episodio:", "LabelEndingEpisodeNumber": "Ultimo Episodio Numero:", @@ -626,12 +627,12 @@ "TabNowPlaying": "In esecuzione", "TabNavigation": "Navigazione", "TabControls": "Controlli", - "ButtonFullscreen": "Schermo intero", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Scene", "ButtonSubtitles": "Sottotitoli", - "ButtonAudioTracks": "Traccia Audio", - "ButtonPreviousTrack": "Precedente", - "ButtonNextTrack": "Prossimo", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Stop", "ButtonPause": "Pausa", "LabelGroupMoviesIntoCollections": "Raggruppa i film nelle collection", @@ -846,33 +847,42 @@ "LabelLoginDisclaimerHelp": "Questo verr\u00e0 visualizzato nella parte inferiore della pagina di accesso.", "LabelAutomaticallyDonate": "Donare automaticamente questo importo ogni mese", "LabelAutomaticallyDonateHelp": "\u00c8 possibile annullare in qualsiasi momento tramite il vostro conto PayPal.", - "OptionList": "List", - "TabDashboard": "Dashboard", + "OptionList": "Lista", + "TabDashboard": "Pannello Controllo", "TitleServer": "Server", "LabelCache": "Cache:", - "LabelLogs": "Logs:", + "LabelLogs": "Log:", "LabelMetadata": "Metadata:", - "LabelImagesByName": "Images by name:", - "LabelTranscodingTemporaryFiles": "Transcoding temporary files:", - "HeaderLatestMusic": "Latest Music", + "LabelImagesByName": "Immagini per nome:", + "LabelTranscodingTemporaryFiles": "transcodifica file temporanei:", + "HeaderLatestMusic": "Musica Recente", "HeaderBranding": "Branding", - "HeaderApiKeys": "Api Keys", - "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.", - "HeaderApiKey": "Api Key", + "HeaderApiKeys": "Chiavi Api", + "HeaderApiKeysHelp": "Le applicazioni estrene richiedono una chiave Api per comunicare con Media Browser. Le chiavi sono create attraverso il log-in con un account Media Browse, o manualmente rilasciando una chiave all'applicazione.", + "HeaderApiKey": "Chiave Api", "HeaderApp": "App", - "HeaderDevice": "Device", - "HeaderUser": "User", - "HeaderDateIssued": "Date Issued", + "HeaderDevice": "Dispositivo", + "HeaderUser": "Utente", + "HeaderDateIssued": "data di pubblicazione", "LabelChapterName": "Chapter {0}", - "HeaderNewApiKey": "New Api Key", - "LabelAppName": "App name", + "HeaderNewApiKey": "Nessuna Chiave Api", + "LabelAppName": "Nome app", "LabelAppNameExample": "Example: Sickbeard, NzbDrone", - "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.", + "HeaderNewApiKeyHelp": "Garantisci all'applicazione il permesso di comunicare con Media Browser.", "HeaderHttpHeaders": "Http Headers", "HeaderIdentificationHeader": "Identification Header", "LabelValue": "Value:", "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/kk.json b/MediaBrowser.Server.Implementations/Localization/Server/kk.json index caee463517..b588e6c11b 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/kk.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/kk.json @@ -199,6 +199,7 @@ "OptionFriday": "\u0436\u04b1\u043c\u0430", "OptionSaturday": "\u0441\u0435\u043d\u0431\u0456", "HeaderManagement": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a:", + "LabelManagement": "Management:", "OptionMissingImdbId": "IMDb Id \u0436\u043e\u049b", "OptionMissingTvdbId": "TheTVDB Id \u0436\u043e\u049b", "OptionMissingOverview": "\u0416\u0430\u043b\u043f\u044b \u0448\u043e\u043b\u0443 \u0436\u043e\u049b", @@ -626,10 +627,10 @@ "TabNowPlaying": "\u041e\u0439\u043d\u0430\u0442\u044b\u043b\u0443\u0434\u0430", "TabNavigation": "\u0428\u0430\u0440\u043b\u0430\u0443", "TabControls": "\u0411\u0430\u0441\u049b\u0430\u0440\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0456", - "ButtonFullscreen": "\u0422\u043e\u043b\u044b\u049b \u044d\u043a\u0440\u0430\u043d", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "\u0421\u0430\u0445\u043d\u0430\u043b\u0430\u0440", "ButtonSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440", - "ButtonAudioTracks": "\u0414\u044b\u0431\u044b\u0441 \u0436\u043e\u043b\u0448\u044b\u049b\u0442\u0430\u0440\u044b", + "ButtonAudioTracks": "Audio tracks", "ButtonPreviousTrack": "\u0410\u043b\u0434\u044b\u04a3\u0493\u044b \u0436\u043e\u043b\u0448\u044b\u049b", "ButtonNextTrack": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0436\u043e\u043b\u0448\u044b\u049b", "ButtonStop": "\u0422\u043e\u049b\u0442\u0430\u0442\u0443", @@ -874,5 +875,14 @@ "LabelMatchType": "\u0421\u04d9\u0439\u043a\u0435\u0441 \u0442\u04af\u0440\u0456:", "OptionEquals": "\u0422\u0435\u04a3", "OptionRegex": "\u04b0\u0434\u0430\u0439\u044b \u04e9\u0440\u043d\u0435\u043a", - "OptionSubstring": "\u0406\u0448\u043a\u0456 \u0436\u043e\u043b" + "OptionSubstring": "\u0406\u0448\u043a\u0456 \u0436\u043e\u043b", + "TabView": "\u041a\u04e9\u0440\u0456\u043d\u0456\u0441", + "TabSort": "\u0421\u04b1\u0440\u044b\u043f\u0442\u0430\u0443", + "TabFilter": "\u0421\u04af\u0437\u0443", + "ButtonView": "\u049a\u0430\u0440\u0430\u0443", + "LabelPageSize": "\u042d\u043a\u0440\u0430\u043d \u04e9\u043b\u0448\u0435\u043c\u0456:", + "LabelView": "\u041a\u04e9\u0440\u0456\u043d\u0456\u0441:", + "TabUsers": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ko.json b/MediaBrowser.Server.Implementations/Localization/Server/ko.json index 18cc943e16..e1a405972a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ko.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ko.json @@ -190,7 +190,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Continuing", "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "Sunday", "OptionMonday": "Monday", "OptionTuesday": "Tuesday", @@ -198,7 +198,8 @@ "OptionThursday": "Thursday", "OptionFriday": "Friday", "OptionSaturday": "Saturday", - "HeaderManagement": "Management:", + "HeaderManagement": "Management", + "LabelManagement": "Management:", "OptionMissingImdbId": "Missing IMDb Id", "OptionMissingTvdbId": "Missing TheTVDB Id", "OptionMissingOverview": "Missing Overview", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "Select Directory", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ms.json b/MediaBrowser.Server.Implementations/Localization/Server/ms.json index f90a350182..515cd70a2d 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ms.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ms.json @@ -190,7 +190,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Continuing", "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "Sunday", "OptionMonday": "Monday", "OptionTuesday": "Tuesday", @@ -198,7 +198,8 @@ "OptionThursday": "Thursday", "OptionFriday": "Friday", "OptionSaturday": "Saturday", - "HeaderManagement": "Management:", + "HeaderManagement": "Management", + "LabelManagement": "Management:", "OptionMissingImdbId": "Missing IMDb Id", "OptionMissingTvdbId": "Missing TheTVDB Id", "OptionMissingOverview": "Missing Overview", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "Select Directory", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nb.json b/MediaBrowser.Server.Implementations/Localization/Server/nb.json index 94927eb12e..c2afde015a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/nb.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/nb.json @@ -190,7 +190,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Fortsetter", "OptionEnded": "Avsluttet", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "S\u00f8ndag", "OptionMonday": "Mandag", "OptionTuesday": "Tirsdag", @@ -198,7 +198,8 @@ "OptionThursday": "Torsdag", "OptionFriday": "Fredag", "OptionSaturday": "L\u00f8rdag", - "HeaderManagement": "Management:", + "HeaderManagement": "Management", + "LabelManagement": "Management:", "OptionMissingImdbId": "Mangler IMDb id", "OptionMissingTvdbId": "Missing TheTVDB Id", "OptionMissingOverview": "Mangler oversikt", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "Select Directory", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nl.json b/MediaBrowser.Server.Implementations/Localization/Server/nl.json index 7f1545c2bb..4e01acfa1d 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json @@ -39,7 +39,7 @@ "HeaderSetupLibrary": "Stel uw mediabibliotheek in", "ButtonAddMediaFolder": "Mediamap toevoegen", "LabelFolderType": "Maptype:", - "MediaFolderHelpPluginRequired": "* Hiervoor is het gebruik van een plug-in vereist, bijvoorbeeld GameBrowser of MB Bookshelf.", + "MediaFolderHelpPluginRequired": "* Hiervoor is het gebruik van een Invoegtoepassing vereist, bijvoorbeeld GameBrowser of MB Bookshelf.", "ReferToMediaLibraryWiki": "Raadpleeg de mediabibliotheek wiki.", "LabelCountry": "Land:", "LabelLanguage": "Taal:", @@ -152,9 +152,9 @@ "OptionResumable": "Hervatbaar", "ScheduledTasksHelp": "Klik op een taak om het schema aan te passen.", "ScheduledTasksTitle": "Geplande taken", - "TabMyPlugins": "Mijn Plug-ins", + "TabMyPlugins": "Mijn Invoegtoepassingen", "TabCatalog": "Catalogus", - "PluginsTitle": "Plug-ins", + "PluginsTitle": "Invoegtoepassingen", "HeaderAutomaticUpdates": "Automatische updates", "HeaderNowPlaying": "Wordt nu afgespeeld", "HeaderLatestAlbums": "Nieuwste Albums", @@ -199,6 +199,7 @@ "OptionFriday": "Vrijdag", "OptionSaturday": "Zaterdag", "HeaderManagement": "Beheer:", + "LabelManagement": "Management:", "OptionMissingImdbId": "IMDb Id ontbreekt", "OptionMissingTvdbId": "TheTVDB Id ontbreekt", "OptionMissingOverview": "Overzicht ontbreekt", @@ -284,7 +285,7 @@ "ButtonAutoScroll": "Auto-scroll", "LabelImageSavingConvention": "Afbeelding opslag conventie:", "LabelImageSavingConventionHelp": "Media Browser herkent afbeeldingen van de meeste grote media-applicaties. Het kiezen van uw download conventie is handig als u ook gebruik wilt maken van andere producten.", - "OptionImageSavingCompatible": "Compatibel - Media Browser \/ Plex \/ XBMC", + "OptionImageSavingCompatible": "Compatibel - Media Browser \/ XBMC \/ Plex", "OptionImageSavingStandard": "Standaard - MB2", "ButtonSignIn": "Aanmelden", "TitleSignIn": "Aanmelden", @@ -332,10 +333,10 @@ "LabelNumberOfGuideDays": "Aantal dagen van de gids om te downloaden:", "LabelNumberOfGuideDaysHelp": "Het downloaden van meer dagen van de gids gegevens biedt de mogelijkheid verder vooruit te plannen en een beter overzicht geven, maar het zal ook langer duren om te downloaden. Auto kiest op basis van het aantal kanalen.", "LabelActiveService": "Actieve Service:", - "LabelActiveServiceHelp": "Er kunnen meerdere tv plug-ins worden ge\u00efnstalleerd, maar er kan er slechts een per keer actief zijn.", + "LabelActiveServiceHelp": "Er kunnen meerdere tv Invoegtoepassingen worden ge\u00efnstalleerd, maar er kan er slechts een per keer actief zijn.", "OptionAutomatic": "Automatisch", - "LiveTvPluginRequired": "Een Live TV service provider plug-in is vereist om door te gaan.", - "LiveTvPluginRequiredHelp": "Installeer a.u b een van onze beschikbare plug-ins, zoals Next PVR of ServerWmc.", + "LiveTvPluginRequired": "Een Live TV service provider Invoegtoepassing is vereist om door te gaan.", + "LiveTvPluginRequiredHelp": "Installeer a.u b een van onze beschikbare Invoegtoepassingen, zoals Next PVR of ServerWmc.", "LabelCustomizeOptionsPerMediaType": "Aanpassen voor mediatype", "OptionDownloadThumbImage": "Miniatuur", "OptionDownloadMenuImage": "Menu", @@ -576,9 +577,9 @@ "HeaderNotificationList": "Klik op een melding om de opties voor het versturen ervan te configureren .", "NotificationOptionApplicationUpdateAvailable": "Programma-update beschikbaar", "NotificationOptionApplicationUpdateInstalled": "Programma-update ge\u00efnstalleerd", - "NotificationOptionPluginUpdateInstalled": "Plugin-update ge\u00efnstalleerd", - "NotificationOptionPluginInstalled": "Plugin ge\u00efnstalleerd", - "NotificationOptionPluginUninstalled": "Plugin verwijderd", + "NotificationOptionPluginUpdateInstalled": "Invoegtoepassings-update ge\u00efnstalleerd", + "NotificationOptionPluginInstalled": "Invoegtoepassing ge\u00efnstalleerd", + "NotificationOptionPluginUninstalled": "Invoegtoepassing verwijderd", "NotificationOptionVideoPlayback": "Video afspelen gestart", "NotificationOptionAudioPlayback": "Audio afspelen gestart", "NotificationOptionGamePlayback": "Game gestart", @@ -589,7 +590,7 @@ "NotificationOptionInstallationFailed": "Mislukken van de installatie", "NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd", "NotificationOptionNewLibraryContentMultiple": "Nieuwe content toegevoegd (meerdere)", - "SendNotificationHelp": "Meldingen worden geplaatst in de inbox op het dashboard. Blader door de Plug-ins catalogus om aanvullende opties voor meldingen te installeren.", + "SendNotificationHelp": "Meldingen worden geplaatst in de inbox op het dashboard. Blader door de Invoegtoepassings catalogus om aanvullende opties voor meldingen te installeren.", "NotificationOptionServerRestartRequired": "Server herstart nodig", "LabelNotificationEnabled": "Deze melding inschakelen", "LabelMonitorUsers": "Monitor activiteit van:", @@ -599,10 +600,10 @@ "CategoryUser": "Gebruiker", "CategorySystem": "Systeem", "CategoryApplication": "Toepassing", - "CategoryPlugin": "Plug-in", + "CategoryPlugin": "Invoegtoepassing", "LabelMessageTitle": "Titel van het bericht:", "LabelAvailableTokens": "Beschikbaar tokens:", - "AdditionalNotificationServices": "Blader door de plug-in catalogus om aanvullende meldingsdiensten te installeren.", + "AdditionalNotificationServices": "Blader door de Invoegtoepassings catalogus om aanvullende meldingsdiensten te installeren.", "OptionAllUsers": "Alle gebruikers", "OptionAdminUsers": "Beheerders", "OptionCustomUsers": "Aangepast", @@ -626,17 +627,17 @@ "TabNowPlaying": "Wordt nu afgespeeld", "TabNavigation": "Navigatie", "TabControls": "Besturing", - "ButtonFullscreen": "Volledig scherm in-\/uitschakelen", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Scenes", "ButtonSubtitles": "Ondertitels", "ButtonAudioTracks": "Audio tracks", - "ButtonPreviousTrack": "Vorig nummer", - "ButtonNextTrack": "Volgend nummer", + "ButtonPreviousTrack": "Vorige track", + "ButtonNextTrack": "Volgende track", "ButtonStop": "Stop", "ButtonPause": "Pauze", "LabelGroupMoviesIntoCollections": "Groepeer films in verzamelingen", "LabelGroupMoviesIntoCollectionsHelp": "Bij de weergave van film lijsten, zullen films die behoren tot een verzameling worden weergegeven als een gegroepeerd object.", - "NotificationOptionPluginError": "Plug-in fout", + "NotificationOptionPluginError": "Invoegtoepassings fout", "ButtonVolumeUp": "Volume omhoog", "ButtonVolumeDown": "Volume omlaag", "ButtonMute": "Dempen", @@ -722,7 +723,7 @@ "OptionReportByteRangeSeekingWhenTranscodingHelp": "Dit is vereist voor bepaalde apparaten die zo goed op tijd zoeken.", "HeaderSubtitleDownloadingHelp": "Bij het scannen van uw videobestanden kan Media Browser naar ontbrekende ondertiteling zoeken en deze downloaden bij ondertiteling providers zoals OpenSubtitles.org.", "HeaderDownloadSubtitlesFor": "Download ondertiteling voor:", - "MessageNoChapterProviders": "Installeer een hoofdstuk provider plug-in zoals ChapterDb of tagChimp om extra hoofdstuk opties in te schakelen.", + "MessageNoChapterProviders": "Installeer een hoofdstuk provider Invoegtoepassing zoals ChapterDb om extra hoofdstuk opties in te schakelen.", "LabelSkipIfGraphicalSubsPresent": "Overslaan als de video al grafische ondertitels bevat", "LabelSkipIfGraphicalSubsPresentHelp": "Tekstversies houden van ondertitels zal resulteren in meer effici\u00ebnte levering aan mobiele clients.", "TabSubtitles": "Ondertiteling", @@ -730,7 +731,7 @@ "HeaderDownloadChaptersFor": "Download hoofdstuk namen voor:", "LabelOpenSubtitlesUsername": "Gebruikersnaam Open Subtitles:", "LabelOpenSubtitlesPassword": "Wachtwoord Open Subtitles:", - "HeaderChapterDownloadingHelp": "Wanneer Media Browser uw videobestanden scant kan het gebruiksvriendelijke namen voor hoofdstukken downloaden van het internet met behulp van hoofdstuk plug-ins zoals ChapterDb en tagChimp.", + "HeaderChapterDownloadingHelp": "Wanneer Media Browser uw videobestanden scant kan het gebruiksvriendelijke namen voor hoofdstukken downloaden van het internet met behulp van hoofdstuk Invoegtoepassing zoals ChapterDb.", "LabelPlayDefaultAudioTrack": "Speel standaard audio spoor ongeacht taal", "LabelSubtitlePlaybackMode": "Ondertitelingsmode:", "LabelDownloadLanguages": "Download talen:", @@ -740,8 +741,8 @@ "HeaderSendMessage": "Stuur bericht", "ButtonSend": "Stuur", "LabelMessageText": "Bericht tekst:", - "MessageNoAvailablePlugins": "Geen beschikbare plugins.", - "LabelDisplayPluginsFor": "Toon plugins voor:", + "MessageNoAvailablePlugins": "Geen beschikbare Invoegtoepassingen.", + "LabelDisplayPluginsFor": "Toon Invoegtoepassingen voor:", "PluginTabMediaBrowserClassic": "MB Classic", "PluginTabMediaBrowserTheater": "MB Theater", "LabelEpisodeName": "Naam aflevering", @@ -802,7 +803,7 @@ "LabelChannelDownloadPathHelp": "Geef een eigen download pad op als dit gewenst is, leeglaten voor dowloaden naar de interne program data map.", "LabelChannelDownloadAge": "Verwijder inhoud na: (dagen)", "LabelChannelDownloadAgeHelp": "Gedownloade inhoud die ouder is zal worden verwijderd. Afspelen via internet streaming blijft mogelijk.", - "ChannelSettingsFormHelp": "Installeer kanalen zoals Trailers en Vimeo in de plug-in catalogus.", + "ChannelSettingsFormHelp": "Installeer kanalen zoals Trailers en Vimeo in de Invoegtoepassings catalogus.", "LabelSelectCollection": "Selecteer verzameling:", "ViewTypeMovies": "Films", "ViewTypeTvShows": "TV", @@ -844,7 +845,7 @@ "HeaderBrandingHelp": "Pas het uiterlijk van Media Browser aan, aan de behoeften van uw groep of organisatie.", "LabelLoginDisclaimer": "Aanmeld vrijwaring:", "LabelLoginDisclaimerHelp": "Dit wordt onderaan de login pagina weergegeven.", - "LabelAutomaticallyDonate": "Doneer dit bedrag automatisch per maand", + "LabelAutomaticallyDonate": "Doneer dit bedrag automatisch elke zes maanden", "LabelAutomaticallyDonateHelp": "U kunt dit via uw PayPal account op elk moment annuleren.", "OptionList": "Lijst", "TabDashboard": "Dashboard", @@ -874,5 +875,14 @@ "LabelMatchType": "Type overeenkomst:", "OptionEquals": "Is gelijk aan", "OptionRegex": "Regex", - "OptionSubstring": "Subtekenreeks" + "OptionSubstring": "Subtekenreeks", + "TabView": "Weergave", + "TabSort": "Sorteren", + "TabFilter": "Filter", + "ButtonView": "Weergave", + "LabelPageSize": "Schermgrootte:", + "LabelView": "Weergave:", + "TabUsers": "Gebruikers", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pl.json b/MediaBrowser.Server.Implementations/Localization/Server/pl.json index 43444b6890..b5b610654d 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pl.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pl.json @@ -190,7 +190,7 @@ "HeaderStatus": "Status", "OptionContinuing": "Continuing", "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "Niedziela", "OptionMonday": "Poniedzia\u0142ek", "OptionTuesday": "Wtorek", @@ -198,7 +198,8 @@ "OptionThursday": "Czwartek", "OptionFriday": "Pi\u0105tek", "OptionSaturday": "Sobota", - "HeaderManagement": "Management:", + "HeaderManagement": "Management", + "LabelManagement": "Management:", "OptionMissingImdbId": "Brakuje Id IMDb", "OptionMissingTvdbId": "Brakuje Id TheTVDB", "OptionMissingOverview": "Missing Overview", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "Wybierz folder", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json index e60c7b3c3c..b635d73184 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json @@ -199,6 +199,7 @@ "OptionFriday": "Sexta-feira", "OptionSaturday": "S\u00e1bado", "HeaderManagement": "Gerenciamento:", + "LabelManagement": "Management:", "OptionMissingImdbId": "Faltando Id IMDb", "OptionMissingTvdbId": "Faltando Id TheTVDB", "OptionMissingOverview": "Faltando Sinopse", @@ -626,12 +627,12 @@ "TabNowPlaying": "Reproduzindo Agora", "TabNavigation": "Navega\u00e7\u00e3o", "TabControls": "Controles", - "ButtonFullscreen": "Alternar tela cheia", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Cenas", "ButtonSubtitles": "Legendas", - "ButtonAudioTracks": "Faixas de \u00e1udio", - "ButtonPreviousTrack": "Faixa Anterior", - "ButtonNextTrack": "Pr\u00f3xima Faixa", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Faixa anterior", + "ButtonNextTrack": "Pr\u00f3xima faixa", "ButtonStop": "Parar", "ButtonPause": "Pausar", "LabelGroupMoviesIntoCollections": "Agrupar filmes nas cole\u00e7\u00f5es", @@ -874,5 +875,14 @@ "LabelMatchType": "Tipo de correspond\u00eancia", "OptionEquals": "Igual", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "Visualizar", + "TabSort": "Ordenar", + "TabFilter": "Filtro", + "ButtonView": "Visualizar", + "LabelPageSize": "Tamanho de exibi\u00e7\u00e3o:", + "LabelView": "Visualizar:", + "TabUsers": "Usu\u00e1rios", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json index c53ecd9d8e..12850f803d 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json @@ -199,6 +199,7 @@ "OptionFriday": "Sexta", "OptionSaturday": "S\u00e1bado", "HeaderManagement": "Gest\u00e3o:", + "LabelManagement": "Management:", "OptionMissingImdbId": "Id do IMDb em falta", "OptionMissingTvdbId": "iD do TheTVDB em falta", "OptionMissingOverview": "Descri\u00e7\u00e3o em falta", @@ -479,10 +480,10 @@ "HeaderProgram": "Programa", "HeaderClients": "Clientes", "LabelCompleted": "Terminado", - "LabelFailed": "Falhou", + "LabelFailed": "Failed", "LabelSkipped": "Ignorado", "HeaderEpisodeOrganization": "Organiza\u00e7\u00e3o dos Epis\u00f3dios", - "LabelSeries": "S\u00e9rie:", + "LabelSeries": "Series:", "LabelSeasonNumber": "N\u00famero da temporada", "LabelEpisodeNumber": "N\u00famero do epis\u00f3dio", "LabelEndingEpisodeNumber": "N\u00famero do epis\u00f3dio final", @@ -629,9 +630,9 @@ "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Cenas", "ButtonSubtitles": "Legendas", - "ButtonAudioTracks": "Faixas de \u00e1udio", - "ButtonPreviousTrack": "Faixa Anterior", - "ButtonNextTrack": "Pr\u00f3xima Faixa", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Parar", "ButtonPause": "Pausar", "LabelGroupMoviesIntoCollections": "Group movies into collections", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ru.json b/MediaBrowser.Server.Implementations/Localization/Server/ru.json index 7d9e83cbc7..fcf3756ab0 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json @@ -19,13 +19,13 @@ "ThisWizardWillGuideYou": "\u042d\u0442\u043e\u0442 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043f\u043e \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043f\u0440\u043e\u0432\u0435\u0434\u0451\u0442 \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0435 \u0444\u0430\u0437\u044b \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430. \u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u044f\u0437\u044b\u043a.", "TellUsAboutYourself": "\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0438\u0442\u0435 \u043e \u0441\u0435\u0431\u0435", "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 \u041f\u0430\u043d\u0435\u043b\u044c \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430.", + "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 \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c.", "UserProfilesIntro": "\u0412 Media Browser \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0438\u043c\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438 \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\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c.", "LabelWindowsService": "\u0421\u043b\u0443\u0436\u0431\u0430 Windows", "AWindowsServiceHasBeenInstalled": "\u0421\u043b\u0443\u0436\u0431\u0430 Windows \u0431\u044b\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430.", "WindowsServiceIntro1": "\u041e\u0431\u044b\u0447\u043d\u043e Media Browser Server \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e \u0437\u043d\u0430\u0447\u043a\u043e\u043c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043b\u043e\u0442\u043a\u0435, \u043d\u043e \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0432 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435, \u0432\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0435\u0433\u043e \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043b\u0443\u0436\u0431\u0430\u043c\u0438 Windows.", "WindowsServiceIntro2": "\u041a\u043e\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u043b\u0443\u0436\u0431\u0430 Windows, \u043f\u0440\u0438\u043c\u0438\u0442\u0435 \u043a \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044e, \u0447\u0442\u043e \u043e\u043d\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441\u043e \u0437\u043d\u0430\u0447\u043a\u043e\u043c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043b\u043e\u0442\u043a\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, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043b\u0443\u0436\u0431\u0443. \u0421\u043b\u0443\u0436\u0431\u0443 \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043e\u0431\u043b\u0430\u0434\u0430\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0430\u043c\u0438, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043b\u0443\u0436\u0431\u0435 \u043d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u0430\u043c\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u0430\u0448\u0435 \u0432\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e.", - "WizardCompleted": "\u042d\u0442\u043e \u0432\u0441\u0451, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. Media Browser \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u0431\u043e\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435. \u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0438 \u0442\u043e\u0433\u0434\u0430 \u0449\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c<\/b>, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u041f\u0430\u043d\u0435\u043b\u044c \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430<\/b>.", + "WizardCompleted": "\u042d\u0442\u043e \u0432\u0441\u0451, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. Media Browser \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u0431\u043e\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435. \u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0438 \u0442\u043e\u0433\u0434\u0430 \u0449\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c<\/b>, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c<\/b>.", "LabelConfigureSettings": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432", "LabelEnableVideoImageExtraction": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0430 \u0438\u0437 \u0432\u0438\u0434\u0435\u043e", "VideoImageExtractionHelp": "\u0414\u043b\u044f \u0432\u0438\u0434\u0435\u043e, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0449\u0451 \u200b\u200b\u043d\u0435 \u0438\u043c\u0435\u044e\u0442 \u043e\u0431\u043b\u043e\u0436\u043a\u0438, \u0438 \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u0442\u0430\u043a\u043e\u0432\u044b\u0445. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438 \u043f\u0440\u043e\u0434\u043b\u0438\u0442\u0441\u044f \u0435\u0449\u0451 \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u043d\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0441\u0442\u0430\u043d\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u044f\u0442\u043d\u043e\u0435 \u0434\u043b\u044f \u0433\u043b\u0430\u0437 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.", @@ -199,6 +199,7 @@ "OptionFriday": "\u043f\u044f\u0442\u043d\u0438\u0446\u0430", "OptionSaturday": "\u0441\u0443\u0431\u0431\u043e\u0442\u0430", "HeaderManagement": "\u0414\u043b\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:", + "LabelManagement": "Management:", "OptionMissingImdbId": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d IMDb Id", "OptionMissingTvdbId": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d TheTVDB Id", "OptionMissingOverview": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043e \u043e\u0431\u043e\u0437\u0440\u0435\u043d\u0438\u0435", @@ -437,9 +438,9 @@ "HeaderSystemDlnaProfiles": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438", "CustomDlnaProfilesHelp": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c.", "SystemDlnaProfilesHelp": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u0432 \u043d\u043e\u0432\u043e\u043c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435.", - "TitleDashboard": "\u041f\u0430\u043d\u0435\u043b\u044c \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430", + "TitleDashboard": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c", "TabHome": "\u0413\u043b\u0430\u0432\u043d\u0430\u044f", - "TabInfo": "\u0418\u043d\u0444\u043e", + "TabInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f", "HeaderLinks": "\u0421\u0441\u044b\u043b\u043a\u0438", "HeaderSystemPaths": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0443\u0442\u0438", "LinkCommunity": "\u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e", @@ -479,7 +480,7 @@ "HeaderProgram": "\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430", "HeaderClients": "\u041a\u043b\u0438\u0435\u043d\u0442\u044b", "LabelCompleted": "\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e", - "LabelFailed": "\u041d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e", + "LabelFailed": "\u041d\u0435\u0443\u0434\u0430\u0447\u0430", "LabelSkipped": "\u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043e", "HeaderEpisodeOrganization": "\u0420\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043f\u0438\u0437\u043e\u0434\u0430", "LabelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b:", @@ -589,7 +590,7 @@ "NotificationOptionInstallationFailed": "\u0421\u0431\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438", "NotificationOptionNewLibraryContent": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e", "NotificationOptionNewLibraryContentMultiple": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e (\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e)", - "SendNotificationHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u044f\u0449\u0438\u043a \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u0430\u043d\u0435\u043b\u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430. \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 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.", + "SendNotificationHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u044f\u0449\u0438\u043a \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u0438. \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 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.", "NotificationOptionServerRestartRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430", "LabelNotificationEnabled": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435", "LabelMonitorUsers": "\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043e\u0442:", @@ -626,10 +627,10 @@ "TabNowPlaying": "\u041f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f", "TabNavigation": "\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f", "TabControls": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f", - "ButtonFullscreen": "\u041f\u043e\u043b\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "\u0421\u0446\u0435\u043d\u044b", "ButtonSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b", - "ButtonAudioTracks": "\u0410\u0443\u0434\u0438\u043e\u0434\u043e\u0440\u043e\u0436\u043a\u0438", + "ButtonAudioTracks": "Audio tracks", "ButtonPreviousTrack": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430", "ButtonNextTrack": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430", "ButtonStop": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c", @@ -673,7 +674,7 @@ "TabContainers": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b", "TabCodecs": "\u041a\u043e\u0434\u0435\u043a\u0438", "TabResponses": "\u041e\u0442\u043a\u043b\u0438\u043a\u0438", - "HeaderProfileInformation": "\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0435", + "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 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u0430\u043b\u044c\u0431\u043e\u043c\u0430 \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 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0439 \u0430\u043b\u044c\u0431\u043e\u043c\u043e\u0432 \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.", "LabelAlbumArtPN": "PN \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0430\u043b\u044c\u0431\u043e\u043c\u0430", @@ -847,7 +848,7 @@ "LabelAutomaticallyDonate": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u0430\u0440\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0443\u043c\u043c\u0443 \u043a\u0430\u0436\u0434\u044b\u0435 \u0448\u0435\u0441\u0442\u044c \u043c\u0435\u0441\u044f\u0446\u0435\u0432", "LabelAutomaticallyDonateHelp": "\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u044e \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c PayPal.", "OptionList": "\u0421\u043f\u0438\u0441\u043e\u043a", - "TabDashboard": "\u041f\u0430\u043d\u0435\u043b\u044c \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430", + "TabDashboard": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c", "TitleServer": "\u0421\u0435\u0440\u0432\u0435\u0440", "LabelCache": "Cache:", "LabelLogs": "Logs:", @@ -867,12 +868,21 @@ "HeaderNewApiKey": "\u041d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447 API", "LabelAppName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f", "LabelAppNameExample": "\u041f\u0440\u0438\u043c\u0435\u0440: Sickbeard, NzbDrone", - "HeaderNewApiKeyHelp": "\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a Media Browser.", + "HeaderNewApiKeyHelp": "\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a Media Browser.", "HeaderHttpHeaders": "HTTP-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438", "HeaderIdentificationHeader": "\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a", "LabelValue": "\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435:", "LabelMatchType": "\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0442\u0438\u043f:", "OptionEquals": "\u0420\u0430\u0432\u043d\u044f\u0435\u0442\u0441\u044f", "OptionRegex": "\u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435", - "OptionSubstring": "\u041f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0430" + "OptionSubstring": "\u041f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0430", + "TabView": "\u0412\u0438\u0434", + "TabSort": "\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430", + "TabFilter": "\u0424\u0438\u043b\u044c\u0442\u0440", + "ButtonView": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c", + "LabelPageSize": "\u0420\u0430\u0437\u043c\u0435\u0440 \u044d\u043a\u0440\u0430\u043d\u0430:", + "LabelView": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440:", + "TabUsers": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 741bc52ca0..4a23b0c073 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -1,893 +1,904 @@ { "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelGithubWiki": "Github Wiki", - "LabelSwagger": "Swagger", - "LabelStandard": "Standard", - "LabelViewApiDocumentation": "View Api Documentation", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureMediaBrowser": "Configure Media Browser", - "LabelOpenLibraryViewer": "Open Library Viewer", - "LabelRestartServer": "Restart Server", - "LabelShowLogWindow": "Show Log Window", - "LabelPrevious": "Previous", - "LabelFinish": "Finish", - "LabelNext": "Next", - "LabelYoureDone": "You're Done!", - "WelcomeToMediaBrowser": "Welcome to Media Browser!", - "TitleMediaBrowser": "Media Browser", - "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.", - "TellUsAboutYourself": "Tell us about yourself", - "LabelYourFirstName": "Your first name:", - "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", - "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", - "LabelWindowsService": "Windows Service", - "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", - "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", - "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", - "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish to view the Dashboard.", - "LabelConfigureSettings": "Configure settings", - "LabelEnableVideoImageExtraction": "Enable video image extraction", - "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", - "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", - "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", - "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", - "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", - "ButtonOk": "Ok", - "ButtonCancel": "Cancel", - "ButtonNew": "New", - "HeaderSetupLibrary": "Setup your media library", - "ButtonAddMediaFolder": "Add media folder", - "LabelFolderType": "Folder type:", - "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", - "ReferToMediaLibraryWiki": "Refer to the media library wiki.", - "LabelCountry": "Country:", - "LabelLanguage": "Language:", - "HeaderPreferredMetadataLanguage": "Preferred metadata language:", - "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", - "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", - "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", - "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.", - "TabPreferences": "Preferences", - "TabPassword": "Password", - "TabLibraryAccess": "Library Access", - "TabImage": "Image", - "TabProfile": "Profile", - "TabMetadata": "Metadata", - "TabImages": "Images", - "TabNotifications": "Notifications", - "TabCollectionTitles": "Titles", - "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", - "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", - "HeaderVideoPlaybackSettings": "Video Playback Settings", - "HeaderPlaybackSettings": "Playback Settings", - "LabelAudioLanguagePreference": "Audio language preference:", - "LabelSubtitleLanguagePreference": "Subtitle language preference:", - "OptionDefaultSubtitles": "Default", - "OptionOnlyForcedSubtitles": "Only forced subtitles", - "OptionAlwaysPlaySubtitles": "Always play subtitles", - "OptionNoSubtitles": "None", - "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.", - "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.", - "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", - "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.", - "TabProfiles": "Profiles", - "TabSecurity": "Security", - "ButtonAddUser": "Add User", - "ButtonSave": "Save", - "ButtonResetPassword": "Reset Password", - "LabelNewPassword": "New password:", - "LabelNewPasswordConfirm": "New password confirm:", - "HeaderCreatePassword": "Create Password", - "LabelCurrentPassword": "Current password:", - "LabelMaxParentalRating": "Maximum allowed parental rating:", - "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.", - "LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.", - "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", - "ButtonDeleteImage": "Delete Image", - "LabelSelectUsers": "Select users:", - "ButtonUpload": "Upload", - "HeaderUploadNewImage": "Upload New Image", - "LabelDropImageHere": "Drop Image Here", - "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG/PNG only.", - "MessageNothingHere": "Nothing here.", - "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", - "TabSuggested": "Suggested", - "TabLatest": "Latest", - "TabUpcoming": "Upcoming", - "TabShows": "Shows", - "TabEpisodes": "Episodes", - "TabGenres": "Genres", - "TabPeople": "People", - "TabNetworks": "Networks", - "HeaderUsers": "Users", - "HeaderFilters": "Filters:", - "ButtonFilter": "Filter", - "OptionFavorite": "Favorites", - "OptionLikes": "Likes", - "OptionDislikes": "Dislikes", - "OptionActors": "Actors", - "OptionGuestStars": "Guest Stars", - "OptionDirectors": "Directors", - "OptionWriters": "Writers", - "OptionProducers": "Producers", - "HeaderResume": "Resume", - "HeaderNextUp": "Next Up", - "NoNextUpItemsMessage": "None found. Start watching your shows!", - "HeaderLatestEpisodes": "Latest Episodes", - "HeaderPersonTypes": "Person Types:", - "TabSongs": "Songs", - "TabAlbums": "Albums", - "TabArtists": "Artists", - "TabAlbumArtists": "Album Artists", - "TabMusicVideos": "Music Videos", - "ButtonSort": "Sort", - "HeaderSortBy": "Sort By:", - "HeaderSortOrder": "Sort Order:", - "OptionPlayed": "Played", - "OptionUnplayed": "Unplayed", - "OptionAscending": "Ascending", - "OptionDescending": "Descending", - "OptionRuntime": "Runtime", - "OptionReleaseDate": "Release Date", - "OptionPlayCount": "Play Count", - "OptionDatePlayed": "Date Played", - "OptionDateAdded": "Date Added", - "OptionAlbumArtist": "Album Artist", - "OptionArtist": "Artist", - "OptionAlbum": "Album", - "OptionTrackName": "Track Name", - "OptionCommunityRating": "Community Rating", - "OptionNameSort": "Name", - "OptionFolderSort": "Folders", - "OptionBudget": "Budget", - "OptionRevenue": "Revenue", - "OptionPoster": "Poster", - "OptionBackdrop": "Backdrop", - "OptionTimeline": "Timeline", - "OptionThumb": "Thumb", - "OptionBanner": "Banner", - "OptionCriticRating": "Critic Rating", - "OptionVideoBitrate": "Video Bitrate", - "OptionResumable": "Resumable", - "ScheduledTasksHelp": "Click a task to adjust its schedule.", - "ScheduledTasksTitle": "Scheduled Tasks", - "TabMyPlugins": "My Plugins", - "TabCatalog": "Catalog", - "PluginsTitle": "Plugins", - "HeaderAutomaticUpdates": "Automatic Updates", - "HeaderNowPlaying": "Now Playing", - "HeaderLatestAlbums": "Latest Albums", - "HeaderLatestSongs": "Latest Songs", - "HeaderRecentlyPlayed": "Recently Played", - "HeaderFrequentlyPlayed": "Frequently Played", - "DevBuildWarning": "Dev builds are the bleeding edge. Released often, these build have not been tested. The application may crash and entire features may not work at all.", - "LabelVideoType": "Video Type:", - "OptionBluray": "Bluray", - "OptionDvd": "Dvd", - "OptionIso": "Iso", - "Option3D": "3D", - "LabelFeatures": "Features:", - "LabelService": "Service:", - "LabelStatus": "Status:", - "LabelVersion": "Version:", - "LabelLastResult": "Last result:", - "OptionHasSubtitles": "Subtitles", - "OptionHasTrailer": "Trailer", - "OptionHasThemeSong": "Theme Song", - "OptionHasThemeVideo": "Theme Video", - "TabMovies": "Movies", - "TabStudios": "Studios", - "TabTrailers": "Trailers", - "HeaderLatestMovies": "Latest Movies", - "HeaderLatestTrailers": "Latest Trailers", - "OptionHasSpecialFeatures": "Special Features", - "OptionImdbRating": "IMDb Rating", - "OptionParentalRating": "Parental Rating", - "OptionPremiereDate": "Premiere Date", - "TabBasic": "Basic", - "TabAdvanced": "Advanced", - "HeaderStatus": "Status", - "OptionContinuing": "Continuing", - "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", - "OptionSunday": "Sunday", - "OptionMonday": "Monday", - "OptionTuesday": "Tuesday", - "OptionWednesday": "Wednesday", - "OptionThursday": "Thursday", - "OptionFriday": "Friday", - "OptionSaturday": "Saturday", - "HeaderManagement": "Management:", - "OptionMissingImdbId": "Missing IMDb Id", - "OptionMissingTvdbId": "Missing TheTVDB Id", - "OptionMissingOverview": "Missing Overview", - "OptionFileMetadataYearMismatch": "File/Metadata Years Mismatched", - "TabGeneral": "General", - "TitleSupport": "Support", - "TabLog": "Log", - "TabAbout": "About", - "TabSupporterKey": "Supporter Key", - "TabBecomeSupporter": "Become a Supporter", - "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.", - "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.", - "SearchKnowledgeBase": "Search the Knowledge Base", - "VisitTheCommunity": "Visit the Community", - "VisitMediaBrowserWebsite": "Visit the Media Browser Web Site", - "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.", - "OptionHideUser": "Hide this user from login screens", - "OptionDisableUser": "Disable this user", - "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.", - "HeaderAdvancedControl": "Advanced Control", - "LabelName": "Name:", - "OptionAllowUserToManageServer": "Allow this user to manage the server", - "HeaderFeatureAccess": "Feature Access", - "OptionAllowMediaPlayback": "Allow media playback", - "OptionAllowBrowsingLiveTv": "Allow browsing of live tv", - "OptionAllowDeleteLibraryContent": "Allow this user to delete library content", - "OptionAllowManageLiveTv": "Allow management of live tv recordings", - "OptionAllowRemoteControlOthers": "Allow this user to remote control other users", - "OptionMissingTmdbId": "Missing Tmdb Id", - "OptionIsHD": "HD", - "OptionIsSD": "SD", - "OptionMetascore": "Metascore", - "ButtonSelect": "Select", - "ButtonSearch": "Search", - "ButtonGroupVersions": "Group Versions", - "ButtonAddToCollection": "Add to Collection", - "PismoMessage": "Utilizing Pismo File Mount through a donated license.", - "TangibleSoftwareMessage": "Utilizing Tangible Solutions Java/C# converters through a donated license.", - "HeaderCredits": "Credits", - "PleaseSupportOtherProduces": "Please support other free products we utilize:", - "VersionNumber": "Version {0}", - "TabPaths": "Paths", - "TabServer": "Server", - "TabTranscoding": "Transcoding", - "TitleAdvanced": "Advanced", - "LabelAutomaticUpdateLevel": "Automatic update level", - "OptionRelease": "Official Release", - "OptionBeta": "Beta", - "OptionDev": "Dev (Unstable)", - "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates", - "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.", - "LabelEnableDebugLogging": "Enable debug logging", - "LabelRunServerAtStartup": "Run server at startup", - "LabelRunServerAtStartupHelp": "This will start the tray icon on windows startup. To start the windows service, uncheck this and run the service from the windows control panel. Please note that you cannot run both at the same time, so you will need to exit the tray icon before starting the service.", - "ButtonSelectDirectory": "Select Directory", - "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", - "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", - "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", - "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", - "LabelTranscodingTempPath": "Transcoding temporary path:", - "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", - "TabBasics": "Basics", - "TabTV": "TV", - "TabGames": "Games", - "TabMusic": "Music", - "TabOthers": "Others", - "HeaderExtractChapterImagesFor": "Extract chapter images for:", - "OptionMovies": "Movies", - "OptionEpisodes": "Episodes", - "OptionOtherVideos": "Other Videos", - "TitleMetadata": "Metadata", - "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", - "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", - "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", - "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", - "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", - "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", - "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", - "LabelMetadataDownloadLanguage": "Preferred download language:", - "ButtonAutoScroll": "Auto-scroll", - "LabelImageSavingConvention": "Image saving convention:", - "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.", - "OptionImageSavingCompatible": "Compatible - Media Browser/Xbmc/Plex", - "OptionImageSavingStandard": "Standard - MB2", - "ButtonSignIn": "Sign In", - "TitleSignIn": "Sign In", - "HeaderPleaseSignIn": "Please sign in", - "LabelUser": "User:", - "LabelPassword": "Password:", - "ButtonManualLogin": "Manual Login", - "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.", - "TabGuide": "Guide", - "TabChannels": "Channels", - "TabCollections": "Collections", - "HeaderChannels": "Channels", - "TabRecordings": "Recordings", - "TabScheduled": "Scheduled", - "TabSeries": "Series", - "TabFavorites": "Favorites", - "TabMyLibrary": "My Library", - "ButtonCancelRecording": "Cancel Recording", - "HeaderPrePostPadding": "Pre/Post Padding", - "LabelPrePaddingMinutes": "Pre-padding minutes:", - "OptionPrePaddingRequired": "Pre-padding is required in order to record.", - "LabelPostPaddingMinutes": "Post-padding minutes:", - "OptionPostPaddingRequired": "Post-padding is required in order to record.", - "HeaderWhatsOnTV": "What's On", - "HeaderUpcomingTV": "Upcoming TV", - "TabStatus": "Status", - "TabSettings": "Settings", - "ButtonRefreshGuideData": "Refresh Guide Data", - "OptionPriority": "Priority", - "OptionRecordOnAllChannels": "Record program on all channels", - "OptionRecordAnytime": "Record program at any time", - "OptionRecordOnlyNewEpisodes": "Record only new episodes", - "HeaderDays": "Days", - "HeaderActiveRecordings": "Active Recordings", - "HeaderLatestRecordings": "Latest Recordings", - "HeaderAllRecordings": "All Recordings", - "ButtonPlay": "Play", - "ButtonEdit": "Edit", - "ButtonRecord": "Record", - "ButtonDelete": "Delete", - "ButtonRemove": "Remove", - "OptionRecordSeries": "Record Series", - "HeaderDetails": "Details", - "ButtonCancelRecording": "Cancel Recording", - "TitleLiveTV": "Live TV", - "LabelNumberOfGuideDays": "Number of days of guide data to download:", - "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.", - "LabelActiveService": "Active Service:", - "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.", - "OptionAutomatic": "Auto", - "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.", - "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.", - "LabelCustomizeOptionsPerMediaType": "Customize for media type:", - "OptionDownloadThumbImage": "Thumb", - "OptionDownloadMenuImage": "Menu", - "OptionDownloadLogoImage": "Logo", - "OptionDownloadBoxImage": "Box", - "OptionDownloadDiscImage": "Disc", - "OptionDownloadBannerImage": "Banner", - "OptionDownloadBackImage": "Back", - "OptionDownloadArtImage": "Art", - "OptionDownloadPrimaryImage": "Primary", - "HeaderFetchImages": "Fetch Images:", - "HeaderImageSettings": "Image Settings", - "TabOther": "Other", - "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:", - "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:", - "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:", - "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:", - "ButtonAddScheduledTaskTrigger": "Add Task Trigger", - "HeaderAddScheduledTaskTrigger": "Add Task Trigger", - "ButtonAdd": "Add", - "LabelTriggerType": "Trigger Type:", - "OptionDaily": "Daily", - "OptionWeekly": "Weekly", - "OptionOnInterval": "On an interval", - "OptionOnAppStartup": "On application startup", - "OptionAfterSystemEvent": "After a system event", - "LabelDay": "Day:", - "LabelTime": "Time:", - "LabelEvent": "Event:", - "OptionWakeFromSleep": "Wake from sleep", - "LabelEveryXMinutes": "Every:", - "HeaderTvTuners": "Tuners", - "HeaderGallery": "Gallery", - "HeaderLatestGames": "Latest Games", - "HeaderRecentlyPlayedGames": "Recently Played Games", - "TabGameSystems": "Game Systems", - "TitleMediaLibrary": "Media Library", - "TabFolders": "Folders", - "TabPathSubstitution": "Path Substitution", - "LabelSeasonZeroDisplayName": "Season 0 display name:", - "LabelEnableRealtimeMonitor": "Enable real time monitoring", - "LabelEnableRealtimeMonitorHelp": "Changes will be processed immediately, on supported file systems.", - "ButtonScanLibrary": "Scan Library", - "HeaderNumberOfPlayers": "Players:", - "OptionAnyNumberOfPlayers": "Any", - "Option1Player": "1+", - "Option2Player": "2+", - "Option3Player": "3+", - "Option4Player": "4+", - "HeaderMediaFolders": "Media Folders", - "HeaderThemeVideos": "Theme Videos", - "HeaderThemeSongs": "Theme Songs", - "HeaderScenes": "Scenes", - "HeaderAwardsAndReviews": "Awards and Reviews", - "HeaderSoundtracks": "Soundtracks", - "HeaderMusicVideos": "Music Videos", - "HeaderSpecialFeatures": "Special Features", - "HeaderCastCrew": "Cast & Crew", - "HeaderAdditionalParts": "Additional Parts", - "ButtonSplitVersionsApart": "Split Versions Apart", - "ButtonPlayTrailer": "Trailer", - "LabelMissing": "Missing", - "LabelOffline": "Offline", - "PathSubstitutionHelp": "Path substitutions are used for mapping a path on the server to a path that clients are able to access. By allowing clients direct access to media on the server they may be able to play them directly over the network and avoid using server resources to stream and transcode them.", - "HeaderFrom": "From", - "HeaderTo": "To", - "LabelFrom": "From:", - "LabelFromHelp": "Example: D:\\Movies (on the server)", - "LabelTo": "To:", - "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)", - "ButtonAddPathSubstitution": "Add Substitution", - "OptionSpecialEpisode": "Specials", - "OptionMissingEpisode": "Missing Episodes", - "OptionUnairedEpisode": "Unaired Episodes", - "OptionEpisodeSortName": "Episode Sort Name", - "OptionSeriesSortName": "Series Name", - "OptionTvdbRating": "Tvdb Rating", - "HeaderTranscodingQualityPreference": "Transcoding Quality Preference:", - "OptionAutomaticTranscodingHelp": "The server will decide quality and speed", - "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding", - "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding", - "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage", - "OptionHighSpeedTranscoding": "Higher speed", - "OptionHighQualityTranscoding": "Higher quality", - "OptionMaxQualityTranscoding": "Max quality", - "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging", - "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.", - "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging", - "OptionUpscaling": "Allow clients to request upscaled video", - "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.", - "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.", - "HeaderAddTitles": "Add Titles", - "LabelEnableDlnaPlayTo": "Enable DLNA Play To", - "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.", - "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", - "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.", - "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)", - "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.", - "HeaderCustomDlnaProfiles": "Custom Profiles", - "HeaderSystemDlnaProfiles": "System Profiles", - "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", - "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", - "TitleDashboard": "Dashboard", - "TabHome": "Home", - "TabInfo": "Info", - "HeaderLinks": "Links", - "HeaderSystemPaths": "System Paths", - "LinkCommunity": "Community", - "LinkGithub": "Github", - "LinkApiDocumentation": "Api Documentation", - "LabelFriendlyServerName": "Friendly server name:", - "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", - "LabelPreferredDisplayLanguage": "Preferred display language", - "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", - "LabelReadHowYouCanContribute": "Read about how you can contribute.", - "HeaderNewCollection": "New Collection", - "HeaderAddToCollection": "Add to Collection", - "ButtonSubmit": "Submit", - "NewCollectionNameExample": "Example: Star Wars Collection", - "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", - "ButtonCreate": "Create", - "LabelHttpServerPortNumber": "Http server port number:", - "LabelWebSocketPortNumber": "Web socket port number:", - "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", - "LabelEnableAutomaticPortHelp": "UPnP allows automated router configuration for remote access. This may not work with some router models.", - "LabelExternalDDNS": "External DDNS:", - "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", - "TabResume": "Resume", - "TabWeather": "Weather", - "TitleAppSettings": "App Settings", - "LabelMinResumePercentage": "Min resume percentage:", - "LabelMaxResumePercentage": "Max resume percentage:", - "LabelMinResumeDuration": "Min resume duration (seconds):", - "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time", - "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time", - "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable", - "TitleAutoOrganize": "Auto-Organize", - "TabActivityLog": "Activity Log", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderSource": "Source", - "HeaderStatus": "Status", - "HeaderDestination": "Destination", - "HeaderProgram": "Program", - "HeaderClients": "Clients", - "LabelCompleted": "Completed", - "LabelFailed": "Failed", - "LabelSkipped": "Skipped", - "HeaderEpisodeOrganization": "Episode Organization", - "LabelSeries": "Series:", - "LabelSeasonNumber": "Season number:", - "LabelEpisodeNumber": "Episode number:", - "LabelEndingEpisodeNumber": "Ending episode number:", - "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files", - "HeaderSupportTheTeam": "Support the Media Browser Team", - "LabelSupportAmount": "Amount (USD)", - "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.", - "ButtonEnterSupporterKey": "Enter supporter key", - "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.", - "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.", - "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.", - "OptionEnableEpisodeOrganization": "Enable new episode organization", - "LabelWatchFolder": "Watch folder:", - "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.", - "ButtonViewScheduledTasks": "View scheduled tasks", - "LabelMinFileSizeForOrganize": "Minimum file size (MB):", - "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.", - "LabelSeasonFolderPattern": "Season folder pattern:", - "LabelSeasonZeroFolderName": "Season zero folder name:", - "HeaderEpisodeFilePattern": "Episode file pattern", - "LabelEpisodePattern": "Episode pattern:", - "LabelMultiEpisodePattern": "Multi-Episode pattern:", - "HeaderSupportedPatterns": "Supported Patterns", - "HeaderTerm": "Term", - "HeaderPattern": "Pattern", - "HeaderResult": "Result", - "LabelDeleteEmptyFolders": "Delete empty folders after organizing", - "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.", - "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:", - "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt", - "OptionOverwriteExistingEpisodes": "Overwrite existing episodes", - "LabelTransferMethod": "Transfer method", - "OptionCopy": "Copy", - "OptionMove": "Move", - "LabelTransferMethodHelp": "Copy or move files from the watch folder", - "HeaderLatestNews": "Latest News", - "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser", - "HeaderRunningTasks": "Running Tasks", - "HeaderActiveDevices": "Active Devices", - "HeaderPendingInstallations": "Pending Installations", - "HeaerServerInformation": "Server Information", - "ButtonRestartNow": "Restart Now", - "ButtonRestart": "Restart", - "ButtonShutdown": "Shutdown", - "ButtonUpdateNow": "Update Now", - "PleaseUpdateManually": "Please shutdown the server and update manually.", - "NewServerVersionAvailable": "A new version of Media Browser Server is available!", - "ServerUpToDate": "Media Browser Server is up to date", - "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.", - "LabelComponentsUpdated": "The following components have been installed or updated:", - "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.", - "LabelDownMixAudioScale": "Audio boost when downmixing:", - "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.", - "ButtonLinkKeys": "Link Keys", - "LabelOldSupporterKey": "Old supporter key", - "LabelNewSupporterKey": "New supporter key", - "HeaderMultipleKeyLinking": "Multiple Key Linking", - "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.", - "LabelCurrentEmailAddress": "Current email address", - "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.", - "HeaderForgotKey": "Forgot Key", - "LabelEmailAddress": "Email address", - "LabelSupporterEmailAddress": "The email address that was used to purchase the key.", - "ButtonRetrieveKey": "Retrieve Key", - "LabelSupporterKey": "Supporter Key (paste from email)", - "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.", - "MessageInvalidKey": "Supporter key is missing or invalid.", - "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.", - "HeaderDisplaySettings": "Display Settings", - "TabPlayTo": "Play To", - "LabelEnableDlnaServer": "Enable Dlna server", - "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.", - "LabelEnableBlastAliveMessages": "Blast alive messages", - "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", - "LabelBlastMessageInterval": "Alive message interval (seconds)", - "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.", - "LabelDefaultUser": "Default user:", - "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", - "TitleDlna": "DLNA", - "TitleChannels": "Channels", - "HeaderServerSettings": "Server Settings", - "LabelWeatherDisplayLocation": "Weather display location:", - "LabelWeatherDisplayLocationHelp": "US zip code / City, State, Country / City, Country", - "LabelWeatherDisplayUnit": "Weather display unit:", - "OptionCelsius": "Celsius", - "OptionFahrenheit": "Fahrenheit", - "HeaderRequireManualLogin": "Require manual username entry for:", - "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.", - "OptionOtherApps": "Other apps", - "OptionMobileApps": "Mobile apps", - "HeaderNotificationList": "Click on a notification to configure it's sending options.", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", - "NotificationOptionServerRestartRequired": "Server restart required", - "LabelNotificationEnabled": "Enable this notification", - "LabelMonitorUsers": "Monitor activity from:", - "LabelSendNotificationToUsers": "Send the notification to:", - "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.", - "LabelUseNotificationServices": "Use the following services:", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "LabelMessageTitle": "Message title:", - "LabelAvailableTokens": "Available tokens:", - "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.", - "OptionAllUsers": "All users", - "OptionAdminUsers": "Administrators", - "OptionCustomUsers": "Custom", - "ButtonArrowUp": "Up", - "ButtonArrowDown": "Down", - "ButtonArrowLeft": "Left", - "ButtonArrowRight": "Right", - "ButtonBack": "Back", - "ButtonInfo": "Info", - "ButtonOsd": "On screen display", - "ButtonPageUp": "Page Up", - "ButtonPageDown": "Page Down", - "PageAbbreviation": "PG", - "ButtonHome": "Home", - "ButtonSearch": "Search", - "ButtonSettings": "Settings", - "ButtonTakeScreenshot": "Capture Screenshot", - "ButtonLetterUp": "Letter Up", - "ButtonLetterDown": "Letter Down", - "PageButtonAbbreviation": "PG", - "LetterButtonAbbreviation": "A", - "TabNowPlaying": "Now Playing", - "TabNavigation": "Navigation", - "TabControls": "Controls", - "ButtonFullscreen": "Toggle fullscreen", - "ButtonScenes": "Scenes", - "ButtonSubtitles": "Subtitles", - "ButtonAudioTracks": "Audio tracks", - "ButtonPreviousTrack": "Previous track", - "ButtonNextTrack": "Next track", - "ButtonStop": "Stop", - "ButtonPlay": "Play", - "ButtonPause": "Pause", - "LabelGroupMoviesIntoCollections": "Group movies into collections", - "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.", - "NotificationOptionPluginError": "Plugin failure", - "ButtonVolumeUp": "Volume up", - "ButtonVolumeDown": "Volume down", - "ButtonMute": "Mute", - "HeaderLatestMedia": "Latest Media", - "OptionNoSubtitles": "No Subtitles", - "OptionSpecialFeatures": "Special Features", - "HeaderCollections": "Collections", - "HeaderChannels": "Channels", - "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", - "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", - "HeaderResponseProfile": "Response Profile", - "LabelType": "Type:", - "LabelProfileContainer": "Container:", - "LabelProfileVideoCodecs": "Video codecs:", - "LabelProfileAudioCodecs": "Audio codecs:", - "LabelProfileCodecs": "Codecs:", - "HeaderDirectPlayProfile": "Direct Play Profile", - "HeaderTranscodingProfile": "Transcoding Profile", - "HeaderCodecProfile": "Codec Profile", - "HeaderCodecProfileHelp": "Define additional conditions that must be met in order for a codec to be direct played.", - "HeaderContainerProfile": "Container Profile", - "HeaderContainerProfileHelp": "Define additional conditions that must be met in order for a file to be direct played.", - "OptionProfileVideo": "Video", - "OptionProfileAudio": "Audio", - "OptionProfileVideoAudio": "Video Audio", - "OptionProfilePhoto": "Photo", - "LabelUserLibrary": "User library:", - "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.", - "OptionPlainStorageFolders": "Display all folders as plain storage folders", - "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".", - "OptionPlainVideoItems": "Display all videos as plain video items", - "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", - "LabelSupportedMediaTypes": "Supported Media Types:", - "TabIdentification": "Identification", - "TabDirectPlay": "Direct Play", - "TabContainers": "Containers", - "TabCodecs": "Codecs", - "TabResponses": "Responses", - "HeaderProfileInformation": "Profile Information", - "LabelEmbedAlbumArtDidl": "Embed album art in Didl", - "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.", - "LabelAlbumArtPN": "Album art PN:", - "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.", - "LabelAlbumArtMaxWidth": "Album art max width:", - "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.", - "LabelAlbumArtMaxHeight": "Album art max height:", - "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.", - "LabelIconMaxWidth": "Icon max width:", - "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.", - "LabelIconMaxHeight": "Icon max height:", - "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.", - "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", - "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.", - "LabelMaxBitrate": "Max bitrate:", - "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.", - "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", - "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.", - "LabelFriendlyName": "Friendly name", - "LabelManufacturer": "Manufacturer", - "LabelManufacturerUrl": "Manufacturer url", - "LabelModelName": "Model name", - "LabelModelNumber": "Model number", - "LabelModelDescription": "Model description", - "LabelModelUrl": "Model url", - "LabelSerialNumber": "Serial number", - "LabelDeviceDescription": "Device description", - "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", - "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.", - "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", - "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.", - "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.", - "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", - "LabelXDlnaCap": "X-Dlna cap:", - "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.", - "LabelXDlnaDoc": "X-Dlna doc:", - "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.", - "LabelSonyAggregationFlags": "Sony aggregation flags:", - "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.", - "LabelTranscodingContainer": "Container:", - "LabelTranscodingVideoCodec": "Video codec:", - "LabelTranscodingVideoProfile": "Video profile:", - "LabelTranscodingAudioCodec": "Audio codec:", - "OptionEnableM2tsMode": "Enable M2ts mode", - "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.", - "OptionEstimateContentLength": "Estimate content length when transcoding", - "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", - "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", - "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.", - "HeaderDownloadSubtitlesFor": "Download subtitles for:", - "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.", - "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles", - "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.", - "TabSubtitles": "Subtitles", - "TabChapters": "Chapters", - "HeaderDownloadChaptersFor": "Download chapter names for:", - "LabelOpenSubtitlesUsername": "Open Subtitles username:", - "LabelOpenSubtitlesPassword": "Open Subtitles password:", - "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.", - "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", - "LabelSubtitlePlaybackMode": "Subtitle mode:", - "LabelDownloadLanguages": "Download languages:", - "ButtonRegister": "Register", - "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", - "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", - "HeaderSendMessage": "Send Message", - "ButtonSend": "Send", - "LabelMessageText": "Message text:", - "LabelMessageTitle": "Message title:", - "MessageNoAvailablePlugins": "No available plugins.", - "LabelDisplayPluginsFor": "Display plugins for:", - "PluginTabMediaBrowserClassic": "MB Classic", - "PluginTabMediaBrowserTheater": "MB Theater", - "LabelEpisodeName": "Episode name", - "LabelSeriesName": "Series name", - "ValueSeriesNamePeriod": "Series.name", - "ValueSeriesNameUnderscore": "Series_name", - "ValueEpisodeNamePeriod": "Episode.name", - "ValueEpisodeNameUnderscore": "Episode_name", - "LabelSeasonNumber": "Season number", - "LabelEpisodeNumber": "Episode number", - "LabelEndingEpisodeNumber": "Ending episode number", - "HeaderTypeText": "Enter Text", - "LabelTypeText": "Text", - "HeaderSearchForSubtitles": "Search for Subtitles", - "MessageNoSubtitleSearchResultsFound": "No search results founds.", - "TabDisplay": "Display", - "TabLanguages": "Languages", - "TabWebClient": "Web Client", - "LabelEnableThemeSongs": "Enable theme songs", - "LabelEnableBackdrops": "Enable backdrops", - "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.", - "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.", - "HeaderHomePage": "Home Page", - "HeaderSettingsForThisDevice": "Settings for This Device", - "OptionAuto": "Auto", - "OptionYes": "Yes", - "OptionNo": "No", - "LabelHomePageSection1": "Home page section one:", - "LabelHomePageSection2": "Home page section two:", - "LabelHomePageSection3": "Home page section three:", - "LabelHomePageSection4": "Home page section four:", - "OptionMyViewsButtons": "My views (buttons)", - "OptionMyViews": "My views", - "OptionMyViewsSmall": "My views (small)", - "OptionResumablemedia": "Resume", - "OptionLatestMedia": "Latest media", - "OptionLatestChannelMedia": "Latest channel items", - "HeaderLatestChannelItems": "Latest Channel Items", - "OptionNone": "None", - "HeaderLiveTv": "Live TV", - "HeaderReports": "Reports", - "HeaderMetadataManager": "Metadata Manager", - "HeaderPreferences": "Preferences", - "MessageLoadingChannels": "Loading channel content...", - "ButtonMarkRead": "Mark Read", - "OptionDefaultSort": "Default", - "OptionCommunityMostWatchedSort": "Most Watched", - "TabNextUp": "Next Up", - "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", - "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the New button to start creating Collections.", - "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", - "ButtonDismiss": "Dismiss", - "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.", - "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.", - "LabelChannelStreamQuality": "Preferred internet stream quality:", - "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.", - "OptionBestAvailableStreamQuality": "Best available", - "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:", - "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.", - "LabelChannelDownloadPath": "Channel content download path:", - "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.", - "LabelChannelDownloadAge": "Delete content after: (days)", - "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", - "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", - "LabelSelectCollection": "Select collection:", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "HeaderOtherDisplaySettings": "Display Settings", - "HeaderMyViews": "My Views", - "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", - "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", - "OptionDisplayAdultContent": "Display adult content", - "OptionLibraryFolders": "Media folders", - "TitleRemoteControl": "Remote Control", - "OptionLatestTvRecordings": "Latest recordings", - "LabelProtocolInfo": "Protocol info:", - "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", - "TabXbmcMetadata": "Xbmc", - "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.", - "LabelXbmcMetadataUser": "Add user watch data to nfo's for:", - "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.", - "LabelXbmcMetadataDateFormat": "Release date format:", - "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.", - "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files", - "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.", - "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution", - "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.", - "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.", - "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", - "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", - "LabelDisplayCollectionsView": "Display a collections view to show movie collections", - "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", - "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.", - "TabServices": "Services", - "TabLogs": "Logs", - "HeaderServerLogFiles": "Server log files:", - "TabBranding": "Branding", - "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.", - "LabelLoginDisclaimer": "Login disclaimer:", - "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", - "LabelAutomaticallyDonate": "Automatically donate this amount every six months", - "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", - "OptionList": "List", - "TabDashboard": "Dashboard", - "TitleServer": "Server", - "LabelCache": "Cache:", - "LabelLogs": "Logs:", - "LabelMetadata": "Metadata:", - "LabelImagesByName": "Images by name:", - "LabelTranscodingTemporaryFiles": "Transcoding temporary files:", - "HeaderLatestMusic": "Latest Music", - "HeaderBranding": "Branding", - "HeaderApiKeys": "Api Keys", - "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.", - "HeaderApiKey": "Api Key", - "HeaderApp": "App", - "HeaderDevice": "Device", - "HeaderUser": "User", - "HeaderDateIssued": "Date Issued", - "LabelChapterName": "Chapter {0}", - "HeaderNewApiKey": "New Api Key", - "LabelAppName": "App name", - "LabelAppNameExample": "Example: Sickbeard, NzbDrone", - "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.", - "ButtonEnterSupporterKey": "Enter supporter key", - "HeaderHttpHeaders": "Http Headers", - "HeaderIdentificationHeader": "Identification Header", - "LabelValue": "Value:", - "LabelMatchType": "Match type:", - "OptionEquals": "Equals", - "OptionRegex": "Regex", - "OptionSubstring": "Substring" -} \ No newline at end of file + "LabelVisitCommunity": "Visit Community", + "LabelGithubWiki": "Github Wiki", + "LabelSwagger": "Swagger", + "LabelStandard": "Standard", + "LabelViewApiDocumentation": "View Api Documentation", + "LabelBrowseLibrary": "Browse Library", + "LabelConfigureMediaBrowser": "Configure Media Browser", + "LabelOpenLibraryViewer": "Open Library Viewer", + "LabelRestartServer": "Restart Server", + "LabelShowLogWindow": "Show Log Window", + "LabelPrevious": "Previous", + "LabelFinish": "Finish", + "LabelNext": "Next", + "LabelYoureDone": "You're Done!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "TitleMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish to view the Dashboard.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "ButtonNew": "New", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.", + "TabPreferences": "Preferences", + "TabPassword": "Password", + "TabLibraryAccess": "Library Access", + "TabImage": "Image", + "TabProfile": "Profile", + "TabMetadata": "Metadata", + "TabImages": "Images", + "TabNotifications": "Notifications", + "TabCollectionTitles": "Titles", + "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", + "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons", + "HeaderVideoPlaybackSettings": "Video Playback Settings", + "HeaderPlaybackSettings": "Playback Settings", + "LabelAudioLanguagePreference": "Audio language preference:", + "LabelSubtitleLanguagePreference": "Subtitle language preference:", + "OptionDefaultSubtitles": "Default", + "OptionOnlyForcedSubtitles": "Only forced subtitles", + "OptionAlwaysPlaySubtitles": "Always play subtitles", + "OptionNoSubtitles": "None", + "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.", + "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.", + "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.", + "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.", + "TabProfiles": "Profiles", + "TabSecurity": "Security", + "ButtonAddUser": "Add User", + "ButtonSave": "Save", + "ButtonResetPassword": "Reset Password", + "LabelNewPassword": "New password:", + "LabelNewPasswordConfirm": "New password confirm:", + "HeaderCreatePassword": "Create Password", + "LabelCurrentPassword": "Current password:", + "LabelMaxParentalRating": "Maximum allowed parental rating:", + "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.", + "LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.", + "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", + "ButtonDeleteImage": "Delete Image", + "LabelSelectUsers": "Select users:", + "ButtonUpload": "Upload", + "HeaderUploadNewImage": "Upload New Image", + "LabelDropImageHere": "Drop Image Here", + "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG/PNG only.", + "MessageNothingHere": "Nothing here.", + "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.", + "TabSuggested": "Suggested", + "TabLatest": "Latest", + "TabUpcoming": "Upcoming", + "TabShows": "Shows", + "TabEpisodes": "Episodes", + "TabGenres": "Genres", + "TabPeople": "People", + "TabNetworks": "Networks", + "HeaderUsers": "Users", + "HeaderFilters": "Filters:", + "ButtonFilter": "Filter", + "OptionFavorite": "Favorites", + "OptionLikes": "Likes", + "OptionDislikes": "Dislikes", + "OptionActors": "Actors", + "OptionGuestStars": "Guest Stars", + "OptionDirectors": "Directors", + "OptionWriters": "Writers", + "OptionProducers": "Producers", + "HeaderResume": "Resume", + "HeaderNextUp": "Next Up", + "NoNextUpItemsMessage": "None found. Start watching your shows!", + "HeaderLatestEpisodes": "Latest Episodes", + "HeaderPersonTypes": "Person Types:", + "TabSongs": "Songs", + "TabAlbums": "Albums", + "TabArtists": "Artists", + "TabAlbumArtists": "Album Artists", + "TabMusicVideos": "Music Videos", + "ButtonSort": "Sort", + "HeaderSortBy": "Sort By:", + "HeaderSortOrder": "Sort Order:", + "OptionPlayed": "Played", + "OptionUnplayed": "Unplayed", + "OptionAscending": "Ascending", + "OptionDescending": "Descending", + "OptionRuntime": "Runtime", + "OptionReleaseDate": "Release Date", + "OptionPlayCount": "Play Count", + "OptionDatePlayed": "Date Played", + "OptionDateAdded": "Date Added", + "OptionAlbumArtist": "Album Artist", + "OptionArtist": "Artist", + "OptionAlbum": "Album", + "OptionTrackName": "Track Name", + "OptionCommunityRating": "Community Rating", + "OptionNameSort": "Name", + "OptionFolderSort": "Folders", + "OptionBudget": "Budget", + "OptionRevenue": "Revenue", + "OptionPoster": "Poster", + "OptionBackdrop": "Backdrop", + "OptionTimeline": "Timeline", + "OptionThumb": "Thumb", + "OptionBanner": "Banner", + "OptionCriticRating": "Critic Rating", + "OptionVideoBitrate": "Video Bitrate", + "OptionResumable": "Resumable", + "ScheduledTasksHelp": "Click a task to adjust its schedule.", + "ScheduledTasksTitle": "Scheduled Tasks", + "TabMyPlugins": "My Plugins", + "TabCatalog": "Catalog", + "PluginsTitle": "Plugins", + "HeaderAutomaticUpdates": "Automatic Updates", + "HeaderNowPlaying": "Now Playing", + "HeaderLatestAlbums": "Latest Albums", + "HeaderLatestSongs": "Latest Songs", + "HeaderRecentlyPlayed": "Recently Played", + "HeaderFrequentlyPlayed": "Frequently Played", + "DevBuildWarning": "Dev builds are the bleeding edge. Released often, these build have not been tested. The application may crash and entire features may not work at all.", + "LabelVideoType": "Video Type:", + "OptionBluray": "Bluray", + "OptionDvd": "Dvd", + "OptionIso": "Iso", + "Option3D": "3D", + "LabelFeatures": "Features:", + "LabelService": "Service:", + "LabelStatus": "Status:", + "LabelVersion": "Version:", + "LabelLastResult": "Last result:", + "OptionHasSubtitles": "Subtitles", + "OptionHasTrailer": "Trailer", + "OptionHasThemeSong": "Theme Song", + "OptionHasThemeVideo": "Theme Video", + "TabMovies": "Movies", + "TabStudios": "Studios", + "TabTrailers": "Trailers", + "HeaderLatestMovies": "Latest Movies", + "HeaderLatestTrailers": "Latest Trailers", + "OptionHasSpecialFeatures": "Special Features", + "OptionImdbRating": "IMDb Rating", + "OptionParentalRating": "Parental Rating", + "OptionPremiereDate": "Premiere Date", + "TabBasic": "Basic", + "TabAdvanced": "Advanced", + "HeaderStatus": "Status", + "OptionContinuing": "Continuing", + "OptionEnded": "Ended", + "HeaderAirDays": "Air Days", + "OptionSunday": "Sunday", + "OptionMonday": "Monday", + "OptionTuesday": "Tuesday", + "OptionWednesday": "Wednesday", + "OptionThursday": "Thursday", + "OptionFriday": "Friday", + "OptionSaturday": "Saturday", + "HeaderManagement": "Management", + "LabelManagement": "Management:", + "OptionMissingImdbId": "Missing IMDb Id", + "OptionMissingTvdbId": "Missing TheTVDB Id", + "OptionMissingOverview": "Missing Overview", + "OptionFileMetadataYearMismatch": "File/Metadata Years Mismatched", + "TabGeneral": "General", + "TitleSupport": "Support", + "TabLog": "Log", + "TabAbout": "About", + "TabSupporterKey": "Supporter Key", + "TabBecomeSupporter": "Become a Supporter", + "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.", + "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.", + "SearchKnowledgeBase": "Search the Knowledge Base", + "VisitTheCommunity": "Visit the Community", + "VisitMediaBrowserWebsite": "Visit the Media Browser Web Site", + "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.", + "OptionHideUser": "Hide this user from login screens", + "OptionDisableUser": "Disable this user", + "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.", + "HeaderAdvancedControl": "Advanced Control", + "LabelName": "Name:", + "OptionAllowUserToManageServer": "Allow this user to manage the server", + "HeaderFeatureAccess": "Feature Access", + "OptionAllowMediaPlayback": "Allow media playback", + "OptionAllowBrowsingLiveTv": "Allow browsing of live tv", + "OptionAllowDeleteLibraryContent": "Allow this user to delete library content", + "OptionAllowManageLiveTv": "Allow management of live tv recordings", + "OptionAllowRemoteControlOthers": "Allow this user to remote control other users", + "OptionMissingTmdbId": "Missing Tmdb Id", + "OptionIsHD": "HD", + "OptionIsSD": "SD", + "OptionMetascore": "Metascore", + "ButtonSelect": "Select", + "ButtonSearch": "Search", + "ButtonGroupVersions": "Group Versions", + "ButtonAddToCollection": "Add to Collection", + "PismoMessage": "Utilizing Pismo File Mount through a donated license.", + "TangibleSoftwareMessage": "Utilizing Tangible Solutions Java/C# converters through a donated license.", + "HeaderCredits": "Credits", + "PleaseSupportOtherProduces": "Please support other free products we utilize:", + "VersionNumber": "Version {0}", + "TabPaths": "Paths", + "TabServer": "Server", + "TabTranscoding": "Transcoding", + "TitleAdvanced": "Advanced", + "LabelAutomaticUpdateLevel": "Automatic update level", + "OptionRelease": "Official Release", + "OptionBeta": "Beta", + "OptionDev": "Dev (Unstable)", + "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates", + "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.", + "LabelEnableDebugLogging": "Enable debug logging", + "LabelRunServerAtStartup": "Run server at startup", + "LabelRunServerAtStartupHelp": "This will start the tray icon on windows startup. To start the windows service, uncheck this and run the service from the windows control panel. Please note that you cannot run both at the same time, so you will need to exit the tray icon before starting the service.", + "ButtonSelectDirectory": "Select Directory", + "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", + "LabelCachePath": "Cache path:", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", + "LabelImagesByNamePath": "Images by name path:", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", + "LabelMetadataPath": "Metadata path:", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", + "LabelTranscodingTempPath": "Transcoding temporary path:", + "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", + "TabBasics": "Basics", + "TabTV": "TV", + "TabGames": "Games", + "TabMusic": "Music", + "TabOthers": "Others", + "HeaderExtractChapterImagesFor": "Extract chapter images for:", + "OptionMovies": "Movies", + "OptionEpisodes": "Episodes", + "OptionOtherVideos": "Other Videos", + "TitleMetadata": "Metadata", + "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv", + "LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org", + "LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com", + "LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.", + "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.", + "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.", + "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelMetadataDownloadLanguage": "Preferred download language:", + "ButtonAutoScroll": "Auto-scroll", + "LabelImageSavingConvention": "Image saving convention:", + "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.", + "OptionImageSavingCompatible": "Compatible - Media Browser/Xbmc/Plex", + "OptionImageSavingStandard": "Standard - MB2", + "ButtonSignIn": "Sign In", + "TitleSignIn": "Sign In", + "HeaderPleaseSignIn": "Please sign in", + "LabelUser": "User:", + "LabelPassword": "Password:", + "ButtonManualLogin": "Manual Login", + "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.", + "TabGuide": "Guide", + "TabChannels": "Channels", + "TabCollections": "Collections", + "HeaderChannels": "Channels", + "TabRecordings": "Recordings", + "TabScheduled": "Scheduled", + "TabSeries": "Series", + "TabFavorites": "Favorites", + "TabMyLibrary": "My Library", + "ButtonCancelRecording": "Cancel Recording", + "HeaderPrePostPadding": "Pre/Post Padding", + "LabelPrePaddingMinutes": "Pre-padding minutes:", + "OptionPrePaddingRequired": "Pre-padding is required in order to record.", + "LabelPostPaddingMinutes": "Post-padding minutes:", + "OptionPostPaddingRequired": "Post-padding is required in order to record.", + "HeaderWhatsOnTV": "What's On", + "HeaderUpcomingTV": "Upcoming TV", + "TabStatus": "Status", + "TabSettings": "Settings", + "ButtonRefreshGuideData": "Refresh Guide Data", + "OptionPriority": "Priority", + "OptionRecordOnAllChannels": "Record program on all channels", + "OptionRecordAnytime": "Record program at any time", + "OptionRecordOnlyNewEpisodes": "Record only new episodes", + "HeaderDays": "Days", + "HeaderActiveRecordings": "Active Recordings", + "HeaderLatestRecordings": "Latest Recordings", + "HeaderAllRecordings": "All Recordings", + "ButtonPlay": "Play", + "ButtonEdit": "Edit", + "ButtonRecord": "Record", + "ButtonDelete": "Delete", + "ButtonRemove": "Remove", + "OptionRecordSeries": "Record Series", + "HeaderDetails": "Details", + "ButtonCancelRecording": "Cancel Recording", + "TitleLiveTV": "Live TV", + "LabelNumberOfGuideDays": "Number of days of guide data to download:", + "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.", + "LabelActiveService": "Active Service:", + "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.", + "OptionAutomatic": "Auto", + "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.", + "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.", + "LabelCustomizeOptionsPerMediaType": "Customize for media type:", + "OptionDownloadThumbImage": "Thumb", + "OptionDownloadMenuImage": "Menu", + "OptionDownloadLogoImage": "Logo", + "OptionDownloadBoxImage": "Box", + "OptionDownloadDiscImage": "Disc", + "OptionDownloadBannerImage": "Banner", + "OptionDownloadBackImage": "Back", + "OptionDownloadArtImage": "Art", + "OptionDownloadPrimaryImage": "Primary", + "HeaderFetchImages": "Fetch Images:", + "HeaderImageSettings": "Image Settings", + "TabOther": "Other", + "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:", + "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:", + "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:", + "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:", + "ButtonAddScheduledTaskTrigger": "Add Task Trigger", + "HeaderAddScheduledTaskTrigger": "Add Task Trigger", + "ButtonAdd": "Add", + "LabelTriggerType": "Trigger Type:", + "OptionDaily": "Daily", + "OptionWeekly": "Weekly", + "OptionOnInterval": "On an interval", + "OptionOnAppStartup": "On application startup", + "OptionAfterSystemEvent": "After a system event", + "LabelDay": "Day:", + "LabelTime": "Time:", + "LabelEvent": "Event:", + "OptionWakeFromSleep": "Wake from sleep", + "LabelEveryXMinutes": "Every:", + "HeaderTvTuners": "Tuners", + "HeaderGallery": "Gallery", + "HeaderLatestGames": "Latest Games", + "HeaderRecentlyPlayedGames": "Recently Played Games", + "TabGameSystems": "Game Systems", + "TitleMediaLibrary": "Media Library", + "TabFolders": "Folders", + "TabPathSubstitution": "Path Substitution", + "LabelSeasonZeroDisplayName": "Season 0 display name:", + "LabelEnableRealtimeMonitor": "Enable real time monitoring", + "LabelEnableRealtimeMonitorHelp": "Changes will be processed immediately, on supported file systems.", + "ButtonScanLibrary": "Scan Library", + "HeaderNumberOfPlayers": "Players:", + "OptionAnyNumberOfPlayers": "Any", + "Option1Player": "1+", + "Option2Player": "2+", + "Option3Player": "3+", + "Option4Player": "4+", + "HeaderMediaFolders": "Media Folders", + "HeaderThemeVideos": "Theme Videos", + "HeaderThemeSongs": "Theme Songs", + "HeaderScenes": "Scenes", + "HeaderAwardsAndReviews": "Awards and Reviews", + "HeaderSoundtracks": "Soundtracks", + "HeaderMusicVideos": "Music Videos", + "HeaderSpecialFeatures": "Special Features", + "HeaderCastCrew": "Cast & Crew", + "HeaderAdditionalParts": "Additional Parts", + "ButtonSplitVersionsApart": "Split Versions Apart", + "ButtonPlayTrailer": "Trailer", + "LabelMissing": "Missing", + "LabelOffline": "Offline", + "PathSubstitutionHelp": "Path substitutions are used for mapping a path on the server to a path that clients are able to access. By allowing clients direct access to media on the server they may be able to play them directly over the network and avoid using server resources to stream and transcode them.", + "HeaderFrom": "From", + "HeaderTo": "To", + "LabelFrom": "From:", + "LabelFromHelp": "Example: D:\\Movies (on the server)", + "LabelTo": "To:", + "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)", + "ButtonAddPathSubstitution": "Add Substitution", + "OptionSpecialEpisode": "Specials", + "OptionMissingEpisode": "Missing Episodes", + "OptionUnairedEpisode": "Unaired Episodes", + "OptionEpisodeSortName": "Episode Sort Name", + "OptionSeriesSortName": "Series Name", + "OptionTvdbRating": "Tvdb Rating", + "HeaderTranscodingQualityPreference": "Transcoding Quality Preference:", + "OptionAutomaticTranscodingHelp": "The server will decide quality and speed", + "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding", + "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding", + "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage", + "OptionHighSpeedTranscoding": "Higher speed", + "OptionHighQualityTranscoding": "Higher quality", + "OptionMaxQualityTranscoding": "Max quality", + "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging", + "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.", + "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging", + "OptionUpscaling": "Allow clients to request upscaled video", + "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.", + "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.", + "HeaderAddTitles": "Add Titles", + "LabelEnableDlnaPlayTo": "Enable DLNA Play To", + "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.", + "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", + "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.", + "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)", + "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.", + "HeaderCustomDlnaProfiles": "Custom Profiles", + "HeaderSystemDlnaProfiles": "System Profiles", + "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", + "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", + "TitleDashboard": "Dashboard", + "TabHome": "Home", + "TabInfo": "Info", + "HeaderLinks": "Links", + "HeaderSystemPaths": "System Paths", + "LinkCommunity": "Community", + "LinkGithub": "Github", + "LinkApiDocumentation": "Api Documentation", + "LabelFriendlyServerName": "Friendly server name:", + "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.", + "LabelPreferredDisplayLanguage": "Preferred display language", + "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.", + "LabelReadHowYouCanContribute": "Read about how you can contribute.", + "HeaderNewCollection": "New Collection", + "HeaderAddToCollection": "Add to Collection", + "ButtonSubmit": "Submit", + "NewCollectionNameExample": "Example: Star Wars Collection", + "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata", + "ButtonCreate": "Create", + "LabelHttpServerPortNumber": "Http server port number:", + "LabelWebSocketPortNumber": "Web socket port number:", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortHelp": "UPnP allows automated router configuration for remote access. This may not work with some router models.", + "LabelExternalDDNS": "External DDNS:", + "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.", + "TabResume": "Resume", + "TabWeather": "Weather", + "TitleAppSettings": "App Settings", + "LabelMinResumePercentage": "Min resume percentage:", + "LabelMaxResumePercentage": "Max resume percentage:", + "LabelMinResumeDuration": "Min resume duration (seconds):", + "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time", + "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time", + "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable", + "TitleAutoOrganize": "Auto-Organize", + "TabActivityLog": "Activity Log", + "HeaderName": "Name", + "HeaderDate": "Date", + "HeaderSource": "Source", + "HeaderStatus": "Status", + "HeaderDestination": "Destination", + "HeaderProgram": "Program", + "HeaderClients": "Clients", + "LabelCompleted": "Completed", + "LabelFailed": "Failed", + "LabelSkipped": "Skipped", + "HeaderEpisodeOrganization": "Episode Organization", + "LabelSeries": "Series:", + "LabelSeasonNumber": "Season number:", + "LabelEpisodeNumber": "Episode number:", + "LabelEndingEpisodeNumber": "Ending episode number:", + "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files", + "HeaderSupportTheTeam": "Support the Media Browser Team", + "LabelSupportAmount": "Amount (USD)", + "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.", + "ButtonEnterSupporterKey": "Enter supporter key", + "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.", + "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.", + "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.", + "OptionEnableEpisodeOrganization": "Enable new episode organization", + "LabelWatchFolder": "Watch folder:", + "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.", + "ButtonViewScheduledTasks": "View scheduled tasks", + "LabelMinFileSizeForOrganize": "Minimum file size (MB):", + "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.", + "LabelSeasonFolderPattern": "Season folder pattern:", + "LabelSeasonZeroFolderName": "Season zero folder name:", + "HeaderEpisodeFilePattern": "Episode file pattern", + "LabelEpisodePattern": "Episode pattern:", + "LabelMultiEpisodePattern": "Multi-Episode pattern:", + "HeaderSupportedPatterns": "Supported Patterns", + "HeaderTerm": "Term", + "HeaderPattern": "Pattern", + "HeaderResult": "Result", + "LabelDeleteEmptyFolders": "Delete empty folders after organizing", + "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.", + "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:", + "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt", + "OptionOverwriteExistingEpisodes": "Overwrite existing episodes", + "LabelTransferMethod": "Transfer method", + "OptionCopy": "Copy", + "OptionMove": "Move", + "LabelTransferMethodHelp": "Copy or move files from the watch folder", + "HeaderLatestNews": "Latest News", + "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser", + "HeaderRunningTasks": "Running Tasks", + "HeaderActiveDevices": "Active Devices", + "HeaderPendingInstallations": "Pending Installations", + "HeaerServerInformation": "Server Information", + "ButtonRestartNow": "Restart Now", + "ButtonRestart": "Restart", + "ButtonShutdown": "Shutdown", + "ButtonUpdateNow": "Update Now", + "PleaseUpdateManually": "Please shutdown the server and update manually.", + "NewServerVersionAvailable": "A new version of Media Browser Server is available!", + "ServerUpToDate": "Media Browser Server is up to date", + "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.", + "LabelComponentsUpdated": "The following components have been installed or updated:", + "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.", + "LabelDownMixAudioScale": "Audio boost when downmixing:", + "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.", + "ButtonLinkKeys": "Link Keys", + "LabelOldSupporterKey": "Old supporter key", + "LabelNewSupporterKey": "New supporter key", + "HeaderMultipleKeyLinking": "Multiple Key Linking", + "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.", + "LabelCurrentEmailAddress": "Current email address", + "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.", + "HeaderForgotKey": "Forgot Key", + "LabelEmailAddress": "Email address", + "LabelSupporterEmailAddress": "The email address that was used to purchase the key.", + "ButtonRetrieveKey": "Retrieve Key", + "LabelSupporterKey": "Supporter Key (paste from email)", + "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.", + "MessageInvalidKey": "Supporter key is missing or invalid.", + "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.", + "HeaderDisplaySettings": "Display Settings", + "TabPlayTo": "Play To", + "LabelEnableDlnaServer": "Enable Dlna server", + "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.", + "LabelEnableBlastAliveMessages": "Blast alive messages", + "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", + "LabelBlastMessageInterval": "Alive message interval (seconds)", + "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.", + "LabelDefaultUser": "Default user:", + "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", + "TitleDlna": "DLNA", + "TitleChannels": "Channels", + "HeaderServerSettings": "Server Settings", + "LabelWeatherDisplayLocation": "Weather display location:", + "LabelWeatherDisplayLocationHelp": "US zip code / City, State, Country / City, Country", + "LabelWeatherDisplayUnit": "Weather display unit:", + "OptionCelsius": "Celsius", + "OptionFahrenheit": "Fahrenheit", + "HeaderRequireManualLogin": "Require manual username entry for:", + "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.", + "OptionOtherApps": "Other apps", + "OptionMobileApps": "Mobile apps", + "HeaderNotificationList": "Click on a notification to configure it's sending options.", + "NotificationOptionApplicationUpdateAvailable": "Application update available", + "NotificationOptionApplicationUpdateInstalled": "Application update installed", + "NotificationOptionPluginUpdateInstalled": "Plugin update installed", + "NotificationOptionPluginInstalled": "Plugin installed", + "NotificationOptionPluginUninstalled": "Plugin uninstalled", + "NotificationOptionVideoPlayback": "Video playback started", + "NotificationOptionAudioPlayback": "Audio playback started", + "NotificationOptionGamePlayback": "Game playback started", + "NotificationOptionVideoPlaybackStopped": "Video playback stopped", + "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", + "NotificationOptionGamePlaybackStopped": "Game playback stopped", + "NotificationOptionTaskFailed": "Scheduled task failure", + "NotificationOptionInstallationFailed": "Installation failure", + "NotificationOptionNewLibraryContent": "New content added", + "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.", + "NotificationOptionServerRestartRequired": "Server restart required", + "LabelNotificationEnabled": "Enable this notification", + "LabelMonitorUsers": "Monitor activity from:", + "LabelSendNotificationToUsers": "Send the notification to:", + "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.", + "LabelUseNotificationServices": "Use the following services:", + "CategoryUser": "User", + "CategorySystem": "System", + "CategoryApplication": "Application", + "CategoryPlugin": "Plugin", + "LabelMessageTitle": "Message title:", + "LabelAvailableTokens": "Available tokens:", + "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.", + "OptionAllUsers": "All users", + "OptionAdminUsers": "Administrators", + "OptionCustomUsers": "Custom", + "ButtonArrowUp": "Up", + "ButtonArrowDown": "Down", + "ButtonArrowLeft": "Left", + "ButtonArrowRight": "Right", + "ButtonBack": "Back", + "ButtonInfo": "Info", + "ButtonOsd": "On screen display", + "ButtonPageUp": "Page Up", + "ButtonPageDown": "Page Down", + "PageAbbreviation": "PG", + "ButtonHome": "Home", + "ButtonSearch": "Search", + "ButtonSettings": "Settings", + "ButtonTakeScreenshot": "Capture Screenshot", + "ButtonLetterUp": "Letter Up", + "ButtonLetterDown": "Letter Down", + "PageButtonAbbreviation": "PG", + "LetterButtonAbbreviation": "A", + "TabNowPlaying": "Now Playing", + "TabNavigation": "Navigation", + "TabControls": "Controls", + "ButtonFullscreen": "Toggle fullscreen", + "ButtonScenes": "Scenes", + "ButtonSubtitles": "Subtitles", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", + "ButtonStop": "Stop", + "ButtonPlay": "Play", + "ButtonPause": "Pause", + "LabelGroupMoviesIntoCollections": "Group movies into collections", + "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.", + "NotificationOptionPluginError": "Plugin failure", + "ButtonVolumeUp": "Volume up", + "ButtonVolumeDown": "Volume down", + "ButtonMute": "Mute", + "HeaderLatestMedia": "Latest Media", + "OptionNoSubtitles": "No Subtitles", + "OptionSpecialFeatures": "Special Features", + "HeaderCollections": "Collections", + "HeaderChannels": "Channels", + "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", + "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", + "HeaderResponseProfile": "Response Profile", + "LabelType": "Type:", + "LabelProfileContainer": "Container:", + "LabelProfileVideoCodecs": "Video codecs:", + "LabelProfileAudioCodecs": "Audio codecs:", + "LabelProfileCodecs": "Codecs:", + "HeaderDirectPlayProfile": "Direct Play Profile", + "HeaderTranscodingProfile": "Transcoding Profile", + "HeaderCodecProfile": "Codec Profile", + "HeaderCodecProfileHelp": "Define additional conditions that must be met in order for a codec to be direct played.", + "HeaderContainerProfile": "Container Profile", + "HeaderContainerProfileHelp": "Define additional conditions that must be met in order for a file to be direct played.", + "OptionProfileVideo": "Video", + "OptionProfileAudio": "Audio", + "OptionProfileVideoAudio": "Video Audio", + "OptionProfilePhoto": "Photo", + "LabelUserLibrary": "User library:", + "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.", + "OptionPlainStorageFolders": "Display all folders as plain storage folders", + "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".", + "OptionPlainVideoItems": "Display all videos as plain video items", + "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", + "LabelSupportedMediaTypes": "Supported Media Types:", + "TabIdentification": "Identification", + "TabDirectPlay": "Direct Play", + "TabContainers": "Containers", + "TabCodecs": "Codecs", + "TabResponses": "Responses", + "HeaderProfileInformation": "Profile Information", + "LabelEmbedAlbumArtDidl": "Embed album art in Didl", + "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.", + "LabelAlbumArtPN": "Album art PN:", + "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.", + "LabelAlbumArtMaxWidth": "Album art max width:", + "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.", + "LabelAlbumArtMaxHeight": "Album art max height:", + "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.", + "LabelIconMaxWidth": "Icon max width:", + "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.", + "LabelIconMaxHeight": "Icon max height:", + "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.", + "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", + "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.", + "LabelMaxBitrate": "Max bitrate:", + "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.", + "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", + "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.", + "LabelFriendlyName": "Friendly name", + "LabelManufacturer": "Manufacturer", + "LabelManufacturerUrl": "Manufacturer url", + "LabelModelName": "Model name", + "LabelModelNumber": "Model number", + "LabelModelDescription": "Model description", + "LabelModelUrl": "Model url", + "LabelSerialNumber": "Serial number", + "LabelDeviceDescription": "Device description", + "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", + "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.", + "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", + "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.", + "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.", + "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", + "LabelXDlnaCap": "X-Dlna cap:", + "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelXDlnaDoc": "X-Dlna doc:", + "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.", + "LabelSonyAggregationFlags": "Sony aggregation flags:", + "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.", + "LabelTranscodingContainer": "Container:", + "LabelTranscodingVideoCodec": "Video codec:", + "LabelTranscodingVideoProfile": "Video profile:", + "LabelTranscodingAudioCodec": "Audio codec:", + "OptionEnableM2tsMode": "Enable M2ts mode", + "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.", + "OptionEstimateContentLength": "Estimate content length when transcoding", + "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", + "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", + "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.", + "HeaderDownloadSubtitlesFor": "Download subtitles for:", + "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.", + "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles", + "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.", + "TabSubtitles": "Subtitles", + "TabChapters": "Chapters", + "HeaderDownloadChaptersFor": "Download chapter names for:", + "LabelOpenSubtitlesUsername": "Open Subtitles username:", + "LabelOpenSubtitlesPassword": "Open Subtitles password:", + "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.", + "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language", + "LabelSubtitlePlaybackMode": "Subtitle mode:", + "LabelDownloadLanguages": "Download languages:", + "ButtonRegister": "Register", + "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language", + "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.", + "HeaderSendMessage": "Send Message", + "ButtonSend": "Send", + "LabelMessageText": "Message text:", + "LabelMessageTitle": "Message title:", + "MessageNoAvailablePlugins": "No available plugins.", + "LabelDisplayPluginsFor": "Display plugins for:", + "PluginTabMediaBrowserClassic": "MB Classic", + "PluginTabMediaBrowserTheater": "MB Theater", + "LabelEpisodeName": "Episode name", + "LabelSeriesName": "Series name", + "ValueSeriesNamePeriod": "Series.name", + "ValueSeriesNameUnderscore": "Series_name", + "ValueEpisodeNamePeriod": "Episode.name", + "ValueEpisodeNameUnderscore": "Episode_name", + "LabelSeasonNumber": "Season number", + "LabelEpisodeNumber": "Episode number", + "LabelEndingEpisodeNumber": "Ending episode number", + "HeaderTypeText": "Enter Text", + "LabelTypeText": "Text", + "HeaderSearchForSubtitles": "Search for Subtitles", + "MessageNoSubtitleSearchResultsFound": "No search results founds.", + "TabDisplay": "Display", + "TabLanguages": "Languages", + "TabWebClient": "Web Client", + "LabelEnableThemeSongs": "Enable theme songs", + "LabelEnableBackdrops": "Enable backdrops", + "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.", + "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.", + "HeaderHomePage": "Home Page", + "HeaderSettingsForThisDevice": "Settings for This Device", + "OptionAuto": "Auto", + "OptionYes": "Yes", + "OptionNo": "No", + "LabelHomePageSection1": "Home page section one:", + "LabelHomePageSection2": "Home page section two:", + "LabelHomePageSection3": "Home page section three:", + "LabelHomePageSection4": "Home page section four:", + "OptionMyViewsButtons": "My views (buttons)", + "OptionMyViews": "My views", + "OptionMyViewsSmall": "My views (small)", + "OptionResumablemedia": "Resume", + "OptionLatestMedia": "Latest media", + "OptionLatestChannelMedia": "Latest channel items", + "HeaderLatestChannelItems": "Latest Channel Items", + "OptionNone": "None", + "HeaderLiveTv": "Live TV", + "HeaderReports": "Reports", + "HeaderMetadataManager": "Metadata Manager", + "HeaderPreferences": "Preferences", + "MessageLoadingChannels": "Loading channel content...", + "ButtonMarkRead": "Mark Read", + "OptionDefaultSort": "Default", + "OptionCommunityMostWatchedSort": "Most Watched", + "TabNextUp": "Next Up", + "MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.", + "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the New button to start creating Collections.", + "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client", + "ButtonDismiss": "Dismiss", + "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.", + "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.", + "LabelChannelStreamQuality": "Preferred internet stream quality:", + "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.", + "OptionBestAvailableStreamQuality": "Best available", + "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:", + "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.", + "LabelChannelDownloadPath": "Channel content download path:", + "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.", + "LabelChannelDownloadAge": "Delete content after: (days)", + "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.", + "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.", + "LabelSelectCollection": "Select collection:", + "ViewTypeMovies": "Movies", + "ViewTypeTvShows": "TV", + "ViewTypeGames": "Games", + "ViewTypeMusic": "Music", + "ViewTypeBoxSets": "Collections", + "ViewTypeChannels": "Channels", + "ViewTypeLiveTV": "Live TV", + "HeaderOtherDisplaySettings": "Display Settings", + "HeaderMyViews": "My Views", + "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", + "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", + "OptionDisplayAdultContent": "Display adult content", + "OptionLibraryFolders": "Media folders", + "TitleRemoteControl": "Remote Control", + "OptionLatestTvRecordings": "Latest recordings", + "LabelProtocolInfo": "Protocol info:", + "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", + "TabXbmcMetadata": "Xbmc", + "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.", + "LabelXbmcMetadataUser": "Add user watch data to nfo's for:", + "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.", + "LabelXbmcMetadataDateFormat": "Release date format:", + "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.", + "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files", + "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.", + "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution", + "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.", + "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.", + "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:", + "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.", + "LabelDisplayCollectionsView": "Display a collections view to show movie collections", + "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs", + "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.", + "TabServices": "Services", + "TabLogs": "Logs", + "HeaderServerLogFiles": "Server log files:", + "TabBranding": "Branding", + "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.", + "LabelLoginDisclaimer": "Login disclaimer:", + "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.", + "LabelAutomaticallyDonate": "Automatically donate this amount every six months", + "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.", + "OptionList": "List", + "TabDashboard": "Dashboard", + "TitleServer": "Server", + "LabelCache": "Cache:", + "LabelLogs": "Logs:", + "LabelMetadata": "Metadata:", + "LabelImagesByName": "Images by name:", + "LabelTranscodingTemporaryFiles": "Transcoding temporary files:", + "HeaderLatestMusic": "Latest Music", + "HeaderBranding": "Branding", + "HeaderApiKeys": "Api Keys", + "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.", + "HeaderApiKey": "Api Key", + "HeaderApp": "App", + "HeaderDevice": "Device", + "HeaderUser": "User", + "HeaderDateIssued": "Date Issued", + "LabelChapterName": "Chapter {0}", + "HeaderNewApiKey": "New Api Key", + "LabelAppName": "App name", + "LabelAppNameExample": "Example: Sickbeard, NzbDrone", + "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.", + "ButtonEnterSupporterKey": "Enter supporter key", + "HeaderHttpHeaders": "Http Headers", + "HeaderIdentificationHeader": "Identification Header", + "LabelValue": "Value:", + "LabelMatchType": "Match type:", + "OptionEquals": "Equals", + "OptionRegex": "Regex", + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced", + "ButtonSync": "Sync" +} diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sv.json b/MediaBrowser.Server.Implementations/Localization/Server/sv.json index 75e204f684..e28dfe231a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/sv.json @@ -199,6 +199,7 @@ "OptionFriday": "Fredag", "OptionSaturday": "L\u00f6rdag", "HeaderManagement": "Administration:", + "LabelManagement": "Management:", "OptionMissingImdbId": "IMDB-ID saknas", "OptionMissingTvdbId": "TVDB-ID saknas", "OptionMissingOverview": "Synopsis saknas", @@ -479,10 +480,10 @@ "HeaderProgram": "Program", "HeaderClients": "Klienter", "LabelCompleted": "Klar", - "LabelFailed": "Misslyckades", + "LabelFailed": "Failed", "LabelSkipped": "Hoppades \u00f6ver", "HeaderEpisodeOrganization": "Katalogisering av avsnitt", - "LabelSeries": "Serie:", + "LabelSeries": "Series:", "LabelSeasonNumber": "S\u00e4songsnummer:", "LabelEpisodeNumber": "Avsnittsnummer:", "LabelEndingEpisodeNumber": "Avslutande avsnittsnummer:", @@ -626,12 +627,12 @@ "TabNowPlaying": "Nu spelas", "TabNavigation": "Navigering", "TabControls": "Kontroller", - "ButtonFullscreen": "V\u00e4xla fullsk\u00e4rmsl\u00e4ge", + "ButtonFullscreen": "Toggle fullscreen", "ButtonScenes": "Scener", "ButtonSubtitles": "Undertexter", - "ButtonAudioTracks": "Ljudsp\u00e5r", - "ButtonPreviousTrack": "F\u00f6reg\u00e5ende sp\u00e5r", - "ButtonNextTrack": "N\u00e4sta sp\u00e5r", + "ButtonAudioTracks": "Audio tracks", + "ButtonPreviousTrack": "Previous track", + "ButtonNextTrack": "Next track", "ButtonStop": "Stopp", "ButtonPause": "Paus", "LabelGroupMoviesIntoCollections": "Gruppera filmer i samlingsboxar", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/vi.json b/MediaBrowser.Server.Implementations/Localization/Server/vi.json index cc5a77433a..78f308b336 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/vi.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/vi.json @@ -190,7 +190,7 @@ "HeaderStatus": "Tr\u1ea1ng th\u00e1i", "OptionContinuing": "Continuing", "OptionEnded": "Ended", - "HeaderAirDays": "Air Days:", + "HeaderAirDays": "Air Days", "OptionSunday": "Ch\u1ee7 Nh\u1eadt", "OptionMonday": "Th\u1ee9 Hai", "OptionTuesday": "Tuesday", @@ -199,6 +199,7 @@ "OptionFriday": "Friday", "OptionSaturday": "Th\u1ee9 B\u1ea3y", "HeaderManagement": "Qu\u1ea3n l\u00fd:", + "LabelManagement": "Management:", "OptionMissingImdbId": "Thi\u1ebfu IMDb ID", "OptionMissingTvdbId": "Missing TheTVDB Id", "OptionMissingOverview": "Missing Overview", @@ -256,11 +257,11 @@ "ButtonSelectDirectory": "L\u1ef1a ch\u1ecdn tr\u1ef1c ti\u1ebfp", "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.", "LabelCachePath": "Cache path:", - "LabelCachePathHelp": "This folder contains server cache files, such as images.", + "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.", "LabelImagesByNamePath": "Images by name path:", - "LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.", + "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.", "LabelMetadataPath": "Metadata path:", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "Transcoding temporary path:", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "Basics", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json index c2c8f50025..e67aa9f581 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json @@ -199,6 +199,7 @@ "OptionFriday": "\u661f\u671f\u4e94", "OptionSaturday": "\u661f\u671f\u516d", "HeaderManagement": "\u7ba1\u7406\uff1a", + "LabelManagement": "Management:", "OptionMissingImdbId": "\u7f3a\u5c11IMDB\u7de8\u865f", "OptionMissingTvdbId": "\u7f3a\u5c11TheTVDB\u7de8\u865f", "OptionMissingOverview": "\u7f3a\u5c11\u6982\u8ff0", @@ -260,7 +261,7 @@ "LabelImagesByNamePath": "\u540d\u7a31\u5716\u50cf\u6587\u4ef6\u593e\u8def\u5f91\uff1a", "LabelImagesByNamePathHelp": "\u6b64\u6587\u4ef6\u593e\u5305\u542b\u6f14\u54e1\uff0c\u6b4c\u624b\uff0c\u5a92\u9ad4\u7a2e\u985e\u548c\u5de5\u4f5c\u5ba4\u7684\u5716\u50cf\u3002", "LabelMetadataPath": "\u5a92\u9ad4\u8cc7\u6599\u6587\u4ef6\u593e\u8def\u5f91\uff1a", - "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.", + "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.", "LabelTranscodingTempPath": "\u8f49\u78bc\u81e8\u6642\u8def\u5f91\uff1a", "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.", "TabBasics": "\u57fa\u672c", @@ -396,7 +397,7 @@ "HeaderCastCrew": "\u62cd\u651d\u4eba\u54e1\u53ca\u6f14\u54e1", "HeaderAdditionalParts": "\u9644\u52a0\u90e8\u4efd", "ButtonSplitVersionsApart": "Split Versions Apart", - "ButtonPlayTrailer": "\u9810\u544a", + "ButtonPlayTrailer": "Trailer", "LabelMissing": "\u7f3a\u5c11", "LabelOffline": "\u96e2\u7dda", "PathSubstitutionHelp": "Path substitutions are used for mapping a path on the server to a path that clients are able to access. By allowing clients direct access to media on the server they may be able to play them directly over the network and avoid using server resources to stream and transcode them.", @@ -874,5 +875,14 @@ "LabelMatchType": "Match type:", "OptionEquals": "Equals", "OptionRegex": "Regex", - "OptionSubstring": "Substring" + "OptionSubstring": "Substring", + "TabView": "View", + "TabSort": "Sort", + "TabFilter": "Filter", + "ButtonView": "View", + "LabelPageSize": "Item limit:", + "LabelView": "View:", + "TabUsers": "Users", + "HeaderFeatures": "Features", + "HeaderAdvanced": "Advanced" } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs index 6f14bb3223..a65184f615 100644 --- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs +++ b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs @@ -249,13 +249,13 @@ namespace MediaBrowser.Server.Implementations.ServerManager _logger.Info("Sending web socket message {0}", messageType); var message = new WebSocketMessage { MessageType = messageType, Data = dataFunction() }; - var bytes = _jsonSerializer.SerializeToBytes(message); + var json = _jsonSerializer.SerializeToString(message); var tasks = connectionsList.Select(s => Task.Run(() => { try { - s.SendAsync(bytes, cancellationToken); + s.SendAsync(json, cancellationToken); } catch (OperationCanceledException) { @@ -265,7 +265,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager { _logger.ErrorException("Error sending web socket message {0} to {1}", ex, messageType, s.RemoteEndPoint); } - })); + + }, cancellationToken)); await Task.WhenAll(tasks).ConfigureAwait(false); } diff --git a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs index 2b60f31160..3c3d7740a0 100644 --- a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs +++ b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs @@ -194,9 +194,9 @@ namespace MediaBrowser.Server.Implementations.ServerManager throw new ArgumentNullException("message"); } - var bytes = _jsonSerializer.SerializeToBytes(message); + var json = _jsonSerializer.SerializeToString(message); - return SendAsync(bytes, cancellationToken); + return SendAsync(json, cancellationToken); } /// @@ -205,24 +205,46 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// The buffer. /// The cancellation token. /// Task. - public Task SendAsync(byte[] buffer, CancellationToken cancellationToken) + public async Task SendAsync(byte[] buffer, CancellationToken cancellationToken) { - return SendAsync(buffer, WebSocketMessageType.Text, cancellationToken); + if (buffer == null) + { + throw new ArgumentNullException("buffer"); + } + + cancellationToken.ThrowIfCancellationRequested(); + + // Per msdn docs, attempting to send simultaneous messages will result in one failing. + // This should help us workaround that and ensure all messages get sent + await _sendSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + await _socket.SendAsync(buffer, true, cancellationToken); + } + catch (OperationCanceledException) + { + _logger.Info("WebSocket message to {0} was cancelled", RemoteEndPoint); + + throw; + } + catch (Exception ex) + { + _logger.ErrorException("Error sending WebSocket message {0}", ex, RemoteEndPoint); + + throw; + } + finally + { + _sendSemaphore.Release(); + } } - /// - /// Sends a message asynchronously. - /// - /// The buffer. - /// The type. - /// The cancellation token. - /// Task. - /// buffer - public async Task SendAsync(byte[] buffer, WebSocketMessageType type, CancellationToken cancellationToken) + public async Task SendAsync(string text, CancellationToken cancellationToken) { - if (buffer == null) + if (string.IsNullOrWhiteSpace(text)) { - throw new ArgumentNullException("buffer"); + throw new ArgumentNullException("text"); } cancellationToken.ThrowIfCancellationRequested(); @@ -233,7 +255,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager try { - await _socket.SendAsync(buffer, type, true, cancellationToken); + await _socket.SendAsync(text, true, cancellationToken); } catch (OperationCanceledException) { diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 3d6865f854..7c36a7c5eb 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -208,12 +208,13 @@ namespace MediaBrowser.ServerApplication private IUserViewManager UserViewManager { get; set; } private IAuthenticationRepository AuthenticationRepository { get; set; } - + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The application paths. /// The log manager. + /// if set to true [is running as service]. public ApplicationHost(ServerApplicationPaths applicationPaths, ILogManager logManager, bool isRunningAsService) : base(applicationPaths, logManager) { @@ -284,7 +285,6 @@ namespace MediaBrowser.ServerApplication await base.Init(progress).ConfigureAwait(false); MigrateModularConfigurations(); - ApplyDefaultMetadataSettings(); } private void PerformVersionMigration() @@ -330,21 +330,6 @@ namespace MediaBrowser.ServerApplication } } - private void ApplyDefaultMetadataSettings() - { - if (!ServerConfigurationManager.Configuration.DefaultMetadataSettingsApplied && - ServerConfigurationManager.Configuration.IsStartupWizardCompleted) - { - // Make sure xbmc metadata is disabled for existing users. - // New users will be handled by the startup wizard. - - ServerConfigurationManager.DisableMetadataService("Xbmc Nfo"); - } - - ServerConfigurationManager.Configuration.DefaultMetadataSettingsApplied = true; - ServerConfigurationManager.SaveConfiguration(); - } - private void DeleteDeprecatedModules() { try @@ -1111,7 +1096,6 @@ namespace MediaBrowser.ServerApplication ServerAuthorization.AuthorizeServer( ServerConfigurationManager.Configuration.HttpServerPortNumber, HttpServerUrlPrefixes.First(), - ServerConfigurationManager.Configuration.LegacyWebSocketPortNumber, UdpServerEntryPoint.PortNumber, ConfigurationManager.CommonApplicationPaths.TempDirectory); } diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 9e31fc800c..f8b03bbc25 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -194,13 +194,7 @@ namespace MediaBrowser.ServerApplication private static void BeginLog(ILogger logger, IApplicationPaths appPaths) { logger.Info("Media Browser Server started"); - logger.Info("Command line: {0}", string.Join(" ", Environment.GetCommandLineArgs())); - - logger.Info("Server: {0}", Environment.MachineName); - logger.Info("Operating system: {0}", Environment.OSVersion.ToString()); - logger.Info("Program data path: {0}", appPaths.ProgramDataPath); - - logger.Info("Application Path: {0}", appPaths.ApplicationPath); + ApplicationHost.LogEnvironmentInfo(logger, appPaths); } private static readonly TaskCompletionSource ApplicationTaskCompletionSource = new TaskCompletionSource(); diff --git a/MediaBrowser.ServerApplication/Native/RegisterServer.bat b/MediaBrowser.ServerApplication/Native/RegisterServer.bat index d762dfaf76..3504123444 100644 --- a/MediaBrowser.ServerApplication/Native/RegisterServer.bat +++ b/MediaBrowser.ServerApplication/Native/RegisterServer.bat @@ -1,7 +1,6 @@ rem %1 = http server port rem %2 = http server url rem %3 = udp server port -rem %4 = tcp server port (web socket) if [%1]==[] GOTO DONE @@ -18,11 +17,6 @@ if [%3]==[] GOTO DONE netsh advfirewall firewall delete rule name="Port %3" protocol=UDP localport=%3 netsh advfirewall firewall add rule name="Port %3" dir=in action=allow protocol=UDP localport=%3 -if [%4]==[] GOTO DONE - -netsh advfirewall firewall delete rule name="Port %4" protocol=TCP localport=%4 -netsh advfirewall firewall add rule name="Port %4" dir=in action=allow protocol=TCP localport=%4 - :DONE Exit \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs b/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs index d2e5425367..e5989db3bf 100644 --- a/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs +++ b/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs @@ -15,10 +15,9 @@ namespace MediaBrowser.ServerApplication.Native /// /// The HTTP server port. /// The HTTP server URL prefix. - /// The web socket port. /// The UDP port. /// The temp directory. - public static void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int webSocketPort, int udpPort, string tempDirectory) + public static void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int udpPort, string tempDirectory) { Directory.CreateDirectory(tempDirectory); @@ -38,10 +37,9 @@ namespace MediaBrowser.ServerApplication.Native { FileName = tmpFile, - Arguments = string.Format("{0} {1} {2} {3}", httpServerPort, + Arguments = string.Format("{0} {1} {2}", httpServerPort, httpServerUrlPrefix, - udpPort, - webSocketPort), + udpPort), CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, diff --git a/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs b/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs index cbd0ce4a18..545894b0d1 100644 --- a/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs +++ b/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs @@ -1,5 +1,4 @@ using MediaBrowser.Controller.Providers; -using MediaBrowser.Providers.Movies; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace MediaBrowser.Tests.Providers { @@ -20,12 +19,6 @@ namespace MediaBrowser.Tests.Providers { Assert.AreEqual("My Movie 2", name); Assert.AreEqual(2013, year); - name = string.Empty; - year = null; - NameParser.ParseName("2013 - My Movie 2", out name, out year); - Assert.AreEqual(2013, year); - Assert.AreEqual("My Movie 2", name); - name = string.Empty; year = null; NameParser.ParseName("My Movie 2001 (2013)", out name, out year); diff --git a/MediaBrowser.Tests/Resolvers/TvUtilTests.cs b/MediaBrowser.Tests/Resolvers/TvUtilTests.cs index 725a5edcbe..104e634472 100644 --- a/MediaBrowser.Tests/Resolvers/TvUtilTests.cs +++ b/MediaBrowser.Tests/Resolvers/TvUtilTests.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Tests.Resolvers [TestMethod] public void TestGetEpisodeNumberFromFile() { - Assert.AreEqual(03, TVUtils.GetEpisodeNumberFromFile(@"S02E03 blah.avi", true)); + Assert.AreEqual(03, TVUtils.GetEpisodeNumberFromFile(@"Season 02\S02E03 blah.avi", true)); Assert.AreEqual(02, TVUtils.GetEpisodeNumberFromFile(@"Season 1\01x02 blah.avi", true)); Assert.AreEqual(02, TVUtils.GetEpisodeNumberFromFile(@"Season 1\S01x02 blah.avi", true)); diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index b50cb254fc..64c055ba00 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -446,7 +446,7 @@ namespace MediaBrowser.WebDashboard.Api var newLineBytes = Encoding.UTF8.GetBytes(Environment.NewLine); // jQuery + jQuery mobile - await AppendResource(memoryStream, "thirdparty/jquery-2.0.3.min.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/jquery-2.1.1.min.js", newLineBytes).ConfigureAwait(false); await AppendResource(memoryStream, "thirdparty/jquerymobile-1.4.3/jquery.mobile-1.4.3.min.js", newLineBytes).ConfigureAwait(false); await AppendResource(memoryStream, "thirdparty/jquery.unveil-custom.js", newLineBytes).ConfigureAwait(false); @@ -534,8 +534,6 @@ namespace MediaBrowser.WebDashboard.Api "alphapicker.js", "addpluginpage.js", "advancedconfigurationpage.js", - "advancedpaths.js", - "advancedserversettings.js", "metadataadvanced.js", "appsplayback.js", "autoorganizetv.js", diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 176094b752..06a44d747c 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -89,12 +89,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - PreserveNewest @@ -590,12 +584,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - PreserveNewest @@ -800,6 +788,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest -- cgit v1.2.3 From 063675bb07f78f99738a3ada061f3e2c16c9cda0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 27 Jul 2014 18:01:29 -0400 Subject: updated nuget --- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 14 +++- MediaBrowser.Api/SystemService.cs | 20 ++++++ MediaBrowser.Controller/IServerApplicationHost.cs | 6 ++ MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs | 8 +++ MediaBrowser.Dlna/Didl/DidlBuilder.cs | 2 +- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 4 +- MediaBrowser.Dlna/Profiles/DefaultProfile.cs | 3 +- MediaBrowser.Dlna/Profiles/Xml/Android.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/Default.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml | 3 +- .../Profiles/Xml/Samsung Smart TV.xml | 3 +- .../Profiles/Xml/Sony Blu-ray Player 2013.xml | 3 +- .../Profiles/Xml/Sony Blu-ray Player.xml | 3 +- .../Profiles/Xml/Sony Bravia (2010).xml | 3 +- .../Profiles/Xml/Sony Bravia (2011).xml | 3 +- .../Profiles/Xml/Sony Bravia (2012).xml | 3 +- .../Profiles/Xml/Sony Bravia (2013).xml | 3 +- .../Profiles/Xml/Sony PlayStation 3.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml | 3 +- MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml | 3 +- .../MediaBrowser.Model.Portable.csproj | 3 + .../MediaBrowser.Model.net35.csproj | 3 + MediaBrowser.Model/ApiClient/IApiClient.cs | 60 ++++++++++++----- .../ApiClient/ServerDiscoveryInfo.cs | 22 +++++++ .../Configuration/ServerConfiguration.cs | 1 - MediaBrowser.Model/Dlna/AudioOptions.cs | 24 +++++++ MediaBrowser.Model/Dlna/DeviceProfile.cs | 5 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 4 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + MediaBrowser.Model/Sync/SyncJobStatus.cs | 2 +- MediaBrowser.Model/System/SystemInfo.cs | 41 ++++++------ MediaBrowser.Model/Users/AuthenticationResult.cs | 6 ++ MediaBrowser.Providers/Manager/ProviderManager.cs | 12 +--- .../Configuration/ServerConfigurationManager.cs | 4 +- .../Dto/DtoService.cs | 25 +++++-- .../EntryPoints/UdpServerEntryPoint.cs | 7 +- .../LiveTv/LiveTvConfigurationFactory.cs | 21 ++++++ .../LiveTv/LiveTvManager.cs | 33 ++++------ .../Localization/Server/server.json | 12 +++- .../MediaBrowser.Server.Implementations.csproj | 1 + .../Security/EncryptionManager.cs | 24 +++++++ .../Session/SessionManager.cs | 3 +- .../Sync/SyncManager.cs | 3 +- .../Udp/UdpServer.cs | 76 +++++++++++++++++----- MediaBrowser.ServerApplication/ApplicationHost.cs | 14 +++- .../MediaBrowser.WebDashboard.csproj | 3 - Nuget/MediaBrowser.Common.Internal.nuspec | 6 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Model.Signed.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 58 files changed, 403 insertions(+), 141 deletions(-) create mode 100644 MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 5e49fbf7aa..fc1c627e94 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -269,10 +269,18 @@ namespace MediaBrowser.Api.Playback.Hls var segmentFilename = Path.GetFileName(segmentPath); - // If it appears in the playlist, it's done - if (File.ReadAllText(playlistPath).IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1) + using (var fileStream = FileSystem.GetFileStream(playlistPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { - return ResultFactory.GetStaticFileResult(Request, segmentPath, FileShare.ReadWrite); + using (var reader = new StreamReader(fileStream)) + { + var text = await reader.ReadToEndAsync().ConfigureAwait(false); + + // If it appears in the playlist, it's done + if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1) + { + return ResultFactory.GetStaticFileResult(Request, segmentPath, FileShare.ReadWrite); + } + } } // if a different file is encoding, it's done diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs index f336736be8..e31e66d19d 100644 --- a/MediaBrowser.Api/SystemService.cs +++ b/MediaBrowser.Api/SystemService.cs @@ -21,6 +21,12 @@ namespace MediaBrowser.Api } + [Route("/System/Info/Public", "GET", Summary = "Gets public information about the server")] + public class GetPublicSystemInfo : IReturn + { + + } + /// /// Class RestartApplication /// @@ -125,6 +131,20 @@ namespace MediaBrowser.Api return ToOptimizedResult(result); } + public object Get(GetPublicSystemInfo request) + { + var result = _appHost.GetSystemInfo(); + + var publicInfo = new PublicSystemInfo + { + Id = result.Id, + ServerName = result.ServerName, + Version = result.Version + }; + + return ToOptimizedResult(publicInfo); + } + /// /// Posts the specified request. /// diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 21f5fa87a3..49061e05c7 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -40,5 +40,11 @@ namespace MediaBrowser.Controller /// /// true if this instance has update available; otherwise, false. bool HasUpdateAvailable { get; } + + /// + /// Gets or sets the server identifier. + /// + /// The server identifier. + string ServerId { get; } } } diff --git a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs index fc5fd4061e..cc5cb1b1a2 100644 --- a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs +++ b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs @@ -201,6 +201,14 @@ namespace MediaBrowser.Dlna.Channels private readonly ILogger _logger; private readonly string _controlUrl; + /// + /// Prevents core from throwing an exception + /// + public ServerChannel() + { + + } + public ServerChannel(List servers, IHttpClient httpClient, ILogger logger, string controlUrl) { _servers = servers; diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 746931b680..739793c032 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -108,7 +108,7 @@ namespace MediaBrowser.Dlna.Didl MediaSources = sources, Profile = _profile, DeviceId = deviceId, - MaxBitrate = _profile.MaxBitrate + MaxBitrate = _profile.MaxStreamingBitrate }); } diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index eb4eb38895..d81e460492 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -537,7 +537,7 @@ namespace MediaBrowser.Dlna.PlayTo MediaSources = mediaSources, Profile = profile, DeviceId = deviceId, - MaxBitrate = profile.MaxBitrate, + MaxBitrate = profile.MaxStreamingBitrate, MediaSourceId = mediaSourceId, AudioStreamIndex = audioStreamIndex, SubtitleStreamIndex = subtitleStreamIndex @@ -557,7 +557,7 @@ namespace MediaBrowser.Dlna.PlayTo MediaSources = mediaSources, Profile = profile, DeviceId = deviceId, - MaxBitrate = profile.MaxBitrate, + MaxBitrate = profile.MaxStreamingBitrate, MediaSourceId = mediaSourceId }), diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs index 9a1992b658..0696b2691c 100644 --- a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs @@ -27,7 +27,8 @@ namespace MediaBrowser.Dlna.Profiles MaxAlbumArtHeight = 512; MaxAlbumArtWidth = 512; - MaxBitrate = 8000000; + MaxStreamingBitrate = 8000000; + MaxStaticBitrate = 8000000; TranscodingProfiles = new[] { diff --git a/MediaBrowser.Dlna/Profiles/Xml/Android.xml b/MediaBrowser.Dlna/Profiles/Xml/Android.xml index e3630bf5e4..8d7b5ea2a8 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Android.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Android.xml @@ -16,7 +16,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml index 07ffc1d2ed..4cc1eca5d4 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml @@ -16,7 +16,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml index a9fdca710f..e25224727f 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml @@ -21,7 +21,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml index c9d17e4a2c..26183da034 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml @@ -22,7 +22,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 10 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml index 6b09e7f94b..0c736cbff8 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml @@ -20,7 +20,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml index 4bcd86b278..39174d85a8 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml @@ -22,7 +22,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml index 9e0763d143..0166160149 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml @@ -23,7 +23,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 10 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml index cb901910d8..980983f130 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml @@ -22,7 +22,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml index 6ef76a5a9e..749b7a1339 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml @@ -22,7 +22,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml index 2ae79f7d63..aa73bc91d9 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml @@ -24,7 +24,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml index 29cbf0e6aa..1b133d8906 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml @@ -23,7 +23,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 10 http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml index 01d332e1c1..29e2a3d712 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml @@ -23,7 +23,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 10 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml index 0f1b2b140e..9805485a3d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml @@ -23,7 +23,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 10 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml index b1f3aabc94..e3068f23e8 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml @@ -23,7 +23,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 10 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml index 2371e1474a..98c781915d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml @@ -23,7 +23,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 10 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 diff --git a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml index 89714d9bcc..fedc1db6a3 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml @@ -23,7 +23,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 5 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml b/MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml index fbc6b6bc81..384a27ca57 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml @@ -20,7 +20,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml b/MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml index a05ad3123d..aec5b44cb7 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml @@ -16,7 +16,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml index fa0f10e26c..17dd473be6 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml @@ -23,7 +23,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 40 diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml index 0c83fce07d..e23ad92136 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml @@ -21,7 +21,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml index 5d50274a7d..53d43a7e47 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml @@ -22,7 +22,8 @@ 512 - 8000000 + 8000000 + 8000000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 0 diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index c397cdcd52..e55d3eec9b 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -98,6 +98,9 @@ ApiClient\IServerEvents.cs + + ApiClient\ServerDiscoveryInfo.cs + ApiClient\SessionUpdatesEventArgs.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 1b74fcf51c..603eecbaed 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -61,6 +61,9 @@ ApiClient\IServerEvents.cs + + ApiClient\ServerDiscoveryInfo.cs + ApiClient\SessionUpdatesEventArgs.cs diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 80a9ec3c4a..e1c736f848 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -226,7 +226,7 @@ namespace MediaBrowser.Model.ApiClient /// The user identifier. /// Task{BaseItemDto[]}. Task GetAdditionalParts(string itemId, string userId); - + /// /// Gets the users async. /// @@ -253,7 +253,7 @@ namespace MediaBrowser.Model.ApiClient /// /// Task{SessionInfoDto}. Task GetCurrentSessionAsync(CancellationToken cancellationToken); - + /// /// Gets the item counts async. /// @@ -368,7 +368,7 @@ namespace MediaBrowser.Model.ApiClient /// The query. /// Task{ItemsResult}. Task GetAlbumArtistsAsync(ArtistsQuery query); - + /// /// Gets a studio /// @@ -467,6 +467,13 @@ namespace MediaBrowser.Model.ApiClient /// Task{SystemInfo}. Task GetSystemInfoAsync(CancellationToken cancellationToken); + /// + /// Gets the public system information asynchronous. + /// + /// The cancellation token. + /// Task<PublicSystemInfo>. + Task GetPublicSystemInfoAsync(CancellationToken cancellationToken); + /// /// Gets a person /// @@ -672,7 +679,7 @@ namespace MediaBrowser.Model.ApiClient /// The index. /// Task. Task SetSubtitleStreamIndex(string sessionId, int? index); - + /// /// Instructs the client to display a message to the user /// @@ -772,23 +779,16 @@ namespace MediaBrowser.Model.ApiClient IJsonSerializer JsonSerializer { get; set; } /// - /// Gets or sets the server host name (myserver or 192.168.x.x) - /// - /// The name of the server host. - string ServerHostName { get; } - - /// - /// Gets or sets the port number used by the API + /// Gets or sets the server address /// - /// The server API port. - int ServerApiPort { get; } + /// The server address. + string ServerAddress { get; } /// /// Changes the server location. /// - /// Name of the host. - /// The API port. - void ChangeServerLocation(string hostName, int apiPort); + /// The address. + void ChangeServerLocation(string address); /// /// Gets or sets the type of the client. @@ -812,7 +812,31 @@ namespace MediaBrowser.Model.ApiClient /// Gets or sets the current user id. /// /// The current user id. - string CurrentUserId { get; set; } + string CurrentUserId { get; } + + /// + /// Gets the access token. + /// + /// The access token. + string AccessToken { get; } + + /// + /// Sets the authentication information. + /// + /// The access token. + /// The user identifier. + void SetAuthenticationInfo(string accessToken, string userId); + + /// + /// Sets the authentication information. + /// + /// The access token. + void SetAuthenticationInfo(string accessToken); + + /// + /// Clears the authentication information. + /// + void ClearAuthenticationInfo(); /// /// Gets the image URL. @@ -853,7 +877,7 @@ namespace MediaBrowser.Model.ApiClient /// The options. /// System.String. string GetSubtitleUrl(SubtitleDownloadOptions options); - + /// /// Gets an image url that can be used to download an image from the api /// diff --git a/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs b/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs new file mode 100644 index 0000000000..bb2b48e76f --- /dev/null +++ b/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs @@ -0,0 +1,22 @@ + +namespace MediaBrowser.Model.ApiClient +{ + public class ServerDiscoveryInfo + { + /// + /// Gets or sets the address. + /// + /// The address. + public string Address { get; set; } + /// + /// Gets or sets the server identifier. + /// + /// The server identifier. + public string Id { get; set; } + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; set; } + } +} diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 3448a2905f..00f7add14c 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -304,7 +304,6 @@ namespace MediaBrowser.Model.Configuration }; SubtitleOptions = new SubtitleOptions(); - LiveTvOptions = new LiveTvOptions(); TvFileOrganizationOptions = new TvFileOrganizationOptions(); } } diff --git a/MediaBrowser.Model/Dlna/AudioOptions.cs b/MediaBrowser.Model/Dlna/AudioOptions.cs index 6e630ee55a..9b54f7e16f 100644 --- a/MediaBrowser.Model/Dlna/AudioOptions.cs +++ b/MediaBrowser.Model/Dlna/AudioOptions.cs @@ -35,5 +35,29 @@ namespace MediaBrowser.Model.Dlna /// /// The context. public EncodingContext Context { get; set; } + + /// + /// Gets the maximum bitrate. + /// + /// System.Nullable<System.Int32>. + public int? GetMaxBitrate() + { + if (MaxBitrate.HasValue) + { + return MaxBitrate; + } + + if (Profile != null) + { + if (Context == EncodingContext.Static) + { + return Profile.MaxStaticBitrate; + } + + return Profile.MaxStreamingBitrate; + } + + return null; + } } } \ No newline at end of file diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index 4040b57f95..9a55068bf8 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -49,8 +49,9 @@ namespace MediaBrowser.Model.Dlna public int? MaxIconWidth { get; set; } public int? MaxIconHeight { get; set; } - public int? MaxBitrate { get; set; } - + public int? MaxStreamingBitrate { get; set; } + public int? MaxStaticBitrate { get; set; } + /// /// Controls the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace. /// diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 57dedf6cfc..6e929564e4 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -105,7 +105,7 @@ namespace MediaBrowser.Model.Dlna RunTimeTicks = item.RunTimeTicks }; - int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate; + int? maxBitrateSetting = options.GetMaxBitrate(); MediaStream audioStream = item.DefaultAudioStream; @@ -243,7 +243,7 @@ namespace MediaBrowser.Model.Dlna MediaStream videoStream = item.VideoStream; - int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate; + int? maxBitrateSetting = options.GetMaxBitrate(); if (IsEligibleForDirectPlay(item, maxBitrateSetting, subtitleStream, options)) { diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index fd38ff7239..f57c3b95db 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -64,6 +64,7 @@ + diff --git a/MediaBrowser.Model/Sync/SyncJobStatus.cs b/MediaBrowser.Model/Sync/SyncJobStatus.cs index ef4d8d7bfc..ebe375ad80 100644 --- a/MediaBrowser.Model/Sync/SyncJobStatus.cs +++ b/MediaBrowser.Model/Sync/SyncJobStatus.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Model.Sync Queued = 0, Transcoding = 1, TranscodingFailed = 2, - Transfering = 3, + Transferring = 3, Completed = 4, Cancelled = 5 } diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 5b1e7d6bb9..7132d110b6 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -6,14 +6,8 @@ namespace MediaBrowser.Model.System /// /// Class SystemInfo /// - public class SystemInfo + public class SystemInfo : PublicSystemInfo { - /// - /// Gets or sets the version. - /// - /// The version. - public string Version { get; set; } - /// /// Gets or sets the operating sytem. /// @@ -86,12 +80,6 @@ namespace MediaBrowser.Model.System /// The failed assembly loads. public List FailedPluginAssemblies { get; set; } - /// - /// Gets or sets the id. - /// - /// The id. - public string Id { get; set; } - /// /// Gets or sets the program data path. /// @@ -152,12 +140,6 @@ namespace MediaBrowser.Model.System /// true if [supports automatic run at startup]; otherwise, false. public bool SupportsAutoRunAtStartup { get; set; } - /// - /// Gets or sets the name of the server. - /// - /// The name of the server. - public string ServerName { get; set; } - /// /// Initializes a new instance of the class. /// @@ -170,4 +152,25 @@ namespace MediaBrowser.Model.System FailedPluginAssemblies = new List(); } } + + public class PublicSystemInfo + { + /// + /// Gets or sets the name of the server. + /// + /// The name of the server. + public string ServerName { get; set; } + + /// + /// Gets or sets the version. + /// + /// The version. + public string Version { get; set; } + + /// + /// Gets or sets the id. + /// + /// The id. + public string Id { get; set; } + } } diff --git a/MediaBrowser.Model/Users/AuthenticationResult.cs b/MediaBrowser.Model/Users/AuthenticationResult.cs index 97fe2ea99e..b4a7cab2aa 100644 --- a/MediaBrowser.Model/Users/AuthenticationResult.cs +++ b/MediaBrowser.Model/Users/AuthenticationResult.cs @@ -22,5 +22,11 @@ namespace MediaBrowser.Model.Users /// /// The authentication token. public string AccessToken { get; set; } + + /// + /// Gets or sets the server identifier. + /// + /// The server identifier. + public string ServerId { get; set; } } } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index bf3183fd2d..3377d15357 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -540,18 +540,10 @@ namespace MediaBrowser.Providers.Manager Type = MetadataPluginType.LocalImageProvider })); - if (ConfigurationManager.Configuration.EnableInternetProviders) - { - // Fetchers - list.AddRange(imageProviders.Where(i => i is IRemoteImageProvider).Select(i => new MetadataPlugin - { - Name = i.Name, - Type = MetadataPluginType.ImageFetcher - })); - } + var enableInternet = ConfigurationManager.Configuration.EnableInternetProviders; // Fetchers - list.AddRange(imageProviders.Where(i => i is IDynamicImageProvider).Select(i => new MetadataPlugin + list.AddRange(imageProviders.Where(i => i is IDynamicImageProvider || (enableInternet && i is IRemoteImageProvider)).Select(i => new MetadataPlugin { Name = i.Name, Type = MetadataPluginType.ImageFetcher diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index 18117c1007..031ca85f99 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -1,5 +1,4 @@ -using System.Linq; -using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; using MediaBrowser.Common.Implementations.Configuration; using MediaBrowser.Controller; @@ -14,6 +13,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using System; using System.IO; +using System.Linq; namespace MediaBrowser.Server.Implementations.Configuration { diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index c4499fac01..afcfde556b 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -66,22 +66,35 @@ namespace MediaBrowser.Server.Implementations.Dto /// item public BaseItemDto GetBaseItemDto(BaseItem item, List fields, User user = null, BaseItem owner = null) { + var dto = GetBaseItemDtoInternal(item, fields, user, owner); + var byName = item as IItemByName; - if (byName != null) + if (byName != null && !(item is LiveTvChannel)) { - var libraryItems = user != null ? - user.RootFolder.GetRecursiveChildren(user) : - _libraryManager.RootFolder.RecursiveChildren; + IEnumerable libraryItems; + + var artist = item as MusicArtist; - var dto = GetBaseItemDtoInternal(item, fields, user); + if (artist == null || artist.IsAccessedByName) + { + libraryItems = user != null ? + user.RootFolder.GetRecursiveChildren(user) : + _libraryManager.RootFolder.RecursiveChildren; + } + else + { + libraryItems = user != null ? + artist.GetRecursiveChildren(user) : + artist.RecursiveChildren; + } SetItemByNameInfo(item, dto, byName.GetTaggedItems(libraryItems).ToList(), user); return dto; } - return GetBaseItemDtoInternal(item, fields, user, owner); + return dto; } private BaseItemDto GetBaseItemDtoInternal(BaseItem item, List fields, User user = null, BaseItem owner = null) diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index 7e5d5d3d83..9191e0bea3 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Net; +using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Plugins; @@ -35,6 +36,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// The _HTTP server /// private readonly IHttpServer _httpServer; + private readonly IServerApplicationHost _appHost; public const int PortNumber = 7359; @@ -45,12 +47,13 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// The network manager. /// The server configuration manager. /// The HTTP server. - public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer) + public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer, IServerApplicationHost appHost) { _logger = logger; _networkManager = networkManager; _serverConfigurationManager = serverConfigurationManager; _httpServer = httpServer; + _appHost = appHost; } /// @@ -58,7 +61,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// public void Run() { - var udpServer = new UdpServer(_logger, _networkManager, _serverConfigurationManager, _httpServer); + var udpServer = new UdpServer(_logger, _networkManager, _serverConfigurationManager, _httpServer, _appHost); try { diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs new file mode 100644 index 0000000000..fefe6401db --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs @@ -0,0 +1,21 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Configuration; +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.LiveTv +{ + public class LiveTvConfigurationFactory : IConfigurationFactory + { + public IEnumerable GetConfigurations() + { + return new List + { + new ConfigurationStore + { + ConfigurationType = typeof(LiveTvOptions), + Key = "livetv" + } + }; + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index a0eb9f2b4b..251acb02dd 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; @@ -11,6 +12,7 @@ using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; @@ -83,6 +85,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv public ILiveTvService ActiveService { get; private set; } + private LiveTvOptions GetConfiguration() + { + return _config.GetConfiguration("livetv"); + } + /// /// Adds the parts. /// @@ -91,7 +98,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { _services.AddRange(services); - SetActiveService(_config.Configuration.LiveTvOptions.ActiveService); + SetActiveService(GetConfiguration().ActiveService); } private void SetActiveService(string name) @@ -303,22 +310,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv try { - // Avoid implicitly captured closure - var itemId = id; - - var stream = _openStreams - .Where(i => string.Equals(i.Value.ItemId, itemId) && isChannel == i.Value.IsChannel) - .Take(1) - .Select(i => i.Value) - .FirstOrDefault(); - - if (stream != null) - { - stream.ConsumerCount++; - _logger.Debug("Returning existing live tv stream"); - return stream.Info; - } - var service = ActiveService; LiveStreamInfo info; @@ -1010,9 +1001,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv private double GetGuideDays(int channelCount) { - if (_config.Configuration.LiveTvOptions.GuideDays.HasValue) + var config = GetConfiguration(); + + if (config.GuideDays.HasValue) { - return _config.Configuration.LiveTvOptions.GuideDays.Value; + return config.GuideDays.Value; } var programsPerDay = channelCount * 48; diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 8b3a5e8c9e..caf8860fc5 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -699,6 +699,10 @@ "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.", "LabelMaxBitrate": "Max bitrate:", "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.", + "LabelMaxStaticBitrate": "Max sync bitrate:", + "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.", "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.", "LabelFriendlyName": "Friendly name", @@ -905,5 +909,11 @@ "HeaderChapters": "Chapters", "HeaderResumeSettings": "Resume Settings", "TabSync": "Sync", - "TitleUsers": "Users" + "TitleUsers": "Users", + "LabelProtocol": "Protocol:", + "OptionProtocolHttp": "Http", + "OptionProtocolHls": "Http Live Streaming", + "LabelContext": "Context:", + "OptionContextStreaming": "Streaming", + "OptionContextStatic": "Sync" } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index ef6730b75b..79d15039b2 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -198,6 +198,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs index 73a4e30048..33818dcea9 100644 --- a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs +++ b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs @@ -17,6 +17,10 @@ namespace MediaBrowser.Server.Implementations.Security { if (value == null) throw new ArgumentNullException("value"); +#if __MonoCS__ + return EncryptStringUniversal(value); +#endif + return Encoding.Default.GetString(ProtectedData.Protect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine)); } @@ -30,7 +34,27 @@ namespace MediaBrowser.Server.Implementations.Security { if (value == null) throw new ArgumentNullException("value"); +#if __MonoCS__ + return DecryptStringUniversal(value); +#endif + return Encoding.Default.GetString(ProtectedData.Unprotect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine)); } + + private string EncryptStringUniversal(string value) + { + // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now + + var bytes = Encoding.UTF8.GetBytes(value); + return Convert.ToBase64String(bytes); + } + + private string DecryptStringUniversal(string value) + { + // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now + + var bytes = Convert.FromBase64String(value); + return Encoding.UTF8.GetString(bytes); + } } } diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 1689488219..61c65cfd6c 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -1236,7 +1236,8 @@ namespace MediaBrowser.Server.Implementations.Session { User = _dtoService.GetUserDto(user), SessionInfo = GetSessionInfoDto(session), - AccessToken = token + AccessToken = token, + ServerId = _appHost.ServerId }; } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index a8d723ce3c..b5e13e306b 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -68,7 +68,8 @@ namespace MediaBrowser.Server.Implementations.Sync LimitType = request.LimitType, RequestedItemIds = request.ItemIds, DateCreated = DateTime.UtcNow, - DateLastModified = DateTime.UtcNow + DateLastModified = DateTime.UtcNow, + ItemCount = 1 }; await _repo.Create(job).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs index 6b5cac1966..f78f983dce 100644 --- a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs +++ b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs @@ -1,8 +1,12 @@ using MediaBrowser.Common.Net; +using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; +using MediaBrowser.Model.ApiClient; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; using System; +using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; @@ -37,6 +41,11 @@ namespace MediaBrowser.Server.Implementations.Udp private bool _isDisposed; + private readonly List>> _responders = new List>>(); + + private readonly IServerApplicationHost _appHost; + private readonly IJsonSerializer _json; + /// /// Initializes a new instance of the class. /// @@ -44,12 +53,24 @@ namespace MediaBrowser.Server.Implementations.Udp /// The network manager. /// The server configuration manager. /// The HTTP server. - public UdpServer(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer) + /// The application host. + public UdpServer(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer, IServerApplicationHost appHost) { _logger = logger; _networkManager = networkManager; _serverConfigurationManager = serverConfigurationManager; _httpServer = httpServer; + _appHost = appHost; + + AddMessageResponder("who is MediaBrowserServer?", RespondToV1Message); + AddMessageResponder("who is MediaBrowserServer_v2?", RespondToV2Message); + } + + private void AddMessageResponder(string message, Action responder) + { + var expectedMessageBytes = Encoding.UTF8.GetBytes(message); + + _responders.Add(new Tuple>(expectedMessageBytes, responder)); } /// @@ -58,28 +79,51 @@ namespace MediaBrowser.Server.Implementations.Udp /// The instance containing the event data. private async void OnMessageReceived(UdpMessageReceivedEventArgs e) { - const string context = "Server"; + var responder = _responders.FirstOrDefault(i => i.Item1.SequenceEqual(e.Bytes)); - var expectedMessage = String.Format("who is MediaBrowser{0}?", context); - var expectedMessageBytes = Encoding.UTF8.GetBytes(expectedMessage); + if (responder != null) + { + responder.Item2(e.RemoteEndPoint); + } + } - if (expectedMessageBytes.SequenceEqual(e.Bytes)) + private async void RespondToV1Message(string endpoint) + { + var localAddress = GetLocalIpAddress(); + + if (!string.IsNullOrEmpty(localAddress)) { - _logger.Info("Received UDP server request from " + e.RemoteEndPoint); + // Send a response back with our ip address and port + var response = String.Format("MediaBrowserServer|{0}:{1}", localAddress, _serverConfigurationManager.Configuration.HttpServerPortNumber); - var localAddress = GetLocalIpAddress(); + await SendAsync(Encoding.UTF8.GetBytes(response), endpoint); + } + else + { + _logger.Warn("Unable to respond to udp request because the local ip address could not be determined."); + } + } - if (!string.IsNullOrEmpty(localAddress)) - { - // Send a response back with our ip address and port - var response = String.Format("MediaBrowser{0}|{1}:{2}", context, GetLocalIpAddress(), _serverConfigurationManager.Configuration.HttpServerPortNumber); + private async void RespondToV2Message(string endpoint) + { + var localAddress = GetLocalIpAddress(); - await SendAsync(Encoding.UTF8.GetBytes(response), e.RemoteEndPoint); - } - else + if (!string.IsNullOrEmpty(localAddress)) + { + var serverAddress = string.Format("http://{0}:{1}", localAddress, _serverConfigurationManager.Configuration.HttpServerPortNumber); + + var response = new ServerDiscoveryInfo { - _logger.Warn("Unable to respond to udp request because the local ip address could not be determined."); - } + Address = serverAddress, + Id = _appHost.ServerId, + Name = _appHost.Name + }; + + await SendAsync(Encoding.UTF8.GetBytes(_json.SerializeToString(response)), endpoint); + } + else + { + _logger.Warn("Unable to respond to udp request because the local ip address could not be determined."); } } diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 5c086c8cc7..5c3c3e9077 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -326,6 +326,13 @@ namespace MediaBrowser.ServerApplication saveConfig = true; } + if (ServerConfigurationManager.Configuration.LiveTvOptions != null) + { + ServerConfigurationManager.SaveConfiguration("livetv", ServerConfigurationManager.Configuration.LiveTvOptions); + ServerConfigurationManager.Configuration.LiveTvOptions = null; + saveConfig = true; + } + if (saveConfig) { ServerConfigurationManager.SaveConfiguration(); @@ -1001,6 +1008,11 @@ namespace MediaBrowser.ServerApplication private readonly string _systemId = Environment.MachineName.GetMD5().ToString(); + public string ServerId + { + get { return _systemId; } + } + /// /// Gets the system status. /// @@ -1017,7 +1029,7 @@ namespace MediaBrowser.ServerApplication FailedPluginAssemblies = FailedAssemblies.ToList(), InProgressInstallations = InstallationManager.CurrentInstallations.Select(i => i.Item1).ToList(), CompletedInstallations = InstallationManager.CompletedInstallations.ToList(), - Id = _systemId, + Id = ServerId, ProgramDataPath = ApplicationPaths.ProgramDataPath, LogPath = ApplicationPaths.LogDirectoryPath, ItemsByNamePath = ApplicationPaths.ItemsByNamePath, diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 73174dacf8..4bc05e0c16 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -185,9 +185,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 0520e45485..884fbe48d9 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.418 + 3.0.421 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,8 +12,8 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - - + + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 4cb876d651..853dc464e1 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.418 + 3.0.421 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index 597a29b7c3..e9355ab484 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.418 + 3.0.421 MediaBrowser.Model - Signed Edition Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 05863d47a8..9d80d47bcf 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.418 + 3.0.421 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - + -- cgit v1.2.3 From a37a11c486350a35cbc9f8763c477dd189e35501 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 30 Jul 2014 22:09:23 -0400 Subject: 3.0.5324.37963 --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 3 +- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 30 ++++++------ MediaBrowser.Controller/Library/TVUtils.cs | 22 +++++---- MediaBrowser.Dlna/Didl/DidlBuilder.cs | 55 +++++++++++++--------- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 8 ++-- .../MediaBrowser.Model.Portable.csproj | 15 +++--- .../MediaBrowser.Model.net35.csproj | 15 +++--- MediaBrowser.Model/Configuration/LiveTvOptions.cs | 8 ---- .../Configuration/ServerConfiguration.cs | 22 +-------- .../Configuration/TvFileOrganizationOptions.cs | 40 ---------------- MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs | 38 ++++++++++----- .../FileOrganization/AutoOrganizeOptions.cs | 17 +++++++ .../FileOrganization/TvFileOrganizationOptions.cs | 40 ++++++++++++++++ MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 8 ++++ MediaBrowser.Model/MediaBrowser.Model.csproj | 5 +- .../FileOrganization/EpisodeFileOrganizer.cs | 2 +- .../FileOrganization/Extensions.cs | 29 ++++++++++++ .../FileOrganization/FileOrganizationService.cs | 9 +++- .../FileOrganization/OrganizerScheduledTask.cs | 12 +++-- .../Library/Resolvers/TV/SeriesResolver.cs | 7 ++- .../LiveTv/LiveTvConfigurationFactory.cs | 2 +- .../MediaBrowser.Server.Implementations.csproj | 1 + MediaBrowser.ServerApplication/ApplicationHost.cs | 8 ++++ 23 files changed, 242 insertions(+), 154 deletions(-) delete mode 100644 MediaBrowser.Model/Configuration/LiveTvOptions.cs delete mode 100644 MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs create mode 100644 MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs create mode 100644 MediaBrowser.Model/FileOrganization/TvFileOrganizationOptions.cs create mode 100644 MediaBrowser.Model/LiveTv/LiveTvOptions.cs create mode 100644 MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index df85ca3cbc..1963ad10a5 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1917,7 +1917,8 @@ namespace MediaBrowser.Api.Playback state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic - ); + + ).FirstOrDefault() ?? string.Empty; } foreach (var item in responseHeaders) diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index ccaa918ec7..c00e0c18b5 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -55,21 +55,6 @@ namespace MediaBrowser.Api.Playback.Hls public object Get(GetMasterHlsVideoStream request) { - if (string.Equals(request.AudioCodec, "copy", StringComparison.OrdinalIgnoreCase)) - { - throw new ArgumentException("Audio codec copy is not allowed here."); - } - - if (string.Equals(request.VideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) - { - throw new ArgumentException("Video codec copy is not allowed here."); - } - - if (string.IsNullOrEmpty(request.MediaSourceId)) - { - throw new ArgumentException("MediaSourceId is required"); - } - var result = GetAsync(request).Result; return result; @@ -332,6 +317,21 @@ namespace MediaBrowser.Api.Playback.Hls { var state = await GetState(request, CancellationToken.None).ConfigureAwait(false); + if (string.Equals(request.AudioCodec, "copy", StringComparison.OrdinalIgnoreCase)) + { + throw new ArgumentException("Audio codec copy is not allowed here."); + } + + if (string.Equals(request.VideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + { + throw new ArgumentException("Video codec copy is not allowed here."); + } + + if (string.IsNullOrEmpty(request.MediaSourceId)) + { + throw new ArgumentException("MediaSourceId is required"); + } + var audioBitrate = state.OutputAudioBitrate ?? 0; var videoBitrate = state.OutputVideoBitrate ?? 0; diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index 6ef1fb6f72..5e43eb6441 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -223,10 +223,11 @@ namespace MediaBrowser.Controller.Library continue; } - if ((attributes & FileAttributes.System) == FileAttributes.System) - { - continue; - } + // Can't enforce this because files saved by Bitcasa are always marked System + //if ((attributes & FileAttributes.System) == FileAttributes.System) + //{ + // continue; + //} if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) { @@ -268,13 +269,16 @@ namespace MediaBrowser.Controller.Library if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden) { + logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName); continue; } - if ((attributes & FileAttributes.System) == FileAttributes.System) - { - continue; - } + // Can't enforce this because files saved by Bitcasa are always marked System + //if ((attributes & FileAttributes.System) == FileAttributes.System) + //{ + // logger.Debug("Igoring series subfolder marked system: {0}", child.FullName); + // continue; + //} if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) { @@ -299,6 +303,8 @@ namespace MediaBrowser.Controller.Library } else { + logger.Debug("Evaluating series file: {0}", child.FullName); + var fullName = child.FullName; if (EntityResolutionHelper.IsVideoFile(fullName) || EntityResolutionHelper.IsVideoPlaceHolder(fullName)) diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 649ba2c8ff..f1377727bb 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -97,8 +97,6 @@ namespace MediaBrowser.Dlna.Didl private void AddVideoResource(XmlElement container, Video video, string deviceId, Filter filter, StreamInfo streamInfo = null) { - var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL); - if (streamInfo == null) { var sources = _user == null ? video.GetMediaSources(true).ToList() : video.GetMediaSources(true, _user).ToList(); @@ -113,6 +111,38 @@ namespace MediaBrowser.Dlna.Didl }); } + var targetWidth = streamInfo.TargetWidth; + var targetHeight = streamInfo.TargetHeight; + + var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container, + streamInfo.VideoCodec, + streamInfo.AudioCodec, + targetWidth, + targetHeight, + streamInfo.TargetVideoBitDepth, + streamInfo.TargetVideoBitrate, + streamInfo.TargetAudioChannels, + streamInfo.TargetAudioBitrate, + streamInfo.TargetTimestamp, + streamInfo.IsDirectStream, + streamInfo.RunTimeTicks, + streamInfo.TargetVideoProfile, + streamInfo.TargetVideoLevel, + streamInfo.TargetFramerate, + streamInfo.TargetPacketLength, + streamInfo.TranscodeSeekInfo, + streamInfo.IsTargetAnamorphic); + + foreach (var contentFeature in contentFeatureList) + { + AddVideoResource(container, video, deviceId, filter, contentFeature, streamInfo); + } + } + + private void AddVideoResource(XmlElement container, Video video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo) + { + var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL); + var url = streamInfo.ToDlnaUrl(_serverAddress); res.InnerText = url; @@ -189,25 +219,6 @@ namespace MediaBrowser.Dlna.Didl ? MimeTypes.GetMimeType(filename) : mediaProfile.MimeType; - var contentFeatures = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container, - streamInfo.VideoCodec, - streamInfo.AudioCodec, - targetWidth, - targetHeight, - streamInfo.TargetVideoBitDepth, - streamInfo.TargetVideoBitrate, - streamInfo.TargetAudioChannels, - streamInfo.TargetAudioBitrate, - streamInfo.TargetTimestamp, - streamInfo.IsDirectStream, - streamInfo.RunTimeTicks, - streamInfo.TargetVideoProfile, - streamInfo.TargetVideoLevel, - streamInfo.TargetFramerate, - streamInfo.TargetPacketLength, - streamInfo.TranscodeSeekInfo, - streamInfo.IsTargetAnamorphic); - res.SetAttribute("protocolInfo", String.Format( "http-get:*:{0}:{1}", mimeType, @@ -216,7 +227,7 @@ namespace MediaBrowser.Dlna.Didl container.AppendChild(res); } - + private void AddAudioResource(XmlElement container, Audio audio, string deviceId, Filter filter, StreamInfo streamInfo = null) { var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL); diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index d81e460492..9e8d8213fd 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -501,7 +501,7 @@ namespace MediaBrowser.Dlna.PlayTo if (streamInfo.MediaType == DlnaProfileType.Video) { - return new ContentFeatureBuilder(profile) + var list = new ContentFeatureBuilder(profile) .BuildVideoHeader(streamInfo.Container, streamInfo.VideoCodec, streamInfo.AudioCodec, @@ -520,6 +520,8 @@ namespace MediaBrowser.Dlna.PlayTo streamInfo.TargetPacketLength, streamInfo.TranscodeSeekInfo, streamInfo.IsTargetAnamorphic); + + return list.FirstOrDefault(); } return null; @@ -600,9 +602,7 @@ namespace MediaBrowser.Dlna.PlayTo _currentPlaylistIndex = index; var currentitem = Playlist[index]; - var dlnaheaders = GetDlnaHeaders(currentitem); - - await _device.SetAvTransport(currentitem.StreamUrl, dlnaheaders, currentitem.Didl); + await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl); var streamInfo = currentitem.StreamInfo; if (streamInfo.StartPositionTicks > 0 && streamInfo.IsDirectStream) diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index e55d3eec9b..f374ed5297 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -152,9 +152,6 @@ Configuration\ImageSavingConvention.cs - - Configuration\LiveTvOptions.cs - Configuration\MetadataOptions.cs @@ -179,9 +176,6 @@ Configuration\SubtitlePlaybackMode.cs - - Configuration\TvFileOrganizationOptions.cs - Configuration\UnratedItem.cs @@ -473,6 +467,9 @@ Extensions\StringHelper.cs + + FileOrganization\AutoOrganizeOptions.cs + FileOrganization\EpisodeFileOrganizationRequest.cs @@ -488,6 +485,9 @@ FileOrganization\FileSortingStatus.cs + + FileOrganization\TvFileOrganizationOptions.cs + Games\GameSystem.cs @@ -542,6 +542,9 @@ LiveTv\LiveTvInfo.cs + + LiveTv\LiveTvOptions.cs + LiveTv\LiveTvServiceInfo.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 603eecbaed..5385ee036c 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -115,9 +115,6 @@ Configuration\ImageSavingConvention.cs - - Configuration\LiveTvOptions.cs - Configuration\MetadataOptions.cs @@ -142,9 +139,6 @@ Configuration\SubtitlePlaybackMode.cs - - Configuration\TvFileOrganizationOptions.cs - Configuration\UnratedItem.cs @@ -436,6 +430,9 @@ Extensions\StringHelper.cs + + FileOrganization\AutoOrganizeOptions.cs + FileOrganization\EpisodeFileOrganizationRequest.cs @@ -451,6 +448,9 @@ FileOrganization\FileSortingStatus.cs + + FileOrganization\TvFileOrganizationOptions.cs + Games\GameSystem.cs @@ -499,6 +499,9 @@ LiveTv\LiveTvInfo.cs + + LiveTv\LiveTvOptions.cs + LiveTv\LiveTvServiceInfo.cs diff --git a/MediaBrowser.Model/Configuration/LiveTvOptions.cs b/MediaBrowser.Model/Configuration/LiveTvOptions.cs deleted file mode 100644 index 575f0b8637..0000000000 --- a/MediaBrowser.Model/Configuration/LiveTvOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace MediaBrowser.Model.Configuration -{ - public class LiveTvOptions - { - public int? GuideDays { get; set; } - public string ActiveService { get; set; } - } -} \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 00f7add14c..4734e2af7d 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -1,7 +1,7 @@ using MediaBrowser.Model.Entities; +using MediaBrowser.Model.FileOrganization; +using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Notifications; -using MediaBrowser.Model.Weather; -using System; namespace MediaBrowser.Model.Configuration { @@ -10,18 +10,6 @@ namespace MediaBrowser.Model.Configuration /// public class ServerConfiguration : BaseApplicationConfiguration { - /// - /// Gets or sets the zip code to use when displaying weather - /// - /// The weather location. - public string WeatherLocation { get; set; } - - /// - /// Gets or sets the weather unit to use when displaying weather - /// - /// The weather unit. - public WeatherUnits WeatherUnit { get; set; } - /// /// Gets or sets a value indicating whether [enable u pn p]. /// @@ -191,9 +179,6 @@ namespace MediaBrowser.Model.Configuration public SubtitleOptions SubtitleOptions { get; set; } - [Obsolete] - public string[] ManualLoginClients { get; set; } - public ChannelOptions ChannelOptions { get; set; } public ChapterOptions ChapterOptions { get; set; } @@ -237,8 +222,6 @@ namespace MediaBrowser.Model.Configuration SortRemoveCharacters = new[] { ",", "&", "-", "{", "}", "'" }; SortRemoveWords = new[] { "the", "a", "an" }; - ManualLoginClients = new string[] { }; - SeasonZeroDisplayName = "Specials"; EnableRealtimeMonitor = true; @@ -304,7 +287,6 @@ namespace MediaBrowser.Model.Configuration }; SubtitleOptions = new SubtitleOptions(); - TvFileOrganizationOptions = new TvFileOrganizationOptions(); } } } diff --git a/MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs b/MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs deleted file mode 100644 index fe32d4a80a..0000000000 --- a/MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs +++ /dev/null @@ -1,40 +0,0 @@ - -namespace MediaBrowser.Model.Configuration -{ - public class TvFileOrganizationOptions - { - public bool IsEnabled { get; set; } - public int MinFileSizeMb { get; set; } - public string[] LeftOverFileExtensionsToDelete { get; set; } - public string[] WatchLocations { get; set; } - - public string SeasonFolderPattern { get; set; } - - public string SeasonZeroFolderName { get; set; } - - public string EpisodeNamePattern { get; set; } - public string MultiEpisodeNamePattern { get; set; } - - public bool OverwriteExistingEpisodes { get; set; } - - public bool DeleteEmptyFolders { get; set; } - - public bool CopyOriginalFile { get; set; } - - public TvFileOrganizationOptions() - { - MinFileSizeMb = 50; - - LeftOverFileExtensionsToDelete = new string[] { }; - - WatchLocations = new string[] { }; - - EpisodeNamePattern = "%sn - %sx%0e - %en.%ext"; - MultiEpisodeNamePattern = "%sn - %sx%0e-x%0ed - %en.%ext"; - SeasonFolderPattern = "Season %s"; - SeasonZeroFolderName = "Season 0"; - - CopyOriginalFile = false; - } - } -} diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index b6d9d9f77d..5417c5b82c 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Model.Dlna return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); } - public string BuildVideoHeader(string container, + public List BuildVideoHeader(string container, string videoCodec, string audioCodec, int? width, @@ -149,30 +149,42 @@ namespace MediaBrowser.Model.Dlna timestamp, isAnamorphic); - string orgPn = mediaProfile == null ? null : mediaProfile.OrgPn; + List orgPnValues = new List(); - if (string.IsNullOrEmpty(orgPn)) + if (mediaProfile != null && !string.IsNullOrEmpty(mediaProfile.OrgPn)) + { + orgPnValues.Add(mediaProfile.OrgPn); + } + else { foreach (string s in GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp)) { - orgPn = s; + orgPnValues.Add(s); break; } } - if (string.IsNullOrEmpty(orgPn)) + List contentFeatureList = new List(); + + foreach (string orgPn in orgPnValues) { - // TODO: Support multiple values and return multiple headers? - foreach (string s in (orgPn ?? string.Empty).Split(',')) - { - orgPn = s; - break; - } + string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn; + + var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); + + contentFeatureList.Add(value); } - string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn; + if (orgPnValues.Count == 0) + { + string contentFeatures = string.Empty; - return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); + var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); + + contentFeatureList.Add(value); + } + + return contentFeatureList; } private string GetImageOrgPnValue(string container, int? width, int? height) diff --git a/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs b/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs new file mode 100644 index 0000000000..ae701ea68d --- /dev/null +++ b/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs @@ -0,0 +1,17 @@ + +namespace MediaBrowser.Model.FileOrganization +{ + public class AutoOrganizeOptions + { + /// + /// Gets or sets the tv options. + /// + /// The tv options. + public TvFileOrganizationOptions TvOptions { get; set; } + + public AutoOrganizeOptions() + { + TvOptions = new TvFileOrganizationOptions(); + } + } +} diff --git a/MediaBrowser.Model/FileOrganization/TvFileOrganizationOptions.cs b/MediaBrowser.Model/FileOrganization/TvFileOrganizationOptions.cs new file mode 100644 index 0000000000..973ecf6e71 --- /dev/null +++ b/MediaBrowser.Model/FileOrganization/TvFileOrganizationOptions.cs @@ -0,0 +1,40 @@ + +namespace MediaBrowser.Model.FileOrganization +{ + public class TvFileOrganizationOptions + { + public bool IsEnabled { get; set; } + public int MinFileSizeMb { get; set; } + public string[] LeftOverFileExtensionsToDelete { get; set; } + public string[] WatchLocations { get; set; } + + public string SeasonFolderPattern { get; set; } + + public string SeasonZeroFolderName { get; set; } + + public string EpisodeNamePattern { get; set; } + public string MultiEpisodeNamePattern { get; set; } + + public bool OverwriteExistingEpisodes { get; set; } + + public bool DeleteEmptyFolders { get; set; } + + public bool CopyOriginalFile { get; set; } + + public TvFileOrganizationOptions() + { + MinFileSizeMb = 50; + + LeftOverFileExtensionsToDelete = new string[] { }; + + WatchLocations = new string[] { }; + + EpisodeNamePattern = "%sn - %sx%0e - %en.%ext"; + MultiEpisodeNamePattern = "%sn - %sx%0e-x%0ed - %en.%ext"; + SeasonFolderPattern = "Season %s"; + SeasonZeroFolderName = "Season 0"; + + CopyOriginalFile = false; + } + } +} diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs new file mode 100644 index 0000000000..05fdc00b12 --- /dev/null +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -0,0 +1,8 @@ +namespace MediaBrowser.Model.LiveTv +{ + public class LiveTvOptions + { + public int? GuideDays { get; set; } + public string ActiveService { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index f57c3b95db..efd8c2a0a2 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -79,13 +79,14 @@ - + + - + diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 594ba9d235..cf9571824c 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -126,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId)); - await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result, cancellationToken).ConfigureAwait(false); + await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, options, true, result, cancellationToken).ConfigureAwait(false); await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs b/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs new file mode 100644 index 0000000000..e43ab3665e --- /dev/null +++ b/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs @@ -0,0 +1,29 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.FileOrganization; +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.FileOrganization +{ + public static class ConfigurationExtension + { + public static AutoOrganizeOptions GetAutoOrganizeOptions(this IConfigurationManager manager) + { + return manager.GetConfiguration("autoorganize"); + } + } + + public class AutoOrganizeOptionsFactory : IConfigurationFactory + { + public IEnumerable GetConfigurations() + { + return new List + { + new ConfigurationStore + { + Key = "autoorganize", + ConfigurationType = typeof (AutoOrganizeOptions) + } + }; + } + } +} diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs index 7cf38b0a0e..7c52696787 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs @@ -95,6 +95,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return _repo.Delete(resultId); } + private TvFileOrganizationOptions GetTvOptions() + { + return _config.GetAutoOrganizeOptions().TvOptions; + } + public async Task PerformOrganization(string resultId) { var result = _repo.GetResult(resultId); @@ -107,7 +112,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); - await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true, CancellationToken.None) + await organizer.OrganizeEpisodeFile(result.OriginalPath, GetTvOptions(), true, CancellationToken.None) .ConfigureAwait(false); } @@ -121,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); - await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions, CancellationToken.None).ConfigureAwait(false); + await organizer.OrganizeWithCorrection(request, GetTvOptions(), CancellationToken.None).ConfigureAwait(false); } } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs index fbb743f943..4e182ea88f 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.FileOrganization; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; @@ -48,10 +49,15 @@ namespace MediaBrowser.Server.Implementations.FileOrganization get { return "Library"; } } + private TvFileOrganizationOptions GetTvOptions() + { + return _config.GetAutoOrganizeOptions().TvOptions; + } + public Task Execute(CancellationToken cancellationToken, IProgress progress) { return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager) - .Organize(_config.Configuration.TvFileOrganizationOptions, cancellationToken, progress); + .Organize(GetTvOptions(), cancellationToken, progress); } public IEnumerable GetDefaultTriggers() @@ -64,12 +70,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization public bool IsHidden { - get { return !_config.Configuration.TvFileOrganizationOptions.IsEnabled; } + get { return !GetTvOptions().IsEnabled; } } public bool IsEnabled { - get { return _config.Configuration.TvFileOrganizationOptions.IsEnabled; } + get { return !GetTvOptions().IsEnabled; } } } } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index a17c33845f..d3aad582a3 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -60,15 +60,18 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV var collectionType = args.GetCollectionType(); + var isTvShowsFolder = string.Equals(collectionType, CollectionType.TvShows, + StringComparison.OrdinalIgnoreCase); + // If there's a collection type and it's not tv, it can't be a series if (!string.IsNullOrEmpty(collectionType) && - !string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) && + !isTvShowsFolder && !string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase)) { return null; } - if (TVUtils.IsSeriesFolder(args.Path, string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase), args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger)) + if (TVUtils.IsSeriesFolder(args.Path, isTvShowsFolder, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger)) { return new Series(); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs index fefe6401db..57d1d79e16 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs @@ -1,5 +1,5 @@ using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.LiveTv; using System.Collections.Generic; namespace MediaBrowser.Server.Implementations.LiveTv diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 79d15039b2..5cc22ac64c 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -127,6 +127,7 @@ + diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index e584a950cd..7dc70627bd 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -43,6 +43,7 @@ using MediaBrowser.LocalMetadata.Providers; using MediaBrowser.MediaEncoding.BdInfo; using MediaBrowser.MediaEncoding.Encoder; using MediaBrowser.MediaEncoding.Subtitles; +using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; @@ -333,6 +334,13 @@ namespace MediaBrowser.ServerApplication saveConfig = true; } + if (ServerConfigurationManager.Configuration.TvFileOrganizationOptions != null) + { + ServerConfigurationManager.SaveConfiguration("autoorganize", new AutoOrganizeOptions { TvOptions = ServerConfigurationManager.Configuration.TvFileOrganizationOptions }); + ServerConfigurationManager.Configuration.TvFileOrganizationOptions = null; + saveConfig = true; + } + if (saveConfig) { ServerConfigurationManager.SaveConfiguration(); -- cgit v1.2.3 From e84ba17b9f48a3bc8811b1a89c54c25bc6607599 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 10 Aug 2014 18:13:17 -0400 Subject: add activity log feature --- MediaBrowser.Api/ChannelService.cs | 2 +- MediaBrowser.Api/Images/ImageService.cs | 1 + MediaBrowser.Api/MediaBrowser.Api.csproj | 11 +- .../Session/SessionInfoWebSocketListener.cs | 116 +++++ MediaBrowser.Api/Session/SessionsService.cs | 506 +++++++++++++++++++ MediaBrowser.Api/SessionsService.cs | 506 ------------------- MediaBrowser.Api/System/ActivityLogService.cs | 44 ++ .../System/SystemInfoWebSocketListener.cs | 49 ++ MediaBrowser.Api/System/SystemService.cs | 178 +++++++ MediaBrowser.Api/SystemService.cs | 177 ------- MediaBrowser.Api/UserService.cs | 21 +- .../WebSocket/SessionInfoWebSocketListener.cs | 116 ----- .../WebSocket/SystemInfoWebSocketListener.cs | 49 -- .../Configuration/BaseConfigurationManager.cs | 12 + .../ScheduledTasks/ScheduledTaskWorker.cs | 1 + .../Configuration/IConfigurationManager.cs | 5 + .../ScheduledTasks/IConfigurableScheduledTask.cs | 5 + .../Activity/IActivityManager.cs | 17 + .../Activity/IActivityRepository.cs | 13 + .../Configuration/IServerConfigurationManager.cs | 7 - MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 14 +- MediaBrowser.Controller/Library/IUserManager.cs | 1 + MediaBrowser.Controller/Library/TVUtils.cs | 2 +- .../MediaBrowser.Controller.csproj | 6 +- .../Notifications/INotificationsRepository.cs | 12 - .../Session/AuthenticationRequest.cs | 14 + MediaBrowser.Controller/Session/ISessionManager.cs | 28 +- .../Subtitles/ISubtitleManager.cs | 17 +- .../Subtitles/SubtitleDownloadEventArgs.cs | 27 + MediaBrowser.LocalMetadata/BaseXmlProvider.cs | 4 +- .../MediaBrowser.Model.Portable.csproj | 9 +- .../MediaBrowser.Model.net35.csproj | 9 +- MediaBrowser.Model/Activity/ActivityLogEntry.cs | 62 +++ MediaBrowser.Model/ApiClient/IApiClient.cs | 2 +- MediaBrowser.Model/Channels/ChannelItemQuery.cs | 5 +- .../Configuration/ServerConfiguration.cs | 3 +- .../Configuration/SubtitleOptions.cs | 22 - MediaBrowser.Model/Events/GenericEventArgs.cs | 16 + MediaBrowser.Model/MediaBrowser.Model.csproj | 5 +- MediaBrowser.Model/Providers/SubtitleOptions.cs | 22 + MediaBrowser.Model/Tasks/TaskResult.cs | 6 + .../MediaBrowser.Providers.csproj | 3 +- .../MediaInfo/FFProbeVideoInfo.cs | 19 +- .../MediaInfo/SubtitleScheduledTask.cs | 30 +- .../Subtitles/ConfigurationExtension.cs | 29 ++ .../Subtitles/OpenSubtitleDownloader.cs | 35 +- .../Subtitles/SubtitleManager.cs | 69 ++- .../Activity/ActivityManager.cs | 40 ++ .../Activity/ActivityRepository.cs | 293 +++++++++++ .../EntryPoints/ActivityLogEntryPoint.cs | 543 +++++++++++++++++++++ .../EntryPoints/Notifications/Notifications.cs | 8 +- .../EntryPoints/Notifications/WebSocketNotifier.cs | 9 - .../EntryPoints/ServerEventNotifier.cs | 13 +- .../FileOrganization/OrganizerScheduledTask.cs | 7 +- .../SocketSharp/WebSocketSharpListener.cs | 2 +- .../Library/UserManager.cs | 7 +- .../Localization/Server/server.json | 138 ++++-- .../MediaBrowser.Server.Implementations.csproj | 5 +- .../Notifications/SqliteNotificationsRepository.cs | 66 --- .../ServerManager/ServerManager.cs | 2 + .../Session/SessionManager.cs | 51 +- .../Session/SessionWebSocketListener.cs | 1 - .../Sync/SyncRepository.cs | 46 +- MediaBrowser.ServerApplication/ApplicationHost.cs | 22 + 64 files changed, 2398 insertions(+), 1162 deletions(-) create mode 100644 MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs create mode 100644 MediaBrowser.Api/Session/SessionsService.cs delete mode 100644 MediaBrowser.Api/SessionsService.cs create mode 100644 MediaBrowser.Api/System/ActivityLogService.cs create mode 100644 MediaBrowser.Api/System/SystemInfoWebSocketListener.cs create mode 100644 MediaBrowser.Api/System/SystemService.cs delete mode 100644 MediaBrowser.Api/SystemService.cs delete mode 100644 MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs delete mode 100644 MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs create mode 100644 MediaBrowser.Controller/Activity/IActivityManager.cs create mode 100644 MediaBrowser.Controller/Activity/IActivityRepository.cs create mode 100644 MediaBrowser.Controller/Session/AuthenticationRequest.cs create mode 100644 MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs create mode 100644 MediaBrowser.Model/Activity/ActivityLogEntry.cs delete mode 100644 MediaBrowser.Model/Configuration/SubtitleOptions.cs create mode 100644 MediaBrowser.Model/Providers/SubtitleOptions.cs create mode 100644 MediaBrowser.Providers/Subtitles/ConfigurationExtension.cs create mode 100644 MediaBrowser.Server.Implementations/Activity/ActivityManager.cs create mode 100644 MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs create mode 100644 MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs (limited to 'MediaBrowser.Model/Configuration') diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs index 2cc046f1d4..3736814e57 100644 --- a/MediaBrowser.Api/ChannelService.cs +++ b/MediaBrowser.Api/ChannelService.cs @@ -230,7 +230,7 @@ namespace MediaBrowser.Api SortOrder = request.SortOrder, SortBy = (request.SortBy ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(), Filters = request.GetFilters().ToArray(), - Fields = request.GetItemFields().ToList() + Fields = request.GetItemFields().ToArray() }, CancellationToken.None).Result; diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index ea7eaa9471..43e9ad3efe 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -40,6 +40,7 @@ namespace MediaBrowser.Api.Images [Route("/Items/{Id}/Images/{Type}", "GET")] [Route("/Items/{Id}/Images/{Type}/{Index}", "GET")] [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}", "GET")] + [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}", "HEAD")] [Api(Description = "Gets an item image")] public class GetItemImage : ImageRequest { diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 9a7d28ec43..df689cb24d 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -118,10 +118,11 @@ - + - + + @@ -139,8 +140,8 @@ - - + + @@ -173,4 +174,4 @@ --> - + \ No newline at end of file diff --git a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs new file mode 100644 index 0000000000..e6b525e534 --- /dev/null +++ b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs @@ -0,0 +1,116 @@ +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Session; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Session +{ + /// + /// Class SessionInfoWebSocketListener + /// + class SessionInfoWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> + { + /// + /// Gets the name. + /// + /// The name. + protected override string Name + { + get { return "Sessions"; } + } + + /// + /// The _kernel + /// + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The session manager. + public SessionInfoWebSocketListener(ILogger logger, ISessionManager sessionManager) + : base(logger) + { + _sessionManager = sessionManager; + + _sessionManager.SessionStarted += _sessionManager_SessionStarted; + _sessionManager.SessionEnded += _sessionManager_SessionEnded; + _sessionManager.PlaybackStart += _sessionManager_PlaybackStart; + _sessionManager.PlaybackStopped += _sessionManager_PlaybackStopped; + _sessionManager.PlaybackProgress += _sessionManager_PlaybackProgress; + _sessionManager.CapabilitiesChanged += _sessionManager_CapabilitiesChanged; + _sessionManager.SessionActivity += _sessionManager_SessionActivity; + } + + void _sessionManager_SessionActivity(object sender, SessionEventArgs e) + { + SendData(false); + } + + void _sessionManager_CapabilitiesChanged(object sender, SessionEventArgs e) + { + SendData(true); + } + + void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e) + { + SendData(false); + } + + void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) + { + SendData(true); + } + + void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e) + { + SendData(true); + } + + void _sessionManager_SessionEnded(object sender, SessionEventArgs e) + { + SendData(true); + } + + void _sessionManager_SessionStarted(object sender, SessionEventArgs e) + { + SendData(true); + } + + /// + /// Gets the data to send. + /// + /// The state. + /// Task{SystemInfo}. + protected override Task> GetDataToSend(WebSocketListenerState state) + { + return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto)); + } + + protected override bool SendOnTimer + { + get + { + return false; + } + } + + protected override void Dispose(bool dispose) + { + _sessionManager.SessionStarted -= _sessionManager_SessionStarted; + _sessionManager.SessionEnded -= _sessionManager_SessionEnded; + _sessionManager.PlaybackStart -= _sessionManager_PlaybackStart; + _sessionManager.PlaybackStopped -= _sessionManager_PlaybackStopped; + _sessionManager.PlaybackProgress -= _sessionManager_PlaybackProgress; + _sessionManager.CapabilitiesChanged -= _sessionManager_CapabilitiesChanged; + _sessionManager.SessionActivity -= _sessionManager_SessionActivity; + + base.Dispose(dispose); + } + } +} diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs new file mode 100644 index 0000000000..e2c95eba9c --- /dev/null +++ b/MediaBrowser.Api/Session/SessionsService.cs @@ -0,0 +1,506 @@ +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Security; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; +using ServiceStack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.Session +{ + /// + /// Class GetSessions + /// + [Route("/Sessions", "GET", Summary = "Gets a list of sessions")] + [Authenticated] + public class GetSessions : IReturn> + { + [ApiMember(Name = "ControllableByUserId", Description = "Optional. Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public Guid? ControllableByUserId { get; set; } + + [ApiMember(Name = "DeviceId", Description = "Optional. Filter by device id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string DeviceId { get; set; } + } + + /// + /// Class DisplayContent + /// + [Route("/Sessions/{Id}/Viewing", "POST", Summary = "Instructs a session to browse to an item or view")] + [Authenticated] + public class DisplayContent : IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + /// + /// Artist, Genre, Studio, Person, or any kind of BaseItem + /// + /// The type of the item. + [ApiMember(Name = "ItemType", Description = "The type of item to browse to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string ItemType { get; set; } + + /// + /// Artist name, genre name, item Id, etc + /// + /// The item identifier. + [ApiMember(Name = "ItemId", Description = "The Id of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string ItemId { get; set; } + + /// + /// Gets or sets the name of the item. + /// + /// The name of the item. + [ApiMember(Name = "ItemName", Description = "The name of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string ItemName { get; set; } + } + + [Route("/Sessions/{Id}/Playing", "POST", Summary = "Instructs a session to play an item")] + [Authenticated] + public class Play : IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + /// + /// Artist, Genre, Studio, Person, or any kind of BaseItem + /// + /// The type of the item. + [ApiMember(Name = "ItemIds", Description = "The ids of the items to play, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] + public string ItemIds { get; set; } + + /// + /// Gets or sets the start position ticks that the first item should be played at + /// + /// The start position ticks. + [ApiMember(Name = "StartPositionTicks", Description = "The starting position of the first item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public long? StartPositionTicks { get; set; } + + /// + /// Gets or sets the play command. + /// + /// The play command. + [ApiMember(Name = "PlayCommand", Description = "The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public PlayCommand PlayCommand { get; set; } + } + + [Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")] + [Authenticated] + public class SendPlaystateCommand : IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + /// + /// Gets or sets the position to seek to + /// + [ApiMember(Name = "SeekPositionTicks", Description = "The position to seek to.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public long? SeekPositionTicks { get; set; } + + /// + /// Gets or sets the play command. + /// + /// The play command. + [ApiMember(Name = "Command", Description = "The command to send - stop, pause, unpause, nexttrack, previoustrack, seek, fullscreen.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public PlaystateCommand Command { get; set; } + } + + [Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")] + [Authenticated] + public class SendSystemCommand : IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + /// + /// Gets or sets the command. + /// + /// The play command. + [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Command { get; set; } + } + + [Route("/Sessions/{Id}/Command/{Command}", "POST", Summary = "Issues a system command to a client")] + [Authenticated] + public class SendGeneralCommand : IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + /// + /// Gets or sets the command. + /// + /// The play command. + [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Command { get; set; } + } + + [Route("/Sessions/{Id}/Command", "POST", Summary = "Issues a system command to a client")] + [Authenticated] + public class SendFullGeneralCommand : GeneralCommand, IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + } + + [Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")] + [Authenticated] + public class SendMessageCommand : IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + [ApiMember(Name = "Text", Description = "The message text.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string Text { get; set; } + + [ApiMember(Name = "Header", Description = "The message header.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string Header { get; set; } + + [ApiMember(Name = "TimeoutMs", Description = "The message timeout. If omitted the user will have to confirm viewing the message.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public long? TimeoutMs { get; set; } + } + + [Route("/Sessions/{Id}/Users/{UserId}", "POST", Summary = "Adds an additional user to a session")] + [Authenticated] + public class AddUserToSession : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + [ApiMember(Name = "UserId", Description = "UserId Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public Guid UserId { get; set; } + } + + [Route("/Sessions/{Id}/Users/{UserId}", "DELETE", Summary = "Removes an additional user from a session")] + [Authenticated] + public class RemoveUserFromSession : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + [ApiMember(Name = "UserId", Description = "UserId Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public Guid UserId { get; set; } + } + + [Route("/Sessions/Capabilities", "POST", Summary = "Updates capabilities for a device")] + [Authenticated] + public class PostCapabilities : IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Id { get; set; } + + [ApiMember(Name = "PlayableMediaTypes", Description = "A list of playable media types, comma delimited. Audio, Video, Book, Game, Photo.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string PlayableMediaTypes { get; set; } + + [ApiMember(Name = "SupportedCommands", Description = "A list of supported remote control commands, comma delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string SupportedCommands { get; set; } + + [ApiMember(Name = "MessageCallbackUrl", Description = "A url to post messages to, including remote control commands.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string MessageCallbackUrl { get; set; } + + [ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] + public bool SupportsMediaControl { get; set; } + } + + [Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")] + public class ReportSessionEnded : IReturnVoid + { + } + + [Route("/Auth/Keys", "GET")] + public class GetApiKeys + { + } + + [Route("/Auth/Keys/{Key}", "DELETE")] + public class RevokeKey + { + [ApiMember(Name = "Key", Description = "Auth Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Key { get; set; } + } + + [Route("/Auth/Keys", "POST")] + public class CreateKey + { + [ApiMember(Name = "App", Description = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string App { get; set; } + } + + /// + /// Class SessionsService + /// + public class SessionsService : BaseApiService + { + /// + /// The _session manager + /// + private readonly ISessionManager _sessionManager; + + private readonly IUserManager _userManager; + private readonly IAuthorizationContext _authContext; + private readonly IAuthenticationRepository _authRepo; + + /// + /// Initializes a new instance of the class. + /// + /// The session manager. + /// The user manager. + /// The authentication context. + /// The authentication repo. + public SessionsService(ISessionManager sessionManager, IUserManager userManager, IAuthorizationContext authContext, IAuthenticationRepository authRepo) + { + _sessionManager = sessionManager; + _userManager = userManager; + _authContext = authContext; + _authRepo = authRepo; + } + + public void Delete(RevokeKey request) + { + var task = _sessionManager.RevokeToken(request.Key); + + Task.WaitAll(task); + } + + public void Post(CreateKey request) + { + var task = _authRepo.Create(new AuthenticationInfo + { + AppName = request.App, + IsActive = true, + AccessToken = Guid.NewGuid().ToString("N"), + DateCreated = DateTime.UtcNow + + }, CancellationToken.None); + + Task.WaitAll(task); + } + + public void Post(ReportSessionEnded request) + { + var auth = _authContext.GetAuthorizationInfo(Request); + + _sessionManager.Logout(auth.Token); + } + + public object Get(GetApiKeys request) + { + var result = _authRepo.Get(new AuthenticationInfoQuery + { + IsActive = true + }); + + return ToOptimizedResult(result); + } + + /// + /// Gets the specified request. + /// + /// The request. + /// System.Object. + public object Get(GetSessions request) + { + var result = _sessionManager.Sessions.Where(i => i.IsActive); + + if (!string.IsNullOrEmpty(request.DeviceId)) + { + result = result.Where(i => string.Equals(i.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase)); + } + + if (request.ControllableByUserId.HasValue) + { + result = result.Where(i => i.SupportsMediaControl); + + var user = _userManager.GetUserById(request.ControllableByUserId.Value); + + if (!user.Configuration.EnableRemoteControlOfOtherUsers) + { + result = result.Where(i => !i.UserId.HasValue || i.ContainsUser(request.ControllableByUserId.Value)); + } + } + + return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToList()); + } + + public void Post(SendPlaystateCommand request) + { + var command = new PlaystateRequest + { + Command = request.Command, + SeekPositionTicks = request.SeekPositionTicks + }; + + var task = _sessionManager.SendPlaystateCommand(GetSession().Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); + } + + /// + /// Posts the specified request. + /// + /// The request. + public void Post(DisplayContent request) + { + var command = new BrowseRequest + { + ItemId = request.ItemId, + ItemName = request.ItemName, + ItemType = request.ItemType + }; + + var task = _sessionManager.SendBrowseCommand(GetSession().Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); + } + + /// + /// Posts the specified request. + /// + /// The request. + public void Post(SendSystemCommand request) + { + GeneralCommandType commandType; + + if (Enum.TryParse(request.Command, true, out commandType)) + { + var currentSession = GetSession(); + + var command = new GeneralCommand + { + Name = commandType.ToString(), + ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null + }; + + var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); + } + } + + /// + /// Posts the specified request. + /// + /// The request. + public void Post(SendMessageCommand request) + { + var command = new MessageCommand + { + Header = string.IsNullOrEmpty(request.Header) ? "Message from Server" : request.Header, + TimeoutMs = request.TimeoutMs, + Text = request.Text + }; + + var task = _sessionManager.SendMessageCommand(GetSession().Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); + } + + /// + /// Posts the specified request. + /// + /// The request. + public void Post(Play request) + { + var command = new PlayRequest + { + ItemIds = request.ItemIds.Split(',').ToArray(), + + PlayCommand = request.PlayCommand, + StartPositionTicks = request.StartPositionTicks + }; + + var task = _sessionManager.SendPlayCommand(GetSession().Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); + } + + public void Post(SendGeneralCommand request) + { + var currentSession = GetSession(); + + var command = new GeneralCommand + { + Name = request.Command, + ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null + }; + + var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); + } + + public void Post(SendFullGeneralCommand request) + { + var currentSession = GetSession(); + + request.ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null; + + var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None); + + Task.WaitAll(task); + } + + public void Post(AddUserToSession request) + { + _sessionManager.AddAdditionalUser(request.Id, request.UserId); + } + + public void Delete(RemoveUserFromSession request) + { + _sessionManager.RemoveAdditionalUser(request.Id, request.UserId); + } + + public void Post(PostCapabilities request) + { + if (string.IsNullOrWhiteSpace(request.Id)) + { + request.Id = GetSession().Id; + } + _sessionManager.ReportCapabilities(request.Id, new SessionCapabilities + { + PlayableMediaTypes = request.PlayableMediaTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(), + + SupportedCommands = request.SupportedCommands.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(), + + SupportsMediaControl = request.SupportsMediaControl, + + MessageCallbackUrl = request.MessageCallbackUrl + }); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs deleted file mode 100644 index 8017f35231..0000000000 --- a/MediaBrowser.Api/SessionsService.cs +++ /dev/null @@ -1,506 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Security; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Session; -using ServiceStack; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Api -{ - /// - /// Class GetSessions - /// - [Route("/Sessions", "GET", Summary = "Gets a list of sessions")] - [Authenticated] - public class GetSessions : IReturn> - { - [ApiMember(Name = "ControllableByUserId", Description = "Optional. Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public Guid? ControllableByUserId { get; set; } - - [ApiMember(Name = "DeviceId", Description = "Optional. Filter by device id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public string DeviceId { get; set; } - } - - /// - /// Class DisplayContent - /// - [Route("/Sessions/{Id}/Viewing", "POST", Summary = "Instructs a session to browse to an item or view")] - [Authenticated] - public class DisplayContent : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// Artist, Genre, Studio, Person, or any kind of BaseItem - /// - /// The type of the item. - [ApiMember(Name = "ItemType", Description = "The type of item to browse to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string ItemType { get; set; } - - /// - /// Artist name, genre name, item Id, etc - /// - /// The item identifier. - [ApiMember(Name = "ItemId", Description = "The Id of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string ItemId { get; set; } - - /// - /// Gets or sets the name of the item. - /// - /// The name of the item. - [ApiMember(Name = "ItemName", Description = "The name of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string ItemName { get; set; } - } - - [Route("/Sessions/{Id}/Playing", "POST", Summary = "Instructs a session to play an item")] - [Authenticated] - public class Play : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// Artist, Genre, Studio, Person, or any kind of BaseItem - /// - /// The type of the item. - [ApiMember(Name = "ItemIds", Description = "The ids of the items to play, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] - public string ItemIds { get; set; } - - /// - /// Gets or sets the start position ticks that the first item should be played at - /// - /// The start position ticks. - [ApiMember(Name = "StartPositionTicks", Description = "The starting position of the first item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public long? StartPositionTicks { get; set; } - - /// - /// Gets or sets the play command. - /// - /// The play command. - [ApiMember(Name = "PlayCommand", Description = "The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public PlayCommand PlayCommand { get; set; } - } - - [Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")] - [Authenticated] - public class SendPlaystateCommand : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// Gets or sets the position to seek to - /// - [ApiMember(Name = "SeekPositionTicks", Description = "The position to seek to.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public long? SeekPositionTicks { get; set; } - - /// - /// Gets or sets the play command. - /// - /// The play command. - [ApiMember(Name = "Command", Description = "The command to send - stop, pause, unpause, nexttrack, previoustrack, seek, fullscreen.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public PlaystateCommand Command { get; set; } - } - - [Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")] - [Authenticated] - public class SendSystemCommand : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// Gets or sets the command. - /// - /// The play command. - [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Command { get; set; } - } - - [Route("/Sessions/{Id}/Command/{Command}", "POST", Summary = "Issues a system command to a client")] - [Authenticated] - public class SendGeneralCommand : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - /// - /// Gets or sets the command. - /// - /// The play command. - [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Command { get; set; } - } - - [Route("/Sessions/{Id}/Command", "POST", Summary = "Issues a system command to a client")] - [Authenticated] - public class SendFullGeneralCommand : GeneralCommand, IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - } - - [Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")] - [Authenticated] - public class SendMessageCommand : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - [ApiMember(Name = "Text", Description = "The message text.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Text { get; set; } - - [ApiMember(Name = "Header", Description = "The message header.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Header { get; set; } - - [ApiMember(Name = "TimeoutMs", Description = "The message timeout. If omitted the user will have to confirm viewing the message.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public long? TimeoutMs { get; set; } - } - - [Route("/Sessions/{Id}/Users/{UserId}", "POST", Summary = "Adds an additional user to a session")] - [Authenticated] - public class AddUserToSession : IReturnVoid - { - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - [ApiMember(Name = "UserId", Description = "UserId Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public Guid UserId { get; set; } - } - - [Route("/Sessions/{Id}/Users/{UserId}", "DELETE", Summary = "Removes an additional user from a session")] - [Authenticated] - public class RemoveUserFromSession : IReturnVoid - { - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - [ApiMember(Name = "UserId", Description = "UserId Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public Guid UserId { get; set; } - } - - [Route("/Sessions/Capabilities", "POST", Summary = "Updates capabilities for a device")] - [Authenticated] - public class PostCapabilities : IReturnVoid - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - [ApiMember(Name = "PlayableMediaTypes", Description = "A list of playable media types, comma delimited. Audio, Video, Book, Game, Photo.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string PlayableMediaTypes { get; set; } - - [ApiMember(Name = "SupportedCommands", Description = "A list of supported remote control commands, comma delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string SupportedCommands { get; set; } - - [ApiMember(Name = "MessageCallbackUrl", Description = "A url to post messages to, including remote control commands.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public string MessageCallbackUrl { get; set; } - - [ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] - public bool SupportsMediaControl { get; set; } - } - - [Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")] - public class ReportSessionEnded : IReturnVoid - { - } - - [Route("/Auth/Keys", "GET")] - public class GetApiKeys - { - } - - [Route("/Auth/Keys/{Key}", "DELETE")] - public class RevokeKey - { - [ApiMember(Name = "Key", Description = "Auth Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Key { get; set; } - } - - [Route("/Auth/Keys", "POST")] - public class CreateKey - { - [ApiMember(Name = "App", Description = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string App { get; set; } - } - - /// - /// Class SessionsService - /// - public class SessionsService : BaseApiService - { - /// - /// The _session manager - /// - private readonly ISessionManager _sessionManager; - - private readonly IUserManager _userManager; - private readonly IAuthorizationContext _authContext; - private readonly IAuthenticationRepository _authRepo; - - /// - /// Initializes a new instance of the class. - /// - /// The session manager. - /// The user manager. - /// The authentication context. - /// The authentication repo. - public SessionsService(ISessionManager sessionManager, IUserManager userManager, IAuthorizationContext authContext, IAuthenticationRepository authRepo) - { - _sessionManager = sessionManager; - _userManager = userManager; - _authContext = authContext; - _authRepo = authRepo; - } - - public void Delete(RevokeKey request) - { - var task = _sessionManager.RevokeToken(request.Key); - - Task.WaitAll(task); - } - - public void Post(CreateKey request) - { - var task = _authRepo.Create(new AuthenticationInfo - { - AppName = request.App, - IsActive = true, - AccessToken = Guid.NewGuid().ToString("N"), - DateCreated = DateTime.UtcNow - - }, CancellationToken.None); - - Task.WaitAll(task); - } - - public void Post(ReportSessionEnded request) - { - var auth = _authContext.GetAuthorizationInfo(Request); - - _sessionManager.Logout(auth.Token); - } - - public object Get(GetApiKeys request) - { - var result = _authRepo.Get(new AuthenticationInfoQuery - { - IsActive = true - }); - - return ToOptimizedResult(result); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetSessions request) - { - var result = _sessionManager.Sessions.Where(i => i.IsActive); - - if (!string.IsNullOrEmpty(request.DeviceId)) - { - result = result.Where(i => string.Equals(i.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase)); - } - - if (request.ControllableByUserId.HasValue) - { - result = result.Where(i => i.SupportsMediaControl); - - var user = _userManager.GetUserById(request.ControllableByUserId.Value); - - if (!user.Configuration.EnableRemoteControlOfOtherUsers) - { - result = result.Where(i => !i.UserId.HasValue || i.ContainsUser(request.ControllableByUserId.Value)); - } - } - - return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToList()); - } - - public void Post(SendPlaystateCommand request) - { - var command = new PlaystateRequest - { - Command = request.Command, - SeekPositionTicks = request.SeekPositionTicks - }; - - var task = _sessionManager.SendPlaystateCommand(GetSession().Id, request.Id, command, CancellationToken.None); - - Task.WaitAll(task); - } - - /// - /// Posts the specified request. - /// - /// The request. - public void Post(DisplayContent request) - { - var command = new BrowseRequest - { - ItemId = request.ItemId, - ItemName = request.ItemName, - ItemType = request.ItemType - }; - - var task = _sessionManager.SendBrowseCommand(GetSession().Id, request.Id, command, CancellationToken.None); - - Task.WaitAll(task); - } - - /// - /// Posts the specified request. - /// - /// The request. - public void Post(SendSystemCommand request) - { - GeneralCommandType commandType; - - if (Enum.TryParse(request.Command, true, out commandType)) - { - var currentSession = GetSession(); - - var command = new GeneralCommand - { - Name = commandType.ToString(), - ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null - }; - - var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); - - Task.WaitAll(task); - } - } - - /// - /// Posts the specified request. - /// - /// The request. - public void Post(SendMessageCommand request) - { - var command = new MessageCommand - { - Header = string.IsNullOrEmpty(request.Header) ? "Message from Server" : request.Header, - TimeoutMs = request.TimeoutMs, - Text = request.Text - }; - - var task = _sessionManager.SendMessageCommand(GetSession().Id, request.Id, command, CancellationToken.None); - - Task.WaitAll(task); - } - - /// - /// Posts the specified request. - /// - /// The request. - public void Post(Play request) - { - var command = new PlayRequest - { - ItemIds = request.ItemIds.Split(',').ToArray(), - - PlayCommand = request.PlayCommand, - StartPositionTicks = request.StartPositionTicks - }; - - var task = _sessionManager.SendPlayCommand(GetSession().Id, request.Id, command, CancellationToken.None); - - Task.WaitAll(task); - } - - public void Post(SendGeneralCommand request) - { - var currentSession = GetSession(); - - var command = new GeneralCommand - { - Name = request.Command, - ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null - }; - - var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); - - Task.WaitAll(task); - } - - public void Post(SendFullGeneralCommand request) - { - var currentSession = GetSession(); - - request.ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null; - - var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None); - - Task.WaitAll(task); - } - - public void Post(AddUserToSession request) - { - _sessionManager.AddAdditionalUser(request.Id, request.UserId); - } - - public void Delete(RemoveUserFromSession request) - { - _sessionManager.RemoveAdditionalUser(request.Id, request.UserId); - } - - public void Post(PostCapabilities request) - { - if (string.IsNullOrWhiteSpace(request.Id)) - { - request.Id = GetSession().Id; - } - _sessionManager.ReportCapabilities(request.Id, new SessionCapabilities - { - PlayableMediaTypes = request.PlayableMediaTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(), - - SupportedCommands = request.SupportedCommands.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(), - - SupportsMediaControl = request.SupportsMediaControl, - - MessageCallbackUrl = request.MessageCallbackUrl - }); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Api/System/ActivityLogService.cs b/MediaBrowser.Api/System/ActivityLogService.cs new file mode 100644 index 0000000000..0ccc28c6ff --- /dev/null +++ b/MediaBrowser.Api/System/ActivityLogService.cs @@ -0,0 +1,44 @@ +using MediaBrowser.Controller.Activity; +using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Querying; +using ServiceStack; + +namespace MediaBrowser.Api.System +{ + [Route("/System/ActivityLog/Entries", "GET", Summary = "Gets activity log entries")] + public class GetActivityLogs : IReturn> + { + /// + /// Skips over a given number of items within the results. Use for paging. + /// + /// The start index. + [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? StartIndex { get; set; } + + /// + /// The maximum number of items to return + /// + /// The limit. + [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? Limit { get; set; } + } + + [Authenticated] + public class ActivityLogService : BaseApiService + { + private readonly IActivityManager _activityManager; + + public ActivityLogService(IActivityManager activityManager) + { + _activityManager = activityManager; + } + + public object Get(GetActivityLogs request) + { + var result = _activityManager.GetActivityLogEntries(request.StartIndex, request.Limit); + + return ToOptimizedResult(result); + } + } +} diff --git a/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs b/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs new file mode 100644 index 0000000000..c20cef3b38 --- /dev/null +++ b/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs @@ -0,0 +1,49 @@ +using MediaBrowser.Common.Net; +using MediaBrowser.Controller; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.System; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.System +{ + /// + /// Class SystemInfoWebSocketListener + /// + public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener + { + /// + /// Gets the name. + /// + /// The name. + protected override string Name + { + get { return "SystemInfo"; } + } + + /// + /// The _kernel + /// + private readonly IServerApplicationHost _appHost; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The app host. + public SystemInfoWebSocketListener(ILogger logger, IServerApplicationHost appHost) + : base(logger) + { + _appHost = appHost; + } + + /// + /// Gets the data to send. + /// + /// The state. + /// Task{SystemInfo}. + protected override Task GetDataToSend(WebSocketListenerState state) + { + return Task.FromResult(_appHost.GetSystemInfo()); + } + } +} diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs new file mode 100644 index 0000000000..3913275eee --- /dev/null +++ b/MediaBrowser.Api/System/SystemService.cs @@ -0,0 +1,178 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Net; +using MediaBrowser.Model.System; +using ServiceStack; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.System +{ + /// + /// Class GetSystemInfo + /// + [Route("/System/Info", "GET", Summary = "Gets information about the server")] + [Authenticated] + public class GetSystemInfo : IReturn + { + + } + + [Route("/System/Info/Public", "GET", Summary = "Gets public information about the server")] + public class GetPublicSystemInfo : IReturn + { + + } + + /// + /// Class RestartApplication + /// + [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")] + [Authenticated] + public class RestartApplication + { + } + + [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")] + [Authenticated] + public class ShutdownApplication + { + } + + [Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")] + [Authenticated] + public class GetServerLogs : IReturn> + { + } + + [Route("/System/Logs/Log", "GET", Summary = "Gets a log file")] + public class GetLogFile + { + [ApiMember(Name = "Name", Description = "The log file name.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string Name { get; set; } + } + + /// + /// Class SystemInfoService + /// + public class SystemService : BaseApiService + { + /// + /// The _app host + /// + private readonly IServerApplicationHost _appHost; + private readonly IApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; + + /// + /// Initializes a new instance of the class. + /// + /// The app host. + /// The application paths. + /// The file system. + /// jsonSerializer + public SystemService(IServerApplicationHost appHost, IApplicationPaths appPaths, IFileSystem fileSystem) + { + _appHost = appHost; + _appPaths = appPaths; + _fileSystem = fileSystem; + } + + public object Get(GetServerLogs request) + { + List files; + + try + { + files = new DirectoryInfo(_appPaths.LogDirectoryPath) + .EnumerateFiles("*", SearchOption.AllDirectories) + .Where(i => string.Equals(i.Extension, ".txt", global::System.StringComparison.OrdinalIgnoreCase)) + .ToList(); + } + catch (DirectoryNotFoundException) + { + files = new List(); + } + + var result = files.Select(i => new LogFile + { + DateCreated = _fileSystem.GetCreationTimeUtc(i), + DateModified = _fileSystem.GetLastWriteTimeUtc(i), + Name = i.Name, + Size = i.Length + + }).OrderByDescending(i => i.DateModified) + .ThenByDescending(i => i.DateCreated) + .ThenBy(i => i.Name) + .ToList(); + + return ToOptimizedResult(result); + } + + public object Get(GetLogFile request) + { + var file = new DirectoryInfo(_appPaths.LogDirectoryPath) + .EnumerateFiles("*", SearchOption.AllDirectories) + .First(i => string.Equals(i.Name, request.Name, global::System.StringComparison.OrdinalIgnoreCase)); + + return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite); + } + + /// + /// Gets the specified request. + /// + /// The request. + /// System.Object. + public object Get(GetSystemInfo request) + { + var result = _appHost.GetSystemInfo(); + + return ToOptimizedResult(result); + } + + public object Get(GetPublicSystemInfo request) + { + var result = _appHost.GetSystemInfo(); + + var publicInfo = new PublicSystemInfo + { + Id = result.Id, + ServerName = result.ServerName, + Version = result.Version + }; + + return ToOptimizedResult(publicInfo); + } + + /// + /// Posts the specified request. + /// + /// The request. + public void Post(RestartApplication request) + { + Task.Run(async () => + { + await Task.Delay(100).ConfigureAwait(false); + await _appHost.Restart().ConfigureAwait(false); + }); + } + + /// + /// Posts the specified request. + /// + /// The request. + public void Post(ShutdownApplication request) + { + Task.Run(async () => + { + await Task.Delay(100).ConfigureAwait(false); + await _appHost.Shutdown().ConfigureAwait(false); + }); + } + + } +} diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs deleted file mode 100644 index 259b1d8921..0000000000 --- a/MediaBrowser.Api/SystemService.cs +++ /dev/null @@ -1,177 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.System; -using ServiceStack; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.Api -{ - /// - /// Class GetSystemInfo - /// - [Route("/System/Info", "GET", Summary = "Gets information about the server")] - [Authenticated] - public class GetSystemInfo : IReturn - { - - } - - [Route("/System/Info/Public", "GET", Summary = "Gets public information about the server")] - public class GetPublicSystemInfo : IReturn - { - - } - - /// - /// Class RestartApplication - /// - [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")] - [Authenticated] - public class RestartApplication - { - } - - [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")] - [Authenticated] - public class ShutdownApplication - { - } - - [Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")] - [Authenticated] - public class GetServerLogs : IReturn> - { - } - - [Route("/System/Logs/Log", "GET", Summary = "Gets a log file")] - public class GetLogFile - { - [ApiMember(Name = "Name", Description = "The log file name.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] - public string Name { get; set; } - } - - /// - /// Class SystemInfoService - /// - public class SystemService : BaseApiService - { - /// - /// The _app host - /// - private readonly IServerApplicationHost _appHost; - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - /// - /// Initializes a new instance of the class. - /// - /// The app host. - /// The application paths. - /// The file system. - /// jsonSerializer - public SystemService(IServerApplicationHost appHost, IApplicationPaths appPaths, IFileSystem fileSystem) - { - _appHost = appHost; - _appPaths = appPaths; - _fileSystem = fileSystem; - } - - public object Get(GetServerLogs request) - { - List files; - - try - { - files = new DirectoryInfo(_appPaths.LogDirectoryPath) - .EnumerateFiles("*", SearchOption.AllDirectories) - .Where(i => string.Equals(i.Extension, ".txt", System.StringComparison.OrdinalIgnoreCase)) - .ToList(); - } - catch (DirectoryNotFoundException) - { - files = new List(); - } - - var result = files.Select(i => new LogFile - { - DateCreated = _fileSystem.GetCreationTimeUtc(i), - DateModified = _fileSystem.GetLastWriteTimeUtc(i), - Name = i.Name, - Size = i.Length - - }).OrderByDescending(i => i.DateModified) - .ThenByDescending(i => i.DateCreated) - .ThenBy(i => i.Name) - .ToList(); - - return ToOptimizedResult(result); - } - - public object Get(GetLogFile request) - { - var file = new DirectoryInfo(_appPaths.LogDirectoryPath) - .EnumerateFiles("*", SearchOption.AllDirectories) - .First(i => string.Equals(i.Name, request.Name, System.StringComparison.OrdinalIgnoreCase)); - - return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite); - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetSystemInfo request) - { - var result = _appHost.GetSystemInfo(); - - return ToOptimizedResult(result); - } - - public object Get(GetPublicSystemInfo request) - { - var result = _appHost.GetSystemInfo(); - - var publicInfo = new PublicSystemInfo - { - Id = result.Id, - ServerName = result.ServerName, - Version = result.Version - }; - - return ToOptimizedResult(publicInfo); - } - - /// - /// Posts the specified request. - /// - /// The request. - public void Post(RestartApplication request) - { - Task.Run(async () => - { - await Task.Delay(100).ConfigureAwait(false); - await _appHost.Restart().ConfigureAwait(false); - }); - } - - /// - /// Posts the specified request. - /// - /// The request. - public void Post(ShutdownApplication request) - { - Task.Run(async () => - { - await Task.Delay(100).ConfigureAwait(false); - await _appHost.Shutdown().ConfigureAwait(false); - }); - } - - } -} diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index f5a1f54cbb..4ffe5b3911 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -195,7 +195,7 @@ namespace MediaBrowser.Api var authInfo = AuthorizationContext.GetAuthorizationInfo(Request); var isDashboard = string.Equals(authInfo.Client, "Dashboard", StringComparison.OrdinalIgnoreCase); - if ((Request.IsLocal && isDashboard) || + if ((Request.IsLocal && isDashboard) || !_config.Configuration.IsStartupWizardCompleted) { return Get(new GetUsers @@ -327,7 +327,7 @@ namespace MediaBrowser.Api var revokeTask = _sessionMananger.RevokeUserTokens(user.Id.ToString("N")); Task.WaitAll(revokeTask); - + var task = _userManager.DeleteUser(user); Task.WaitAll(task); @@ -374,8 +374,17 @@ namespace MediaBrowser.Api auth.DeviceId = "Unknown device id"; } - var result = _sessionMananger.AuthenticateNewSession(request.Username, request.Password, auth.Client, auth.Version, - auth.DeviceId, auth.Device, Request.RemoteIp, Request.IsLocal).Result; + var result = _sessionMananger.AuthenticateNewSession(new AuthenticationRequest + { + App = auth.Client, + AppVersion = auth.Version, + DeviceId = auth.DeviceId, + DeviceName = auth.Device, + Password = request.Password, + RemoteEndPoint = Request.RemoteIp, + Username = request.Username + + }, Request.IsLocal).Result; return ToOptimizedResult(result); } @@ -457,8 +466,8 @@ namespace MediaBrowser.Api Task.WaitAll(revokeTask); } - var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ? - _userManager.UpdateUser(user) : + var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ? + _userManager.UpdateUser(user) : _userManager.RenameUser(user, dtoUser.Name); Task.WaitAll(task); diff --git a/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs deleted file mode 100644 index 600d9e405a..0000000000 --- a/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs +++ /dev/null @@ -1,116 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Session; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.Api.WebSocket -{ - /// - /// Class SessionInfoWebSocketListener - /// - class SessionInfoWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> - { - /// - /// Gets the name. - /// - /// The name. - protected override string Name - { - get { return "Sessions"; } - } - - /// - /// The _kernel - /// - private readonly ISessionManager _sessionManager; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The session manager. - public SessionInfoWebSocketListener(ILogger logger, ISessionManager sessionManager) - : base(logger) - { - _sessionManager = sessionManager; - - _sessionManager.SessionStarted += _sessionManager_SessionStarted; - _sessionManager.SessionEnded += _sessionManager_SessionEnded; - _sessionManager.PlaybackStart += _sessionManager_PlaybackStart; - _sessionManager.PlaybackStopped += _sessionManager_PlaybackStopped; - _sessionManager.PlaybackProgress += _sessionManager_PlaybackProgress; - _sessionManager.CapabilitiesChanged += _sessionManager_CapabilitiesChanged; - _sessionManager.SessionActivity += _sessionManager_SessionActivity; - } - - void _sessionManager_SessionActivity(object sender, SessionEventArgs e) - { - SendData(false); - } - - void _sessionManager_CapabilitiesChanged(object sender, SessionEventArgs e) - { - SendData(true); - } - - void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e) - { - SendData(false); - } - - void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) - { - SendData(true); - } - - void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e) - { - SendData(true); - } - - void _sessionManager_SessionEnded(object sender, SessionEventArgs e) - { - SendData(true); - } - - void _sessionManager_SessionStarted(object sender, SessionEventArgs e) - { - SendData(true); - } - - /// - /// Gets the data to send. - /// - /// The state. - /// Task{SystemInfo}. - protected override Task> GetDataToSend(WebSocketListenerState state) - { - return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto)); - } - - protected override bool SendOnTimer - { - get - { - return false; - } - } - - protected override void Dispose(bool dispose) - { - _sessionManager.SessionStarted -= _sessionManager_SessionStarted; - _sessionManager.SessionEnded -= _sessionManager_SessionEnded; - _sessionManager.PlaybackStart -= _sessionManager_PlaybackStart; - _sessionManager.PlaybackStopped -= _sessionManager_PlaybackStopped; - _sessionManager.PlaybackProgress -= _sessionManager_PlaybackProgress; - _sessionManager.CapabilitiesChanged -= _sessionManager_CapabilitiesChanged; - _sessionManager.SessionActivity -= _sessionManager_SessionActivity; - - base.Dispose(dispose); - } - } -} diff --git a/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs b/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs deleted file mode 100644 index 2940bcef06..0000000000 --- a/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs +++ /dev/null @@ -1,49 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.System; -using System.Threading.Tasks; - -namespace MediaBrowser.Api.WebSocket -{ - /// - /// Class SystemInfoWebSocketListener - /// - public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener - { - /// - /// Gets the name. - /// - /// The name. - protected override string Name - { - get { return "SystemInfo"; } - } - - /// - /// The _kernel - /// - private readonly IServerApplicationHost _appHost; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The app host. - public SystemInfoWebSocketListener(ILogger logger, IServerApplicationHost appHost) - : base(logger) - { - _appHost = appHost; - } - - /// - /// Gets the data to send. - /// - /// The state. - /// Task{SystemInfo}. - protected override Task GetDataToSend(WebSocketListenerState state) - { - return Task.FromResult(_appHost.GetSystemInfo()); - } - } -} diff --git a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs index 60abc14f1a..cb6121c9ff 100644 --- a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs +++ b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs @@ -28,6 +28,11 @@ namespace MediaBrowser.Common.Implementations.Configuration /// public event EventHandler ConfigurationUpdated; + /// + /// Occurs when [configuration updating]. + /// + public event EventHandler NamedConfigurationUpdating; + /// /// Occurs when [named configuration updated]. /// @@ -217,6 +222,13 @@ namespace MediaBrowser.Common.Implementations.Configuration throw new ArgumentException("Expected configuration type is " + configurationType.Name); } + EventHelper.FireEventIfNotNull(NamedConfigurationUpdating, this, new ConfigurationUpdateEventArgs + { + Key = key, + NewConfiguration = configuration + + }, Logger); + _configurations.AddOrUpdate(key, configuration, (k, v) => configuration); var path = GetConfigurationFile(key); diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 68222d8436..0dc67f8c00 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -547,6 +547,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks if (ex != null) { result.ErrorMessage = ex.Message; + result.LongErrorMessage = ex.StackTrace; } var path = GetHistoryFilePath(); diff --git a/MediaBrowser.Common/Configuration/IConfigurationManager.cs b/MediaBrowser.Common/Configuration/IConfigurationManager.cs index 25698d9729..d826a3ee78 100644 --- a/MediaBrowser.Common/Configuration/IConfigurationManager.cs +++ b/MediaBrowser.Common/Configuration/IConfigurationManager.cs @@ -6,6 +6,11 @@ namespace MediaBrowser.Common.Configuration { public interface IConfigurationManager { + /// + /// Occurs when [configuration updating]. + /// + event EventHandler NamedConfigurationUpdating; + /// /// Occurs when [configuration updated]. /// diff --git a/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs index fc69630709..6989dea06b 100644 --- a/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs @@ -13,4 +13,9 @@ /// true if this instance is enabled; otherwise, false. bool IsEnabled { get; } } + + public interface IScheduledTaskActivityLog + { + bool IsActivityLogged { get; } + } } \ No newline at end of file diff --git a/MediaBrowser.Controller/Activity/IActivityManager.cs b/MediaBrowser.Controller/Activity/IActivityManager.cs new file mode 100644 index 0000000000..0c565ae36c --- /dev/null +++ b/MediaBrowser.Controller/Activity/IActivityManager.cs @@ -0,0 +1,17 @@ +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Events; +using MediaBrowser.Model.Querying; +using System; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Activity +{ + public interface IActivityManager + { + event EventHandler> EntryCreated; + + Task Create(ActivityLogEntry entry); + + QueryResult GetActivityLogEntries(int? startIndex, int? limit); + } +} diff --git a/MediaBrowser.Controller/Activity/IActivityRepository.cs b/MediaBrowser.Controller/Activity/IActivityRepository.cs new file mode 100644 index 0000000000..29e60ff1f0 --- /dev/null +++ b/MediaBrowser.Controller/Activity/IActivityRepository.cs @@ -0,0 +1,13 @@ +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Querying; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Activity +{ + public interface IActivityRepository + { + Task Create(ActivityLogEntry entry); + + QueryResult GetActivityLogEntries(int? startIndex, int? limit); + } +} diff --git a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs index aac8cda2eb..13c9f8d84b 100644 --- a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs +++ b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs @@ -1,7 +1,5 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Events; -using System; namespace MediaBrowser.Controller.Configuration { @@ -10,11 +8,6 @@ namespace MediaBrowser.Controller.Configuration /// public interface IServerConfigurationManager : IConfigurationManager { - /// - /// Occurs when [configuration updating]. - /// - event EventHandler> ConfigurationUpdating; - /// /// Gets the application paths. /// diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 5e6bd97079..19c9601671 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -102,17 +102,9 @@ namespace MediaBrowser.Controller.Entities.Movies var totalItems = items.Count; var percentages = new Dictionary(totalItems); - var tasks = new List(); - // Refresh songs foreach (var item in items) { - if (tasks.Count >= 3) - { - await Task.WhenAll(tasks).ConfigureAwait(false); - tasks.Clear(); - } - cancellationToken.ThrowIfCancellationRequested(); var innerProgress = new ActionableProgress(); @@ -132,13 +124,9 @@ namespace MediaBrowser.Controller.Entities.Movies }); // Avoid implicitly captured closure - var taskChild = item; - tasks.Add(Task.Run(async () => await RefreshItem(taskChild, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false), cancellationToken)); + await RefreshItem(item, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false); } - await Task.WhenAll(tasks).ConfigureAwait(false); - tasks.Clear(); - // Refresh current item await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index 0da5f92728..c6bbf02ae7 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -31,6 +31,7 @@ namespace MediaBrowser.Controller.Library event EventHandler> UserCreated; event EventHandler> UserConfigurationUpdated; + event EventHandler> UserPasswordChanged; /// /// Updates the configuration. diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index d8d836597b..34486182b7 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -269,7 +269,7 @@ namespace MediaBrowser.Controller.Library if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden) { - logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName); + //logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName); continue; } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 5243e1a2ae..28e1ffb1c8 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -68,6 +68,8 @@ Properties\SharedVersion.cs + + @@ -241,6 +243,7 @@ + @@ -320,6 +323,7 @@ + @@ -360,4 +364,4 @@ xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i --> - + \ No newline at end of file diff --git a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs index 87b89e79c8..254e56e059 100644 --- a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs +++ b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs @@ -16,10 +16,6 @@ namespace MediaBrowser.Controller.Notifications /// event EventHandler NotificationAdded; /// - /// Occurs when [notification updated]. - /// - event EventHandler NotificationUpdated; - /// /// Occurs when [notifications marked read]. /// event EventHandler NotificationsMarkedRead; @@ -37,14 +33,6 @@ namespace MediaBrowser.Controller.Notifications /// NotificationResult. NotificationResult GetNotifications(NotificationQuery query); - /// - /// Gets the notification. - /// - /// The id. - /// The user id. - /// Notification. - Notification GetNotification(string id, string userId); - /// /// Adds the notification. /// diff --git a/MediaBrowser.Controller/Session/AuthenticationRequest.cs b/MediaBrowser.Controller/Session/AuthenticationRequest.cs new file mode 100644 index 0000000000..38871e8147 --- /dev/null +++ b/MediaBrowser.Controller/Session/AuthenticationRequest.cs @@ -0,0 +1,14 @@ + +namespace MediaBrowser.Controller.Session +{ + public class AuthenticationRequest + { + public string Username { get; set; } + public string Password { get; set; } + public string App { get; set; } + public string AppVersion { get; set; } + public string DeviceId { get; set; } + public string DeviceName { get; set; } + public string RemoteEndPoint { get; set; } + } +} diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index e37a139233..f715ce7703 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Events; using MediaBrowser.Model.Session; using MediaBrowser.Model.Users; using System; @@ -46,6 +47,16 @@ namespace MediaBrowser.Controller.Session /// Occurs when [capabilities changed]. /// event EventHandler CapabilitiesChanged; + + /// + /// Occurs when [authentication failed]. + /// + event EventHandler> AuthenticationFailed; + + /// + /// Occurs when [authentication succeeded]. + /// + event EventHandler> AuthenticationSucceeded; /// /// Gets the sessions. @@ -211,23 +222,10 @@ namespace MediaBrowser.Controller.Session /// /// Authenticates the new session. /// - /// The username. - /// The password. - /// Type of the client. - /// The application version. - /// The device identifier. - /// Name of the device. - /// The remote end point. + /// The request. /// if set to true [is local]. /// Task{SessionInfo}. - Task AuthenticateNewSession(string username, - string password, - string clientType, - string appVersion, - string deviceId, - string deviceName, - string remoteEndPoint, - bool isLocal); + Task AuthenticateNewSession(AuthenticationRequest request, bool isLocal); /// /// Reports the capabilities. diff --git a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs index 1d66d1505b..0c814c0d4c 100644 --- a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs +++ b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs @@ -1,5 +1,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Providers; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -8,6 +9,16 @@ namespace MediaBrowser.Controller.Subtitles { public interface ISubtitleManager { + /// + /// Occurs when [subtitle download failure]. + /// + event EventHandler SubtitleDownloadFailure; + + /// + /// Occurs when [subtitles downloaded]. + /// + event EventHandler SubtitlesDownloaded; + /// /// Adds the parts. /// @@ -31,7 +42,7 @@ namespace MediaBrowser.Controller.Subtitles /// The request. /// The cancellation token. /// Task{IEnumerable{RemoteSubtitleInfo}}. - Task> SearchSubtitles(SubtitleSearchRequest request, + Task> SearchSubtitles(SubtitleSearchRequest request, CancellationToken cancellationToken); /// @@ -41,8 +52,8 @@ namespace MediaBrowser.Controller.Subtitles /// The subtitle identifier. /// The cancellation token. /// Task. - Task DownloadSubtitles(Video video, - string subtitleId, + Task DownloadSubtitles(Video video, + string subtitleId, CancellationToken cancellationToken); /// diff --git a/MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs b/MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs new file mode 100644 index 0000000000..1d204f2cbd --- /dev/null +++ b/MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs @@ -0,0 +1,27 @@ +using System; +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Subtitles +{ + public class SubtitleDownloadEventArgs + { + public BaseItem Item { get; set; } + + public string Format { get; set; } + + public string Language { get; set; } + + public bool IsForced { get; set; } + + public string Provider { get; set; } + } + + public class SubtitleDownloadFailureEventArgs + { + public BaseItem Item { get; set; } + + public string Provider { get; set; } + + public Exception Exception { get; set; } + } +} diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs index 62aec5ecbd..25778d036b 100644 --- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -27,7 +27,7 @@ namespace MediaBrowser.LocalMetadata var path = file.FullName; - await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + //await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); try { @@ -46,7 +46,7 @@ namespace MediaBrowser.LocalMetadata } finally { - XmlProviderUtils.XmlParsingResourcePool.Release(); + //XmlProviderUtils.XmlParsingResourcePool.Release(); } return result; diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index ca48b88896..2a99076d42 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -83,6 +83,9 @@ + + Activity\ActivityLogEntry.cs + ApiClient\ApiClientExtensions.cs @@ -173,9 +176,6 @@ Configuration\ServerConfiguration.cs - - Configuration\SubtitleOptions.cs - Configuration\SubtitlePlaybackMode.cs @@ -728,6 +728,9 @@ Providers\RemoteSubtitleInfo.cs + + Providers\SubtitleOptions.cs + Querying\AllThemeMediaResult.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 1adf83d36a..72414d454c 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -52,6 +52,9 @@ + + Activity\ActivityLogEntry.cs + ApiClient\GeneralCommandEventArgs.cs @@ -136,9 +139,6 @@ Configuration\ServerConfiguration.cs - - Configuration\SubtitleOptions.cs - Configuration\SubtitlePlaybackMode.cs @@ -685,6 +685,9 @@ Providers\RemoteSubtitleInfo.cs + + Providers\SubtitleOptions.cs + Querying\AllThemeMediaResult.cs diff --git a/MediaBrowser.Model/Activity/ActivityLogEntry.cs b/MediaBrowser.Model/Activity/ActivityLogEntry.cs new file mode 100644 index 0000000000..8fad574618 --- /dev/null +++ b/MediaBrowser.Model/Activity/ActivityLogEntry.cs @@ -0,0 +1,62 @@ +using MediaBrowser.Model.Logging; +using System; + +namespace MediaBrowser.Model.Activity +{ + public class ActivityLogEntry + { + /// + /// Gets or sets the identifier. + /// + /// The identifier. + public string Id { get; set; } + + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; set; } + + /// + /// Gets or sets the overview. + /// + /// The overview. + public string Overview { get; set; } + + /// + /// Gets or sets the short overview. + /// + /// The short overview. + public string ShortOverview { get; set; } + + /// + /// Gets or sets the type. + /// + /// The type. + public string Type { get; set; } + + /// + /// Gets or sets the item identifier. + /// + /// The item identifier. + public string ItemId { get; set; } + + /// + /// Gets or sets the date. + /// + /// The date. + public DateTime Date { get; set; } + + /// + /// Gets or sets the user identifier. + /// + /// The user identifier. + public string UserId { get; set; } + + /// + /// Gets or sets the log severity. + /// + /// The log severity. + public LogSeverity Severity { get; set; } + } +} diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 363500954a..98b765e6bd 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -623,7 +623,7 @@ namespace MediaBrowser.Model.ApiClient Task ReportPlaybackStoppedAsync(PlaybackStopInfo info); /// - /// Instructs antoher client to browse to a library item. + /// Instructs another client to browse to a library item. /// /// The session id. /// The id of the item to browse to. diff --git a/MediaBrowser.Model/Channels/ChannelItemQuery.cs b/MediaBrowser.Model/Channels/ChannelItemQuery.cs index a76c6cd2d3..4aacc16194 100644 --- a/MediaBrowser.Model/Channels/ChannelItemQuery.cs +++ b/MediaBrowser.Model/Channels/ChannelItemQuery.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; -using System.Collections.Generic; namespace MediaBrowser.Model.Channels { @@ -39,13 +38,13 @@ namespace MediaBrowser.Model.Channels public SortOrder? SortOrder { get; set; } public string[] SortBy { get; set; } public ItemFilter[] Filters { get; set; } - public List Fields { get; set; } + public ItemFields[] Fields { get; set; } public ChannelItemQuery() { Filters = new ItemFilter[] { }; SortBy = new string[] { }; - Fields = new List(); + Fields = new ItemFields[] { }; } } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 4734e2af7d..6600a3e912 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -2,6 +2,7 @@ using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Notifications; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Model.Configuration { @@ -285,8 +286,6 @@ namespace MediaBrowser.Model.Configuration new MetadataOptions(0, 1280) {ItemType = "Season"} }; - - SubtitleOptions = new SubtitleOptions(); } } } diff --git a/MediaBrowser.Model/Configuration/SubtitleOptions.cs b/MediaBrowser.Model/Configuration/SubtitleOptions.cs deleted file mode 100644 index d50dba1b2e..0000000000 --- a/MediaBrowser.Model/Configuration/SubtitleOptions.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace MediaBrowser.Model.Configuration -{ - public class SubtitleOptions - { - public bool SkipIfGraphicalSubtitlesPresent { get; set; } - public bool SkipIfAudioTrackMatches { get; set; } - public string[] DownloadLanguages { get; set; } - public bool DownloadMovieSubtitles { get; set; } - public bool DownloadEpisodeSubtitles { get; set; } - - public string OpenSubtitlesUsername { get; set; } - public string OpenSubtitlesPasswordHash { get; set; } - public bool IsOpenSubtitleVipAccount { get; set; } - - public SubtitleOptions() - { - DownloadLanguages = new string[] { }; - - SkipIfAudioTrackMatches = true; - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Model/Events/GenericEventArgs.cs b/MediaBrowser.Model/Events/GenericEventArgs.cs index 5a83419e19..3c558577ad 100644 --- a/MediaBrowser.Model/Events/GenericEventArgs.cs +++ b/MediaBrowser.Model/Events/GenericEventArgs.cs @@ -13,5 +13,21 @@ namespace MediaBrowser.Model.Events /// /// The argument. public T Argument { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The argument. + public GenericEventArgs(T arg) + { + Argument = arg; + } + + /// + /// Initializes a new instance of the class. + /// + public GenericEventArgs() + { + } } } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 042828887f..75694cb04d 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -59,6 +59,7 @@ Properties\SharedVersion.cs + @@ -99,7 +100,7 @@ - + @@ -378,4 +379,4 @@ xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\net45\" /y /d /r /i --> - + \ No newline at end of file diff --git a/MediaBrowser.Model/Providers/SubtitleOptions.cs b/MediaBrowser.Model/Providers/SubtitleOptions.cs new file mode 100644 index 0000000000..84f01e0b7a --- /dev/null +++ b/MediaBrowser.Model/Providers/SubtitleOptions.cs @@ -0,0 +1,22 @@ +namespace MediaBrowser.Model.Providers +{ + public class SubtitleOptions + { + public bool SkipIfGraphicalSubtitlesPresent { get; set; } + public bool SkipIfAudioTrackMatches { get; set; } + public string[] DownloadLanguages { get; set; } + public bool DownloadMovieSubtitles { get; set; } + public bool DownloadEpisodeSubtitles { get; set; } + + public string OpenSubtitlesUsername { get; set; } + public string OpenSubtitlesPasswordHash { get; set; } + public bool IsOpenSubtitleVipAccount { get; set; } + + public SubtitleOptions() + { + DownloadLanguages = new string[] { }; + + SkipIfAudioTrackMatches = true; + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Model/Tasks/TaskResult.cs b/MediaBrowser.Model/Tasks/TaskResult.cs index e73b4c9a11..956d68ae4d 100644 --- a/MediaBrowser.Model/Tasks/TaskResult.cs +++ b/MediaBrowser.Model/Tasks/TaskResult.cs @@ -42,5 +42,11 @@ namespace MediaBrowser.Model.Tasks /// /// The error message. public string ErrorMessage { get; set; } + + /// + /// Gets or sets the long error message. + /// + /// The long error message. + public string LongErrorMessage { get; set; } } } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 76a1e52f5b..66188f796a 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -152,6 +152,7 @@ + @@ -213,4 +214,4 @@ --> - + \ No newline at end of file diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index a2e1ba05a7..f48707582c 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -13,10 +13,12 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Subtitles; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; @@ -464,6 +466,11 @@ namespace MediaBrowser.Providers.MediaInfo } } + private SubtitleOptions GetOptions() + { + return _config.GetConfiguration("subtitles"); + } + /// /// Adds the external subtitles. /// @@ -484,9 +491,11 @@ namespace MediaBrowser.Providers.MediaInfo var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh; - if (enableSubtitleDownloading && (_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles && + var subtitleOptions = GetOptions(); + + if (enableSubtitleDownloading && (subtitleOptions.DownloadEpisodeSubtitles && video is Episode) || - (_config.Configuration.SubtitleOptions.DownloadMovieSubtitles && + (subtitleOptions.DownloadMovieSubtitles && video is Movie)) { var downloadedLanguages = await new SubtitleDownloader(_logger, @@ -494,9 +503,9 @@ namespace MediaBrowser.Providers.MediaInfo .DownloadSubtitles(video, currentStreams, externalSubtitleStreams, - _config.Configuration.SubtitleOptions.SkipIfGraphicalSubtitlesPresent, - _config.Configuration.SubtitleOptions.SkipIfAudioTrackMatches, - _config.Configuration.SubtitleOptions.DownloadLanguages, + subtitleOptions.SkipIfGraphicalSubtitlesPresent, + subtitleOptions.SkipIfAudioTrackMatches, + subtitleOptions.DownloadLanguages, cancellationToken).ConfigureAwait(false); // Rescan diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index 361cc317c2..63df3f50d5 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -1,10 +1,12 @@ -using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Subtitles; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; @@ -12,6 +14,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Providers.MediaInfo { @@ -45,8 +48,15 @@ namespace MediaBrowser.Providers.MediaInfo get { return "Library"; } } + private SubtitleOptions GetOptions() + { + return _config.GetConfiguration("subtitles"); + } + public async Task Execute(CancellationToken cancellationToken, IProgress progress) { + var options = GetOptions(); + var videos = _libraryManager.RootFolder .RecursiveChildren .OfType