aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj6
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs7
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs3
-rw-r--r--MediaBrowser.Api/System/SystemService.cs11
-rw-r--r--MediaBrowser.Api/packages.config2
-rw-r--r--MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj14
-rw-r--r--MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs146
-rw-r--r--MediaBrowser.Common.Implementations/packages.config5
-rw-r--r--MediaBrowser.Common/Net/INetworkManager.cs9
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs3
-rw-r--r--MediaBrowser.Controller/IServerApplicationHost.cs4
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj6
-rw-r--r--MediaBrowser.Controller/Net/IHttpServer.cs6
-rw-r--r--MediaBrowser.Controller/Providers/ItemLookupInfo.cs1
-rw-r--r--MediaBrowser.Controller/packages.config2
-rw-r--r--MediaBrowser.Dlna/Main/DlnaEntryPoint.cs43
-rw-r--r--MediaBrowser.Dlna/MediaBrowser.Dlna.csproj3
-rw-r--r--MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs29
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Default.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Kodi.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Vlc.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml11
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml3
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml3
-rw-r--r--MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs104
-rw-r--r--MediaBrowser.Dlna/Ssdp/SsdpHandler.cs15
-rw-r--r--MediaBrowser.Dlna/packages.config1
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs39
-rw-r--r--MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs4
-rw-r--r--MediaBrowser.Model/Configuration/UserConfiguration.cs5
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs19
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj5
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbProvider.cs2
-rw-r--r--MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs156
-rw-r--r--MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs1153
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeriesProvider.cs13
-rw-r--r--MediaBrowser.Providers/packages.config2
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs4
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs13
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs47
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs5
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs941
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs3
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserViewManager.cs11
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs59
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListingsNorthAmerica.cs366
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/IEmbyListingProvider.cs18
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/hu.json102
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/id.json2
-rw-r--r--MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs1
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj17
-rw-r--r--MediaBrowser.Server.Implementations/packages.config4
-rw-r--r--MediaBrowser.Server.Mono/Native/BaseMonoApp.cs2
-rw-r--r--MediaBrowser.Server.Startup.Common/ApplicationHost.cs81
-rw-r--r--MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj20
-rw-r--r--MediaBrowser.ServerApplication/Native/WindowsApp.cs2
-rw-r--r--MediaBrowser.WebDashboard/Api/PackageCreator.cs24
-rw-r--r--MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj6
-rw-r--r--SharedVersion.cs2
82 files changed, 2202 insertions, 1444 deletions
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 7be644bc8..08b99d5a4 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -49,6 +49,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
</Reference>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
<Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
</Reference>
@@ -63,9 +66,6 @@
<Reference Include="ServiceStack.Text">
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
</Reference>
- <Reference Include="MoreLinq">
- <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 4de29b3f2..9e2e399d7 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1562,6 +1562,13 @@ namespace MediaBrowser.Api.Playback
RequestedUrl = url
};
+ //if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
+ // (Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 ||
+ // (Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
+ //{
+ // state.SegmentLength = 6;
+ //}
+
if (!string.IsNullOrWhiteSpace(request.AudioCodec))
{
state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 60412159c..766e8a003 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -111,7 +111,8 @@ namespace MediaBrowser.Api.Playback.Hls
throw;
}
- await WaitForMinimumSegmentCount(playlist, 3, cancellationTokenSource.Token).ConfigureAwait(false);
+ var waitForSegments = state.SegmentLength >= 10 ? 2 : 3;
+ await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
}
}
finally
diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs
index 3f2b3d66a..9b6b6a7d6 100644
--- a/MediaBrowser.Api/System/SystemService.cs
+++ b/MediaBrowser.Api/System/SystemService.cs
@@ -32,6 +32,12 @@ namespace MediaBrowser.Api.System
}
+ [Route("/System/Ping", "POST")]
+ public class PingSystem : IReturnVoid
+ {
+
+ }
+
/// <summary>
/// Class RestartApplication
/// </summary>
@@ -104,6 +110,11 @@ namespace MediaBrowser.Api.System
_security = security;
}
+ public object Post(PingSystem request)
+ {
+ return _appHost.Name;
+ }
+
public object Get(GetServerLogs request)
{
List<FileSystemMetadata> files;
diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config
index d96012318..258a097cd 100644
--- a/MediaBrowser.Api/packages.config
+++ b/MediaBrowser.Api/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
- <package id="morelinq" version="1.1.1" targetFramework="net45" />
+ <package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
index d857e58b6..59e20ec6e 100644
--- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
+++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
@@ -51,9 +51,11 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
</Reference>
- <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\NLog.4.1.1\lib\net45\NLog.dll</HintPath>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
+ <Reference Include="NLog">
+ <HintPath>..\packages\NLog.4.2.3\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
@@ -62,13 +64,13 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
</Reference>
- <Reference Include="SimpleInjector, Version=2.8.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\SimpleInjector.3.0.5\lib\net45\SimpleInjector.dll</HintPath>
+ <Reference Include="SimpleInjector">
+ <HintPath>..\packages\SimpleInjector.3.1.2\lib\net45\SimpleInjector.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
<Reference Include="System.Net" />
<Reference Include="System.Xml" />
<Reference Include="ServiceStack.Text">
diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
index c27dfd68d..9b278b889 100644
--- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
+++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
@@ -7,6 +7,7 @@ using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
+using MoreLinq;
namespace MediaBrowser.Common.Implementations.Networking
{
@@ -31,14 +32,14 @@ namespace MediaBrowser.Common.Implementations.Networking
}
}
- private volatile List<string> _localIpAddresses;
+ private volatile List<IPAddress> _localIpAddresses;
private readonly object _localIpAddressSyncLock = new object();
/// <summary>
/// Gets the machine's local ip address
/// </summary>
/// <returns>IPAddress.</returns>
- public IEnumerable<string> GetLocalIpAddresses()
+ public IEnumerable<IPAddress> GetLocalIpAddresses()
{
if (_localIpAddresses == null)
{
@@ -58,25 +59,24 @@ namespace MediaBrowser.Common.Implementations.Networking
return _localIpAddresses;
}
- private IEnumerable<string> GetLocalIpAddressesInternal()
+ private IEnumerable<IPAddress> GetLocalIpAddressesInternal()
{
var list = GetIPsDefault()
- .Where(i => !IPAddress.IsLoopback(i))
- .Select(i => i.ToString())
- .Where(FilterIpAddress)
.ToList();
- if (list.Count > 0)
+ if (list.Count == 0)
{
- return list;
+ list.AddRange(GetLocalIpAddressesFallback());
}
- return GetLocalIpAddressesFallback().Where(FilterIpAddress);
+ return list.Where(FilterIpAddress).DistinctBy(i => i.ToString());
}
- private bool FilterIpAddress(string address)
+ private bool FilterIpAddress(IPAddress address)
{
- if (address.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
+ var addressString = address.ToString ();
+
+ if (addressString.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
{
return false;
}
@@ -84,8 +84,16 @@ namespace MediaBrowser.Common.Implementations.Networking
return true;
}
- private bool IsInPrivateAddressSpace(string endpoint)
+ public bool IsInPrivateAddressSpace(string endpoint)
{
+ if (string.Equals(endpoint, "::1", StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+
+ // Handle ipv4 mapped to ipv6
+ endpoint = endpoint.Replace("::ffff:", string.Empty);
+
// Private address space:
// http://en.wikipedia.org/wiki/Private_network
@@ -96,9 +104,6 @@ namespace MediaBrowser.Common.Implementations.Networking
return
- // If url was requested with computer name, we may see this
- endpoint.IndexOf("::", StringComparison.OrdinalIgnoreCase) != -1 ||
-
endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
@@ -131,26 +136,41 @@ namespace MediaBrowser.Common.Implementations.Networking
throw new ArgumentNullException("endpoint");
}
- if (IsInPrivateAddressSpace(endpoint))
- {
- return true;
- }
-
- const int lengthMatch = 4;
-
- if (endpoint.Length >= lengthMatch)
+ IPAddress address;
+ if (IPAddress.TryParse(endpoint, out address))
{
- var prefix = endpoint.Substring(0, lengthMatch);
+ var addressString = address.ToString();
- if (GetLocalIpAddresses()
- .Any(i => i.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
+ int lengthMatch = 100;
+ if (address.AddressFamily == AddressFamily.InterNetwork)
{
- return true;
+ lengthMatch = 4;
+ if (IsInPrivateAddressSpace(addressString))
+ {
+ return true;
+ }
+ }
+ else if (address.AddressFamily == AddressFamily.InterNetworkV6)
+ {
+ lengthMatch = 10;
+ if (IsInPrivateAddressSpace(endpoint))
+ {
+ return true;
+ }
}
- }
- IPAddress address;
- if (resolveHost && !IPAddress.TryParse(endpoint, out address))
+ // Should be even be doing this with ipv6?
+ if (addressString.Length >= lengthMatch)
+ {
+ var prefix = addressString.Substring(0, lengthMatch);
+
+ if (GetLocalIpAddresses().Any(i => i.ToString().StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
+ {
+ return true;
+ }
+ }
+ }
+ else if (resolveHost)
{
Uri uri;
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
@@ -188,33 +208,44 @@ namespace MediaBrowser.Common.Implementations.Networking
return Dns.GetHostAddresses(hostName);
}
- private IEnumerable<IPAddress> GetIPsDefault()
- {
- foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
- {
- var props = adapter.GetIPProperties();
- var gateways = from ga in props.GatewayAddresses
- where !ga.Address.Equals(IPAddress.Any)
- select true;
-
- if (!gateways.Any())
- {
- continue;
- }
-
- foreach (var uni in props.UnicastAddresses)
- {
- var address = uni.Address;
- if (address.AddressFamily != AddressFamily.InterNetwork)
- {
- continue;
- }
- yield return address;
- }
- }
- }
-
- private IEnumerable<string> GetLocalIpAddressesFallback()
+ private List<IPAddress> GetIPsDefault()
+ {
+ NetworkInterface[] interfaces;
+
+ try
+ {
+ interfaces = NetworkInterface.GetAllNetworkInterfaces();
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
+ return new List<IPAddress>();
+ }
+
+ return interfaces.SelectMany(network => {
+
+ try
+ {
+ Logger.Debug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
+
+ var properties = network.GetIPProperties();
+
+ return properties.UnicastAddresses
+ .Select(i => i.Address)
+ .Where(i => i.AddressFamily == AddressFamily.InterNetwork)
+ .ToList();
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error querying network interface", ex);
+ return new List<IPAddress>();
+ }
+
+ }).DistinctBy(i => i.ToString())
+ .ToList();
+ }
+
+ private IEnumerable<IPAddress> GetLocalIpAddressesFallback()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
@@ -222,7 +253,6 @@ namespace MediaBrowser.Common.Implementations.Networking
// It's not fool-proof so ultimately the consumer will have to examine them and decide
return host.AddressList
.Where(i => i.AddressFamily == AddressFamily.InterNetwork)
- .Select(i => i.ToString())
.Reverse();
}
diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config
index a0711a9c7..84f663268 100644
--- a/MediaBrowser.Common.Implementations/packages.config
+++ b/MediaBrowser.Common.Implementations/packages.config
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
- <package id="NLog" version="4.1.0" targetFramework="net45" />
+ <package id="morelinq" version="1.4.0" targetFramework="net45" />
+ <package id="NLog" version="4.2.3" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
- <package id="SimpleInjector" version="3.0.5" targetFramework="net45" />
+ <package id="SimpleInjector" version="3.1.2" targetFramework="net45" />
</packages>
diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs
index 8fc947e8f..de63ddd51 100644
--- a/MediaBrowser.Common/Net/INetworkManager.cs
+++ b/MediaBrowser.Common/Net/INetworkManager.cs
@@ -11,7 +11,7 @@ namespace MediaBrowser.Common.Net
/// Gets the machine's local ip address
/// </summary>
/// <returns>IPAddress.</returns>
- IEnumerable<string> GetLocalIpAddresses();
+ IEnumerable<IPAddress> GetLocalIpAddresses();
/// <summary>
/// Gets a random port number that is currently available
@@ -26,6 +26,13 @@ namespace MediaBrowser.Common.Net
string GetMacAddress();
/// <summary>
+ /// Determines whether [is in private address space] [the specified endpoint].
+ /// </summary>
+ /// <param name="endpoint">The endpoint.</param>
+ /// <returns><c>true</c> if [is in private address space] [the specified endpoint]; otherwise, <c>false</c>.</returns>
+ bool IsInPrivateAddressSpace(string endpoint);
+
+ /// <summary>
/// Gets the network shares.
/// </summary>
/// <param name="path">The path.</param>
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 7086ac743..0fbe51622 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1779,7 +1779,8 @@ namespace MediaBrowser.Controller.Entities
ProviderIds = ProviderIds,
IndexNumber = IndexNumber,
ParentIndexNumber = ParentIndexNumber,
- Year = ProductionYear
+ Year = ProductionYear,
+ PremiereDate = PremiereDate
};
}
diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs
index 1b842a5f6..fb843d191 100644
--- a/MediaBrowser.Controller/IServerApplicationHost.cs
+++ b/MediaBrowser.Controller/IServerApplicationHost.cs
@@ -1,6 +1,8 @@
using MediaBrowser.Common;
using MediaBrowser.Model.System;
using System;
+using System.Collections.Generic;
+using System.Net;
namespace MediaBrowser.Controller
{
@@ -63,7 +65,7 @@ namespace MediaBrowser.Controller
/// Gets the local ip address.
/// </summary>
/// <value>The local ip address.</value>
- string LocalIpAddress { get; }
+ List<IPAddress> LocalIpAddresses { get; }
/// <summary>
/// Gets the local API URL.
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index bcf4de2a2..b6dc7365a 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -51,6 +51,9 @@
<Reference Include="Interfaces.IO">
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
</Reference>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
<Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
</Reference>
@@ -65,9 +68,6 @@
<Reference Include="ServiceStack.Interfaces">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
- <Reference Include="MoreLinq">
- <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs
index 91da5fab2..97c5dd31b 100644
--- a/MediaBrowser.Controller/Net/IHttpServer.cs
+++ b/MediaBrowser.Controller/Net/IHttpServer.cs
@@ -29,12 +29,6 @@ namespace MediaBrowser.Controller.Net
void StartServer(IEnumerable<string> urlPrefixes, string certificatePath);
/// <summary>
- /// Gets the local end points.
- /// </summary>
- /// <value>The local end points.</value>
- IEnumerable<string> LocalEndPoints { get; }
-
- /// <summary>
/// Stops this instance.
/// </summary>
void Stop();
diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs
index 91dc33214..7114cde3e 100644
--- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs
+++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs
@@ -33,6 +33,7 @@ namespace MediaBrowser.Controller.Providers
public int? Year { get; set; }
public int? IndexNumber { get; set; }
public int? ParentIndexNumber { get; set; }
+ public DateTime? PremiereDate { get; set; }
public ItemLookupInfo()
{
diff --git a/MediaBrowser.Controller/packages.config b/MediaBrowser.Controller/packages.config
index a0aacbc95..90b347929 100644
--- a/MediaBrowser.Controller/packages.config
+++ b/MediaBrowser.Controller/packages.config
@@ -2,6 +2,6 @@
<packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
- <package id="morelinq" version="1.1.1" targetFramework="net45" />
+ <package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
index 8c45757e7..d79ef9eaf 100644
--- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
+++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
@@ -43,19 +43,19 @@ namespace MediaBrowser.Dlna.Main
private readonly List<string> _registeredServerIds = new List<string>();
private bool _dlnaServerStarted;
- public DlnaEntryPoint(IServerConfigurationManager config,
- ILogManager logManager,
- IServerApplicationHost appHost,
- INetworkManager network,
- ISessionManager sessionManager,
- IHttpClient httpClient,
- ILibraryManager libraryManager,
- IUserManager userManager,
- IDlnaManager dlnaManager,
- IImageProcessor imageProcessor,
- IUserDataManager userDataManager,
- ILocalizationManager localization,
- IMediaSourceManager mediaSourceManager,
+ public DlnaEntryPoint(IServerConfigurationManager config,
+ ILogManager logManager,
+ IServerApplicationHost appHost,
+ INetworkManager network,
+ ISessionManager sessionManager,
+ IHttpClient httpClient,
+ ILibraryManager libraryManager,
+ IUserManager userManager,
+ IDlnaManager dlnaManager,
+ IImageProcessor imageProcessor,
+ IUserDataManager userDataManager,
+ ILocalizationManager localization,
+ IMediaSourceManager mediaSourceManager,
ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery)
{
_config = config;
@@ -148,13 +148,20 @@ namespace MediaBrowser.Dlna.Main
private void RegisterServerEndpoints()
{
- foreach (var address in _network.GetLocalIpAddresses())
+ foreach (var address in _appHost.LocalIpAddresses)
{
- var guid = address.GetMD5();
+ //if (IPAddress.IsLoopback(address))
+ //{
+ // // Should we allow this?
+ // continue;
+ //}
+
+ var addressString = address.ToString();
+ var guid = addressString.GetMD5();
var descriptorURI = "/dlna/" + guid.ToString("N") + "/description.xml";
- var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorURI);
+ var uri = new Uri(_appHost.GetLocalApiUrl(addressString) + descriptorURI);
var services = new List<string>
{
@@ -165,8 +172,8 @@ namespace MediaBrowser.Dlna.Main
"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
"uuid:" + guid.ToString("N")
};
-
- _ssdpHandler.RegisterNotification(guid, uri, IPAddress.Parse(address), services);
+
+ _ssdpHandler.RegisterNotification(guid, uri, address, services);
_registeredServerIds.Add(guid.ToString("N"));
}
diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
index b8ac60ef6..db69a45c8 100644
--- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
+++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
@@ -44,6 +44,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
</Reference>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
<Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
</Reference>
diff --git a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs
index 63bb0b52a..5bfd37726 100644
--- a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs
@@ -232,6 +232,35 @@ namespace MediaBrowser.Dlna.Profiles
}
}
};
+
+ SubtitleProfiles = new[]
+ {
+ new SubtitleProfile
+ {
+ Format = "srt",
+ Method = SubtitleDeliveryMethod.External
+ },
+ new SubtitleProfile
+ {
+ Format = "srt",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+ new SubtitleProfile
+ {
+ Format = "sub",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+ new SubtitleProfile
+ {
+ Format = "subrip",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+ new SubtitleProfile
+ {
+ Format = "idx",
+ Method = SubtitleDeliveryMethod.Embed
+ }
+ };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml b/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml
index a537cbfcf..ca98f950b 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>BubbleUPnp</Name>
<Identification>
<ModelName>BubbleUPnp</ModelName>
@@ -16,6 +16,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
index 72cad4513..58c37a423 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Generic Device</Name>
<FriendlyName>Emby</FriendlyName>
<Manufacturer>Emby</Manufacturer>
@@ -10,6 +10,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
index bbaf23cc5..86be2d18b 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Denon AVR</Name>
<Identification>
<FriendlyName>Denon:\[AVR:.*</FriendlyName>
@@ -15,6 +15,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
index 5de643b02..c553f9a06 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>DirecTV HD-DVR</Name>
<Identification>
<FriendlyName>^DIRECTV.*$</FriendlyName>
@@ -16,6 +16,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml b/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml
index bf65212b9..bb14ea309 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Dish Hopper-Joey</Name>
<Identification>
<Manufacturer>Echostar Technologies LLC</Manufacturer>
@@ -17,6 +17,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Kodi.xml b/MediaBrowser.Dlna/Profiles/Xml/Kodi.xml
index 42a255a37..5d30d141e 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Kodi.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Kodi.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Kodi</Name>
<Identification>
<ModelName>Kodi</ModelName>
@@ -16,6 +16,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
index 044baaa70..62da6dbf4 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>LG Smart TV</Name>
<Identification>
<FriendlyName>LG.*</FriendlyName>
@@ -16,6 +16,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
index ca64d36d4..9d83164d8 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Linksys DMA2100</Name>
<Identification>
<ModelName>DMA2100us</ModelName>
@@ -14,6 +14,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml
index 61e7fedf8..b66ebfe9e 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>MediaMonkey</Name>
<Identification>
<FriendlyName>MediaMonkey</FriendlyName>
@@ -16,6 +16,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
index 147182b7e..329c97fbd 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Panasonic Viera</Name>
<Identification>
<FriendlyName>VIERA</FriendlyName>
@@ -17,6 +17,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml b/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml
index 1378341fb..a53e731cf 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Popcorn Hour</Name>
<FriendlyName>Emby</FriendlyName>
<Manufacturer>Emby</Manufacturer>
@@ -10,6 +10,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
index c9f139eaa..642395ac8 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Samsung Smart TV</Name>
<Identification>
<ModelUrl>samsung.com</ModelUrl>
@@ -16,6 +16,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
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 7eb9db7f6..afcce2b07 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Sony Blu-ray Player 2013</Name>
<Identification>
<FriendlyName>Blu-ray Disc Player</FriendlyName>
@@ -16,6 +16,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
index 013600f87..8dc221251 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Sony Blu-ray Player</Name>
<Identification>
<FriendlyName>Blu-ray Disc Player</FriendlyName>
@@ -18,6 +18,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
index 65252f749..69dae2806 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Sony Bravia (2010)</Name>
<Identification>
<FriendlyName>KDL-\d{2}[EHLNPB]X\d[01]\d.*</FriendlyName>
@@ -17,6 +17,7 @@
<ModelUrl>http://www.microsoft.com/</ModelUrl>
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
index 5f7f0a2ee..2292d634d 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Sony Bravia (2011)</Name>
<Identification>
<FriendlyName>KDL-\d{2}([A-Z]X\d2\d|CX400).*</FriendlyName>
@@ -17,6 +17,7 @@
<ModelUrl>http://www.microsoft.com/</ModelUrl>
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
index 0951d5e0e..095fcb28e 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Sony Bravia (2012)</Name>
<Identification>
<FriendlyName>KDL-\d{2}[A-Z]X\d5(\d|G).*</FriendlyName>
@@ -17,6 +17,7 @@
<ModelUrl>http://www.microsoft.com/</ModelUrl>
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
index d3a7dbab9..c700c4bfb 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Sony Bravia (2013)</Name>
<Identification>
<FriendlyName>KDL-\d{2}[WR][5689]\d{2}A.*</FriendlyName>
@@ -17,6 +17,7 @@
<ModelUrl>http://www.microsoft.com/</ModelUrl>
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml
index 2859743fb..96fa2861d 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Sony Bravia (2014)</Name>
<Identification>
<FriendlyName>(KDL-\d{2}W[5-9]\d{2}B|KDL-\d{2}R480|XBR-\d{2}X[89]\d{2}B|KD-\d{2}[SX][89]\d{3}B).*</FriendlyName>
@@ -17,6 +17,7 @@
<ModelUrl>http://www.microsoft.com/</ModelUrl>
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
index 33066d8ef..5d6e72000 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Sony PlayStation 3</Name>
<Identification>
<FriendlyName>PLAYSTATION 3</FriendlyName>
@@ -17,6 +17,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml
index 3b372aec5..939c8a813 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Sony PlayStation 4</Name>
<Identification>
<FriendlyName>PLAYSTATION 4</FriendlyName>
@@ -17,6 +17,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml b/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml
index 6b341671c..82b806f1a 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Vlc</Name>
<Identification>
<ModelName>Vlc</ModelName>
@@ -16,6 +16,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
index 7f216a65c..df2a746d0 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>WDTV Live</Name>
<Identification>
<ModelName>WD TV</ModelName>
@@ -17,6 +17,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
@@ -83,5 +84,11 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
- <SubtitleProfiles />
+ <SubtitleProfiles>
+ <SubtitleProfile format="srt" method="External" />
+ <SubtitleProfile format="srt" method="Embed" />
+ <SubtitleProfile format="sub" method="Embed" />
+ <SubtitleProfile format="subrip" method="Embed" />
+ <SubtitleProfile format="idx" method="Embed" />
+ </SubtitleProfiles>
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
index 118224380..bfe1fceea 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Xbox 360</Name>
<Identification>
<ModelName>Xbox 360</ModelName>
@@ -17,6 +17,7 @@
<ModelUrl>http://go.microsoft.com/fwlink/?LinkId=105926</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
index 4c6287442..bd315ac66 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Xbox One</Name>
<Identification>
<ModelName>Xbox One</ModelName>
@@ -17,6 +17,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
index ca95ecde3..a282af655 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>foobar2000</Name>
<Identification>
<FriendlyName>foobar</FriendlyName>
@@ -16,6 +16,7 @@
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
+ <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs
index c9b983bae..279979550 100644
--- a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs
+++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs
@@ -11,6 +11,7 @@ using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
+using MoreLinq;
namespace MediaBrowser.Dlna.Ssdp
{
@@ -36,40 +37,60 @@ namespace MediaBrowser.Dlna.Ssdp
_appHost = appHost;
}
+ private List<IPAddress> GetLocalIpAddresses()
+ {
+ NetworkInterface[] interfaces;
+
+ try
+ {
+ interfaces = NetworkInterface.GetAllNetworkInterfaces();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
+ return new List<IPAddress>();
+ }
+
+ return interfaces.SelectMany(network => {
+
+ try
+ {
+ _logger.Debug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
+
+ var properties = network.GetIPProperties();
+
+ return properties.UnicastAddresses
+ .Select(i => i.Address)
+ .Where(i => i.AddressFamily == AddressFamily.InterNetwork)
+ .ToList();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error querying network interface", ex);
+ return new List<IPAddress>();
+ }
+
+ })
+ .DistinctBy(i => i.ToString())
+ .ToList();
+ }
+
public void Start(SsdpHandler ssdpHandler)
{
_ssdpHandler = ssdpHandler;
_ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived;
- foreach (var network in GetNetworkInterfaces())
- {
- _logger.Debug("Found interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
-
- if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any())
- continue;
-
- var properties = network.GetIPProperties();
- var ipV4 = properties.GetIPv4Properties();
- if (null == ipV4)
- continue;
-
- var localIps = properties.UnicastAddresses
- .Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork)
- .Select(i => i.Address)
- .ToList();
-
- foreach (var localIp in localIps)
- {
- try
- {
- CreateListener(localIp);
- }
- catch (Exception e)
- {
- _logger.ErrorException("Failed to Initilize Socket", e);
- }
- }
- }
+ foreach (var localIp in GetLocalIpAddresses())
+ {
+ try
+ {
+ CreateListener(localIp);
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to Initilize Socket", e);
+ }
+ }
}
void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
@@ -89,8 +110,11 @@ namespace MediaBrowser.Dlna.Ssdp
{
if (e.LocalEndPoint == null)
{
- var ip = _appHost.LocalIpAddress;
- e.LocalEndPoint = new IPEndPoint(IPAddress.Parse(ip), 0);
+ var ip = _appHost.LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i));
+ if (ip != null)
+ {
+ e.LocalEndPoint = new IPEndPoint(ip, 0);
+ }
}
if (e.LocalEndPoint != null)
@@ -107,29 +131,17 @@ namespace MediaBrowser.Dlna.Ssdp
}
}
- private IEnumerable<NetworkInterface> GetNetworkInterfaces()
- {
- try
- {
- return NetworkInterface.GetAllNetworkInterfaces();
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
- return new List<NetworkInterface>();
- }
- }
private void CreateListener(IPAddress localIp)
{
Task.Factory.StartNew(async (o) =>
{
try
{
- var endPoint = new IPEndPoint(localIp, 1900);
+ _logger.Info("Creating SSDP listener on {0}", localIp);
- var socket = GetMulticastSocket(localIp, endPoint);
+ var endPoint = new IPEndPoint(localIp, 1900);
- _logger.Info("Creating SSDP listener on {0}", localIp);
+ var socket = GetMulticastSocket(localIp, endPoint);
var receiveBuffer = new byte[64000];
diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
index 5dd05fd64..32c369a8f 100644
--- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
+++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
@@ -15,6 +15,7 @@ using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.Win32;
namespace MediaBrowser.Dlna.Ssdp
{
@@ -112,7 +113,9 @@ namespace MediaBrowser.Dlna.Ssdp
{
get
{
- return _devices.Values.SelectMany(i => i).ToList();
+ var devices = _devices.Values.ToList();
+
+ return devices.SelectMany(i => i).ToList();
}
}
@@ -121,6 +124,15 @@ namespace MediaBrowser.Dlna.Ssdp
RestartSocketListener();
ReloadAliveNotifier();
+ SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
+ }
+
+ void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
+ {
+ if (e.Mode == PowerModes.Resume)
+ {
+ NotifyAll();
+ }
}
public void SendSearchMessage(EndPoint localIp)
@@ -433,6 +445,7 @@ namespace MediaBrowser.Dlna.Ssdp
public void Dispose()
{
_config.NamedConfigurationUpdated -= _config_ConfigurationUpdated;
+ SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
_isDisposed = true;
while (_messageQueue.Count != 0)
diff --git a/MediaBrowser.Dlna/packages.config b/MediaBrowser.Dlna/packages.config
index fad6af08e..258a097cd 100644
--- a/MediaBrowser.Dlna/packages.config
+++ b/MediaBrowser.Dlna/packages.config
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
+ <package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
index afbd29578..9cdc4a7bf 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
@@ -505,7 +505,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
return "libx264";
}
- if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
{
return "libx265";
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index f44d922d5..f436ca3a0 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -258,17 +258,17 @@ namespace MediaBrowser.MediaEncoding.Encoder
var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol);
- //var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
+ var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
- //if (videoStream != null)
- //{
- // var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false);
+ if (videoStream != null)
+ {
+ var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false);
- // if (isInterlaced)
- // {
- // videoStream.IsInterlaced = true;
- // }
- //}
+ if (isInterlaced)
+ {
+ videoStream.IsInterlaced = true;
+ }
+ }
return mediaInfo;
}
@@ -292,16 +292,19 @@ namespace MediaBrowser.MediaEncoding.Encoder
return false;
}
- var formats = (video.Container ?? string.Empty).Split(',').ToList();
-
- // Take a shortcut and limit this to containers that are likely to have interlaced content
- if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) &&
- !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) &&
- !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) &&
- !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) &&
- !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase))
+ // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content
+ if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) == -1)
{
- return false;
+ var formats = (video.Container ?? string.Empty).Split(',').ToList();
+
+ if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) &&
+ !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) &&
+ !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) &&
+ !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) &&
+ !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase))
+ {
+ return false;
+ }
}
var args = "{0} -i {1} -map 0:v:{2} -filter:v idet -frames:v 500 -an -f null /dev/null";
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index b52446ac6..d98efffe7 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -455,7 +455,7 @@ namespace MediaBrowser.MediaEncoding.Probing
if (!string.IsNullOrWhiteSpace(artists))
{
- audio.Artists = SplitArtists(artists, new[] { '/' }, false)
+ audio.Artists = SplitArtists(artists, new[] { '/', ';' }, false)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
}
@@ -864,7 +864,7 @@ namespace MediaBrowser.MediaEncoding.Probing
}
}
- private void ExtractTimestamp(Model.MediaInfo.MediaInfo video)
+ private void ExtractTimestamp(MediaInfo video)
{
if (video.VideoType == VideoType.VideoFile)
{
diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs
index 278d22cfb..ab3a861a3 100644
--- a/MediaBrowser.Model/Configuration/UserConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs
@@ -29,8 +29,6 @@ namespace MediaBrowser.Model.Configuration
public bool GroupMoviesIntoBoxSets { get; set; }
- public string[] DisplayChannelsWithinViews { get; set; }
-
public string[] ExcludeFoldersFromGrouping { get; set; }
public string[] GroupedFolders { get; set; }
@@ -50,7 +48,6 @@ namespace MediaBrowser.Model.Configuration
public string[] PlainFolderViews { get; set; }
public bool HidePlayedInLatest { get; set; }
- public bool DisplayChannelsInline { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
@@ -62,8 +59,6 @@ namespace MediaBrowser.Model.Configuration
LatestItemsExcludes = new string[] { };
OrderedViews = new string[] { };
- DisplayChannelsWithinViews = new string[] { };
- DisplayChannelsInline = true;
PlainFolderViews = new string[] { };
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index f80b3f14d..083c8f1f3 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -97,7 +97,7 @@ namespace MediaBrowser.Providers.Manager
var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem);
var localImagesFailed = false;
- var allImageProviders = ((ProviderManager)ProviderManager).GetImageProviders(item).ToList();
+ var allImageProviders = ((ProviderManager)ProviderManager).GetImageProviders(item, refreshOptions).ToList();
// Start by validating images
try
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index f504c9612..580e9c4ac 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -249,17 +249,17 @@ namespace MediaBrowser.Providers.Manager
});
}
- public IEnumerable<IImageProvider> GetImageProviders(IHasImages item)
+ public IEnumerable<IImageProvider> GetImageProviders(IHasImages item, ImageRefreshOptions refreshOptions)
{
- return GetImageProviders(item, GetMetadataOptions(item), false);
+ return GetImageProviders(item, GetMetadataOptions(item), refreshOptions, false);
}
- private IEnumerable<IImageProvider> GetImageProviders(IHasImages item, MetadataOptions options, bool includeDisabled)
+ private IEnumerable<IImageProvider> GetImageProviders(IHasImages item, MetadataOptions options, ImageRefreshOptions refreshOptions, bool includeDisabled)
{
// Avoid implicitly captured closure
var currentOptions = options;
- return ImageProviders.Where(i => CanRefresh(i, item, options, includeDisabled))
+ return ImageProviders.Where(i => CanRefresh(i, item, options, refreshOptions, includeDisabled))
.OrderBy(i =>
{
// See if there's a user-defined order
@@ -315,7 +315,7 @@ namespace MediaBrowser.Providers.Manager
{
var options = GetMetadataOptions(item);
- return GetImageProviders(item, options, includeDisabled).OfType<IRemoteImageProvider>();
+ return GetImageProviders(item, options, new ImageRefreshOptions(new DirectoryService(_fileSystem)), includeDisabled).OfType<IRemoteImageProvider>();
}
private bool CanRefresh(IMetadataProvider provider, IHasMetadata item, MetadataOptions options, bool includeDisabled, bool checkIsOwnedItem)
@@ -359,14 +359,17 @@ namespace MediaBrowser.Providers.Manager
return true;
}
- private bool CanRefresh(IImageProvider provider, IHasImages item, MetadataOptions options, bool includeDisabled)
+ private bool CanRefresh(IImageProvider provider, IHasImages item, MetadataOptions options, ImageRefreshOptions refreshOptions, bool includeDisabled)
{
if (!includeDisabled)
{
// If locked only allow local providers
if (item.IsLocked && !(provider is ILocalImageProvider))
{
- return false;
+ if (refreshOptions.ImageRefreshMode != ImageRefreshMode.FullRefresh)
+ {
+ return false;
+ }
}
if (provider is IRemoteImageProvider || provider is IDynamicImageProvider)
@@ -502,7 +505,7 @@ namespace MediaBrowser.Providers.Manager
ItemType = typeof(T).Name
};
- var imageProviders = GetImageProviders(dummy, options, true).ToList();
+ var imageProviders = GetImageProviders(dummy, options, new ImageRefreshOptions(new DirectoryService(_fileSystem)), true).ToList();
AddMetadataPlugins(summary.Plugins, dummy, options);
AddImagePlugins(summary.Plugins, dummy, imageProviders);
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 731d30d84..7478b2738 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -56,9 +56,8 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
</Reference>
- <Reference Include="MoreLinq, Version=1.1.18418.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index f917bc727..6b21fdfb8 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -367,7 +367,7 @@ namespace MediaBrowser.Providers.Movies
}
private static long _lastRequestTicks;
- private static int requestIntervalMs = 150;
+ private static int requestIntervalMs = 200;
/// <summary>
/// Gets the movie db response.
diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs
index 1a6327d00..50ecc6bbf 100644
--- a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs
@@ -63,97 +63,89 @@ namespace MediaBrowser.Providers.TV
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.ProviderIds);
var indexOffset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds) ?? 0;
- var files = TvdbEpisodeProvider.Current.GetEpisodeXmlFiles(episode.ParentIndexNumber + indexOffset, episode.IndexNumber, episode.IndexNumberEnd, seriesDataPath);
+ var nodes = TvdbEpisodeProvider.Current.GetEpisodeXmlNodes(seriesDataPath, episode.GetLookupInfo());
- var result = files.Select(i => GetImageInfo(i, cancellationToken))
- .Where(i => i != null);
+ var result = nodes.Select(i => GetImageInfo(i, cancellationToken))
+ .Where(i => i != null)
+ .ToList();
- return Task.FromResult(result);
+ return Task.FromResult<IEnumerable<RemoteImageInfo>>(result);
}
return Task.FromResult<IEnumerable<RemoteImageInfo>>(new RemoteImageInfo[] { });
}
- private RemoteImageInfo GetImageInfo(FileSystemMetadata xmlFile, CancellationToken cancellationToken)
+ private RemoteImageInfo GetImageInfo(XmlReader reader, CancellationToken cancellationToken)
{
var height = 225;
var width = 400;
var url = string.Empty;
- using (var streamReader = new StreamReader(xmlFile.FullName, Encoding.UTF8))
- {
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- }))
- {
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "thumb_width":
- {
- 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))
- {
- width = rval;
- }
- }
- break;
- }
-
- case "thumb_height":
- {
- 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))
- {
- height = rval;
- }
- }
- break;
- }
-
- case "filename":
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- url = TVUtils.BannerUrl + val;
- }
- break;
- }
-
- default:
- reader.Skip();
- break;
- }
- }
- }
- }
- }
+ // Use XmlReader for best performance
+ using (reader)
+ {
+ reader.MoveToContent();
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "thumb_width":
+ {
+ 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))
+ {
+ width = rval;
+ }
+ }
+ break;
+ }
+
+ case "thumb_height":
+ {
+ 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))
+ {
+ height = rval;
+ }
+ }
+ break;
+ }
+
+ case "filename":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ url = TVUtils.BannerUrl + val;
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
if (string.IsNullOrEmpty(url))
{
@@ -205,11 +197,9 @@ namespace MediaBrowser.Providers.TV
if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
{
// Process images
- var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.ProviderIds);
-
- var files = TvdbEpisodeProvider.Current.GetEpisodeXmlFiles(episode.ParentIndexNumber, episode.IndexNumber, episode.IndexNumberEnd, seriesDataPath);
+ var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath(series.ProviderIds, series.GetPreferredMetadataLanguage());
- return files.Any(i => _fileSystem.GetLastWriteTimeUtc(i) > date);
+ return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > date;
}
}
diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
index ae247c931..6b902ed8a 100644
--- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
@@ -47,12 +47,22 @@ namespace MediaBrowser.Providers.TV
{
var list = new List<RemoteSearchResult>();
- if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) && searchInfo.IndexNumber.HasValue)
+ // The search query must either provide an episode number or date
+ if (!searchInfo.IndexNumber.HasValue && !searchInfo.PremiereDate.HasValue)
+ {
+ return list;
+ }
+
+ if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds))
{
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, searchInfo.SeriesProviderIds);
var searchNumbers = new EpisodeNumbers();
- searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
+
+ if (searchInfo.IndexNumber.HasValue) {
+ searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
+ }
+
searchNumbers.SeasonNumber = searchInfo.ParentIndexNumber;
searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
@@ -97,47 +107,17 @@ namespace MediaBrowser.Providers.TV
public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, CancellationToken cancellationToken)
{
- var identity = Identity.ParseIdentity(searchInfo.GetProviderId(FullIdKey));
-
- if (identity == null)
- {
- await Identify(searchInfo).ConfigureAwait(false);
- identity = Identity.ParseIdentity(searchInfo.GetProviderId(FullIdKey));
- }
-
var result = new MetadataResult<Episode>();
- if (identity != null)
- {
- var seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
- seriesProviderIds[MetadataProviders.Tvdb.ToString()] = identity.Value.SeriesId;
- var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
-
- var searchNumbers = new EpisodeNumbers();
- searchNumbers.EpisodeNumber = identity.Value.EpisodeNumber;
- var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(searchInfo.SeriesProviderIds) ?? 0;
- searchNumbers.SeasonNumber = identity.Value.SeasonIndex + seasonOffset;
- searchNumbers.EpisodeNumberEnd = identity.Value.EpisodeNumberEnd ?? searchNumbers.EpisodeNumber;
-
- try
- {
- result = FetchEpisodeData(searchInfo, searchNumbers, seriesDataPath, cancellationToken);
- }
- catch (FileNotFoundException)
- {
- // Don't fail the provider because this will just keep on going and going.
- }
- catch (DirectoryNotFoundException)
- {
- // Don't fail the provider because this will just keep on going and going.
- }
- }
- else if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) && searchInfo.IndexNumber.HasValue)
+ if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) &&
+ (searchInfo.IndexNumber.HasValue || searchInfo.PremiereDate.HasValue))
{
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, searchInfo.SeriesProviderIds);
var searchNumbers = new EpisodeNumbers();
- searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
+ if (searchInfo.IndexNumber.HasValue) {
+ searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
+ }
searchNumbers.SeasonNumber = searchInfo.ParentIndexNumber;
searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
@@ -176,11 +156,9 @@ namespace MediaBrowser.Providers.TV
if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
{
// Process images
- var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.ProviderIds);
+ var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath(series.ProviderIds, series.GetPreferredMetadataLanguage());
- var files = GetEpisodeXmlFiles(episode.ParentIndexNumber, episode.IndexNumber, episode.IndexNumberEnd, seriesDataPath);
-
- return files.Any(i => _fileSystem.GetLastWriteTimeUtc(i) > date);
+ return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > date;
}
return false;
@@ -194,68 +172,22 @@ namespace MediaBrowser.Providers.TV
/// <param name="endingEpisodeNumber">The ending episode number.</param>
/// <param name="seriesDataPath">The series data path.</param>
/// <returns>List{FileInfo}.</returns>
- internal List<FileSystemMetadata> GetEpisodeXmlFiles(int? seasonNumber, int? episodeNumber, int? endingEpisodeNumber, string seriesDataPath)
+ internal List<XmlReader> GetEpisodeXmlNodes(string seriesDataPath, EpisodeInfo searchInfo)
{
- var files = new List<FileSystemMetadata>();
-
- if (episodeNumber == null)
- {
- return files;
- }
-
- if (seasonNumber == null)
- {
- return files;
- }
-
- var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
-
- var fileInfo = _fileSystem.GetFileInfo(file);
- var usingAbsoluteData = false;
-
- if (fileInfo.Exists)
- {
- files.Add(fileInfo);
- }
- else
- {
- file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
- fileInfo = _fileSystem.GetFileInfo(file);
- if (fileInfo.Exists)
- {
- files.Add(fileInfo);
- usingAbsoluteData = true;
- }
- }
-
- var end = endingEpisodeNumber ?? episodeNumber;
- episodeNumber++;
-
- while (episodeNumber <= end)
- {
- if (usingAbsoluteData)
- {
- file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
- }
- else
- {
- file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
- }
-
- fileInfo = _fileSystem.GetFileInfo(file);
- if (fileInfo.Exists)
- {
- files.Add(fileInfo);
- }
- else
- {
- break;
- }
-
- episodeNumber++;
- }
-
- return files;
+ var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath (searchInfo.SeriesProviderIds, searchInfo.MetadataLanguage);
+
+ try
+ {
+ return GetXmlNodes(seriesXmlPath, searchInfo);
+ }
+ catch (DirectoryNotFoundException)
+ {
+ return new List<XmlReader> ();
+ }
+ catch (FileNotFoundException)
+ {
+ return new List<XmlReader> ();
+ }
}
private class EpisodeNumbers
@@ -275,368 +207,544 @@ namespace MediaBrowser.Providers.TV
/// <returns>Task{System.Boolean}.</returns>
private MetadataResult<Episode> FetchEpisodeData(EpisodeInfo id, EpisodeNumbers searchNumbers, string seriesDataPath, CancellationToken cancellationToken)
{
- var episodeNumber = searchNumbers.EpisodeNumber;
- var seasonNumber = searchNumbers.SeasonNumber;
-
- string file;
- var usingAbsoluteData = false;
-
- var result = new MetadataResult<Episode>()
- {
- Item = new Episode
- {
- IndexNumber = id.IndexNumber,
- ParentIndexNumber = id.ParentIndexNumber,
- IndexNumberEnd = id.IndexNumberEnd
- }
- };
-
- try
- {
- if (seasonNumber != null)
- {
- file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
- FetchMainEpisodeInfo(result, file, cancellationToken);
+ var result = new MetadataResult<Episode>()
+ {
+ Item = new Episode
+ {
+ IndexNumber = id.IndexNumber,
+ ParentIndexNumber = id.ParentIndexNumber,
+ IndexNumberEnd = id.IndexNumberEnd
+ }
+ };
- result.HasMetadata = true;
- }
- }
- catch (FileNotFoundException)
- {
- // Could be using absolute numbering
- if (seasonNumber.HasValue && seasonNumber.Value != 1)
- {
- throw;
- }
- }
-
- if (!result.HasMetadata)
- {
- file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
-
- FetchMainEpisodeInfo(result, file, cancellationToken);
- result.HasMetadata = true;
- usingAbsoluteData = true;
- }
+ var xmlNodes = GetEpisodeXmlNodes (seriesDataPath, id);
- var end = searchNumbers.EpisodeNumberEnd;
- episodeNumber++;
+ if (xmlNodes.Count > 0) {
+ FetchMainEpisodeInfo(result, xmlNodes[0], cancellationToken);
- while (episodeNumber <= end)
- {
- if (usingAbsoluteData)
- {
- file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
- }
- else
- {
- file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
- }
-
- try
- {
- FetchAdditionalPartInfo(result, file, cancellationToken);
- }
- catch (FileNotFoundException)
- {
- break;
- }
- catch (DirectoryNotFoundException)
- {
- break;
- }
+ result.HasMetadata = true;
+ }
- episodeNumber++;
- }
+ foreach (var node in xmlNodes.Skip(1)) {
+ FetchAdditionalPartInfo(result, node, cancellationToken);
+ }
return result;
}
+ private List<XmlReader> GetXmlNodes(string xmlFile, EpisodeInfo searchInfo)
+ {
+ var list = new List<XmlReader> ();
+
+ if (searchInfo.IndexNumber.HasValue)
+ {
+ var files = GetEpisodeXmlFiles (searchInfo.ParentIndexNumber, searchInfo.IndexNumber, searchInfo.IndexNumberEnd, Path.GetDirectoryName (xmlFile));
+
+ list = files.Select (GetXmlReader).ToList ();
+ }
+
+ if (list.Count == 0 && searchInfo.PremiereDate.HasValue) {
+ list = GetXmlNodesByPremiereDate (xmlFile, searchInfo.PremiereDate.Value);
+ }
+
+ return list;
+ }
+
+ private List<FileSystemMetadata> GetEpisodeXmlFiles(int? seasonNumber, int? episodeNumber, int? endingEpisodeNumber, string seriesDataPath)
+ {
+ var files = new List<FileSystemMetadata>();
+
+ if (episodeNumber == null)
+ {
+ return files;
+ }
+
+ if (seasonNumber == null)
+ {
+ return files;
+ }
+
+ var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
+
+ var fileInfo = _fileSystem.GetFileInfo(file);
+ var usingAbsoluteData = false;
+
+ if (fileInfo.Exists)
+ {
+ files.Add(fileInfo);
+ }
+ else
+ {
+ file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
+ fileInfo = _fileSystem.GetFileInfo(file);
+ if (fileInfo.Exists)
+ {
+ files.Add(fileInfo);
+ usingAbsoluteData = true;
+ }
+ }
+
+ var end = endingEpisodeNumber ?? episodeNumber;
+ episodeNumber++;
+
+ while (episodeNumber <= end)
+ {
+ if (usingAbsoluteData)
+ {
+ file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
+ }
+ else
+ {
+ file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
+ }
+
+ fileInfo = _fileSystem.GetFileInfo(file);
+ if (fileInfo.Exists)
+ {
+ files.Add(fileInfo);
+ }
+ else
+ {
+ break;
+ }
+
+ episodeNumber++;
+ }
+
+ return files;
+ }
+
+ private XmlReader GetXmlReader(FileSystemMetadata xmlFile)
+ {
+ return GetXmlReader (_fileSystem.ReadAllText(xmlFile.FullName, Encoding.UTF8));
+ }
+
+ private XmlReader GetXmlReader(String xml)
+ {
+ var streamReader = new StringReader (xml);
+
+ return XmlReader.Create (streamReader, new XmlReaderSettings {
+ CheckCharacters = false,
+ IgnoreProcessingInstructions = true,
+ IgnoreComments = true,
+ ValidationType = ValidationType.None
+ });
+ }
+
+ private List<XmlReader> GetXmlNodesByPremiereDate(string xmlFile, DateTime premiereDate)
+ {
+ var list = new List<XmlReader> ();
+
+ using (var streamReader = new StreamReader (xmlFile, Encoding.UTF8)) {
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create (streamReader, new XmlReaderSettings {
+ CheckCharacters = false,
+ IgnoreProcessingInstructions = true,
+ IgnoreComments = true,
+ ValidationType = ValidationType.None
+ }))
+ {
+ reader.MoveToContent();
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Episode":
+ {
+ var outerXml = reader.ReadOuterXml();
+
+ var airDate = GetEpisodeAirDate (outerXml);
+
+ if (airDate.HasValue && premiereDate.Date == airDate.Value.Date)
+ {
+ list.Add (GetXmlReader(outerXml));
+ return list;
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return list;
+ }
+
+ private DateTime? GetEpisodeAirDate(string xml)
+ {
+ using (var streamReader = new StringReader (xml))
+ {
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create (streamReader, new XmlReaderSettings {
+ CheckCharacters = false,
+ IgnoreProcessingInstructions = true,
+ IgnoreComments = true,
+ ValidationType = ValidationType.None
+ }))
+ {
+ reader.MoveToContent ();
+
+ // Loop through each element
+ while (reader.Read ()) {
+
+ if (reader.NodeType == XmlNodeType.Element) {
+ switch (reader.Name) {
+
+ case "FirstAired":
+ {
+ var val = reader.ReadElementContentAsString ();
+
+ if (!string.IsNullOrWhiteSpace (val)) {
+ DateTime date;
+ if (DateTime.TryParse (val, out date)) {
+ date = date.ToUniversalTime ();
+
+ return date;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip ();
+ break;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private void FetchMainEpisodeInfo(MetadataResult<Episode> result, string xmlFile, CancellationToken cancellationToken)
+ private void FetchMainEpisodeInfo(MetadataResult<Episode> result, XmlReader reader, CancellationToken cancellationToken)
{
var item = result.Item;
- using (var streamReader = new StreamReader(xmlFile, Encoding.UTF8))
- {
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- }))
- {
- reader.MoveToContent();
-
- result.ResetPeople();
-
- // Loop through each element
- while (reader.Read())
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
+ // Use XmlReader for best performance
+ using (reader)
+ {
+ reader.MoveToContent();
+
+ result.ResetPeople();
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "id":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.SetProviderId(MetadataProviders.Tvdb, val);
+ }
+ break;
+ }
+
+ case "IMDB_ID":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.SetProviderId(MetadataProviders.Imdb, val);
+ }
+ break;
+ }
+
+ case "DVD_episodenumber":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ float num;
+
+ if (float.TryParse(val, NumberStyles.Any, _usCulture, out num))
+ {
+ item.DvdEpisodeNumber = num;
+ }
+ }
+
+ break;
+ }
+
+ case "DVD_season":
{
- case "id":
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.SetProviderId(MetadataProviders.Tvdb, val);
- }
- break;
- }
-
- case "IMDB_ID":
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.SetProviderId(MetadataProviders.Imdb, val);
- }
- break;
- }
-
- case "DVD_episodenumber":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- float num;
-
- if (float.TryParse(val, NumberStyles.Any, _usCulture, out num))
- {
- item.DvdEpisodeNumber = num;
- }
- }
-
- break;
- }
-
- case "DVD_season":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- float num;
-
- if (float.TryParse(val, NumberStyles.Any, _usCulture, out num))
- {
- item.DvdSeasonNumber = Convert.ToInt32(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 "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;
- }
- }
+ var val = reader.ReadElementContentAsString();
- break;
- }
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ float num;
- case "airsbefore_season":
+ if (float.TryParse(val, NumberStyles.Any, _usCulture, out num))
{
- 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;
+ item.DvdSeasonNumber = Convert.ToInt32(num);
}
+ }
- case "EpisodeName":
- {
- if (!item.LockedFields.Contains(MetadataFields.Name))
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.Name = val;
- }
- }
- break;
- }
-
- case "Overview":
- {
- if (!item.LockedFields.Contains(MetadataFields.Overview))
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.Overview = val;
- }
- }
- break;
- }
- case "Rating":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- float rval;
-
- // float.TryParse is local aware, so it can be probamatic, force us culture
- if (float.TryParse(val, NumberStyles.AllowDecimalPoint, _usCulture, out rval))
- {
- item.CommunityRating = rval;
- }
- }
- break;
- }
- case "RatingCount":
- {
- 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.VoteCount = rval;
- }
- }
+ break;
+ }
- break;
- }
+ case "EpisodeNumber":
+ {
+ if (!item.IndexNumber.HasValue)
+ {
+ var val = reader.ReadElementContentAsString();
- case "FirstAired":
+ if (!string.IsNullOrWhiteSpace(val))
{
- var val = reader.ReadElementContentAsString();
+ int rval;
- if (!string.IsNullOrWhiteSpace(val))
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
{
- DateTime date;
- if (DateTime.TryParse(val, out date))
- {
- date = date.ToUniversalTime();
-
- item.PremiereDate = date;
- item.ProductionYear = date.Year;
- }
+ item.IndexNumber = rval;
}
-
- break;
}
+ }
- case "Director":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddPeople(result, val, PersonType.Director);
- }
- }
-
- break;
- }
- case "GuestStars":
- {
- var val = reader.ReadElementContentAsString();
+ break;
+ }
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddGuestStars(result, val);
- }
- }
+ case "SeasonNumber":
+ {
+ if (!item.ParentIndexNumber.HasValue)
+ {
+ var val = reader.ReadElementContentAsString();
- break;
- }
- case "Writer":
+ if (!string.IsNullOrWhiteSpace(val))
{
- var val = reader.ReadElementContentAsString();
+ int rval;
- if (!string.IsNullOrWhiteSpace(val))
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
{
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddPeople(result, val, PersonType.Writer);
- }
+ item.ParentIndexNumber = rval;
}
-
- break;
}
+ }
- default:
- reader.Skip();
- break;
+ 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 "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":
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Name))
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Name = val;
+ }
+ }
+ break;
+ }
+
+ case "Overview":
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Overview))
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Overview = val;
+ }
+ }
+ break;
+ }
+ case "Rating":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ float rval;
+
+ // float.TryParse is local aware, so it can be probamatic, force us culture
+ if (float.TryParse(val, NumberStyles.AllowDecimalPoint, _usCulture, out rval))
+ {
+ item.CommunityRating = rval;
+ }
+ }
+ break;
+ }
+ case "RatingCount":
+ {
+ 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.VoteCount = rval;
+ }
+ }
+
+ break;
+ }
+
+ case "FirstAired":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ DateTime date;
+ if (DateTime.TryParse(val, out date))
+ {
+ date = date.ToUniversalTime();
+
+ item.PremiereDate = date;
+ item.ProductionYear = date.Year;
+ }
+ }
+
+ break;
+ }
+
+ case "Director":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddPeople(result, val, PersonType.Director);
+ }
+ }
+
+ break;
+ }
+ case "GuestStars":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddGuestStars(result, val);
+ }
+ }
+
+ break;
+ }
+ case "Writer":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddPeople(result, val, PersonType.Writer);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
}
private void AddPeople<T>(MetadataResult<T> result, string val, string personType)
@@ -680,108 +788,99 @@ namespace MediaBrowser.Providers.TV
}
}
- private void FetchAdditionalPartInfo(MetadataResult<Episode> result, string xmlFile, CancellationToken cancellationToken)
+ private void FetchAdditionalPartInfo(MetadataResult<Episode> result, XmlReader reader, CancellationToken cancellationToken)
{
var item = result.Item;
- using (var streamReader = new StreamReader(xmlFile, Encoding.UTF8))
- {
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- }))
- {
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "EpisodeName":
- {
- if (!item.LockedFields.Contains(MetadataFields.Name))
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.Name += ", " + val;
- }
- }
- break;
- }
-
- case "Overview":
- {
- if (!item.LockedFields.Contains(MetadataFields.Overview))
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.Overview += Environment.NewLine + Environment.NewLine + val;
- }
- }
- break;
- }
- case "Director":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddPeople(result, val, PersonType.Director);
- }
- }
-
- break;
- }
- case "GuestStars":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddGuestStars(result, val);
- }
- }
-
- break;
- }
- case "Writer":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddPeople(result, val, PersonType.Writer);
- }
- }
-
- break;
- }
-
- default:
- reader.Skip();
- break;
- }
- }
- }
- }
- }
+ // Use XmlReader for best performance
+ using (reader)
+ {
+ reader.MoveToContent();
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "EpisodeName":
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Name))
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Name += ", " + val;
+ }
+ }
+ break;
+ }
+
+ case "Overview":
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Overview))
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Overview += Environment.NewLine + Environment.NewLine + val;
+ }
+ }
+ break;
+ }
+ case "Director":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddPeople(result, val, PersonType.Director);
+ }
+ }
+
+ break;
+ }
+ case "GuestStars":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddGuestStars(result, val);
+ }
+ }
+
+ break;
+ }
+ case "Writer":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddPeople(result, val, PersonType.Writer);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
index d63022900..7250dbee4 100644
--- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
@@ -161,9 +161,7 @@ namespace MediaBrowser.Providers.TV
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
- var seriesXmlFilename = metadataLanguage.ToLower() + ".xml";
-
- var seriesXmlPath = Path.Combine(seriesDataPath, seriesXmlFilename);
+ var seriesXmlPath = GetSeriesXmlPath (seriesProviderIds, metadataLanguage);
var actorsXmlPath = Path.Combine(seriesDataPath, "actors.xml");
FetchSeriesInfo(series, seriesXmlPath, cancellationToken);
@@ -1278,6 +1276,15 @@ namespace MediaBrowser.Providers.TV
return null;
}
+ public string GetSeriesXmlPath(Dictionary<string, string> seriesProviderIds, string language)
+ {
+ var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
+
+ var seriesXmlFilename = language.ToLower() + ".xml";
+
+ return Path.Combine (seriesDataPath, seriesXmlFilename);
+ }
+
/// <summary>
/// Gets the series data path.
/// </summary>
diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config
index 9ff08e4f4..9002f1a40 100644
--- a/MediaBrowser.Providers/packages.config
+++ b/MediaBrowser.Providers/packages.config
@@ -2,7 +2,7 @@
<packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
- <package id="morelinq" version="1.1.1" targetFramework="net45" />
+ <package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
<package id="taglib" version="2.1.0.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
index f9a141da3..c3b9c0d4d 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
@@ -66,7 +66,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
try
{
- await new UsageReporter(_applicationHost, _httpClient, _userManager)
+ await new UsageReporter(_applicationHost, _httpClient, _userManager, _logger)
.ReportAppUsage(client, CancellationToken.None)
.ConfigureAwait(false);
}
@@ -108,7 +108,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
try
{
- await new UsageReporter(_applicationHost, _httpClient, _userManager)
+ await new UsageReporter(_applicationHost, _httpClient, _userManager, _logger)
.ReportServerUsage(CancellationToken.None)
.ConfigureAwait(false);
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs
index 77dd54a80..5496bd9b2 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs
@@ -8,6 +8,7 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.EntryPoints
{
@@ -16,13 +17,15 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly IApplicationHost _applicationHost;
private readonly IHttpClient _httpClient;
private readonly IUserManager _userManager;
+ private readonly ILogger _logger;
private const string MbAdminUrl = "http://www.mb3admin.com/admin/";
- public UsageReporter(IApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager)
+ public UsageReporter(IApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger)
{
_applicationHost = applicationHost;
_httpClient = httpClient;
_userManager = userManager;
+ _logger = logger;
}
public Task ReportServerUsage(CancellationToken cancellationToken)
@@ -47,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
data["linkedusers"] = users.Count(i => i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.LinkedUser).ToString(CultureInfo.InvariantCulture);
data["plugins"] = string.Join(",", _applicationHost.Plugins.Select(i => i.Id).ToArray());
-
+
return _httpClient.Post(MbAdminUrl + "service/registration/ping", data, cancellationToken);
}
@@ -58,6 +61,12 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
throw new ArgumentException("Client info must have a device Id");
}
+ _logger.Info("App Activity: app: {0}, version: {1}, deviceId: {2}, deviceName: {3}",
+ app.AppName ?? "Unknown App",
+ app.AppVersion ?? "Unknown",
+ app.DeviceId,
+ app.DeviceName ?? "Unknown");
+
cancellationToken.ThrowIfCancellationRequested();
var data = new Dictionary<string, string>
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index 6ade9a8f6..0283c1f7a 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -19,6 +19,7 @@ using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
using MediaBrowser.Common.Security;
namespace MediaBrowser.Server.Implementations.HttpServer
@@ -39,40 +40,20 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
public event EventHandler<WebSocketConnectingEventArgs> WebSocketConnecting;
- private readonly List<string> _localEndpoints = new List<string>();
-
- private readonly ReaderWriterLockSlim _localEndpointLock = new ReaderWriterLockSlim();
-
public string CertificatePath { get; private set; }
private readonly IServerConfigurationManager _config;
-
- /// <summary>
- /// Gets the local end points.
- /// </summary>
- /// <value>The local end points.</value>
- public IEnumerable<string> LocalEndPoints
- {
- get
- {
- _localEndpointLock.EnterReadLock();
-
- var list = _localEndpoints.ToList();
-
- _localEndpointLock.ExitReadLock();
-
- return list;
- }
- }
+ private readonly INetworkManager _networkManager;
public HttpListenerHost(IApplicationHost applicationHost,
ILogManager logManager,
IServerConfigurationManager config,
string serviceName,
- string defaultRedirectPath, params Assembly[] assembliesWithServices)
+ string defaultRedirectPath, INetworkManager networkManager, params Assembly[] assembliesWithServices)
: base(serviceName, assembliesWithServices)
{
DefaultRedirectPath = defaultRedirectPath;
+ _networkManager = networkManager;
_config = config;
_logger = logManager.GetLogger("HttpServer");
@@ -175,26 +156,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private void OnRequestReceived(string localEndPoint)
{
- var ignore = localEndPoint.IndexOf("::", StringComparison.OrdinalIgnoreCase) != -1 ||
-
- localEndPoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
- localEndPoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
- localEndPoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase);
-
- if (ignore)
- {
- return;
- }
-
- if (_localEndpointLock.TryEnterWriteLock(100))
- {
- var list = _localEndpoints.ToList();
-
- list.Remove(localEndPoint);
- list.Insert(0, localEndPoint);
-
- _localEndpointLock.ExitWriteLock();
- }
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs
index 4d81ec157..cc351f6b3 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
@@ -17,18 +18,20 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="applicationHost">The application host.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="config">The configuration.</param>
+ /// <param name="_networkmanager">The _networkmanager.</param>
/// <param name="serverName">Name of the server.</param>
/// <param name="defaultRedirectpath">The default redirectpath.</param>
/// <returns>IHttpServer.</returns>
public static IHttpServer CreateServer(IApplicationHost applicationHost,
ILogManager logManager,
IServerConfigurationManager config,
+ INetworkManager _networkmanager,
string serverName,
string defaultRedirectpath)
{
LogManager.LogFactory = new ServerLogFactory(logManager);
- return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath);
+ return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs
new file mode 100644
index 000000000..3ef48d13a
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs
@@ -0,0 +1,941 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
+{
+ public static class MyHttpUtility
+ {
+ sealed class HttpQSCollection : NameValueCollection
+ {
+ public override string ToString()
+ {
+ int count = Count;
+ if (count == 0)
+ return "";
+ StringBuilder sb = new StringBuilder();
+ string[] keys = AllKeys;
+ for (int i = 0; i < count; i++)
+ {
+ sb.AppendFormat("{0}={1}&", keys[i], this[keys[i]]);
+ }
+ if (sb.Length > 0)
+ sb.Length--;
+ return sb.ToString();
+ }
+ }
+
+ // Must be sorted
+ static readonly long[] entities = new long[] {
+ (long)'A' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'A' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'A' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'A' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'A' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24,
+ (long)'A' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24,
+ (long)'A' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'A' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'B' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'C' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16,
+ (long)'C' << 56 | (long)'h' << 48 | (long)'i' << 40,
+ (long)'D' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16,
+ (long)'D' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24,
+ (long)'E' << 56 | (long)'T' << 48 | (long)'H' << 40,
+ (long)'E' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'E' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'E' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'E' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'E' << 56 | (long)'t' << 48 | (long)'a' << 40,
+ (long)'E' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'G' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24,
+ (long)'I' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'I' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'I' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'I' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'I' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'K' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24,
+ (long)'L' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16,
+ (long)'M' << 56 | (long)'u' << 48,
+ (long)'N' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'N' << 56 | (long)'u' << 48,
+ (long)'O' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'O' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'O' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'O' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'O' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24,
+ (long)'O' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'O' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16,
+ (long)'O' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'O' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'P' << 56 | (long)'h' << 48 | (long)'i' << 40,
+ (long)'P' << 56 | (long)'i' << 48,
+ (long)'P' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24,
+ (long)'P' << 56 | (long)'s' << 48 | (long)'i' << 40,
+ (long)'R' << 56 | (long)'h' << 48 | (long)'o' << 40,
+ (long)'S' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16,
+ (long)'S' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24,
+ (long)'T' << 56 | (long)'H' << 48 | (long)'O' << 40 | (long)'R' << 32 | (long)'N' << 24,
+ (long)'T' << 56 | (long)'a' << 48 | (long)'u' << 40,
+ (long)'T' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24,
+ (long)'U' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'U' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'U' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'U' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'U' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'X' << 56 | (long)'i' << 48,
+ (long)'Y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'Y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'Z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'a' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'a' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'a' << 56 | (long)'c' << 48 | (long)'u' << 40 | (long)'t' << 32 | (long)'e' << 24,
+ (long)'a' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'a' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'a' << 56 | (long)'l' << 48 | (long)'e' << 40 | (long)'f' << 32 | (long)'s' << 24 | (long)'y' << 16 | (long)'m' << 8,
+ (long)'a' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24,
+ (long)'a' << 56 | (long)'m' << 48 | (long)'p' << 40,
+ (long)'a' << 56 | (long)'n' << 48 | (long)'d' << 40,
+ (long)'a' << 56 | (long)'n' << 48 | (long)'g' << 40,
+ (long)'a' << 56 | (long)'p' << 48 | (long)'o' << 40 | (long)'s' << 32,
+ (long)'a' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24,
+ (long)'a' << 56 | (long)'s' << 48 | (long)'y' << 40 | (long)'m' << 32 | (long)'p' << 24,
+ (long)'a' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'a' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'b' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'b' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'b' << 56 | (long)'r' << 48 | (long)'v' << 40 | (long)'b' << 32 | (long)'a' << 24 | (long)'r' << 16,
+ (long)'b' << 56 | (long)'u' << 48 | (long)'l' << 40 | (long)'l' << 32,
+ (long)'c' << 56 | (long)'a' << 48 | (long)'p' << 40,
+ (long)'c' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16,
+ (long)'c' << 56 | (long)'e' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'l' << 24,
+ (long)'c' << 56 | (long)'e' << 48 | (long)'n' << 40 | (long)'t' << 32,
+ (long)'c' << 56 | (long)'h' << 48 | (long)'i' << 40,
+ (long)'c' << 56 | (long)'i' << 48 | (long)'r' << 40 | (long)'c' << 32,
+ (long)'c' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'b' << 32 | (long)'s' << 24,
+ (long)'c' << 56 | (long)'o' << 48 | (long)'n' << 40 | (long)'g' << 32,
+ (long)'c' << 56 | (long)'o' << 48 | (long)'p' << 40 | (long)'y' << 32,
+ (long)'c' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'r' << 24,
+ (long)'c' << 56 | (long)'u' << 48 | (long)'p' << 40,
+ (long)'c' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'n' << 16,
+ (long)'d' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'d' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16,
+ (long)'d' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'d' << 56 | (long)'e' << 48 | (long)'g' << 40,
+ (long)'d' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24,
+ (long)'d' << 56 | (long)'i' << 48 | (long)'a' << 40 | (long)'m' << 32 | (long)'s' << 24,
+ (long)'d' << 56 | (long)'i' << 48 | (long)'v' << 40 | (long)'i' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'e' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'e' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'e' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'e' << 56 | (long)'m' << 48 | (long)'p' << 40 | (long)'t' << 32 | (long)'y' << 24,
+ (long)'e' << 56 | (long)'m' << 48 | (long)'s' << 40 | (long)'p' << 32,
+ (long)'e' << 56 | (long)'n' << 48 | (long)'s' << 40 | (long)'p' << 32,
+ (long)'e' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'e' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'i' << 32 | (long)'v' << 24,
+ (long)'e' << 56 | (long)'t' << 48 | (long)'a' << 40,
+ (long)'e' << 56 | (long)'t' << 48 | (long)'h' << 40,
+ (long)'e' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'e' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'o' << 32,
+ (long)'e' << 56 | (long)'x' << 48 | (long)'i' << 40 | (long)'s' << 32 | (long)'t' << 24,
+ (long)'f' << 56 | (long)'n' << 48 | (long)'o' << 40 | (long)'f' << 32,
+ (long)'f' << 56 | (long)'o' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'l' << 24 | (long)'l' << 16,
+ (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'2' << 16,
+ (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'4' << 16,
+ (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'3' << 24 | (long)'4' << 16,
+ (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'l' << 24,
+ (long)'g' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24,
+ (long)'g' << 56 | (long)'e' << 48,
+ (long)'g' << 56 | (long)'t' << 48,
+ (long)'h' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'h' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'h' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'t' << 24 | (long)'s' << 16,
+ (long)'h' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'l' << 32 | (long)'i' << 24 | (long)'p' << 16,
+ (long)'i' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'i' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'i' << 56 | (long)'e' << 48 | (long)'x' << 40 | (long)'c' << 32 | (long)'l' << 24,
+ (long)'i' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'i' << 56 | (long)'m' << 48 | (long)'a' << 40 | (long)'g' << 32 | (long)'e' << 24,
+ (long)'i' << 56 | (long)'n' << 48 | (long)'f' << 40 | (long)'i' << 32 | (long)'n' << 24,
+ (long)'i' << 56 | (long)'n' << 48 | (long)'t' << 40,
+ (long)'i' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'i' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'e' << 32 | (long)'s' << 24 | (long)'t' << 16,
+ (long)'i' << 56 | (long)'s' << 48 | (long)'i' << 40 | (long)'n' << 32,
+ (long)'i' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'k' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24,
+ (long)'l' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'l' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16,
+ (long)'l' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32,
+ (long)'l' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'l' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'l' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24,
+ (long)'l' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'l' << 56 | (long)'e' << 48,
+ (long)'l' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16,
+ (long)'l' << 56 | (long)'o' << 48 | (long)'w' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'t' << 16,
+ (long)'l' << 56 | (long)'o' << 48 | (long)'z' << 40,
+ (long)'l' << 56 | (long)'r' << 48 | (long)'m' << 40,
+ (long)'l' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16,
+ (long)'l' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'l' << 56 | (long)'t' << 48,
+ (long)'m' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'r' << 32,
+ (long)'m' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24,
+ (long)'m' << 56 | (long)'i' << 48 | (long)'c' << 40 | (long)'r' << 32 | (long)'o' << 24,
+ (long)'m' << 56 | (long)'i' << 48 | (long)'d' << 40 | (long)'d' << 32 | (long)'o' << 24 | (long)'t' << 16,
+ (long)'m' << 56 | (long)'i' << 48 | (long)'n' << 40 | (long)'u' << 32 | (long)'s' << 24,
+ (long)'m' << 56 | (long)'u' << 48,
+ (long)'n' << 56 | (long)'a' << 48 | (long)'b' << 40 | (long)'l' << 32 | (long)'a' << 24,
+ (long)'n' << 56 | (long)'b' << 48 | (long)'s' << 40 | (long)'p' << 32,
+ (long)'n' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24,
+ (long)'n' << 56 | (long)'e' << 48,
+ (long)'n' << 56 | (long)'i' << 48,
+ (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40,
+ (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'i' << 32 | (long)'n' << 24,
+ (long)'n' << 56 | (long)'s' << 48 | (long)'u' << 40 | (long)'b' << 32,
+ (long)'n' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'n' << 56 | (long)'u' << 48,
+ (long)'o' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'o' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'o' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'o' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'o' << 56 | (long)'l' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'e' << 24,
+ (long)'o' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24,
+ (long)'o' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'o' << 56 | (long)'p' << 48 | (long)'l' << 40 | (long)'u' << 32 | (long)'s' << 24,
+ (long)'o' << 56 | (long)'r' << 48,
+ (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'f' << 32,
+ (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'m' << 32,
+ (long)'o' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16,
+ (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24 | (long)'s' << 16,
+ (long)'o' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'a' << 32,
+ (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'t' << 32,
+ (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'m' << 32 | (long)'i' << 24 | (long)'l' << 16,
+ (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'p' << 32,
+ (long)'p' << 56 | (long)'h' << 48 | (long)'i' << 40,
+ (long)'p' << 56 | (long)'i' << 48,
+ (long)'p' << 56 | (long)'i' << 48 | (long)'v' << 40,
+ (long)'p' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'s' << 32 | (long)'m' << 24 | (long)'n' << 16,
+ (long)'p' << 56 | (long)'o' << 48 | (long)'u' << 40 | (long)'n' << 32 | (long)'d' << 24,
+ (long)'p' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24,
+ (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'d' << 32,
+ (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'p' << 32,
+ (long)'p' << 56 | (long)'s' << 48 | (long)'i' << 40,
+ (long)'q' << 56 | (long)'u' << 48 | (long)'o' << 40 | (long)'t' << 32,
+ (long)'r' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'r' << 56 | (long)'a' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'c' << 24,
+ (long)'r' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32,
+ (long)'r' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'r' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'r' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24,
+ (long)'r' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'r' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'l' << 32,
+ (long)'r' << 56 | (long)'e' << 48 | (long)'g' << 40,
+ (long)'r' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16,
+ (long)'r' << 56 | (long)'h' << 48 | (long)'o' << 40,
+ (long)'r' << 56 | (long)'l' << 48 | (long)'m' << 40,
+ (long)'r' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16,
+ (long)'r' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'s' << 56 | (long)'b' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'s' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16,
+ (long)'s' << 56 | (long)'d' << 48 | (long)'o' << 40 | (long)'t' << 32,
+ (long)'s' << 56 | (long)'e' << 48 | (long)'c' << 40 | (long)'t' << 32,
+ (long)'s' << 56 | (long)'h' << 48 | (long)'y' << 40,
+ (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24,
+ (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24 | (long)'f' << 16,
+ (long)'s' << 56 | (long)'i' << 48 | (long)'m' << 40,
+ (long)'s' << 56 | (long)'p' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24 | (long)'s' << 16,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40 | (long)'e' << 32,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'m' << 40,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'1' << 32,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'2' << 32,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'3' << 32,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'e' << 32,
+ (long)'s' << 56 | (long)'z' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'t' << 56 | (long)'a' << 48 | (long)'u' << 40,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'4' << 16,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24 | (long)'s' << 16 | (long)'y' << 8 | (long)'m' << 0,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'s' << 24 | (long)'p' << 16,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'o' << 40 | (long)'r' << 32 | (long)'n' << 24,
+ (long)'t' << 56 | (long)'i' << 48 | (long)'l' << 40 | (long)'d' << 32 | (long)'e' << 24,
+ (long)'t' << 56 | (long)'i' << 48 | (long)'m' << 40 | (long)'e' << 32 | (long)'s' << 24,
+ (long)'t' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24,
+ (long)'u' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'u' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'u' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'u' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'u' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'u' << 56 | (long)'m' << 48 | (long)'l' << 40,
+ (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'h' << 24,
+ (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'u' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'w' << 56 | (long)'e' << 48 | (long)'i' << 40 | (long)'e' << 32 | (long)'r' << 24 | (long)'p' << 16,
+ (long)'x' << 56 | (long)'i' << 48,
+ (long)'y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'y' << 56 | (long)'e' << 48 | (long)'n' << 40,
+ (long)'y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'z' << 56 | (long)'w' << 48 | (long)'j' << 40,
+ (long)'z' << 56 | (long)'w' << 48 | (long)'n' << 40 | (long)'j' << 32
+ };
+
+ static readonly char[] entities_values = new char[] {
+ '\u00C6',
+ '\u00C1',
+ '\u00C2',
+ '\u00C0',
+ '\u0391',
+ '\u00C5',
+ '\u00C3',
+ '\u00C4',
+ '\u0392',
+ '\u00C7',
+ '\u03A7',
+ '\u2021',
+ '\u0394',
+ '\u00D0',
+ '\u00C9',
+ '\u00CA',
+ '\u00C8',
+ '\u0395',
+ '\u0397',
+ '\u00CB',
+ '\u0393',
+ '\u00CD',
+ '\u00CE',
+ '\u00CC',
+ '\u0399',
+ '\u00CF',
+ '\u039A',
+ '\u039B',
+ '\u039C',
+ '\u00D1',
+ '\u039D',
+ '\u0152',
+ '\u00D3',
+ '\u00D4',
+ '\u00D2',
+ '\u03A9',
+ '\u039F',
+ '\u00D8',
+ '\u00D5',
+ '\u00D6',
+ '\u03A6',
+ '\u03A0',
+ '\u2033',
+ '\u03A8',
+ '\u03A1',
+ '\u0160',
+ '\u03A3',
+ '\u00DE',
+ '\u03A4',
+ '\u0398',
+ '\u00DA',
+ '\u00DB',
+ '\u00D9',
+ '\u03A5',
+ '\u00DC',
+ '\u039E',
+ '\u00DD',
+ '\u0178',
+ '\u0396',
+ '\u00E1',
+ '\u00E2',
+ '\u00B4',
+ '\u00E6',
+ '\u00E0',
+ '\u2135',
+ '\u03B1',
+ '\u0026',
+ '\u2227',
+ '\u2220',
+ '\u0027',
+ '\u00E5',
+ '\u2248',
+ '\u00E3',
+ '\u00E4',
+ '\u201E',
+ '\u03B2',
+ '\u00A6',
+ '\u2022',
+ '\u2229',
+ '\u00E7',
+ '\u00B8',
+ '\u00A2',
+ '\u03C7',
+ '\u02C6',
+ '\u2663',
+ '\u2245',
+ '\u00A9',
+ '\u21B5',
+ '\u222A',
+ '\u00A4',
+ '\u21D3',
+ '\u2020',
+ '\u2193',
+ '\u00B0',
+ '\u03B4',
+ '\u2666',
+ '\u00F7',
+ '\u00E9',
+ '\u00EA',
+ '\u00E8',
+ '\u2205',
+ '\u2003',
+ '\u2002',
+ '\u03B5',
+ '\u2261',
+ '\u03B7',
+ '\u00F0',
+ '\u00EB',
+ '\u20AC',
+ '\u2203',
+ '\u0192',
+ '\u2200',
+ '\u00BD',
+ '\u00BC',
+ '\u00BE',
+ '\u2044',
+ '\u03B3',
+ '\u2265',
+ '\u003E',
+ '\u21D4',
+ '\u2194',
+ '\u2665',
+ '\u2026',
+ '\u00ED',
+ '\u00EE',
+ '\u00A1',
+ '\u00EC',
+ '\u2111',
+ '\u221E',
+ '\u222B',
+ '\u03B9',
+ '\u00BF',
+ '\u2208',
+ '\u00EF',
+ '\u03BA',
+ '\u21D0',
+ '\u03BB',
+ '\u2329',
+ '\u00AB',
+ '\u2190',
+ '\u2308',
+ '\u201C',
+ '\u2264',
+ '\u230A',
+ '\u2217',
+ '\u25CA',
+ '\u200E',
+ '\u2039',
+ '\u2018',
+ '\u003C',
+ '\u00AF',
+ '\u2014',
+ '\u00B5',
+ '\u00B7',
+ '\u2212',
+ '\u03BC',
+ '\u2207',
+ '\u00A0',
+ '\u2013',
+ '\u2260',
+ '\u220B',
+ '\u00AC',
+ '\u2209',
+ '\u2284',
+ '\u00F1',
+ '\u03BD',
+ '\u00F3',
+ '\u00F4',
+ '\u0153',
+ '\u00F2',
+ '\u203E',
+ '\u03C9',
+ '\u03BF',
+ '\u2295',
+ '\u2228',
+ '\u00AA',
+ '\u00BA',
+ '\u00F8',
+ '\u00F5',
+ '\u2297',
+ '\u00F6',
+ '\u00B6',
+ '\u2202',
+ '\u2030',
+ '\u22A5',
+ '\u03C6',
+ '\u03C0',
+ '\u03D6',
+ '\u00B1',
+ '\u00A3',
+ '\u2032',
+ '\u220F',
+ '\u221D',
+ '\u03C8',
+ '\u0022',
+ '\u21D2',
+ '\u221A',
+ '\u232A',
+ '\u00BB',
+ '\u2192',
+ '\u2309',
+ '\u201D',
+ '\u211C',
+ '\u00AE',
+ '\u230B',
+ '\u03C1',
+ '\u200F',
+ '\u203A',
+ '\u2019',
+ '\u201A',
+ '\u0161',
+ '\u22C5',
+ '\u00A7',
+ '\u00AD',
+ '\u03C3',
+ '\u03C2',
+ '\u223C',
+ '\u2660',
+ '\u2282',
+ '\u2286',
+ '\u2211',
+ '\u2283',
+ '\u00B9',
+ '\u00B2',
+ '\u00B3',
+ '\u2287',
+ '\u00DF',
+ '\u03C4',
+ '\u2234',
+ '\u03B8',
+ '\u03D1',
+ '\u2009',
+ '\u00FE',
+ '\u02DC',
+ '\u00D7',
+ '\u2122',
+ '\u21D1',
+ '\u00FA',
+ '\u2191',
+ '\u00FB',
+ '\u00F9',
+ '\u00A8',
+ '\u03D2',
+ '\u03C5',
+ '\u00FC',
+ '\u2118',
+ '\u03BE',
+ '\u00FD',
+ '\u00A5',
+ '\u00FF',
+ '\u03B6',
+ '\u200D',
+ '\u200C'
+ };
+
+ #region Methods
+
+ static void WriteCharBytes(IList buf, char ch, Encoding e)
+ {
+ if (ch > 255)
+ {
+ foreach (byte b in e.GetBytes(new char[] { ch }))
+ buf.Add(b);
+ }
+ else
+ buf.Add((byte)ch);
+ }
+
+ public static string UrlDecode(string s, Encoding e)
+ {
+ if (null == s)
+ return null;
+
+ if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1)
+ return s;
+
+ if (e == null)
+ e = Encoding.UTF8;
+
+ long len = s.Length;
+ var bytes = new List<byte>();
+ int xchar;
+ char ch;
+
+ for (int i = 0; i < len; i++)
+ {
+ ch = s[i];
+ if (ch == '%' && i + 2 < len && s[i + 1] != '%')
+ {
+ if (s[i + 1] == 'u' && i + 5 < len)
+ {
+ // unicode hex sequence
+ xchar = GetChar(s, i + 2, 4);
+ if (xchar != -1)
+ {
+ WriteCharBytes(bytes, (char)xchar, e);
+ i += 5;
+ }
+ else
+ WriteCharBytes(bytes, '%', e);
+ }
+ else if ((xchar = GetChar(s, i + 1, 2)) != -1)
+ {
+ WriteCharBytes(bytes, (char)xchar, e);
+ i += 2;
+ }
+ else
+ {
+ WriteCharBytes(bytes, '%', e);
+ }
+ continue;
+ }
+
+ if (ch == '+')
+ WriteCharBytes(bytes, ' ', e);
+ else
+ WriteCharBytes(bytes, ch, e);
+ }
+
+ byte[] buf = bytes.ToArray();
+ bytes = null;
+ return e.GetString(buf);
+
+ }
+
+ static int GetInt(byte b)
+ {
+ char c = (char)b;
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+
+ return -1;
+ }
+
+ static int GetChar(string str, int offset, int length)
+ {
+ int val = 0;
+ int end = length + offset;
+ for (int i = offset; i < end; i++)
+ {
+ char c = str[i];
+ if (c > 127)
+ return -1;
+
+ int current = GetInt((byte)c);
+ if (current == -1)
+ return -1;
+ val = (val << 4) + current;
+ }
+
+ return val;
+ }
+
+ static bool TryConvertKeyToEntity(string key, out char value)
+ {
+ var token = CalculateKeyValue(key);
+ if (token == 0)
+ {
+ value = '\0';
+ return false;
+ }
+
+ var idx = Array.BinarySearch(entities, token);
+ if (idx < 0)
+ {
+ value = '\0';
+ return false;
+ }
+
+ value = entities_values[idx];
+ return true;
+ }
+
+ static long CalculateKeyValue(string s)
+ {
+ if (s.Length > 8)
+ return 0;
+
+ long key = 0;
+ for (int i = 0; i < s.Length; ++i)
+ {
+ long ch = s[i];
+ if (ch > 'z' || ch < '0')
+ return 0;
+
+ key |= ch << ((7 - i) * 8);
+ }
+
+ return key;
+ }
+
+ /// <summary>
+ /// Decodes an HTML-encoded string and returns the decoded string.
+ /// </summary>
+ /// <param name="s">The HTML string to decode. </param>
+ /// <returns>The decoded text.</returns>
+ public static string HtmlDecode(string s)
+ {
+ if (s == null)
+ throw new ArgumentNullException("s");
+
+ if (s.IndexOf('&') == -1)
+ return s;
+
+ StringBuilder entity = new StringBuilder();
+ StringBuilder output = new StringBuilder();
+ int len = s.Length;
+ // 0 -> nothing,
+ // 1 -> right after '&'
+ // 2 -> between '&' and ';' but no '#'
+ // 3 -> '#' found after '&' and getting numbers
+ int state = 0;
+ int number = 0;
+ int digit_start = 0;
+ bool hex_number = false;
+
+ for (int i = 0; i < len; i++)
+ {
+ char c = s[i];
+ if (state == 0)
+ {
+ if (c == '&')
+ {
+ entity.Append(c);
+ state = 1;
+ }
+ else
+ {
+ output.Append(c);
+ }
+ continue;
+ }
+
+ if (c == '&')
+ {
+ state = 1;
+ if (digit_start > 0)
+ {
+ entity.Append(s, digit_start, i - digit_start);
+ digit_start = 0;
+ }
+
+ output.Append(entity.ToString());
+ entity.Length = 0;
+ entity.Append('&');
+ continue;
+ }
+
+ switch (state)
+ {
+ case 1:
+ if (c == ';')
+ {
+ state = 0;
+ output.Append(entity.ToString());
+ output.Append(c);
+ entity.Length = 0;
+ break;
+ }
+
+ number = 0;
+ hex_number = false;
+ if (c != '#')
+ {
+ state = 2;
+ }
+ else
+ {
+ state = 3;
+ }
+ entity.Append(c);
+
+ break;
+ case 2:
+ entity.Append(c);
+ if (c == ';')
+ {
+ string key = entity.ToString();
+ state = 0;
+ entity.Length = 0;
+
+ if (key.Length > 1)
+ {
+ var skey = key.Substring(1, key.Length - 2);
+ if (TryConvertKeyToEntity(skey, out c))
+ {
+ output.Append(c);
+ break;
+ }
+ }
+
+ output.Append(key);
+ }
+
+ break;
+ case 3:
+ if (c == ';')
+ {
+ if (number < 0x10000)
+ {
+ output.Append((char)number);
+ }
+ else
+ {
+ output.Append((char)(0xd800 + ((number - 0x10000) >> 10)));
+ output.Append((char)(0xdc00 + ((number - 0x10000) & 0x3ff)));
+ }
+ state = 0;
+ entity.Length = 0;
+ digit_start = 0;
+ break;
+ }
+
+ if (c == 'x' || c == 'X' && !hex_number)
+ {
+ digit_start = i;
+ hex_number = true;
+ break;
+ }
+
+ if (Char.IsDigit(c))
+ {
+ if (digit_start == 0)
+ digit_start = i;
+
+ number = number * (hex_number ? 16 : 10) + ((int)c - '0');
+ break;
+ }
+
+ if (hex_number)
+ {
+ if (c >= 'a' && c <= 'f')
+ {
+ number = number * 16 + 10 + ((int)c - 'a');
+ break;
+ }
+ if (c >= 'A' && c <= 'F')
+ {
+ number = number * 16 + 10 + ((int)c - 'A');
+ break;
+ }
+ }
+
+ state = 2;
+ if (digit_start > 0)
+ {
+ entity.Append(s, digit_start, i - digit_start);
+ digit_start = 0;
+ }
+
+ entity.Append(c);
+ break;
+ }
+ }
+
+ if (entity.Length > 0)
+ {
+ output.Append(entity);
+ }
+ else if (digit_start > 0)
+ {
+ output.Append(s, digit_start, s.Length - digit_start);
+ }
+ return output.ToString();
+ }
+
+ public static NameValueCollection ParseQueryString(string query)
+ {
+ return ParseQueryString(query, Encoding.UTF8);
+ }
+
+ public static NameValueCollection ParseQueryString(string query, Encoding encoding)
+ {
+ if (query == null)
+ throw new ArgumentNullException("query");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (query.Length == 0 || (query.Length == 1 && query[0] == '?'))
+ return new NameValueCollection();
+ if (query[0] == '?')
+ query = query.Substring(1);
+
+ NameValueCollection result = new HttpQSCollection();
+ ParseQueryString(query, encoding, result);
+ return result;
+ }
+
+ internal static void ParseQueryString(string query, Encoding encoding, NameValueCollection result)
+ {
+ if (query.Length == 0)
+ return;
+
+ string decoded = HtmlDecode(query);
+ int decodedLength = decoded.Length;
+ int namePos = 0;
+ bool first = true;
+ while (namePos <= decodedLength)
+ {
+ int valuePos = -1, valueEnd = -1;
+ for (int q = namePos; q < decodedLength; q++)
+ {
+ if (valuePos == -1 && decoded[q] == '=')
+ {
+ valuePos = q + 1;
+ }
+ else if (decoded[q] == '&')
+ {
+ valueEnd = q;
+ break;
+ }
+ }
+
+ if (first)
+ {
+ first = false;
+ if (decoded[namePos] == '?')
+ namePos++;
+ }
+
+ string name, value;
+ if (valuePos == -1)
+ {
+ name = null;
+ valuePos = namePos;
+ }
+ else
+ {
+ name = UrlDecode(decoded.Substring(namePos, valuePos - namePos - 1), encoding);
+ }
+ if (valueEnd < 0)
+ {
+ namePos = -1;
+ valueEnd = decoded.Length;
+ }
+ else
+ {
+ namePos = valueEnd + 1;
+ }
+ value = UrlDecode(decoded.Substring(valuePos, valueEnd - valuePos), encoding);
+
+ result.Add(name, value);
+ if (namePos == -1)
+ break;
+ }
+ }
+ #endregion // Methods
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
index 54c27cf0a..b3fbd2d1d 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
+using System.Web;
using Funq;
using MediaBrowser.Model.Logging;
using ServiceStack;
@@ -236,7 +237,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
private NameValueCollectionWrapper queryString;
public INameValueCollection QueryString
{
- get { return queryString ?? (queryString = new NameValueCollectionWrapper(HttpUtility.ParseQueryString(request.Url.Query))); }
+ get { return queryString ?? (queryString = new NameValueCollectionWrapper(MyHttpUtility.ParseQueryString(request.Url.Query))); }
}
private NameValueCollectionWrapper formData;
diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
index c2938475c..30a720a62 100644
--- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
@@ -163,16 +163,7 @@ namespace MediaBrowser.Server.Implementations.Library
var channels = channelResult.Items;
- var embeddedChannels = channels
- .Where(i => user.Configuration.DisplayChannelsInline || user.Configuration.DisplayChannelsWithinViews.Contains(i.Id.ToString("N")))
- .ToList();
-
- list.AddRange(embeddedChannels);
-
- if (channels.Length > embeddedChannels.Count)
- {
- list.Add(await _channelManager.GetInternalChannelFolder(cancellationToken).ConfigureAwait(false));
- }
+ list.AddRange(channels);
if (_liveTvManager.GetEnabledUsers().Select(i => i.Id.ToString("N")).Contains(query.UserId))
{
diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs
deleted file mode 100644
index ae441b44e..000000000
--- a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.LiveTv;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Serialization;
-
-namespace MediaBrowser.Server.Implementations.LiveTv.Listings.Emby
-{
- public class EmbyGuide : IListingsProvider
- {
- private readonly IHttpClient _httpClient;
- private readonly IJsonSerializer _jsonSerializer;
-
- public EmbyGuide(IHttpClient httpClient, IJsonSerializer jsonSerializer)
- {
- _httpClient = httpClient;
- _jsonSerializer = jsonSerializer;
- }
-
- public string Name
- {
- get { return "Emby Guide"; }
- }
-
- public string Type
- {
- get { return "emby"; }
- }
-
- public Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
- {
- return GetListingsProvider(info.Country).GetProgramsAsync(info, channelNumber, startDateUtc, endDateUtc, cancellationToken);
- }
-
- public Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken)
- {
- return GetListingsProvider(info.Country).AddMetadata(info, channels, cancellationToken);
- }
-
- public Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings)
- {
- return GetListingsProvider(info.Country).Validate(info, validateLogin, validateListings);
- }
-
- public Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location)
- {
- return GetListingsProvider(country).GetLineups(country, location);
- }
-
- private IEmbyListingProvider GetListingsProvider(string country)
- {
- return new EmbyListingsNorthAmerica(_httpClient, _jsonSerializer);
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListingsNorthAmerica.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListingsNorthAmerica.cs
deleted file mode 100644
index 2993740d6..000000000
--- a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListingsNorthAmerica.cs
+++ /dev/null
@@ -1,366 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.LiveTv;
-using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Server.Implementations.LiveTv.Listings.Emby
-{
- public class EmbyListingsNorthAmerica : IEmbyListingProvider
- {
- private readonly IHttpClient _httpClient;
- private readonly IJsonSerializer _jsonSerializer;
-
- public EmbyListingsNorthAmerica(IHttpClient httpClient, IJsonSerializer jsonSerializer)
- {
- _httpClient = httpClient;
- _jsonSerializer = jsonSerializer;
- }
-
- public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
- {
- channelNumber = NormalizeNumber(channelNumber);
-
- var url = "https://data.emby.media/service/listings?id=" + info.ListingsId;
-
- // Normalize
- startDateUtc = startDateUtc.Date;
- endDateUtc = startDateUtc.AddDays(7);
-
- url += "&start=" + startDateUtc.ToString("s", CultureInfo.InvariantCulture) + "Z";
- url += "&end=" + endDateUtc.ToString("s", CultureInfo.InvariantCulture) + "Z";
-
- var response = await GetResponse<ListingInfo[]>(url).ConfigureAwait(false);
-
- return response.Where(i => IncludeInResults(i, channelNumber)).Select(GetProgramInfo).OrderBy(i => i.StartDate);
- }
-
- private ProgramInfo GetProgramInfo(ListingInfo info)
- {
- var showType = info.showType ?? string.Empty;
-
- var program = new ProgramInfo
- {
- Id = info.listingID.ToString(CultureInfo.InvariantCulture),
- Name = GetStringValue(info.showName),
- HomePageUrl = GetStringValue(info.webLink),
- Overview = info.description,
- IsHD = info.hd,
- IsLive = info.live,
- IsPremiere = info.seasonPremiere || info.seriesPremiere,
- IsMovie = showType.IndexOf("Movie", StringComparison.OrdinalIgnoreCase) != -1,
- IsKids = showType.IndexOf("Children", StringComparison.OrdinalIgnoreCase) != -1,
- IsNews = showType.IndexOf("News", StringComparison.OrdinalIgnoreCase) != -1,
- IsSports = showType.IndexOf("Sports", StringComparison.OrdinalIgnoreCase) != -1
- };
-
- if (!string.IsNullOrWhiteSpace(info.listDateTime))
- {
- program.StartDate = DateTime.ParseExact(info.listDateTime, "yyyy'-'MM'-'dd' 'HH':'mm':'ss", CultureInfo.InvariantCulture);
- program.StartDate = DateTime.SpecifyKind(program.StartDate, DateTimeKind.Utc);
- program.EndDate = program.StartDate.AddMinutes(info.duration);
- }
-
- if (info.starRating > 0)
- {
- program.CommunityRating = info.starRating*2;
- }
-
- if (!string.IsNullOrWhiteSpace(info.rating))
- {
- // They don't have dashes so try to normalize
- program.OfficialRating = info.rating.Replace("TV", "TV-").Replace("--", "-");
-
- var invalid = new[] { "N/A", "Approved", "Not Rated" };
- if (invalid.Contains(program.OfficialRating, StringComparer.OrdinalIgnoreCase))
- {
- program.OfficialRating = null;
- }
- }
-
- if (!string.IsNullOrWhiteSpace(info.year))
- {
- program.ProductionYear = int.Parse(info.year, CultureInfo.InvariantCulture);
- }
-
- if (info.showID > 0)
- {
- program.ShowId = info.showID.ToString(CultureInfo.InvariantCulture);
- }
-
- if (info.seriesID > 0)
- {
- program.SeriesId = info.seriesID.ToString(CultureInfo.InvariantCulture);
- program.IsSeries = true;
- program.IsRepeat = info.repeat;
-
- program.EpisodeTitle = GetStringValue(info.episodeTitle);
-
- if (string.Equals(program.Name, program.EpisodeTitle, StringComparison.OrdinalIgnoreCase))
- {
- program.EpisodeTitle = null;
- }
- }
-
- if (info.starRating > 0)
- {
- program.CommunityRating = info.starRating * 2;
- }
-
- if (string.Equals(info.showName, "Movie", StringComparison.OrdinalIgnoreCase))
- {
- // Sometimes the movie title will be in here
- if (!string.IsNullOrWhiteSpace(info.episodeTitle))
- {
- program.Name = info.episodeTitle;
- }
- }
-
- return program;
- }
-
- private string GetStringValue(string s)
- {
- return string.IsNullOrWhiteSpace(s) ? null : s;
- }
-
- private bool IncludeInResults(ListingInfo info, string itemNumber)
- {
- if (string.Equals(itemNumber, NormalizeNumber(info.number), StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
-
- var channelNumber = info.channelNumber.ToString(CultureInfo.InvariantCulture);
- if (info.subChannelNumber > 0)
- {
- channelNumber += "." + info.subChannelNumber.ToString(CultureInfo.InvariantCulture);
- }
-
- return string.Equals(channelNumber, itemNumber, StringComparison.OrdinalIgnoreCase);
- }
-
- public async Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken)
- {
- var response = await GetResponse<LineupDetailResponse>("https://data.emby.media/service/lineups?id=" + info.ListingsId).ConfigureAwait(false);
-
- foreach (var channel in channels)
- {
- var station = response.stations.FirstOrDefault(i =>
- {
- var itemNumber = NormalizeNumber(channel.Number);
-
- if (string.Equals(itemNumber, NormalizeNumber(i.number), StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
-
- var channelNumber = i.channelNumber.ToString(CultureInfo.InvariantCulture);
- if (i.subChannelNumber > 0)
- {
- channelNumber += "." + i.subChannelNumber.ToString(CultureInfo.InvariantCulture);
- }
-
- return string.Equals(channelNumber, itemNumber, StringComparison.OrdinalIgnoreCase);
- });
-
- if (station != null)
- {
- //channel.Name = station.name;
-
- if (!string.IsNullOrWhiteSpace(station.logoFilename))
- {
- channel.HasImage = true;
- channel.ImageUrl = "http://cdn.tvpassport.com/image/station/100x100/" + station.logoFilename;
- }
- }
- }
- }
-
- private string NormalizeNumber(string number)
- {
- return number.Replace('-', '.');
- }
-
- public Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings)
- {
- return Task.FromResult(true);
- }
-
- public async Task<List<NameIdPair>> GetLineups(string country, string location)
- {
- // location = postal code
- var response = await GetResponse<LineupInfo[]>("https://data.emby.media/service/lineups?postalCode=" + location).ConfigureAwait(false);
-
- return response.Select(i => new NameIdPair
- {
- Name = GetName(i),
- Id = i.lineupID
-
- }).OrderBy(i => i.Name).ToList();
- }
-
- private string GetName(LineupInfo info)
- {
- var name = info.lineupName;
-
- if (string.Equals(info.lineupType, "cab", StringComparison.OrdinalIgnoreCase))
- {
- name += " - Cable";
- }
- else if (string.Equals(info.lineupType, "sat", StringComparison.OrdinalIgnoreCase))
- {
- name += " - SAT";
- }
- else if (string.Equals(info.lineupType, "ota", StringComparison.OrdinalIgnoreCase))
- {
- name += " - OTA";
- }
-
- return name;
- }
-
- private async Task<T> GetResponse<T>(string url, Func<string, string> filter = null)
- where T : class
- {
- using (var stream = await _httpClient.Get(new HttpRequestOptions
- {
- Url = url,
- CacheLength = TimeSpan.FromDays(1),
- CacheMode = CacheMode.Unconditional
-
- }).ConfigureAwait(false))
- {
- using (var reader = new StreamReader(stream))
- {
- var path = await reader.ReadToEndAsync().ConfigureAwait(false);
-
- using (var secondStream = await _httpClient.Get(new HttpRequestOptions
- {
- Url = "https://www.mb3admin.com" + path,
- CacheLength = TimeSpan.FromDays(1),
- CacheMode = CacheMode.Unconditional
-
- }).ConfigureAwait(false))
- {
- return ParseResponse<T>(secondStream, filter);
- }
- }
- }
- }
-
- private T ParseResponse<T>(Stream response, Func<string,string> filter)
- {
- using (var reader = new StreamReader(response))
- {
- var json = reader.ReadToEnd();
-
- if (filter != null)
- {
- json = filter(json);
- }
-
- return _jsonSerializer.DeserializeFromString<T>(json);
- }
- }
-
- private class LineupInfo
- {
- public string lineupID { get; set; }
- public string lineupName { get; set; }
- public string lineupType { get; set; }
- public string providerID { get; set; }
- public string providerName { get; set; }
- public string serviceArea { get; set; }
- public string country { get; set; }
- }
-
- private class Station
- {
- public string number { get; set; }
- public int channelNumber { get; set; }
- public int subChannelNumber { get; set; }
- public int stationID { get; set; }
- public string name { get; set; }
- public string callsign { get; set; }
- public string network { get; set; }
- public string stationType { get; set; }
- public int NTSC_TSID { get; set; }
- public int DTV_TSID { get; set; }
- public string webLink { get; set; }
- public string logoFilename { get; set; }
- }
-
- private class LineupDetailResponse
- {
- public string lineupID { get; set; }
- public string lineupName { get; set; }
- public string lineupType { get; set; }
- public string providerID { get; set; }
- public string providerName { get; set; }
- public string serviceArea { get; set; }
- public string country { get; set; }
- public List<Station> stations { get; set; }
- }
-
- private class ListingInfo
- {
- public string number { get; set; }
- public int channelNumber { get; set; }
- public int subChannelNumber { get; set; }
- public int stationID { get; set; }
- public string name { get; set; }
- public string callsign { get; set; }
- public string network { get; set; }
- public string stationType { get; set; }
- public string webLink { get; set; }
- public string logoFilename { get; set; }
- public int listingID { get; set; }
- public string listDateTime { get; set; }
- public int duration { get; set; }
- public int showID { get; set; }
- public int seriesID { get; set; }
- public string showName { get; set; }
- public string episodeTitle { get; set; }
- public string episodeNumber { get; set; }
- public int parts { get; set; }
- public int partNum { get; set; }
- public bool seriesPremiere { get; set; }
- public bool seasonPremiere { get; set; }
- public bool seriesFinale { get; set; }
- public bool seasonFinale { get; set; }
- public bool repeat { get; set; }
- public bool @new { get; set; }
- public string rating { get; set; }
- public bool captioned { get; set; }
- public bool educational { get; set; }
- public bool blackWhite { get; set; }
- public bool subtitled { get; set; }
- public bool live { get; set; }
- public bool hd { get; set; }
- public bool descriptiveVideo { get; set; }
- public bool inProgress { get; set; }
- public string showTypeID { get; set; }
- public int breakoutLevel { get; set; }
- public string showType { get; set; }
- public string year { get; set; }
- public string guest { get; set; }
- public string cast { get; set; }
- public string director { get; set; }
- public int starRating { get; set; }
- public string description { get; set; }
- public string league { get; set; }
- public string team1 { get; set; }
- public string team2 { get; set; }
- public string @event { get; set; }
- public string location { get; set; }
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/IEmbyListingProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/IEmbyListingProvider.cs
deleted file mode 100644
index 95c22b986..000000000
--- a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/IEmbyListingProvider.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.LiveTv;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Server.Implementations.LiveTv.Listings.Emby
-{
- public interface IEmbyListingProvider
- {
- Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken);
- Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
- Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
- Task<List<NameIdPair>> GetLineups(string country, string location);
- }
-}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index fb8e77006..0671a9b56 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -252,7 +252,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
height = 1080;
isInterlaced = false;
videoCodec = "h264";
- videoBitrate = 8000000;
+ videoBitrate = 15000000;
}
else if (string.Equals(profile, "internet720", StringComparison.OrdinalIgnoreCase))
{
@@ -260,7 +260,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
height = 720;
isInterlaced = false;
videoCodec = "h264";
- videoBitrate = 5000000;
+ videoBitrate = 8000000;
}
else if (string.Equals(profile, "internet540", StringComparison.OrdinalIgnoreCase))
{
@@ -326,12 +326,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
// Set the index to -1 because we don't know the exact index of the audio stream within the container
Index = -1,
Codec = "ac3",
- BitRate = 128000
+ BitRate = 192000
}
},
RequiresOpening = false,
RequiresClosing = false,
- BufferMs = 1000,
+ BufferMs = 0,
Container = "ts",
Id = profile,
SupportsDirectPlay = true,
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/hu.json b/MediaBrowser.Server.Implementations/Localization/Core/hu.json
index 546e704a4..2dc90fb7e 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/hu.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/hu.json
@@ -15,7 +15,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderPeople": "People",
"ValueSpecialEpisodeName": "Special - {0}",
- "LabelChapterName": "Chapter {0}",
+ "LabelChapterName": "Fejezet {0}",
"NameSeasonNumber": "Season {0}",
"LabelExit": "Kil\u00e9p\u00e9s",
"LabelVisitCommunity": "K\u00f6z\u00f6ss\u00e9g",
@@ -27,10 +27,10 @@
"LabelRestartServer": "Szerver \u00fajraindit\u00e1sa",
"CategorySync": "Sync",
"CategoryUser": "User",
- "CategorySystem": "System",
- "CategoryApplication": "Application",
- "CategoryPlugin": "Plugin",
- "NotificationOptionPluginError": "Plugin failure",
+ "CategorySystem": "Rendszer",
+ "CategoryApplication": "Alkalmaz\u00e1s",
+ "CategoryPlugin": "Be\u00e9p\u00fcl\u0151",
+ "NotificationOptionPluginError": "Be\u00e9p\u00fcl\u0151 hiba",
"NotificationOptionApplicationUpdateAvailable": "Application update available",
"NotificationOptionApplicationUpdateInstalled": "Application update installed",
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
@@ -48,60 +48,60 @@
"NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
"NotificationOptionUserLockedOut": "User locked out",
- "NotificationOptionServerRestartRequired": "Server restart required",
- "ViewTypePlaylists": "Playlists",
- "ViewTypeMovies": "Movies",
+ "NotificationOptionServerRestartRequired": "\u00dajraind\u00edt\u00e1s sz\u00fcks\u00e9ges",
+ "ViewTypePlaylists": "Lej\u00e1tsz\u00e1si list\u00e1k",
+ "ViewTypeMovies": "Filmek",
"ViewTypeTvShows": "TV",
- "ViewTypeGames": "Games",
- "ViewTypeMusic": "Music",
- "ViewTypeMusicGenres": "Genres",
- "ViewTypeMusicArtists": "Artists",
- "ViewTypeBoxSets": "Collections",
- "ViewTypeChannels": "Channels",
- "ViewTypeLiveTV": "Live TV",
- "ViewTypeLiveTvNowPlaying": "Now Airing",
- "ViewTypeLatestGames": "Latest Games",
- "ViewTypeRecentlyPlayedGames": "Recently Played",
- "ViewTypeGameFavorites": "Favorites",
+ "ViewTypeGames": "J\u00e1t\u00e9kok",
+ "ViewTypeMusic": "Zene",
+ "ViewTypeMusicGenres": "M\u0171fajok",
+ "ViewTypeMusicArtists": "M\u0171v\u00e9szek",
+ "ViewTypeBoxSets": "Gy\u0171jtem\u00e9nyek",
+ "ViewTypeChannels": "Csatorn\u00e1k",
+ "ViewTypeLiveTV": "\u00c9l\u0151 TV",
+ "ViewTypeLiveTvNowPlaying": "Most J\u00e1tszott",
+ "ViewTypeLatestGames": "Leg\u00fajabb J\u00e1t\u00e9kok",
+ "ViewTypeRecentlyPlayedGames": "Legut\u00f3bb J\u00e1tszott",
+ "ViewTypeGameFavorites": "Kedvencek",
"ViewTypeGameSystems": "Game Systems",
- "ViewTypeGameGenres": "Genres",
- "ViewTypeTvResume": "Resume",
- "ViewTypeTvNextUp": "Next Up",
- "ViewTypeTvLatest": "Latest",
- "ViewTypeTvShowSeries": "Series",
- "ViewTypeTvGenres": "Genres",
- "ViewTypeTvFavoriteSeries": "Favorite Series",
- "ViewTypeTvFavoriteEpisodes": "Favorite Episodes",
- "ViewTypeMovieResume": "Resume",
- "ViewTypeMovieLatest": "Latest",
- "ViewTypeMovieMovies": "Movies",
- "ViewTypeMovieCollections": "Collections",
- "ViewTypeMovieFavorites": "Favorites",
- "ViewTypeMovieGenres": "Genres",
- "ViewTypeMusicLatest": "Latest",
+ "ViewTypeGameGenres": "M\u0171fajok",
+ "ViewTypeTvResume": "Folytat\u00e1s",
+ "ViewTypeTvNextUp": "K\u00f6vetkez\u0151",
+ "ViewTypeTvLatest": "Leg\u00fajabb",
+ "ViewTypeTvShowSeries": "Sorozat",
+ "ViewTypeTvGenres": "M\u0171fajok",
+ "ViewTypeTvFavoriteSeries": "Kedvenc Sorozat",
+ "ViewTypeTvFavoriteEpisodes": "Kedvenc R\u00e9szek",
+ "ViewTypeMovieResume": "Folytat\u00e1s",
+ "ViewTypeMovieLatest": "Leg\u00fajabb",
+ "ViewTypeMovieMovies": "Filmek",
+ "ViewTypeMovieCollections": "Gy\u0171jtem\u00e9nyek",
+ "ViewTypeMovieFavorites": "Kedvencek",
+ "ViewTypeMovieGenres": "M\u0171fajok",
+ "ViewTypeMusicLatest": "Leg\u00fajabb",
"ViewTypeMusicPlaylists": "Playlists",
- "ViewTypeMusicAlbums": "Albums",
- "ViewTypeMusicAlbumArtists": "Album Artists",
- "HeaderOtherDisplaySettings": "Display Settings",
- "ViewTypeMusicSongs": "Songs",
- "ViewTypeMusicFavorites": "Favorites",
- "ViewTypeMusicFavoriteAlbums": "Favorite Albums",
- "ViewTypeMusicFavoriteArtists": "Favorite Artists",
- "ViewTypeMusicFavoriteSongs": "Favorite Songs",
+ "ViewTypeMusicAlbums": "Albumok",
+ "ViewTypeMusicAlbumArtists": "Album El\u0151ad\u00f3k",
+ "HeaderOtherDisplaySettings": "Megjelen\u00edt\u00e9si Be\u00e1ll\u00edt\u00e1sok",
+ "ViewTypeMusicSongs": "Dalok",
+ "ViewTypeMusicFavorites": "Kedvencek",
+ "ViewTypeMusicFavoriteAlbums": "Kedvenc Albumok",
+ "ViewTypeMusicFavoriteArtists": "Kedvenc M\u0171v\u00e9szek",
+ "ViewTypeMusicFavoriteSongs": "Kedvenc Dalok",
"ViewTypeFolders": "Folders",
"ViewTypeLiveTvRecordingGroups": "Recordings",
"ViewTypeLiveTvChannels": "Channels",
"ScheduledTaskFailedWithName": "{0} failed",
"LabelRunningTimeValue": "Running time: {0}",
- "ScheduledTaskStartedWithName": "{0} started",
- "VersionNumber": "Version {0}",
- "PluginInstalledWithName": "{0} was installed",
- "PluginUpdatedWithName": "{0} was updated",
+ "ScheduledTaskStartedWithName": "{0} elkezdve",
+ "VersionNumber": "Verzi\u00f3 {0}",
+ "PluginInstalledWithName": "{0} telep\u00edtve",
+ "PluginUpdatedWithName": "{0} friss\u00edtve",
"PluginUninstalledWithName": "{0} was uninstalled",
- "ItemAddedWithName": "{0} was added to the library",
- "ItemRemovedWithName": "{0} was removed from the library",
+ "ItemAddedWithName": "{0} k\u00f6nyvt\u00e1rhoz adva",
+ "ItemRemovedWithName": "{0} t\u00f6r\u00f6lve a k\u00f6nyvt\u00e1rb\u00f3l",
"LabelIpAddressValue": "Ip address: {0}",
- "DeviceOnlineWithName": "{0} is connected",
+ "DeviceOnlineWithName": "{0} kapcsol\u00f3dva",
"UserOnlineFromDevice": "{0} is online from {1}",
"ProviderValue": "Provider: {0}",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
@@ -114,7 +114,7 @@
"MessageApplicationUpdated": "Emby Server has been updated",
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
"AuthenticationSucceededWithUserName": "{0} successfully authenticated",
- "DeviceOfflineWithName": "{0} has disconnected",
+ "DeviceOfflineWithName": "{0} sz\u00e9tkapcsolt",
"UserLockedOutWithName": "User {0} has been locked out",
"UserOfflineFromDevice": "{0} has disconnected from {1}",
"UserStartedPlayingItemWithValues": "{0} has started playing {1}",
@@ -131,7 +131,7 @@
"HeaderSeverity": "Severity",
"HeaderUser": "User",
"HeaderName": "Name",
- "HeaderDate": "Date",
+ "HeaderDate": "D\u00e1tum",
"HeaderPremiereDate": "Premiere Date",
"HeaderDateAdded": "Date Added",
"HeaderReleaseDate": "Release date",
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/id.json b/MediaBrowser.Server.Implementations/Localization/Core/id.json
index 47f679041..4fb839fe8 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/id.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/id.json
@@ -11,7 +11,7 @@
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
"FolderTypeTvShows": "TV",
- "FolderTypeInherit": "Inherit",
+ "FolderTypeInherit": "Mewarisi",
"HeaderCastCrew": "Cast & Crew",
"HeaderPeople": "People",
"ValueSpecialEpisodeName": "Special - {0}",
diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
index 94038c76a..2fb8eb002 100644
--- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
+++ b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
@@ -378,6 +378,7 @@ namespace MediaBrowser.Server.Implementations.Localization
new LocalizatonOption{ Name="Greek", Value="el"},
new LocalizatonOption{ Name="Hebrew", Value="he"},
new LocalizatonOption{ Name="Hungarian", Value="hu"},
+ new LocalizatonOption{ Name="Indonesian", Value="id"},
new LocalizatonOption{ Name="Italian", Value="it"},
new LocalizatonOption{ Name="Kazakh", Value="kk"},
new LocalizatonOption{ Name="Norwegian Bokmål", Value="nb"},
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index f488f443e..c5b6c1c42 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -52,15 +52,18 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.41\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
</Reference>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
<Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Api.Swagger">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
</Reference>
- <Reference Include="SocketHttpListener, Version=1.0.5754.42244, Culture=neutral, processorArchitecture=MSIL">
+ <Reference Include="SocketHttpListener, Version=1.0.5840.28948, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\SocketHttpListener.1.0.0.10\lib\net45\SocketHttpListener.dll</HintPath>
+ <HintPath>..\packages\SocketHttpListener.1.0.0.25\lib\net45\SocketHttpListener.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -70,6 +73,7 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net" />
+ <Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
@@ -94,9 +98,6 @@
<Reference Include="Mono.Nat">
<HintPath>..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll</HintPath>
</Reference>
- <Reference Include="MoreLinq">
- <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
@@ -160,6 +161,7 @@
<Compile Include="HttpServer\ServerLogFactory.cs" />
<Compile Include="HttpServer\ServerLogger.cs" />
<Compile Include="HttpServer\Security\SessionContext.cs" />
+ <Compile Include="HttpServer\SocketSharp\HttpUtility.cs" />
<Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" />
<Compile Include="HttpServer\StreamWriter.cs" />
<Compile Include="HttpServer\SwaggerService.cs" />
@@ -216,9 +218,6 @@
<Compile Include="LiveTv\EmbyTV\RecordingHelper.cs" />
<Compile Include="LiveTv\EmbyTV\SeriesTimerManager.cs" />
<Compile Include="LiveTv\EmbyTV\TimerManager.cs" />
- <Compile Include="LiveTv\Listings\Emby\EmbyListings.cs" />
- <Compile Include="LiveTv\Listings\Emby\EmbyListingsNorthAmerica.cs" />
- <Compile Include="LiveTv\Listings\Emby\IEmbyListingProvider.cs" />
<Compile Include="LiveTv\Listings\SchedulesDirect.cs" />
<Compile Include="LiveTv\Listings\XmlTv.cs" />
<Compile Include="LiveTv\LiveTvConfigurationFactory.cs" />
@@ -408,6 +407,8 @@
<EmbeddedResource Include="Localization\Core\zh-CN.json" />
<EmbeddedResource Include="Localization\Core\zh-TW.json" />
<EmbeddedResource Include="Localization\Core\zh-HK.json" />
+ <EmbeddedResource Include="Localization\Core\hu.json" />
+ <EmbeddedResource Include="Localization\Core\id.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index 7d9453822..aac5951b5 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -4,7 +4,7 @@
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
<package id="MediaBrowser.Naming" version="1.0.0.41" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.24.0" targetFramework="net45" />
- <package id="morelinq" version="1.1.1" targetFramework="net45" />
+ <package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
- <package id="SocketHttpListener" version="1.0.0.10" targetFramework="net45" />
+ <package id="SocketHttpListener" version="1.0.0.25" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
index ba6d7ad1f..8f3006e11 100644
--- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
+++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
@@ -119,7 +119,7 @@ namespace MediaBrowser.Server.Mono.Native
{
get
{
- return false;
+ return Environment.OperatingSystem == Startup.Common.OperatingSystem.Linux;
}
}
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index 99a7f0a15..c6e2dd98f 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -91,10 +91,12 @@ using MediaBrowser.Server.Startup.Common.Migrations;
using MediaBrowser.WebDashboard.Api;
using MediaBrowser.XbmcMetadata.Providers;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Net;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
@@ -207,6 +209,7 @@ namespace MediaBrowser.Server.Startup.Common
private readonly string _remotePackageName;
internal INativeApp NativeApp { get; set; }
+ private Timer _ipAddressCacheTimer;
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost" /> class.
@@ -230,6 +233,8 @@ namespace MediaBrowser.Server.Startup.Common
NativeApp = nativeApp;
SetBaseExceptionMessage();
+
+ _ipAddressCacheTimer = new Timer(OnCacheClearTimerFired, null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3));
}
private Version _version;
@@ -316,6 +321,7 @@ namespace MediaBrowser.Server.Startup.Common
{
await base.RunStartupTasks().ConfigureAwait(false);
+ Logger.Info("ServerId: {0}", SystemId);
Logger.Info("Core startup complete");
HttpServer.GlobalResponse = null;
@@ -436,7 +442,7 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
- HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, "Emby", "web/index.html");
+ HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, "Emby", "web/index.html");
HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
RegisterSingleInstance(HttpServer, false);
progress.Report(10);
@@ -1108,14 +1114,14 @@ namespace MediaBrowser.Server.Startup.Common
try
{
// Return the first matched address, if found, or the first known local address
- var address = LocalIpAddress;
+ var address = LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i));
- if (!string.IsNullOrWhiteSpace(address))
+ if (address != null)
{
- address = GetLocalApiUrl(address);
+ return GetLocalApiUrl(address.ToString());
}
- return address;
+ return null;
}
catch (Exception ex)
{
@@ -1133,40 +1139,71 @@ namespace MediaBrowser.Server.Startup.Common
HttpPort.ToString(CultureInfo.InvariantCulture));
}
- public string LocalIpAddress
+ public List<IPAddress> LocalIpAddresses
{
get
{
- return HttpServerIpAddresses.FirstOrDefault();
+ var localAddresses = NetworkManager.GetLocalIpAddresses()
+ .Where(IsIpAddressValid)
+ .ToList();
+
+ return localAddresses;
}
}
- private IEnumerable<string> HttpServerIpAddresses
+ private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
+ private bool IsIpAddressValid(IPAddress address)
{
- get
+ if (IPAddress.IsLoopback(address))
{
- var localAddresses = NetworkManager.GetLocalIpAddresses()
- .ToList();
+ return true;
+ }
- var httpServerAddresses = HttpServer.LocalEndPoints
- .Select(i => i.Split(':').FirstOrDefault())
- .Where(i => !string.IsNullOrEmpty(i))
- .ToList();
+ var apiUrl = GetLocalApiUrl(address.ToString());
+ apiUrl += "/system/ping";
- // Cross-check the local ip addresses with addresses that have been received on with the http server
- var matchedAddresses = httpServerAddresses
- .Where(i => localAddresses.Contains(i, StringComparer.OrdinalIgnoreCase))
- .ToList();
+ bool cachedResult;
+ if (_validAddressResults.TryGetValue(apiUrl, out cachedResult))
+ {
+ return cachedResult;
+ }
- if (matchedAddresses.Count == 0)
+ try
+ {
+ using (var response = HttpClient.SendAsync(new HttpRequestOptions
+ {
+ Url = apiUrl,
+ LogErrorResponseBody = false,
+ LogErrors = false,
+ LogRequest = false
+
+ }, "POST").Result)
{
- return localAddresses;
+ using (var reader = new StreamReader(response.Content))
+ {
+ var result = reader.ReadToEnd();
+ var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase);
+
+ _validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid);
+ Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, valid);
+ return valid;
+ }
}
+ }
+ catch
+ {
+ Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false);
- return matchedAddresses;
+ _validAddressResults.AddOrUpdate(apiUrl, false, (k, v) => false);
+ return false;
}
}
+ private void OnCacheClearTimerFired(object state)
+ {
+ _validAddressResults.Clear();
+ }
+
public string FriendlyName
{
get
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index 5813dcac5..fdbcf015a 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -156,24 +156,24 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
- <Content Include="..\Installation\MediaBrowser.InstallUtil.dll">
- <Link>MediaBrowser.InstallUtil.dll</Link>
+ <Content Include="..\packages\System.Data.SQLite.Core.1.0.94.0\build\net45\x64\SQLite.Interop.dll">
+ <Link>x64\SQLite.Interop.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="..\Installation\MediaBrowser.Uninstaller.exe">
- <Link>MediaBrowser.Uninstaller.exe</Link>
+ <Content Include="..\packages\System.Data.SQLite.Core.1.0.94.0\build\net45\x86\SQLite.Interop.dll">
+ <Link>x86\SQLite.Interop.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="..\Installation\MediaBrowser.Updater.exe">
- <Link>MediaBrowser.Updater.exe</Link>
+ <Content Include="..\Tools\Installation\MediaBrowser.InstallUtil.dll">
+ <Link>MediaBrowser.InstallUtil.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="..\packages\System.Data.SQLite.Core.1.0.94.0\build\net45\x64\SQLite.Interop.dll">
- <Link>x64\SQLite.Interop.dll</Link>
+ <Content Include="..\Tools\Installation\MediaBrowser.Uninstaller.exe">
+ <Link>MediaBrowser.Uninstaller.exe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="..\packages\System.Data.SQLite.Core.1.0.94.0\build\net45\x86\SQLite.Interop.dll">
- <Link>x86\SQLite.Interop.dll</Link>
+ <Content Include="..\Tools\Installation\MediaBrowser.Updater.exe">
+ <Link>MediaBrowser.Updater.exe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="CORE_RL_bzlib_.dll">
diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs
index bff342d01..ceab5379d 100644
--- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs
+++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs
@@ -24,7 +24,7 @@ namespace MediaBrowser.ServerApplication.Native
if (!System.Environment.Is64BitProcess)
{
- list.Add(typeof(PismoIsoManager).Assembly);
+ //list.Add(typeof(PismoIsoManager).Assembly);
}
list.Add(GetType().Assembly);
diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
index 1065f9130..4a6289771 100644
--- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs
+++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
@@ -367,22 +367,22 @@ namespace MediaBrowser.WebDashboard.Api
sb.Append("<meta name=\"application-name\" content=\"Emby\">");
//sb.Append("<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">");
- sb.Append("<meta name=\"robots\" content=\"noindex, nofollow, noarchive\" />");
+ sb.Append("<meta name=\"robots\" content=\"noindex, nofollow, noarchive\">");
// Open graph tags
- sb.Append("<meta property=\"og:title\" content=\"Emby\" />");
- sb.Append("<meta property=\"og:site_name\" content=\"Emby\"/>");
- sb.Append("<meta property=\"og:url\" content=\"http://emby.media\" />");
- sb.Append("<meta property=\"og:description\" content=\"Energize your media.\" />");
- sb.Append("<meta property=\"og:type\" content=\"article\" />");
- sb.Append("<meta property=\"fb:app_id\" content=\"1618309211750238\" />");
+ sb.Append("<meta property=\"og:title\" content=\"Emby\">");
+ sb.Append("<meta property=\"og:site_name\" content=\"Emby\">");
+ sb.Append("<meta property=\"og:url\" content=\"http://emby.media\">");
+ sb.Append("<meta property=\"og:description\" content=\"Energize your media.\">");
+ sb.Append("<meta property=\"og:type\" content=\"article\">");
+ sb.Append("<meta property=\"fb:app_id\" content=\"1618309211750238\">");
// http://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html
- sb.Append("<link rel=\"apple-touch-icon\" href=\"css/images/touchicon.png\" />");
- sb.Append("<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"css/images/touchicon72.png\" />");
- sb.Append("<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"css/images/touchicon114.png\" />");
- sb.Append("<link rel=\"apple-touch-startup-image\" href=\"css/images/iossplash.png\" />");
- sb.Append("<link rel=\"shortcut icon\" href=\"css/images/favicon.ico\" />");
+ sb.Append("<link rel=\"apple-touch-icon\" href=\"css/images/touchicon.png\">");
+ sb.Append("<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"css/images/touchicon72.png\">");
+ sb.Append("<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"css/images/touchicon114.png\">");
+ sb.Append("<link rel=\"apple-touch-startup-image\" href=\"css/images/iossplash.png\">");
+ sb.Append("<link rel=\"shortcut icon\" href=\"css/images/favicon.ico\">");
sb.Append("<meta name=\"msapplication-TileImage\" content=\"css/images/touchicon144.png\">");
sb.Append("<meta name=\"msapplication-TileColor\" content=\"#333333\">");
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 531c2b7e4..4da1f42c4 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -248,6 +248,9 @@
<Content Include="dashboard-ui\mysyncsettings.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\robots.txt">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\actionsheet.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -2470,6 +2473,9 @@
<None Include="dashboard-ui\strings\html\hu.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
+ <None Include="dashboard-ui\strings\html\id.json">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
<None Include="dashboard-ui\strings\html\zh-HK.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
diff --git a/SharedVersion.cs b/SharedVersion.cs
index e0732b997..323710f1c 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,4 +1,4 @@
using System.Reflection;
//[assembly: AssemblyVersion("3.0.*")]
-[assembly: AssemblyVersion("3.0.5784.0")]
+[assembly: AssemblyVersion("3.0.5802")]