mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
commit
236b5caee2
@ -33,11 +33,11 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll</HintPath>
|
<HintPath>..\packages\ImageMagickSharp.1.0.0.17\lib\net45\ImageMagickSharp.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||||
|
@ -72,11 +72,16 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
|
|
||||||
private void LogVersion()
|
private void LogVersion()
|
||||||
{
|
{
|
||||||
_logger.Info("ImageMagick version: " + Wand.VersionString);
|
_logger.Info("ImageMagick version: " + GetVersion());
|
||||||
TestWebp();
|
TestWebp();
|
||||||
Wand.SetMagickThreadCount(1);
|
Wand.SetMagickThreadCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetVersion()
|
||||||
|
{
|
||||||
|
return Wand.VersionString;
|
||||||
|
}
|
||||||
|
|
||||||
private bool _webpAvailable = true;
|
private bool _webpAvailable = true;
|
||||||
private void TestWebp()
|
private void TestWebp()
|
||||||
{
|
{
|
||||||
@ -148,7 +153,7 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
DrawIndicator(originalImage, width, height, options);
|
DrawIndicator(originalImage, width, height, options);
|
||||||
|
|
||||||
originalImage.CurrentImage.CompressionQuality = quality;
|
originalImage.CurrentImage.CompressionQuality = quality;
|
||||||
//originalImage.CurrentImage.StripImage();
|
originalImage.CurrentImage.StripImage();
|
||||||
|
|
||||||
originalImage.SaveImage(outputPath);
|
originalImage.SaveImage(outputPath);
|
||||||
}
|
}
|
||||||
@ -165,7 +170,7 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
DrawIndicator(wand, width, height, options);
|
DrawIndicator(wand, width, height, options);
|
||||||
|
|
||||||
wand.CurrentImage.CompressionQuality = quality;
|
wand.CurrentImage.CompressionQuality = quality;
|
||||||
//wand.CurrentImage.StripImage();
|
wand.CurrentImage.StripImage();
|
||||||
|
|
||||||
wand.SaveImage(outputPath);
|
wand.SaveImage(outputPath);
|
||||||
}
|
}
|
||||||
@ -176,15 +181,16 @@ namespace Emby.Drawing.ImageMagick
|
|||||||
|
|
||||||
private void ScaleImage(MagickWand wand, int width, int height)
|
private void ScaleImage(MagickWand wand, int width, int height)
|
||||||
{
|
{
|
||||||
wand.CurrentImage.ResizeImage(width, height);
|
var highQuality = false;
|
||||||
//if (_config.Configuration.EnableHighQualityImageScaling)
|
|
||||||
//{
|
if (highQuality)
|
||||||
// wand.CurrentImage.ResizeImage(width, height);
|
{
|
||||||
//}
|
wand.CurrentImage.ResizeImage(width, height);
|
||||||
//else
|
}
|
||||||
//{
|
else
|
||||||
// wand.CurrentImage.ScaleImage(width, height);
|
{
|
||||||
//}
|
wand.CurrentImage.ScaleImage(width, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" targetFramework="net45" />
|
||||||
<package id="ImageMagickSharp" version="1.0.0.16" targetFramework="net45" />
|
<package id="ImageMagickSharp" version="1.0.0.17" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -17,6 +17,7 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
@ -112,13 +113,15 @@ namespace MediaBrowser.Api
|
|||||||
private readonly IServerApplicationPaths _appPaths;
|
private readonly IServerApplicationPaths _appPaths;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
private readonly IJsonSerializer _json;
|
||||||
|
|
||||||
public ItemLookupService(IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager)
|
public ItemLookupService(IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager, IJsonSerializer json)
|
||||||
{
|
{
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
_json = json;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetExternalIdInfos request)
|
public object Get(GetExternalIdInfos request)
|
||||||
@ -199,6 +202,7 @@ namespace MediaBrowser.Api
|
|||||||
// item.SetProviderId(key.Key, value);
|
// item.SetProviderId(key.Key, value);
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
Logger.Info("Setting provider id's to item {0}-{1}: {2}", item.Id, item.Name, _json.SerializeToString(request.ProviderIds));
|
||||||
item.ProviderIds = request.ProviderIds;
|
item.ProviderIds = request.ProviderIds;
|
||||||
|
|
||||||
var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem)
|
var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem)
|
||||||
|
@ -162,6 +162,14 @@ namespace MediaBrowser.Api.Library
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/Items", "DELETE", Summary = "Deletes an item from the library and file system")]
|
||||||
|
[Authenticated]
|
||||||
|
public class DeleteItems : IReturnVoid
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Ids", Description = "Ids", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
|
||||||
|
public string Ids { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/Items/Counts", "GET")]
|
[Route("/Items/Counts", "GET")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetItemCounts : IReturn<ItemCounts>
|
public class GetItemCounts : IReturn<ItemCounts>
|
||||||
@ -711,31 +719,53 @@ namespace MediaBrowser.Api.Library
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the specified request.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The request.</param>
|
||||||
|
public void Delete(DeleteItems request)
|
||||||
|
{
|
||||||
|
var ids = string.IsNullOrWhiteSpace(request.Ids)
|
||||||
|
? new string[] { }
|
||||||
|
: request.Ids.Split(',');
|
||||||
|
|
||||||
|
var tasks = ids.Select(i =>
|
||||||
|
{
|
||||||
|
var item = _libraryManager.GetItemById(i);
|
||||||
|
var auth = _authContext.GetAuthorizationInfo(Request);
|
||||||
|
var user = _userManager.GetUserById(auth.UserId);
|
||||||
|
|
||||||
|
if (!item.CanDelete(user))
|
||||||
|
{
|
||||||
|
if (ids.Length > 1)
|
||||||
|
{
|
||||||
|
throw new SecurityException("Unauthorized access");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is ILiveTvRecording)
|
||||||
|
{
|
||||||
|
return _liveTv.DeleteRecording(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _libraryManager.DeleteItem(item);
|
||||||
|
}).ToArray();
|
||||||
|
|
||||||
|
Task.WaitAll(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes the specified request.
|
/// Deletes the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
public void Delete(DeleteItem request)
|
public void Delete(DeleteItem request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
Delete(new DeleteItems
|
||||||
var auth = _authContext.GetAuthorizationInfo(Request);
|
|
||||||
var user = _userManager.GetUserById(auth.UserId);
|
|
||||||
|
|
||||||
if (!item.CanDelete(user))
|
|
||||||
{
|
{
|
||||||
throw new SecurityException("Unauthorized access");
|
Ids = request.Id
|
||||||
}
|
});
|
||||||
|
|
||||||
if (item is ILiveTvRecording)
|
|
||||||
{
|
|
||||||
var task = _liveTv.DeleteRecording(request.Id);
|
|
||||||
Task.WaitAll(task);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var task = _libraryManager.DeleteItem(item);
|
|
||||||
Task.WaitAll(task);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -47,7 +47,10 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="MoreLinq">
|
||||||
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||||
@ -63,9 +66,6 @@
|
|||||||
<Reference Include="ServiceStack.Text">
|
<Reference Include="ServiceStack.Text">
|
||||||
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="MoreLinq">
|
|
||||||
<HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\SharedVersion.cs">
|
<Compile Include="..\SharedVersion.cs">
|
||||||
|
@ -233,7 +233,7 @@ namespace MediaBrowser.Api
|
|||||||
throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name));
|
throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
Task.Run(() => _installationManager.InstallPackage(package, new Progress<double>(), CancellationToken.None));
|
Task.Run(() => _installationManager.InstallPackage(package, true, new Progress<double>(), CancellationToken.None));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1562,6 +1562,13 @@ namespace MediaBrowser.Api.Playback
|
|||||||
RequestedUrl = url
|
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))
|
if (!string.IsNullOrWhiteSpace(request.AudioCodec))
|
||||||
{
|
{
|
||||||
state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
|
state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
|
||||||
|
@ -111,7 +111,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
throw;
|
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
|
finally
|
||||||
|
@ -179,6 +179,7 @@ namespace MediaBrowser.Api
|
|||||||
if (primaryImageTag != null)
|
if (primaryImageTag != null)
|
||||||
{
|
{
|
||||||
result.PrimaryImageTag = primaryImageTag;
|
result.PrimaryImageTag = primaryImageTag;
|
||||||
|
result.PrimaryImageAspectRatio = _dtoService.GetPrimaryImageAspectRatio(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetThumbImageInfo(result, item);
|
SetThumbImageInfo(result, item);
|
||||||
|
@ -13,6 +13,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.Net;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.System
|
namespace MediaBrowser.Api.System
|
||||||
{
|
{
|
||||||
@ -32,6 +33,12 @@ namespace MediaBrowser.Api.System
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/System/Ping", "POST")]
|
||||||
|
public class PingSystem : IReturnVoid
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class RestartApplication
|
/// Class RestartApplication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -59,7 +66,7 @@ namespace MediaBrowser.Api.System
|
|||||||
|
|
||||||
[Route("/System/Endpoint", "GET", Summary = "Gets information about the request endpoint")]
|
[Route("/System/Endpoint", "GET", Summary = "Gets information about the request endpoint")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetEndpointInfo : IReturn<EndpointInfo>
|
public class GetEndpointInfo : IReturn<EndPointInfo>
|
||||||
{
|
{
|
||||||
public string Endpoint { get; set; }
|
public string Endpoint { get; set; }
|
||||||
}
|
}
|
||||||
@ -104,6 +111,11 @@ namespace MediaBrowser.Api.System
|
|||||||
_security = security;
|
_security = security;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Post(PingSystem request)
|
||||||
|
{
|
||||||
|
return _appHost.Name;
|
||||||
|
}
|
||||||
|
|
||||||
public object Get(GetServerLogs request)
|
public object Get(GetServerLogs request)
|
||||||
{
|
{
|
||||||
List<FileSystemMetadata> files;
|
List<FileSystemMetadata> files;
|
||||||
@ -199,17 +211,11 @@ namespace MediaBrowser.Api.System
|
|||||||
|
|
||||||
public object Get(GetEndpointInfo request)
|
public object Get(GetEndpointInfo request)
|
||||||
{
|
{
|
||||||
return ToOptimizedResult(new EndpointInfo
|
return ToOptimizedResult(new EndPointInfo
|
||||||
{
|
{
|
||||||
IsLocal = Request.IsLocal,
|
IsLocal = Request.IsLocal,
|
||||||
IsInNetwork = _network.IsInLocalNetwork(request.Endpoint ?? Request.RemoteIp)
|
IsInNetwork = _network.IsInLocalNetwork(request.Endpoint ?? Request.RemoteIp)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EndpointInfo
|
|
||||||
{
|
|
||||||
public bool IsLocal { get; set; }
|
|
||||||
public bool IsInNetwork { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" 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="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -133,7 +133,7 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
/// Gets the HTTP client.
|
/// Gets the HTTP client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The HTTP client.</value>
|
/// <value>The HTTP client.</value>
|
||||||
protected IHttpClient HttpClient { get; private set; }
|
public IHttpClient HttpClient { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the network manager.
|
/// Gets the network manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -150,7 +150,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
request.Method = method;
|
request.Method = method;
|
||||||
request.Timeout = options.TimeoutMs;
|
request.Timeout = options.TimeoutMs;
|
||||||
|
|
||||||
if (httpWebRequest != null)
|
if (httpWebRequest != null)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(options.Host))
|
if (!string.IsNullOrEmpty(options.Host))
|
||||||
|
@ -49,11 +49,13 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
<Reference Include="MoreLinq">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
<HintPath>..\packages\NLog.4.1.1\lib\net45\NLog.dll</HintPath>
|
</Reference>
|
||||||
|
<Reference Include="NLog">
|
||||||
|
<HintPath>..\packages\NLog.4.2.3\lib\net45\NLog.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||||
@ -62,13 +64,14 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SimpleInjector, Version=2.8.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
<Reference Include="SimpleInjector">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<HintPath>..\packages\SimpleInjector.3.1.2\lib\net45\SimpleInjector.dll</HintPath>
|
||||||
<HintPath>..\packages\SimpleInjector.3.0.5\lib\net45\SimpleInjector.dll</HintPath>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Configuration" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Net" />
|
<Reference Include="System.Net" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="ServiceStack.Text">
|
<Reference Include="ServiceStack.Text">
|
||||||
@ -105,6 +108,7 @@
|
|||||||
<Compile Include="Security\SuppporterInfoResponse.cs" />
|
<Compile Include="Security\SuppporterInfoResponse.cs" />
|
||||||
<Compile Include="Serialization\JsonSerializer.cs" />
|
<Compile Include="Serialization\JsonSerializer.cs" />
|
||||||
<Compile Include="Serialization\XmlSerializer.cs" />
|
<Compile Include="Serialization\XmlSerializer.cs" />
|
||||||
|
<Compile Include="Updates\GithubUpdater.cs" />
|
||||||
<Compile Include="Updates\InstallationManager.cs" />
|
<Compile Include="Updates\InstallationManager.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,6 +7,7 @@ using System.Net;
|
|||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using MoreLinq;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Implementations.Networking
|
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();
|
private readonly object _localIpAddressSyncLock = new object();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the machine's local ip address
|
/// Gets the machine's local ip address
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IPAddress.</returns>
|
/// <returns>IPAddress.</returns>
|
||||||
public IEnumerable<string> GetLocalIpAddresses()
|
public IEnumerable<IPAddress> GetLocalIpAddresses()
|
||||||
{
|
{
|
||||||
if (_localIpAddresses == null)
|
if (_localIpAddresses == null)
|
||||||
{
|
{
|
||||||
@ -58,25 +59,24 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||||||
return _localIpAddresses;
|
return _localIpAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<string> GetLocalIpAddressesInternal()
|
private IEnumerable<IPAddress> GetLocalIpAddressesInternal()
|
||||||
{
|
{
|
||||||
var list = GetIPsDefault()
|
var list = GetIPsDefault()
|
||||||
.Where(i => !IPAddress.IsLoopback(i))
|
|
||||||
.Select(i => i.ToString())
|
|
||||||
.Where(FilterIpAddress)
|
|
||||||
.ToList();
|
.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;
|
return false;
|
||||||
}
|
}
|
||||||
@ -84,8 +84,16 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||||||
return true;
|
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:
|
// Private address space:
|
||||||
// http://en.wikipedia.org/wiki/Private_network
|
// http://en.wikipedia.org/wiki/Private_network
|
||||||
|
|
||||||
@ -96,9 +104,6 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
// If url was requested with computer name, we may see this
|
|
||||||
endpoint.IndexOf("::", StringComparison.OrdinalIgnoreCase) != -1 ||
|
|
||||||
|
|
||||||
endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
|
endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
|
||||||
endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
|
endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
|
||||||
endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
|
endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
|
||||||
@ -131,26 +136,41 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||||||
throw new ArgumentNullException("endpoint");
|
throw new ArgumentNullException("endpoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsInPrivateAddressSpace(endpoint))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int lengthMatch = 4;
|
|
||||||
|
|
||||||
if (endpoint.Length >= lengthMatch)
|
|
||||||
{
|
|
||||||
var prefix = endpoint.Substring(0, lengthMatch);
|
|
||||||
|
|
||||||
if (GetLocalIpAddresses()
|
|
||||||
.Any(i => i.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPAddress address;
|
IPAddress address;
|
||||||
if (resolveHost && !IPAddress.TryParse(endpoint, out address))
|
if (IPAddress.TryParse(endpoint, out address))
|
||||||
|
{
|
||||||
|
var addressString = address.ToString();
|
||||||
|
|
||||||
|
int lengthMatch = 100;
|
||||||
|
if (address.AddressFamily == AddressFamily.InterNetwork)
|
||||||
|
{
|
||||||
|
lengthMatch = 4;
|
||||||
|
if (IsInPrivateAddressSpace(addressString))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
|
{
|
||||||
|
lengthMatch = 10;
|
||||||
|
if (IsInPrivateAddressSpace(endpoint))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
Uri uri;
|
||||||
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
|
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
|
||||||
@ -188,33 +208,45 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||||||
return Dns.GetHostAddresses(hostName);
|
return Dns.GetHostAddresses(hostName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<IPAddress> GetIPsDefault()
|
private List<IPAddress> GetIPsDefault()
|
||||||
{
|
{
|
||||||
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
|
NetworkInterface[] interfaces;
|
||||||
{
|
|
||||||
var props = adapter.GetIPProperties();
|
|
||||||
var gateways = from ga in props.GatewayAddresses
|
|
||||||
where !ga.Address.Equals(IPAddress.Any)
|
|
||||||
select true;
|
|
||||||
|
|
||||||
if (!gateways.Any())
|
try
|
||||||
{
|
{
|
||||||
continue;
|
interfaces = NetworkInterface.GetAllNetworkInterfaces();
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
|
||||||
|
return new List<IPAddress>();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var uni in props.UnicastAddresses)
|
return interfaces.SelectMany(network => {
|
||||||
{
|
|
||||||
var address = uni.Address;
|
|
||||||
if (address.AddressFamily != AddressFamily.InterNetwork)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
yield return address;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<string> GetLocalIpAddressesFallback()
|
try
|
||||||
|
{
|
||||||
|
Logger.Debug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
|
||||||
|
|
||||||
|
var properties = network.GetIPProperties();
|
||||||
|
|
||||||
|
return properties.UnicastAddresses
|
||||||
|
.Where(i => i.IsDnsEligible)
|
||||||
|
.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());
|
var host = Dns.GetHostEntry(Dns.GetHostName());
|
||||||
|
|
||||||
@ -222,7 +254,6 @@ namespace MediaBrowser.Common.Implementations.Networking
|
|||||||
// It's not fool-proof so ultimately the consumer will have to examine them and decide
|
// It's not fool-proof so ultimately the consumer will have to examine them and decide
|
||||||
return host.AddressList
|
return host.AddressList
|
||||||
.Where(i => i.AddressFamily == AddressFamily.InterNetwork)
|
.Where(i => i.AddressFamily == AddressFamily.InterNetwork)
|
||||||
.Select(i => i.ToString())
|
|
||||||
.Reverse();
|
.Reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
212
MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs
Normal file
212
MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using MediaBrowser.Model.Updates;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Common.Implementations.Updates
|
||||||
|
{
|
||||||
|
public class GithubUpdater
|
||||||
|
{
|
||||||
|
private readonly IHttpClient _httpClient;
|
||||||
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
|
private TimeSpan _cacheLength;
|
||||||
|
|
||||||
|
public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer, TimeSpan cacheLength)
|
||||||
|
{
|
||||||
|
_httpClient = httpClient;
|
||||||
|
_jsonSerializer = jsonSerializer;
|
||||||
|
_cacheLength = cacheLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CheckForUpdateResult> CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository);
|
||||||
|
|
||||||
|
var options = new HttpRequestOptions
|
||||||
|
{
|
||||||
|
Url = url,
|
||||||
|
EnableKeepAlive = false,
|
||||||
|
CancellationToken = cancellationToken,
|
||||||
|
UserAgent = "Emby/3.0"
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_cacheLength.Ticks > 0)
|
||||||
|
{
|
||||||
|
options.CacheMode = CacheMode.Unconditional;
|
||||||
|
options.CacheLength = _cacheLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var obj = _jsonSerializer.DeserializeFromStream<RootObject[]>(stream);
|
||||||
|
|
||||||
|
return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckForUpdateResult CheckForUpdateResult(RootObject[] obj, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename)
|
||||||
|
{
|
||||||
|
if (updateLevel == PackageVersionClass.Release)
|
||||||
|
{
|
||||||
|
obj = obj.Where(i => !i.prerelease).ToArray();
|
||||||
|
}
|
||||||
|
else if (updateLevel == PackageVersionClass.Beta)
|
||||||
|
{
|
||||||
|
obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||||
|
}
|
||||||
|
else if (updateLevel == PackageVersionClass.Dev)
|
||||||
|
{
|
||||||
|
obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
var availableUpdate = obj
|
||||||
|
.Select(i => CheckForUpdateResult(i, minVersion, assetFilename, packageName, targetFilename))
|
||||||
|
.Where(i => i != null)
|
||||||
|
.OrderByDescending(i => Version.Parse(i.AvailableVersion))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
return availableUpdate ?? new CheckForUpdateResult
|
||||||
|
{
|
||||||
|
IsUpdateAvailable = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckForUpdateResult CheckForUpdateResult(RootObject obj, Version minVersion, string assetFilename, string packageName, string targetFilename)
|
||||||
|
{
|
||||||
|
Version version;
|
||||||
|
if (!Version.TryParse(obj.tag_name, out version))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version < minVersion)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var asset = (obj.assets ?? new List<Asset>()).FirstOrDefault(i => IsAsset(i, assetFilename));
|
||||||
|
|
||||||
|
if (asset == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CheckForUpdateResult
|
||||||
|
{
|
||||||
|
AvailableVersion = version.ToString(),
|
||||||
|
IsUpdateAvailable = version > minVersion,
|
||||||
|
Package = new PackageVersionInfo
|
||||||
|
{
|
||||||
|
classification = obj.prerelease ?
|
||||||
|
(obj.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase) ? PackageVersionClass.Dev : PackageVersionClass.Beta) :
|
||||||
|
PackageVersionClass.Release,
|
||||||
|
name = packageName,
|
||||||
|
sourceUrl = asset.browser_download_url,
|
||||||
|
targetFilename = targetFilename,
|
||||||
|
versionStr = version.ToString(),
|
||||||
|
requiredVersionStr = "1.0.0",
|
||||||
|
description = obj.body
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsAsset(Asset asset, string assetFilename)
|
||||||
|
{
|
||||||
|
var downloadFilename = Path.GetFileName(asset.browser_download_url) ?? string.Empty;
|
||||||
|
|
||||||
|
if (downloadFilename.IndexOf(assetFilename, StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Equals(assetFilename, downloadFilename, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Uploader
|
||||||
|
{
|
||||||
|
public string login { get; set; }
|
||||||
|
public int id { get; set; }
|
||||||
|
public string avatar_url { get; set; }
|
||||||
|
public string gravatar_id { get; set; }
|
||||||
|
public string url { get; set; }
|
||||||
|
public string html_url { get; set; }
|
||||||
|
public string followers_url { get; set; }
|
||||||
|
public string following_url { get; set; }
|
||||||
|
public string gists_url { get; set; }
|
||||||
|
public string starred_url { get; set; }
|
||||||
|
public string subscriptions_url { get; set; }
|
||||||
|
public string organizations_url { get; set; }
|
||||||
|
public string repos_url { get; set; }
|
||||||
|
public string events_url { get; set; }
|
||||||
|
public string received_events_url { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
public bool site_admin { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Asset
|
||||||
|
{
|
||||||
|
public string url { get; set; }
|
||||||
|
public int id { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public object label { get; set; }
|
||||||
|
public Uploader uploader { get; set; }
|
||||||
|
public string content_type { get; set; }
|
||||||
|
public string state { get; set; }
|
||||||
|
public int size { get; set; }
|
||||||
|
public int download_count { get; set; }
|
||||||
|
public string created_at { get; set; }
|
||||||
|
public string updated_at { get; set; }
|
||||||
|
public string browser_download_url { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Author
|
||||||
|
{
|
||||||
|
public string login { get; set; }
|
||||||
|
public int id { get; set; }
|
||||||
|
public string avatar_url { get; set; }
|
||||||
|
public string gravatar_id { get; set; }
|
||||||
|
public string url { get; set; }
|
||||||
|
public string html_url { get; set; }
|
||||||
|
public string followers_url { get; set; }
|
||||||
|
public string following_url { get; set; }
|
||||||
|
public string gists_url { get; set; }
|
||||||
|
public string starred_url { get; set; }
|
||||||
|
public string subscriptions_url { get; set; }
|
||||||
|
public string organizations_url { get; set; }
|
||||||
|
public string repos_url { get; set; }
|
||||||
|
public string events_url { get; set; }
|
||||||
|
public string received_events_url { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
public bool site_admin { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RootObject
|
||||||
|
{
|
||||||
|
public string url { get; set; }
|
||||||
|
public string assets_url { get; set; }
|
||||||
|
public string upload_url { get; set; }
|
||||||
|
public string html_url { get; set; }
|
||||||
|
public int id { get; set; }
|
||||||
|
public string tag_name { get; set; }
|
||||||
|
public string target_commitish { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public bool draft { get; set; }
|
||||||
|
public Author author { get; set; }
|
||||||
|
public bool prerelease { get; set; }
|
||||||
|
public string created_at { get; set; }
|
||||||
|
public string published_at { get; set; }
|
||||||
|
public List<Asset> assets { get; set; }
|
||||||
|
public string tarball_url { get; set; }
|
||||||
|
public string zipball_url { get; set; }
|
||||||
|
public string body { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -437,11 +437,12 @@ namespace MediaBrowser.Common.Implementations.Updates
|
|||||||
/// Installs the package.
|
/// Installs the package.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="package">The package.</param>
|
/// <param name="package">The package.</param>
|
||||||
|
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
|
||||||
/// <param name="progress">The progress.</param>
|
/// <param name="progress">The progress.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">package</exception>
|
/// <exception cref="System.ArgumentNullException">package</exception>
|
||||||
public async Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken)
|
public async Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (package == null)
|
if (package == null)
|
||||||
{
|
{
|
||||||
@ -494,7 +495,7 @@ namespace MediaBrowser.Common.Implementations.Updates
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await InstallPackageInternal(package, innerProgress, linkedToken).ConfigureAwait(false);
|
await InstallPackageInternal(package, isPlugin, innerProgress, linkedToken).ConfigureAwait(false);
|
||||||
|
|
||||||
lock (CurrentInstallations)
|
lock (CurrentInstallations)
|
||||||
{
|
{
|
||||||
@ -550,18 +551,17 @@ namespace MediaBrowser.Common.Implementations.Updates
|
|||||||
/// Installs the package internal.
|
/// Installs the package internal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="package">The package.</param>
|
/// <param name="package">The package.</param>
|
||||||
|
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
|
||||||
/// <param name="progress">The progress.</param>
|
/// <param name="progress">The progress.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
private async Task InstallPackageInternal(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken)
|
private async Task InstallPackageInternal(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// Do the install
|
// Do the install
|
||||||
await PerformPackageInstallation(progress, package, cancellationToken).ConfigureAwait(false);
|
await PerformPackageInstallation(progress, package, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var extension = Path.GetExtension(package.targetFilename) ?? "";
|
|
||||||
|
|
||||||
// Do plugin-specific processing
|
// Do plugin-specific processing
|
||||||
if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase) && !string.Equals(extension, ".rar", StringComparison.OrdinalIgnoreCase) && !string.Equals(extension, ".7z", StringComparison.OrdinalIgnoreCase))
|
if (isPlugin)
|
||||||
{
|
{
|
||||||
// Set last update time if we were installed before
|
// Set last update time if we were installed before
|
||||||
var plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
|
var plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" 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="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>
|
</packages>
|
||||||
|
@ -11,7 +11,7 @@ namespace MediaBrowser.Common.Net
|
|||||||
/// Gets the machine's local ip address
|
/// Gets the machine's local ip address
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IPAddress.</returns>
|
/// <returns>IPAddress.</returns>
|
||||||
IEnumerable<string> GetLocalIpAddresses();
|
IEnumerable<IPAddress> GetLocalIpAddresses();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a random port number that is currently available
|
/// Gets a random port number that is currently available
|
||||||
@ -25,6 +25,13 @@ namespace MediaBrowser.Common.Net
|
|||||||
/// <returns>[string] MAC Address</returns>
|
/// <returns>[string] MAC Address</returns>
|
||||||
string GetMacAddress();
|
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>
|
/// <summary>
|
||||||
/// Gets the network shares.
|
/// Gets the network shares.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -105,11 +105,12 @@ namespace MediaBrowser.Common.Updates
|
|||||||
/// Installs the package.
|
/// Installs the package.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="package">The package.</param>
|
/// <param name="package">The package.</param>
|
||||||
|
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
|
||||||
/// <param name="progress">The progress.</param>
|
/// <param name="progress">The progress.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">package</exception>
|
/// <exception cref="System.ArgumentNullException">package</exception>
|
||||||
Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken);
|
Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Uninstalls a plugin
|
/// Uninstalls a plugin
|
||||||
|
@ -22,8 +22,14 @@ namespace MediaBrowser.Controller.Dto
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dto">The dto.</param>
|
/// <param name="dto">The dto.</param>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <param name="fields">The fields.</param>
|
void AttachPrimaryImageAspectRatio(IItemDto dto, IHasImages item);
|
||||||
void AttachPrimaryImageAspectRatio(IItemDto dto, IHasImages item, List<ItemFields> fields);
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the primary image aspect ratio.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
|
/// <returns>System.Nullable<System.Double>.</returns>
|
||||||
|
double? GetPrimaryImageAspectRatio(IHasImages item);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the base item dto.
|
/// Gets the base item dto.
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Model.System;
|
using MediaBrowser.Model.System;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller
|
namespace MediaBrowser.Controller
|
||||||
{
|
{
|
||||||
@ -63,7 +65,7 @@ namespace MediaBrowser.Controller
|
|||||||
/// Gets the local ip address.
|
/// Gets the local ip address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The local ip address.</value>
|
/// <value>The local ip address.</value>
|
||||||
string LocalIpAddress { get; }
|
List<IPAddress> LocalIpAddresses { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the local API URL.
|
/// Gets the local API URL.
|
||||||
|
@ -46,11 +46,14 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Interfaces.IO">
|
<Reference Include="Interfaces.IO">
|
||||||
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
|
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="MoreLinq">
|
||||||
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
@ -65,9 +68,6 @@
|
|||||||
<Reference Include="ServiceStack.Interfaces">
|
<Reference Include="ServiceStack.Interfaces">
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="MoreLinq">
|
|
||||||
<HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\SharedVersion.cs">
|
<Compile Include="..\SharedVersion.cs">
|
||||||
|
@ -28,12 +28,6 @@ namespace MediaBrowser.Controller.Net
|
|||||||
/// the ssl certificate localtion on the file system.</param>
|
/// the ssl certificate localtion on the file system.</param>
|
||||||
void StartServer(IEnumerable<string> urlPrefixes, string certificatePath);
|
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>
|
/// <summary>
|
||||||
/// Stops this instance.
|
/// Stops this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" targetFramework="net45" />
|
||||||
<package id="Interfaces.IO" 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" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -43,19 +43,19 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
private readonly List<string> _registeredServerIds = new List<string>();
|
private readonly List<string> _registeredServerIds = new List<string>();
|
||||||
private bool _dlnaServerStarted;
|
private bool _dlnaServerStarted;
|
||||||
|
|
||||||
public DlnaEntryPoint(IServerConfigurationManager config,
|
public DlnaEntryPoint(IServerConfigurationManager config,
|
||||||
ILogManager logManager,
|
ILogManager logManager,
|
||||||
IServerApplicationHost appHost,
|
IServerApplicationHost appHost,
|
||||||
INetworkManager network,
|
INetworkManager network,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
IDlnaManager dlnaManager,
|
IDlnaManager dlnaManager,
|
||||||
IImageProcessor imageProcessor,
|
IImageProcessor imageProcessor,
|
||||||
IUserDataManager userDataManager,
|
IUserDataManager userDataManager,
|
||||||
ILocalizationManager localization,
|
ILocalizationManager localization,
|
||||||
IMediaSourceManager mediaSourceManager,
|
IMediaSourceManager mediaSourceManager,
|
||||||
ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery)
|
ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
@ -148,13 +148,20 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
|
|
||||||
private void RegisterServerEndpoints()
|
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 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>
|
var services = new List<string>
|
||||||
{
|
{
|
||||||
@ -165,8 +172,8 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
|
"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
|
||||||
"uuid:" + guid.ToString("N")
|
"uuid:" + guid.ToString("N")
|
||||||
};
|
};
|
||||||
|
|
||||||
_ssdpHandler.RegisterNotification(guid, uri, IPAddress.Parse(address), services);
|
_ssdpHandler.RegisterNotification(guid, uri, address, services);
|
||||||
|
|
||||||
_registeredServerIds.Add(guid.ToString("N"));
|
_registeredServerIds.Add(guid.ToString("N"));
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,10 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="MoreLinq">
|
||||||
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||||
|
@ -37,7 +37,6 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
MusicSyncBitrate = 128000;
|
MusicSyncBitrate = 128000;
|
||||||
|
|
||||||
EnableAlbumArtInDidl = false;
|
EnableAlbumArtInDidl = false;
|
||||||
EnableDlnaProtocol = true;
|
|
||||||
|
|
||||||
TranscodingProfiles = new[]
|
TranscodingProfiles = new[]
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
Name = "Xbox 360";
|
Name = "Xbox 360";
|
||||||
|
|
||||||
// Required according to above
|
// Required according to above
|
||||||
ModelName = "Windows Media Connect";
|
ModelName = "Windows Media Player Sharing";
|
||||||
|
|
||||||
ModelNumber = "12.0";
|
ModelNumber = "12.0";
|
||||||
|
|
||||||
@ -25,13 +25,11 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
ManufacturerUrl = "http://www.microsoft.com";
|
ManufacturerUrl = "http://www.microsoft.com";
|
||||||
XDlnaDoc = "DMS-1.50";
|
XDlnaDoc = "DMS-1.50";
|
||||||
ModelDescription = "Emby : UPnP Media Server";
|
ModelDescription = "Emby : UPnP Media Server";
|
||||||
ModelNumber = "001";
|
|
||||||
|
|
||||||
TimelineOffsetSeconds = 40;
|
TimelineOffsetSeconds = 40;
|
||||||
RequiresPlainFolders = true;
|
RequiresPlainFolders = true;
|
||||||
RequiresPlainVideoItems = true;
|
RequiresPlainVideoItems = true;
|
||||||
EnableMSMediaReceiverRegistrar = true;
|
EnableMSMediaReceiverRegistrar = true;
|
||||||
EnableDlnaProtocol = false;
|
|
||||||
|
|
||||||
Identification = new DeviceIdentification
|
Identification = new DeviceIdentification
|
||||||
{
|
{
|
||||||
|
@ -81,7 +81,7 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4,mov,mkv",
|
Container = "mp4,mov,mkv",
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4,mpeg2video",
|
||||||
AudioCodec = "aac,ac3",
|
AudioCodec = "aac,ac3",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso" type="Video" />
|
<DirectPlayProfile container="avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso" type="Video" />
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp3,wma" type="Audio" />
|
<DirectPlayProfile container="mp3,wma" type="Audio" />
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
<RequiresPlainFolders>true</RequiresPlainFolders>
|
<RequiresPlainFolders>true</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg2video" type="Video" />
|
<DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg2video" type="Video" />
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp4,mkv,mpeg,ts" audioCodec="mp3,ac3,aac,he-aac,pcm" videoCodec="h264,mpeg2video" type="Video" />
|
<DirectPlayProfile container="mp4,mkv,mpeg,ts" audioCodec="mp3,ac3,aac,he-aac,pcm" videoCodec="h264,mpeg2video" type="Video" />
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="" type="Video" />
|
<DirectPlayProfile container="" type="Video" />
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="ts" audioCodec="aac,ac3,mp3" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="aac,ac3,mp3" videoCodec="h264" type="Video" />
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes>
|
<XmlRootAttributes>
|
||||||
<XmlAttribute name="xmlns:pv" value="http://www.pv.com/pvns/" />
|
<XmlAttribute name="xmlns:pv" value="http://www.pv.com/pvns/" />
|
||||||
</XmlRootAttributes>
|
</XmlRootAttributes>
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp4,mov" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,mov" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" />
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes>
|
<XmlRootAttributes>
|
||||||
<XmlAttribute name="xmlns:sec" value="http://www.sec.co.kr/" />
|
<XmlAttribute name="xmlns:sec" value="http://www.sec.co.kr/" />
|
||||||
</XmlRootAttributes>
|
</XmlRootAttributes>
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes>
|
<XmlRootAttributes>
|
||||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||||
</XmlRootAttributes>
|
</XmlRootAttributes>
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes>
|
<XmlRootAttributes>
|
||||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||||
</XmlRootAttributes>
|
</XmlRootAttributes>
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes>
|
<XmlRootAttributes>
|
||||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||||
</XmlRootAttributes>
|
</XmlRootAttributes>
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes>
|
<XmlRootAttributes>
|
||||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||||
</XmlRootAttributes>
|
</XmlRootAttributes>
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes>
|
<XmlRootAttributes>
|
||||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||||
</XmlRootAttributes>
|
</XmlRootAttributes>
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes>
|
<XmlRootAttributes>
|
||||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||||
</XmlRootAttributes>
|
</XmlRootAttributes>
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes>
|
<XmlRootAttributes>
|
||||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||||
</XmlRootAttributes>
|
</XmlRootAttributes>
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso" type="Video" />
|
<DirectPlayProfile container="avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso" type="Video" />
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>true</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>true</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="avi" audioCodec="ac3,dca,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="ac3,dca,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
<FriendlyName>${HostName}: 1</FriendlyName>
|
<FriendlyName>${HostName}: 1</FriendlyName>
|
||||||
<Manufacturer>Microsoft Corporation</Manufacturer>
|
<Manufacturer>Microsoft Corporation</Manufacturer>
|
||||||
<ManufacturerUrl>http://www.microsoft.com</ManufacturerUrl>
|
<ManufacturerUrl>http://www.microsoft.com</ManufacturerUrl>
|
||||||
<ModelName>Windows Media Connect</ModelName>
|
<ModelName>Windows Media Player Sharing</ModelName>
|
||||||
<ModelDescription>Emby : UPnP Media Server</ModelDescription>
|
<ModelDescription>Emby : UPnP Media Server</ModelDescription>
|
||||||
<ModelNumber>001</ModelNumber>
|
<ModelNumber>12.0</ModelNumber>
|
||||||
<ModelUrl>http://go.microsoft.com/fwlink/?LinkId=105926</ModelUrl>
|
<ModelUrl>http://go.microsoft.com/fwlink/?LinkId=105926</ModelUrl>
|
||||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||||
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
|
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
|
||||||
@ -35,7 +35,6 @@
|
|||||||
<RequiresPlainFolders>true</RequiresPlainFolders>
|
<RequiresPlainFolders>true</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>true</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>true</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>false</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
|
||||||
|
@ -35,13 +35,12 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="ts" audioCodec="ac3" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="ac3" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="aac" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="aac" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="mp4,mov,mkv" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,mov,mkv" audioCodec="aac,ac3" videoCodec="h264,mpeg4,mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="wmv2,wmv3,vc1" type="Video" />
|
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="wmv2,wmv3,vc1" type="Video" />
|
||||||
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
|
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
|
||||||
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
|
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||||
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
<EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<EnableDlnaProtocol>true</EnableDlnaProtocol>
|
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
||||||
|
@ -54,14 +54,11 @@ namespace MediaBrowser.Dlna.Server
|
|||||||
|
|
||||||
var attributes = _profile.XmlRootAttributes.ToList();
|
var attributes = _profile.XmlRootAttributes.ToList();
|
||||||
|
|
||||||
if (_profile.EnableDlnaProtocol)
|
attributes.Insert(0, new XmlAttribute
|
||||||
{
|
{
|
||||||
attributes.Insert(0, new XmlAttribute
|
Name = "xmlns:dlna",
|
||||||
{
|
Value = "urn:schemas-dlna-org:device-1-0"
|
||||||
Name = "xmlns:dlna",
|
});
|
||||||
Value = "urn:schemas-dlna-org:device-1-0"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
attributes.Insert(0, new XmlAttribute
|
attributes.Insert(0, new XmlAttribute
|
||||||
{
|
{
|
||||||
Name = "xmlns",
|
Name = "xmlns",
|
||||||
@ -92,10 +89,7 @@ namespace MediaBrowser.Dlna.Server
|
|||||||
builder.Append("<device>");
|
builder.Append("<device>");
|
||||||
AppendDeviceProperties(builder);
|
AppendDeviceProperties(builder);
|
||||||
|
|
||||||
if (_profile.EnableDlnaProtocol)
|
AppendIconList(builder);
|
||||||
{
|
|
||||||
AppendIconList(builder);
|
|
||||||
}
|
|
||||||
AppendServiceList(builder);
|
AppendServiceList(builder);
|
||||||
builder.Append("</device>");
|
builder.Append("</device>");
|
||||||
}
|
}
|
||||||
@ -104,13 +98,10 @@ namespace MediaBrowser.Dlna.Server
|
|||||||
{
|
{
|
||||||
builder.Append("<deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>");
|
builder.Append("<deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>");
|
||||||
|
|
||||||
if (_profile.EnableDlnaProtocol)
|
builder.Append("<dlna:X_DLNACAP>" + SecurityElement.Escape(_profile.XDlnaCap ?? string.Empty) + "</dlna:X_DLNACAP>");
|
||||||
{
|
|
||||||
builder.Append("<dlna:X_DLNACAP>" + SecurityElement.Escape(_profile.XDlnaCap ?? string.Empty) + "</dlna:X_DLNACAP>");
|
|
||||||
|
|
||||||
builder.Append("<dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">M-DMS-1.50</dlna:X_DLNADOC>");
|
builder.Append("<dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">M-DMS-1.50</dlna:X_DLNADOC>");
|
||||||
builder.Append("<dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">" + SecurityElement.Escape(_profile.XDlnaDoc ?? string.Empty) + "</dlna:X_DLNADOC>");
|
builder.Append("<dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">" + SecurityElement.Escape(_profile.XDlnaDoc ?? string.Empty) + "</dlna:X_DLNADOC>");
|
||||||
}
|
|
||||||
|
|
||||||
builder.Append("<friendlyName>" + SecurityElement.Escape(GetFriendlyName()) + "</friendlyName>");
|
builder.Append("<friendlyName>" + SecurityElement.Escape(GetFriendlyName()) + "</friendlyName>");
|
||||||
builder.Append("<manufacturer>" + SecurityElement.Escape(_profile.Manufacturer ?? string.Empty) + "</manufacturer>");
|
builder.Append("<manufacturer>" + SecurityElement.Escape(_profile.Manufacturer ?? string.Empty) + "</manufacturer>");
|
||||||
|
@ -11,6 +11,8 @@ using System.Net.NetworkInformation;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
using MoreLinq;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Ssdp
|
namespace MediaBrowser.Dlna.Ssdp
|
||||||
{
|
{
|
||||||
@ -26,50 +28,39 @@ namespace MediaBrowser.Dlna.Ssdp
|
|||||||
|
|
||||||
public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
|
public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
|
||||||
public event EventHandler<SsdpMessageEventArgs> DeviceLeft;
|
public event EventHandler<SsdpMessageEventArgs> DeviceLeft;
|
||||||
|
private readonly INetworkManager _networkManager;
|
||||||
|
|
||||||
public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IServerApplicationHost appHost)
|
public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IServerApplicationHost appHost, INetworkManager networkManager)
|
||||||
{
|
{
|
||||||
_tokenSource = new CancellationTokenSource();
|
_tokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_config = config;
|
_config = config;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
|
_networkManager = networkManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<IPAddress> GetLocalIpAddresses()
|
||||||
|
{
|
||||||
|
return _networkManager.GetLocalIpAddresses().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public void Start(SsdpHandler ssdpHandler)
|
public void Start(SsdpHandler ssdpHandler)
|
||||||
{
|
{
|
||||||
_ssdpHandler = ssdpHandler;
|
_ssdpHandler = ssdpHandler;
|
||||||
_ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived;
|
_ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived;
|
||||||
|
|
||||||
foreach (var network in GetNetworkInterfaces())
|
foreach (var localIp in GetLocalIpAddresses())
|
||||||
{
|
{
|
||||||
_logger.Debug("Found interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
|
try
|
||||||
|
{
|
||||||
if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any())
|
CreateListener(localIp);
|
||||||
continue;
|
}
|
||||||
|
catch (Exception e)
|
||||||
var properties = network.GetIPProperties();
|
{
|
||||||
var ipV4 = properties.GetIPv4Properties();
|
_logger.ErrorException("Failed to Initilize Socket", e);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
|
void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
|
||||||
@ -89,8 +80,11 @@ namespace MediaBrowser.Dlna.Ssdp
|
|||||||
{
|
{
|
||||||
if (e.LocalEndPoint == null)
|
if (e.LocalEndPoint == null)
|
||||||
{
|
{
|
||||||
var ip = _appHost.LocalIpAddress;
|
var ip = _appHost.LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i));
|
||||||
e.LocalEndPoint = new IPEndPoint(IPAddress.Parse(ip), 0);
|
if (ip != null)
|
||||||
|
{
|
||||||
|
e.LocalEndPoint = new IPEndPoint(ip, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.LocalEndPoint != null)
|
if (e.LocalEndPoint != null)
|
||||||
@ -107,30 +101,18 @@ 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)
|
private void CreateListener(IPAddress localIp)
|
||||||
{
|
{
|
||||||
Task.Factory.StartNew(async (o) =>
|
Task.Factory.StartNew(async (o) =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var endPoint = new IPEndPoint(localIp, 1900);
|
_logger.Info("Creating SSDP listener on {0}", localIp);
|
||||||
|
|
||||||
|
var endPoint = new IPEndPoint(localIp, 1900);
|
||||||
|
|
||||||
var socket = GetMulticastSocket(localIp, endPoint);
|
var socket = GetMulticastSocket(localIp, endPoint);
|
||||||
|
|
||||||
_logger.Info("Creating SSDP listener on {0}", localIp);
|
|
||||||
|
|
||||||
var receiveBuffer = new byte[64000];
|
var receiveBuffer = new byte[64000];
|
||||||
|
|
||||||
CreateNotifier(localIp);
|
CreateNotifier(localIp);
|
||||||
|
@ -15,6 +15,7 @@ using System.Net.Sockets;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Ssdp
|
namespace MediaBrowser.Dlna.Ssdp
|
||||||
{
|
{
|
||||||
@ -112,7 +113,9 @@ namespace MediaBrowser.Dlna.Ssdp
|
|||||||
{
|
{
|
||||||
get
|
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();
|
RestartSocketListener();
|
||||||
|
|
||||||
ReloadAliveNotifier();
|
ReloadAliveNotifier();
|
||||||
|
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Mode == PowerModes.Resume)
|
||||||
|
{
|
||||||
|
NotifyAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendSearchMessage(EndPoint localIp)
|
public void SendSearchMessage(EndPoint localIp)
|
||||||
@ -433,6 +445,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_config.NamedConfigurationUpdated -= _config_ConfigurationUpdated;
|
_config.NamedConfigurationUpdated -= _config_ConfigurationUpdated;
|
||||||
|
SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
|
||||||
|
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
while (_messageQueue.Count != 0)
|
while (_messageQueue.Count != 0)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" targetFramework="net45" />
|
||||||
|
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -33,7 +33,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -41,7 +41,7 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="DvdLib">
|
<Reference Include="DvdLib">
|
||||||
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
|
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" targetFramework="net45" />
|
||||||
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
|
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -78,7 +78,6 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
|
|
||||||
public bool EnableMSMediaReceiverRegistrar { get; set; }
|
public bool EnableMSMediaReceiverRegistrar { get; set; }
|
||||||
public bool IgnoreTranscodeByteRangeRequests { get; set; }
|
public bool IgnoreTranscodeByteRangeRequests { get; set; }
|
||||||
public bool EnableDlnaProtocol { get; set; }
|
|
||||||
|
|
||||||
public XmlAttribute[] XmlRootAttributes { get; set; }
|
public XmlAttribute[] XmlRootAttributes { get; set; }
|
||||||
|
|
||||||
|
@ -144,5 +144,11 @@ namespace MediaBrowser.Model.Search
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name of the channel.</value>
|
/// <value>The name of the channel.</value>
|
||||||
public string ChannelName { get; set; }
|
public string ChannelName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the primary image aspect ratio.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The primary image aspect ratio.</value>
|
||||||
|
public double? PrimaryImageAspectRatio { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,7 @@ namespace MediaBrowser.Providers.Manager
|
|||||||
source = memoryStream;
|
source = memoryStream;
|
||||||
|
|
||||||
var currentImage = GetCurrentImage(item, type, index);
|
var currentImage = GetCurrentImage(item, type, index);
|
||||||
|
var savedPaths = new List<string>();
|
||||||
|
|
||||||
using (source)
|
using (source)
|
||||||
{
|
{
|
||||||
@ -146,17 +147,17 @@ namespace MediaBrowser.Providers.Manager
|
|||||||
{
|
{
|
||||||
retryPath = retryPaths[currentPathIndex];
|
retryPath = retryPaths[currentPathIndex];
|
||||||
}
|
}
|
||||||
await SaveImageToLocation(source, path, retryPath, cancellationToken).ConfigureAwait(false);
|
var savedPath = await SaveImageToLocation(source, path, retryPath, cancellationToken).ConfigureAwait(false);
|
||||||
|
savedPaths.Add(savedPath);
|
||||||
currentPathIndex++;
|
currentPathIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the path into the item
|
// Set the path into the item
|
||||||
SetImagePath(item, type, imageIndex, paths[0]);
|
SetImagePath(item, type, imageIndex, savedPaths[0]);
|
||||||
|
|
||||||
// Delete the current path
|
// Delete the current path
|
||||||
if (currentImage != null && currentImage.IsLocalFile && !paths.Contains(currentImage.Path, StringComparer.OrdinalIgnoreCase))
|
if (currentImage != null && currentImage.IsLocalFile && !savedPaths.Contains(currentImage.Path, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var currentPath = currentImage.Path;
|
var currentPath = currentImage.Path;
|
||||||
|
|
||||||
@ -184,11 +185,12 @@ namespace MediaBrowser.Providers.Manager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveImageToLocation(Stream source, string path, string retryPath, CancellationToken cancellationToken)
|
private async Task<string> SaveImageToLocation(Stream source, string path, string retryPath, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await SaveImageToLocation(source, path, cancellationToken).ConfigureAwait(false);
|
await SaveImageToLocation(source, path, cancellationToken).ConfigureAwait(false);
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
catch (UnauthorizedAccessException)
|
catch (UnauthorizedAccessException)
|
||||||
{
|
{
|
||||||
@ -207,6 +209,7 @@ namespace MediaBrowser.Providers.Manager
|
|||||||
|
|
||||||
source.Position = 0;
|
source.Position = 0;
|
||||||
await SaveImageToLocation(source, retryPath, cancellationToken).ConfigureAwait(false);
|
await SaveImageToLocation(source, retryPath, cancellationToken).ConfigureAwait(false);
|
||||||
|
return retryPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -795,22 +795,6 @@ namespace MediaBrowser.Providers.Manager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a workaround duplicate check for movies, where intersecting provider ids are not always available
|
|
||||||
if (typeof(TItemType) == typeof(Movie) || typeof(TItemType) == typeof(Series))
|
|
||||||
{
|
|
||||||
var titleYearString = string.Format("{0} ({1})", result.Name, result.ProductionYear);
|
|
||||||
|
|
||||||
if (foundTitleYearStrings.Contains(titleYearString))
|
|
||||||
{
|
|
||||||
bFound = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foundTitleYearStrings.Add(titleYearString);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bFound && resultList.Count < maxResults)
|
if (!bFound && resultList.Count < maxResults)
|
||||||
{
|
{
|
||||||
resultList.Add(result);
|
resultList.Add(result);
|
||||||
|
@ -50,15 +50,14 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="DvdLib, Version=1.0.5167.21152, Culture=neutral, PublicKeyToken=7a2f3f5ec8d93575, processorArchitecture=MSIL">
|
<Reference Include="DvdLib, Version=1.0.5167.21152, Culture=neutral, PublicKeyToken=7a2f3f5ec8d93575, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
|
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="MoreLinq, Version=1.1.18418.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL">
|
<Reference Include="MoreLinq">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
<HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||||
|
@ -68,7 +68,14 @@ namespace MediaBrowser.Providers.Music
|
|||||||
|
|
||||||
var list = new List<RemoteImageInfo>();
|
var list = new List<RemoteImageInfo>();
|
||||||
|
|
||||||
var artistMusicBrainzId = album.MusicArtist.GetProviderId(MetadataProviders.MusicBrainzArtist);
|
var musicArtist = album.MusicArtist;
|
||||||
|
|
||||||
|
if (musicArtist == null)
|
||||||
|
{
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
var artistMusicBrainzId = musicArtist.GetProviderId(MetadataProviders.MusicBrainzArtist);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(artistMusicBrainzId))
|
if (!string.IsNullOrEmpty(artistMusicBrainzId))
|
||||||
{
|
{
|
||||||
|
@ -51,25 +51,15 @@ namespace MediaBrowser.Providers.Omdb
|
|||||||
return Task.FromResult<IEnumerable<RemoteImageInfo>>(list);
|
return Task.FromResult<IEnumerable<RemoteImageInfo>>(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = OmdbProvider.ResourcePool
|
ResourcePool = OmdbProvider.ResourcePool
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
});
|
||||||
|
|
||||||
if (response.ContentLength == 11059)
|
|
||||||
{
|
|
||||||
throw new HttpException("File not found")
|
|
||||||
{
|
|
||||||
StatusCode = HttpStatusCode.NotFound
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
|
@ -57,7 +57,12 @@ namespace MediaBrowser.Providers.Omdb
|
|||||||
return GetSearchResults(searchInfo, "movie", cancellationToken);
|
return GetSearchResults(searchInfo, "movie", cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ItemLookupInfo searchInfo, string type, CancellationToken cancellationToken)
|
public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ItemLookupInfo searchInfo, string type, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return GetSearchResultsInternal(searchInfo, type, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<RemoteSearchResult>> GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool enableMultipleResults, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
bool isSearch = false;
|
bool isSearch = false;
|
||||||
|
|
||||||
@ -86,7 +91,14 @@ namespace MediaBrowser.Providers.Omdb
|
|||||||
}
|
}
|
||||||
|
|
||||||
// &s means search and returns a list of results as opposed to t
|
// &s means search and returns a list of results as opposed to t
|
||||||
url += "&s=" + WebUtility.UrlEncode(name);
|
if (enableMultipleResults)
|
||||||
|
{
|
||||||
|
url += "&s=" + WebUtility.UrlEncode(name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url += "&t=" + WebUtility.UrlEncode(name);
|
||||||
|
}
|
||||||
url += "&type=" + type;
|
url += "&type=" + type;
|
||||||
isSearch = true;
|
isSearch = true;
|
||||||
}
|
}
|
||||||
@ -239,14 +251,14 @@ namespace MediaBrowser.Providers.Omdb
|
|||||||
|
|
||||||
private async Task<string> GetMovieImdbId(ItemLookupInfo info, CancellationToken cancellationToken)
|
private async Task<string> GetMovieImdbId(ItemLookupInfo info, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var results = await GetSearchResults(info, "movie", cancellationToken).ConfigureAwait(false);
|
var results = await GetSearchResultsInternal(info, "movie", false, cancellationToken).ConfigureAwait(false);
|
||||||
var first = results.FirstOrDefault();
|
var first = results.FirstOrDefault();
|
||||||
return first == null ? null : first.GetProviderId(MetadataProviders.Imdb);
|
return first == null ? null : first.GetProviderId(MetadataProviders.Imdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> GetSeriesImdbId(SeriesInfo info, CancellationToken cancellationToken)
|
private async Task<string> GetSeriesImdbId(SeriesInfo info, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var results = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
|
var results = await GetSearchResultsInternal(info, "series", false, cancellationToken).ConfigureAwait(false);
|
||||||
var first = results.FirstOrDefault();
|
var first = results.FirstOrDefault();
|
||||||
return first == null ? null : first.GetProviderId(MetadataProviders.Imdb);
|
return first == null ? null : first.GetProviderId(MetadataProviders.Imdb);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Net;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.Subtitles
|
namespace MediaBrowser.Providers.Subtitles
|
||||||
{
|
{
|
||||||
@ -30,15 +31,6 @@ namespace MediaBrowser.Providers.Subtitles
|
|||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IEncryptionManager _encryption;
|
private readonly IEncryptionManager _encryption;
|
||||||
|
|
||||||
private Timer _dailyTimer;
|
|
||||||
|
|
||||||
// This is limited to 200 per day
|
|
||||||
private int _dailyDownloadCount;
|
|
||||||
|
|
||||||
// It's 200 but this will be in-exact so buffer a little
|
|
||||||
// And the user may restart the server
|
|
||||||
private const int MaxDownloadsPerDay = 150;
|
|
||||||
|
|
||||||
private readonly IJsonSerializer _json;
|
private readonly IJsonSerializer _json;
|
||||||
|
|
||||||
public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption, IJsonSerializer json)
|
public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption, IJsonSerializer json)
|
||||||
@ -51,9 +43,6 @@ namespace MediaBrowser.Providers.Subtitles
|
|||||||
|
|
||||||
_config.NamedConfigurationUpdating += _config_NamedConfigurationUpdating;
|
_config.NamedConfigurationUpdating += _config_NamedConfigurationUpdating;
|
||||||
|
|
||||||
// Reset the count every 24 hours
|
|
||||||
_dailyTimer = new Timer(state => _dailyDownloadCount = 0, null, TimeSpan.FromHours(24), TimeSpan.FromHours(24));
|
|
||||||
|
|
||||||
Utilities.HttpClient = httpClient;
|
Utilities.HttpClient = httpClient;
|
||||||
OpenSubtitles.SetUserAgent("mediabrowser.tv");
|
OpenSubtitles.SetUserAgent("mediabrowser.tv");
|
||||||
}
|
}
|
||||||
@ -123,6 +112,7 @@ namespace MediaBrowser.Providers.Subtitles
|
|||||||
return GetSubtitlesInternal(id, GetOptions(), cancellationToken);
|
return GetSubtitlesInternal(id, GetOptions(), cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DateTime _lastRateLimitException;
|
||||||
private async Task<SubtitleResponse> GetSubtitlesInternal(string id,
|
private async Task<SubtitleResponse> GetSubtitlesInternal(string id,
|
||||||
SubtitleOptions options,
|
SubtitleOptions options,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
@ -132,12 +122,6 @@ namespace MediaBrowser.Providers.Subtitles
|
|||||||
throw new ArgumentNullException("id");
|
throw new ArgumentNullException("id");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dailyDownloadCount >= MaxDownloadsPerDay &&
|
|
||||||
!options.IsOpenSubtitleVipAccount)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Open Subtitle's daily download limit has been exceeded. Please try again tomorrow.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var idParts = id.Split(new[] { '-' }, 3);
|
var idParts = id.Split(new[] { '-' }, 3);
|
||||||
|
|
||||||
var format = idParts[0];
|
var format = idParts[0];
|
||||||
@ -148,8 +132,19 @@ namespace MediaBrowser.Providers.Subtitles
|
|||||||
|
|
||||||
await Login(cancellationToken).ConfigureAwait(false);
|
await Login(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if ((DateTime.UtcNow - _lastRateLimitException).TotalHours < 1)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("OpenSubtitles rate limit reached");
|
||||||
|
}
|
||||||
|
|
||||||
var resultDownLoad = await OpenSubtitles.DownloadSubtitlesAsync(downloadsList, cancellationToken).ConfigureAwait(false);
|
var resultDownLoad = await OpenSubtitles.DownloadSubtitlesAsync(downloadsList, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if ((resultDownLoad.Status ?? string.Empty).IndexOf("407", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
|
{
|
||||||
|
_lastRateLimitException = DateTime.UtcNow;
|
||||||
|
throw new ApplicationException("OpenSubtitles rate limit reached");
|
||||||
|
}
|
||||||
|
|
||||||
if (!(resultDownLoad is MethodResponseSubtitleDownload))
|
if (!(resultDownLoad is MethodResponseSubtitleDownload))
|
||||||
{
|
{
|
||||||
throw new ApplicationException("Invalid response type");
|
throw new ApplicationException("Invalid response type");
|
||||||
@ -157,13 +152,15 @@ namespace MediaBrowser.Providers.Subtitles
|
|||||||
|
|
||||||
var results = ((MethodResponseSubtitleDownload)resultDownLoad).Results;
|
var results = ((MethodResponseSubtitleDownload)resultDownLoad).Results;
|
||||||
|
|
||||||
|
_lastRateLimitException = DateTime.MinValue;
|
||||||
|
|
||||||
if (results.Count == 0)
|
if (results.Count == 0)
|
||||||
{
|
{
|
||||||
var msg = string.Format("Subtitle with Id {0} was not found. Name: {1}. Status: {2}. Message: {3}",
|
var msg = string.Format("Subtitle with Id {0} was not found. Name: {1}. Status: {2}. Message: {3}",
|
||||||
ossId,
|
ossId,
|
||||||
resultDownLoad.Name ?? string.Empty,
|
resultDownLoad.Name ?? string.Empty,
|
||||||
resultDownLoad.Message ?? string.Empty,
|
resultDownLoad.Status ?? string.Empty,
|
||||||
resultDownLoad.Status ?? string.Empty);
|
resultDownLoad.Message ?? string.Empty);
|
||||||
|
|
||||||
throw new ResourceNotFoundException(msg);
|
throw new ResourceNotFoundException(msg);
|
||||||
}
|
}
|
||||||
@ -339,12 +336,6 @@ namespace MediaBrowser.Providers.Subtitles
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_config.NamedConfigurationUpdating -= _config_NamedConfigurationUpdating;
|
_config.NamedConfigurationUpdating -= _config_NamedConfigurationUpdating;
|
||||||
|
|
||||||
if (_dailyTimer != null)
|
|
||||||
{
|
|
||||||
_dailyTimer.Dispose();
|
|
||||||
_dailyTimer = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,8 @@ namespace MediaBrowser.Providers.TV
|
|||||||
if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) &&
|
if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) &&
|
||||||
(searchInfo.IndexNumber.HasValue || searchInfo.PremiereDate.HasValue))
|
(searchInfo.IndexNumber.HasValue || searchInfo.PremiereDate.HasValue))
|
||||||
{
|
{
|
||||||
|
await TvdbSeriesProvider.Current.EnsureSeriesInfo(searchInfo.SeriesProviderIds, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, searchInfo.SeriesProviderIds);
|
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, searchInfo.SeriesProviderIds);
|
||||||
|
|
||||||
var searchNumbers = new EpisodeNumbers();
|
var searchNumbers = new EpisodeNumbers();
|
||||||
|
@ -222,6 +222,11 @@ namespace MediaBrowser.Providers.TV
|
|||||||
seriesId = await GetSeriesByRemoteId(seriesId, idType, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
seriesId = await GetSeriesByRemoteId(seriesId, idType, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(seriesId))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("seriesId");
|
||||||
|
}
|
||||||
|
|
||||||
var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, preferredMetadataLanguage);
|
var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, preferredMetadataLanguage);
|
||||||
|
|
||||||
using (var zipStream = await _httpClient.Get(new HttpRequestOptions
|
using (var zipStream = await _httpClient.Get(new HttpRequestOptions
|
||||||
@ -324,38 +329,48 @@ namespace MediaBrowser.Providers.TV
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SemaphoreSlim _ensureSemaphore = new SemaphoreSlim(1,1);
|
||||||
internal async Task<string> EnsureSeriesInfo(Dictionary<string, string> seriesProviderIds, string preferredMetadataLanguage, CancellationToken cancellationToken)
|
internal async Task<string> EnsureSeriesInfo(Dictionary<string, string> seriesProviderIds, string preferredMetadataLanguage, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
string seriesId;
|
await _ensureSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId))
|
|
||||||
{
|
|
||||||
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
|
|
||||||
|
|
||||||
// Only download if not already there
|
try
|
||||||
// The post-scan task will take care of updates so we don't need to re-download here
|
{
|
||||||
if (!IsCacheValid(seriesDataPath, preferredMetadataLanguage))
|
string seriesId;
|
||||||
|
if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId))
|
||||||
{
|
{
|
||||||
await DownloadSeriesZip(seriesId, MetadataProviders.Tvdb.ToString(), seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
|
||||||
|
|
||||||
|
// Only download if not already there
|
||||||
|
// The post-scan task will take care of updates so we don't need to re-download here
|
||||||
|
if (!IsCacheValid(seriesDataPath, preferredMetadataLanguage))
|
||||||
|
{
|
||||||
|
await DownloadSeriesZip(seriesId, MetadataProviders.Tvdb.ToString(), seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return seriesDataPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return seriesDataPath;
|
if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId))
|
||||||
}
|
|
||||||
|
|
||||||
if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId))
|
|
||||||
{
|
|
||||||
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
|
|
||||||
|
|
||||||
// Only download if not already there
|
|
||||||
// The post-scan task will take care of updates so we don't need to re-download here
|
|
||||||
if (!IsCacheValid(seriesDataPath, preferredMetadataLanguage))
|
|
||||||
{
|
{
|
||||||
await DownloadSeriesZip(seriesId, MetadataProviders.Imdb.ToString(), seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
|
||||||
|
|
||||||
|
// Only download if not already there
|
||||||
|
// The post-scan task will take care of updates so we don't need to re-download here
|
||||||
|
if (!IsCacheValid(seriesDataPath, preferredMetadataLanguage))
|
||||||
|
{
|
||||||
|
await DownloadSeriesZip(seriesId, MetadataProviders.Imdb.ToString(), seriesDataPath, null, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return seriesDataPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return seriesDataPath;
|
return null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_ensureSemaphore.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsCacheValid(string seriesDataPath, string preferredMetadataLanguage)
|
private bool IsCacheValid(string seriesDataPath, string preferredMetadataLanguage)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" targetFramework="net45" />
|
||||||
<package id="MediaBrowser.BdInfo" version="1.0.0.10" 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="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
<package id="taglib" version="2.1.0.0" targetFramework="net45" />
|
<package id="taglib" version="2.1.0.0" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -310,7 +310,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AttachPrimaryImageAspectRatio(dto, item, fields);
|
AttachPrimaryImageAspectRatio(dto, item);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -1742,15 +1742,19 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dto">The dto.</param>
|
/// <param name="dto">The dto.</param>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <param name="fields">The fields.</param>
|
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public void AttachPrimaryImageAspectRatio(IItemDto dto, IHasImages item, List<ItemFields> fields)
|
public void AttachPrimaryImageAspectRatio(IItemDto dto, IHasImages item)
|
||||||
|
{
|
||||||
|
dto.PrimaryImageAspectRatio = GetPrimaryImageAspectRatio(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double? GetPrimaryImageAspectRatio(IHasImages item)
|
||||||
{
|
{
|
||||||
var imageInfo = item.GetImageInfo(ImageType.Primary, 0);
|
var imageInfo = item.GetImageInfo(ImageType.Primary, 0);
|
||||||
|
|
||||||
if (imageInfo == null || !imageInfo.IsLocalFile)
|
if (imageInfo == null || !imageInfo.IsLocalFile)
|
||||||
{
|
{
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageSize size;
|
ImageSize size;
|
||||||
@ -1762,7 +1766,7 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
//_logger.ErrorException("Failed to determine primary image aspect ratio for {0}", ex, path);
|
//_logger.ErrorException("Failed to determine primary image aspect ratio for {0}", ex, path);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary).ToList();
|
var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary).ToList();
|
||||||
@ -1781,8 +1785,9 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
|
|
||||||
if (size.Width > 0 && size.Height > 0)
|
if (size.Width > 0 && size.Height > 0)
|
||||||
{
|
{
|
||||||
dto.PrimaryImageAspectRatio = size.Width / size.Height;
|
return size.Width / size.Height;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,42 +74,52 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(seriesName))
|
if (!string.IsNullOrEmpty(seriesName))
|
||||||
{
|
{
|
||||||
var season = episodeInfo.SeasonNumber;
|
var seasonNumber = episodeInfo.SeasonNumber;
|
||||||
|
|
||||||
result.ExtractedSeasonNumber = season;
|
result.ExtractedSeasonNumber = seasonNumber;
|
||||||
|
|
||||||
if (season.HasValue)
|
// Passing in true will include a few extra regex's
|
||||||
{
|
var episodeNumber = episodeInfo.EpisodeNumber;
|
||||||
// Passing in true will include a few extra regex's
|
|
||||||
var episode = episodeInfo.EpisodeNumber;
|
|
||||||
|
|
||||||
result.ExtractedEpisodeNumber = episode;
|
result.ExtractedEpisodeNumber = episodeNumber;
|
||||||
|
|
||||||
if (episode.HasValue)
|
var premiereDate = episodeInfo.IsByDate ?
|
||||||
{
|
new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value) :
|
||||||
_logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, season, episode);
|
(DateTime?)null;
|
||||||
|
|
||||||
var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;
|
if (episodeInfo.IsByDate || (seasonNumber.HasValue && episodeNumber.HasValue))
|
||||||
|
{
|
||||||
|
if (episodeInfo.IsByDate)
|
||||||
|
{
|
||||||
|
_logger.Debug("Extracted information from {0}. Series name {1}, Date {2}", path, seriesName, premiereDate.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, seasonNumber, episodeNumber);
|
||||||
|
}
|
||||||
|
|
||||||
result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
|
var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;
|
||||||
|
|
||||||
await OrganizeEpisode(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, overwriteExisting, result, cancellationToken).ConfigureAwait(false);
|
result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
|
||||||
}
|
|
||||||
else
|
await OrganizeEpisode(path,
|
||||||
{
|
seriesName,
|
||||||
var msg = string.Format("Unable to determine episode number from {0}", path);
|
seasonNumber,
|
||||||
result.Status = FileSortingStatus.Failure;
|
episodeNumber,
|
||||||
result.StatusMessage = msg;
|
endingEpisodeNumber,
|
||||||
_logger.Warn(msg);
|
premiereDate,
|
||||||
}
|
options,
|
||||||
}
|
overwriteExisting,
|
||||||
else
|
result,
|
||||||
{
|
cancellationToken).ConfigureAwait(false);
|
||||||
var msg = string.Format("Unable to determine season number from {0}", path);
|
}
|
||||||
result.Status = FileSortingStatus.Failure;
|
else
|
||||||
result.StatusMessage = msg;
|
{
|
||||||
_logger.Warn(msg);
|
var msg = string.Format("Unable to determine episode number from {0}", path);
|
||||||
}
|
result.Status = FileSortingStatus.Failure;
|
||||||
|
result.StatusMessage = msg;
|
||||||
|
_logger.Warn(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -141,14 +151,32 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||||||
|
|
||||||
var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId));
|
var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId));
|
||||||
|
|
||||||
await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, options, true, result, cancellationToken).ConfigureAwait(false);
|
await OrganizeEpisode(result.OriginalPath,
|
||||||
|
series,
|
||||||
|
request.SeasonNumber,
|
||||||
|
request.EpisodeNumber,
|
||||||
|
request.EndingEpisodeNumber,
|
||||||
|
null,
|
||||||
|
options,
|
||||||
|
true,
|
||||||
|
result,
|
||||||
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
|
await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task OrganizeEpisode(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken)
|
private Task OrganizeEpisode(string sourcePath,
|
||||||
|
string seriesName,
|
||||||
|
int? seasonNumber,
|
||||||
|
int? episodeNumber,
|
||||||
|
int? endingEpiosdeNumber,
|
||||||
|
DateTime? premiereDate,
|
||||||
|
TvFileOrganizationOptions options,
|
||||||
|
bool overwriteExisting,
|
||||||
|
FileOrganizationResult result,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var series = GetMatchingSeries(seriesName, result);
|
var series = GetMatchingSeries(seriesName, result);
|
||||||
|
|
||||||
@ -161,15 +189,33 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OrganizeEpisode(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, overwriteExisting, result, cancellationToken);
|
return OrganizeEpisode(sourcePath,
|
||||||
|
series,
|
||||||
|
seasonNumber,
|
||||||
|
episodeNumber,
|
||||||
|
endingEpiosdeNumber,
|
||||||
|
premiereDate,
|
||||||
|
options,
|
||||||
|
overwriteExisting,
|
||||||
|
result,
|
||||||
|
cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OrganizeEpisode(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken)
|
private async Task OrganizeEpisode(string sourcePath,
|
||||||
|
Series series,
|
||||||
|
int? seasonNumber,
|
||||||
|
int? episodeNumber,
|
||||||
|
int? endingEpiosdeNumber,
|
||||||
|
DateTime? premiereDate,
|
||||||
|
TvFileOrganizationOptions options,
|
||||||
|
bool overwriteExisting,
|
||||||
|
FileOrganizationResult result,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path);
|
_logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path);
|
||||||
|
|
||||||
// Proceed to sort the file
|
// Proceed to sort the file
|
||||||
var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, cancellationToken).ConfigureAwait(false);
|
var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(newPath))
|
if (string.IsNullOrEmpty(newPath))
|
||||||
{
|
{
|
||||||
@ -278,8 +324,18 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<string> GetOtherDuplicatePaths(string targetPath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber)
|
private List<string> GetOtherDuplicatePaths(string targetPath,
|
||||||
|
Series series,
|
||||||
|
int? seasonNumber,
|
||||||
|
int? episodeNumber,
|
||||||
|
int? endingEpisodeNumber)
|
||||||
{
|
{
|
||||||
|
// TODO: Support date-naming?
|
||||||
|
if (!seasonNumber.HasValue || episodeNumber.HasValue)
|
||||||
|
{
|
||||||
|
return new List<string> ();
|
||||||
|
}
|
||||||
|
|
||||||
var episodePaths = series.GetRecursiveChildren()
|
var episodePaths = series.GetRecursiveChildren()
|
||||||
.OfType<Episode>()
|
.OfType<Episode>()
|
||||||
.Where(i =>
|
.Where(i =>
|
||||||
@ -408,7 +464,14 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||||||
/// <param name="endingEpisodeNumber">The ending episode number.</param>
|
/// <param name="endingEpisodeNumber">The ending episode number.</param>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
private async Task<string> GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options, CancellationToken cancellationToken)
|
private async Task<string> GetNewPath(string sourcePath,
|
||||||
|
Series series,
|
||||||
|
int? seasonNumber,
|
||||||
|
int? episodeNumber,
|
||||||
|
int? endingEpisodeNumber,
|
||||||
|
DateTime? premiereDate,
|
||||||
|
TvFileOrganizationOptions options,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var episodeInfo = new EpisodeInfo
|
var episodeInfo = new EpisodeInfo
|
||||||
{
|
{
|
||||||
@ -417,7 +480,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||||||
MetadataCountryCode = series.GetPreferredMetadataCountryCode(),
|
MetadataCountryCode = series.GetPreferredMetadataCountryCode(),
|
||||||
MetadataLanguage = series.GetPreferredMetadataLanguage(),
|
MetadataLanguage = series.GetPreferredMetadataLanguage(),
|
||||||
ParentIndexNumber = seasonNumber,
|
ParentIndexNumber = seasonNumber,
|
||||||
SeriesProviderIds = series.ProviderIds
|
SeriesProviderIds = series.ProviderIds,
|
||||||
|
PremiereDate = premiereDate
|
||||||
};
|
};
|
||||||
|
|
||||||
var searchResults = await _providerManager.GetRemoteSearchResults<Episode, EpisodeInfo>(new RemoteSearchQuery<EpisodeInfo>
|
var searchResults = await _providerManager.GetRemoteSearchResults<Episode, EpisodeInfo>(new RemoteSearchQuery<EpisodeInfo>
|
||||||
@ -427,14 +491,24 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||||||
}, cancellationToken).ConfigureAwait(false);
|
}, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var episode = searchResults.FirstOrDefault();
|
var episode = searchResults.FirstOrDefault();
|
||||||
|
|
||||||
|
string episodeName = string.Empty;
|
||||||
|
|
||||||
if (episode == null)
|
if (episode == null)
|
||||||
{
|
{
|
||||||
_logger.Warn("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber);
|
var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber);
|
||||||
return null;
|
_logger.Warn(msg);
|
||||||
|
//throw new Exception(msg);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
episodeName = episode.Name;
|
||||||
|
}
|
||||||
|
|
||||||
var newPath = GetSeasonFolderPath(series, seasonNumber, options);
|
seasonNumber = seasonNumber ?? episode.ParentIndexNumber;
|
||||||
|
episodeNumber = episodeNumber ?? episode.IndexNumber;
|
||||||
|
|
||||||
|
var newPath = GetSeasonFolderPath(series, seasonNumber.Value, options);
|
||||||
|
|
||||||
// MAX_PATH - trailing <NULL> charachter - drive component: 260 - 1 - 3 = 256
|
// MAX_PATH - trailing <NULL> charachter - drive component: 260 - 1 - 3 = 256
|
||||||
// Usually newPath would include the drive component, but use 256 to be sure
|
// Usually newPath would include the drive component, but use 256 to be sure
|
||||||
@ -449,7 +523,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||||||
// Remove additional 4 chars to prevent PathTooLongException for downloaded subtitles (eg. filename.ext.eng.srt)
|
// Remove additional 4 chars to prevent PathTooLongException for downloaded subtitles (eg. filename.ext.eng.srt)
|
||||||
maxFilenameLength -= 4;
|
maxFilenameLength -= 4;
|
||||||
|
|
||||||
var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options, maxFilenameLength);
|
var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber.Value, episodeNumber.Value, endingEpisodeNumber, episodeName, options, maxFilenameLength);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(episodeFileName))
|
if (string.IsNullOrEmpty(episodeFileName))
|
||||||
{
|
{
|
||||||
@ -505,7 +579,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||||||
{
|
{
|
||||||
seriesName = _fileSystem.GetValidFilename(seriesName).Trim();
|
seriesName = _fileSystem.GetValidFilename(seriesName).Trim();
|
||||||
|
|
||||||
if (episodeTitle == null)
|
if (string.IsNullOrEmpty(episodeTitle))
|
||||||
{
|
{
|
||||||
episodeTitle = string.Empty;
|
episodeTitle = string.Empty;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Common.Security;
|
using MediaBrowser.Common.Security;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.HttpServer
|
namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
@ -39,40 +40,20 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
|||||||
public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
|
public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
|
||||||
public event EventHandler<WebSocketConnectingEventArgs> WebSocketConnecting;
|
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; }
|
public string CertificatePath { get; private set; }
|
||||||
|
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
private readonly INetworkManager _networkManager;
|
||||||
/// <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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpListenerHost(IApplicationHost applicationHost,
|
public HttpListenerHost(IApplicationHost applicationHost,
|
||||||
ILogManager logManager,
|
ILogManager logManager,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
string serviceName,
|
string serviceName,
|
||||||
string defaultRedirectPath, params Assembly[] assembliesWithServices)
|
string defaultRedirectPath, INetworkManager networkManager, params Assembly[] assembliesWithServices)
|
||||||
: base(serviceName, assembliesWithServices)
|
: base(serviceName, assembliesWithServices)
|
||||||
{
|
{
|
||||||
DefaultRedirectPath = defaultRedirectPath;
|
DefaultRedirectPath = defaultRedirectPath;
|
||||||
|
_networkManager = networkManager;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
_logger = logManager.GetLogger("HttpServer");
|
_logger = logManager.GetLogger("HttpServer");
|
||||||
@ -175,26 +156,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
|||||||
|
|
||||||
private void OnRequestReceived(string localEndPoint)
|
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>
|
/// <summary>
|
||||||
|
@ -58,7 +58,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
|||||||
|
|
||||||
if (hasOptions != null)
|
if (hasOptions != null)
|
||||||
{
|
{
|
||||||
hasOptions.Options["Server"] = "Mono-HTTPAPI/1.1";
|
if (!hasOptions.Options.ContainsKey("Server"))
|
||||||
|
{
|
||||||
|
hasOptions.Options["Server"] = "Mono-HTTPAPI/1.1, UPnP/1.0 DLNADOC/1.50";
|
||||||
|
}
|
||||||
|
|
||||||
// Content length has to be explicitly set on on HttpListenerResponse or it won't be happy
|
// Content length has to be explicitly set on on HttpListenerResponse or it won't be happy
|
||||||
string contentLength;
|
string contentLength;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
@ -17,18 +18,20 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
|||||||
/// <param name="applicationHost">The application host.</param>
|
/// <param name="applicationHost">The application host.</param>
|
||||||
/// <param name="logManager">The log manager.</param>
|
/// <param name="logManager">The log manager.</param>
|
||||||
/// <param name="config">The configuration.</param>
|
/// <param name="config">The configuration.</param>
|
||||||
|
/// <param name="_networkmanager">The _networkmanager.</param>
|
||||||
/// <param name="serverName">Name of the server.</param>
|
/// <param name="serverName">Name of the server.</param>
|
||||||
/// <param name="defaultRedirectpath">The default redirectpath.</param>
|
/// <param name="defaultRedirectpath">The default redirectpath.</param>
|
||||||
/// <returns>IHttpServer.</returns>
|
/// <returns>IHttpServer.</returns>
|
||||||
public static IHttpServer CreateServer(IApplicationHost applicationHost,
|
public static IHttpServer CreateServer(IApplicationHost applicationHost,
|
||||||
ILogManager logManager,
|
ILogManager logManager,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
|
INetworkManager _networkmanager,
|
||||||
string serverName,
|
string serverName,
|
||||||
string defaultRedirectpath)
|
string defaultRedirectpath)
|
||||||
{
|
{
|
||||||
LogManager.LogFactory = new ServerLogFactory(logManager);
|
LogManager.LogFactory = new ServerLogFactory(logManager);
|
||||||
|
|
||||||
return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath);
|
return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Web;
|
||||||
using Funq;
|
using Funq;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
@ -236,7 +237,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
|
|||||||
private NameValueCollectionWrapper queryString;
|
private NameValueCollectionWrapper queryString;
|
||||||
public INameValueCollection 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;
|
private NameValueCollectionWrapper formData;
|
||||||
|
@ -403,10 +403,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_dtoServiceFactory().AttachPrimaryImageAspectRatio(dto, user, new List<ItemFields>
|
_dtoServiceFactory().AttachPrimaryImageAspectRatio(dto, user);
|
||||||
{
|
|
||||||
ItemFields.PrimaryImageAspectRatio
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -114,7 +114,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
var requestString = _jsonSerializer.SerializeToString(requestList);
|
var requestString = _jsonSerializer.SerializeToString(requestList);
|
||||||
_logger.Debug("Request string for schedules is: " + requestString);
|
_logger.Debug("Request string for schedules is: " + requestString);
|
||||||
httpOptions.RequestContent = requestString;
|
httpOptions.RequestContent = requestString;
|
||||||
using (var response = await Post(httpOptions).ConfigureAwait(false))
|
using (var response = await Post(httpOptions, true, info).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
StreamReader reader = new StreamReader(response.Content);
|
StreamReader reader = new StreamReader(response.Content);
|
||||||
string responseString = reader.ReadToEnd();
|
string responseString = reader.ReadToEnd();
|
||||||
@ -138,7 +138,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
var requestBody = "[\"" + string.Join("\", \"", programsID) + "\"]";
|
var requestBody = "[\"" + string.Join("\", \"", programsID) + "\"]";
|
||||||
httpOptions.RequestContent = requestBody;
|
httpOptions.RequestContent = requestBody;
|
||||||
|
|
||||||
using (var innerResponse = await Post(httpOptions).ConfigureAwait(false))
|
using (var innerResponse = await Post(httpOptions, true, info).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
StreamReader innerReader = new StreamReader(innerResponse.Content);
|
StreamReader innerReader = new StreamReader(innerResponse.Content);
|
||||||
responseString = innerReader.ReadToEnd();
|
responseString = innerReader.ReadToEnd();
|
||||||
@ -148,7 +148,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
responseString);
|
responseString);
|
||||||
var programDict = programDetails.ToDictionary(p => p.programID, y => y);
|
var programDict = programDetails.ToDictionary(p => p.programID, y => y);
|
||||||
|
|
||||||
var images = await GetImageForPrograms(programDetails.Where(p => p.hasImageArtwork).Select(p => p.programID).ToList(), cancellationToken);
|
var images = await GetImageForPrograms(info, programDetails.Where(p => p.hasImageArtwork).Select(p => p.programID).ToList(), cancellationToken);
|
||||||
|
|
||||||
var schedules = dailySchedules.SelectMany(d => d.programs);
|
var schedules = dailySchedules.SelectMany(d => d.programs);
|
||||||
foreach (ScheduleDirect.Program schedule in schedules)
|
foreach (ScheduleDirect.Program schedule in schedules)
|
||||||
@ -229,7 +229,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
httpOptions.RequestHeaders["token"] = token;
|
httpOptions.RequestHeaders["token"] = token;
|
||||||
|
|
||||||
using (var response = await Get(httpOptions).ConfigureAwait(false))
|
using (var response = await Get(httpOptions, true, info).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
|
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
|
||||||
_logger.Info("Found " + root.map.Count() + " channels on the lineup on ScheduleDirect");
|
_logger.Info("Found " + root.map.Count() + " channels on the lineup on ScheduleDirect");
|
||||||
@ -447,7 +447,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<ScheduleDirect.ShowImages>> GetImageForPrograms(List<string> programIds,
|
private async Task<List<ScheduleDirect.ShowImages>> GetImageForPrograms(
|
||||||
|
ListingsProviderInfo info,
|
||||||
|
List<string> programIds,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var imageIdString = "[";
|
var imageIdString = "[";
|
||||||
@ -472,7 +474,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
TimeoutMs = 60000
|
TimeoutMs = 60000
|
||||||
};
|
};
|
||||||
List<ScheduleDirect.ShowImages> images;
|
List<ScheduleDirect.ShowImages> images;
|
||||||
using (var innerResponse2 = await Post(httpOptions).ConfigureAwait(false))
|
using (var innerResponse2 = await Post(httpOptions, true, info).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
images = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.ShowImages>>(
|
images = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.ShowImages>>(
|
||||||
innerResponse2.Content);
|
innerResponse2.Content);
|
||||||
@ -504,7 +506,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (Stream responce = await Get(options).ConfigureAwait(false))
|
using (Stream responce = await Get(options, false, info).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
var root = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.Headends>>(responce);
|
var root = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.Headends>>(responce);
|
||||||
|
|
||||||
@ -606,30 +608,58 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<HttpResponseInfo> Post(HttpRequestOptions options)
|
private async Task<HttpResponseInfo> Post(HttpRequestOptions options,
|
||||||
|
bool enableRetry,
|
||||||
|
ListingsProviderInfo providerInfo)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await _httpClient.Post(options).ConfigureAwait(false);
|
return await _httpClient.Post(options).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
_tokens.Clear();
|
_tokens.Clear();
|
||||||
throw;
|
|
||||||
}
|
if (!ex.StatusCode.HasValue || (int)ex.StatusCode.Value >= 500)
|
||||||
|
{
|
||||||
|
enableRetry = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enableRetry) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var newToken = await GetToken (providerInfo, options.CancellationToken).ConfigureAwait (false);
|
||||||
|
options.RequestHeaders ["token"] = newToken;
|
||||||
|
return await Post (options, false, providerInfo).ConfigureAwait (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Stream> Get(HttpRequestOptions options)
|
private async Task<Stream> Get(HttpRequestOptions options,
|
||||||
|
bool enableRetry,
|
||||||
|
ListingsProviderInfo providerInfo)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await _httpClient.Get(options).ConfigureAwait(false);
|
return await _httpClient.Get(options).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
_tokens.Clear();
|
_tokens.Clear();
|
||||||
throw;
|
|
||||||
}
|
if (!ex.StatusCode.HasValue || (int)ex.StatusCode.Value >= 500)
|
||||||
|
{
|
||||||
|
enableRetry = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enableRetry) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var newToken = await GetToken (providerInfo, options.CancellationToken).ConfigureAwait (false);
|
||||||
|
options.RequestHeaders ["token"] = newToken;
|
||||||
|
return await Get (options, false, providerInfo).ConfigureAwait (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> GetTokenInternal(string username, string password,
|
private async Task<string> GetTokenInternal(string username, string password,
|
||||||
@ -646,7 +676,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
//_logger.Info("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " +
|
//_logger.Info("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " +
|
||||||
// httpOptions.RequestContent);
|
// httpOptions.RequestContent);
|
||||||
|
|
||||||
using (var responce = await Post(httpOptions).ConfigureAwait(false))
|
using (var responce = await Post(httpOptions, false, null).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Token>(responce.Content);
|
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Token>(responce.Content);
|
||||||
if (root.message == "OK")
|
if (root.message == "OK")
|
||||||
@ -728,7 +758,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var response = await Get(options).ConfigureAwait(false))
|
using (var response = await Get(options, false, null).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Lineups>(response);
|
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Lineups>(response);
|
||||||
|
|
||||||
|
@ -231,10 +231,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
dto.ImageTags[ImageType.Primary] = imageTag;
|
dto.ImageTags[ImageType.Primary] = imageTag;
|
||||||
|
|
||||||
_dtoService.AttachPrimaryImageAspectRatio(dto, info, new List<ItemFields>
|
_dtoService.AttachPrimaryImageAspectRatio(dto, info);
|
||||||
{
|
|
||||||
ItemFields.PrimaryImageAspectRatio
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentProgram != null)
|
if (currentProgram != null)
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
using MediaBrowser.Model.Serialization;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||||
|
{
|
||||||
|
public class SatIp : BaseTunerHost
|
||||||
|
{
|
||||||
|
public SatIp(IConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder)
|
||||||
|
: base(config, logger, jsonSerializer, mediaEncoder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Type
|
||||||
|
{
|
||||||
|
get { return "SatIp"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task<MediaSourceInfo> GetChannelStream(TunerHostInfo tuner, string channelId, string streamId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsValidChannelId(string channelId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -71,7 +71,7 @@
|
|||||||
"ViewTypeTvShowSeries": "S\u00e8ries:",
|
"ViewTypeTvShowSeries": "S\u00e8ries:",
|
||||||
"ViewTypeTvGenres": "G\u00e8neres",
|
"ViewTypeTvGenres": "G\u00e8neres",
|
||||||
"ViewTypeTvFavoriteSeries": "S\u00e8ries Preferides",
|
"ViewTypeTvFavoriteSeries": "S\u00e8ries Preferides",
|
||||||
"ViewTypeTvFavoriteEpisodes": "Episodis preferits",
|
"ViewTypeTvFavoriteEpisodes": "Episodis Preferits",
|
||||||
"ViewTypeMovieResume": "Resume",
|
"ViewTypeMovieResume": "Resume",
|
||||||
"ViewTypeMovieLatest": "Darrers",
|
"ViewTypeMovieLatest": "Darrers",
|
||||||
"ViewTypeMovieMovies": "Pel\u00b7l\u00edcules",
|
"ViewTypeMovieMovies": "Pel\u00b7l\u00edcules",
|
||||||
@ -173,5 +173,5 @@
|
|||||||
"HeaderWriter": "Escriptors",
|
"HeaderWriter": "Escriptors",
|
||||||
"HeaderParentalRatings": "Parental Ratings",
|
"HeaderParentalRatings": "Parental Ratings",
|
||||||
"HeaderCommunityRatings": "Qualificacions de la comunitat",
|
"HeaderCommunityRatings": "Qualificacions de la comunitat",
|
||||||
"StartupEmbyServerIsLoading": "El servidor d'Emby s'est\u00e0 carregant. Si us plau, torneu-ho a provar de nou en breu."
|
"StartupEmbyServerIsLoading": "El servidor d'Emby s'està carregant. Si et plau, tornau-ho a provar de nou en breu."
|
||||||
}
|
}
|
@ -43,7 +43,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Interfaces.IO">
|
<Reference Include="Interfaces.IO">
|
||||||
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
|
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
|
||||||
@ -52,15 +52,18 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.41\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
|
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.41\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="MoreLinq">
|
||||||
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ServiceStack.Api.Swagger">
|
<Reference Include="ServiceStack.Api.Swagger">
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
|
||||||
</Reference>
|
</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>
|
<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>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
@ -70,6 +73,7 @@
|
|||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Net" />
|
<Reference Include="System.Net" />
|
||||||
|
<Reference Include="System.Runtime.Serialization" />
|
||||||
<Reference Include="System.Security" />
|
<Reference Include="System.Security" />
|
||||||
<Reference Include="System.Web" />
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
@ -94,9 +98,6 @@
|
|||||||
<Reference Include="Mono.Nat">
|
<Reference Include="Mono.Nat">
|
||||||
<HintPath>..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll</HintPath>
|
<HintPath>..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="MoreLinq">
|
|
||||||
<HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\SharedVersion.cs">
|
<Compile Include="..\SharedVersion.cs">
|
||||||
@ -160,6 +161,7 @@
|
|||||||
<Compile Include="HttpServer\ServerLogFactory.cs" />
|
<Compile Include="HttpServer\ServerLogFactory.cs" />
|
||||||
<Compile Include="HttpServer\ServerLogger.cs" />
|
<Compile Include="HttpServer\ServerLogger.cs" />
|
||||||
<Compile Include="HttpServer\Security\SessionContext.cs" />
|
<Compile Include="HttpServer\Security\SessionContext.cs" />
|
||||||
|
<Compile Include="HttpServer\SocketSharp\HttpUtility.cs" />
|
||||||
<Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" />
|
<Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" />
|
||||||
<Compile Include="HttpServer\StreamWriter.cs" />
|
<Compile Include="HttpServer\StreamWriter.cs" />
|
||||||
<Compile Include="HttpServer\SwaggerService.cs" />
|
<Compile Include="HttpServer\SwaggerService.cs" />
|
||||||
@ -216,9 +218,6 @@
|
|||||||
<Compile Include="LiveTv\EmbyTV\RecordingHelper.cs" />
|
<Compile Include="LiveTv\EmbyTV\RecordingHelper.cs" />
|
||||||
<Compile Include="LiveTv\EmbyTV\SeriesTimerManager.cs" />
|
<Compile Include="LiveTv\EmbyTV\SeriesTimerManager.cs" />
|
||||||
<Compile Include="LiveTv\EmbyTV\TimerManager.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\SchedulesDirect.cs" />
|
||||||
<Compile Include="LiveTv\Listings\XmlTv.cs" />
|
<Compile Include="LiveTv\Listings\XmlTv.cs" />
|
||||||
<Compile Include="LiveTv\LiveTvConfigurationFactory.cs" />
|
<Compile Include="LiveTv\LiveTvConfigurationFactory.cs" />
|
||||||
|
@ -72,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _installationManager.InstallPackage(i, new Progress<double>(), cancellationToken).ConfigureAwait(false);
|
await _installationManager.InstallPackage(i, true, new Progress<double>(), cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" targetFramework="net45" />
|
||||||
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
|
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
|
||||||
<package id="MediaBrowser.Naming" version="1.0.0.41" 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="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="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>
|
</packages>
|
@ -54,7 +54,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Mono.Posix, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
<Reference Include="Mono.Posix, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
@ -82,7 +82,7 @@ namespace MediaBrowser.Server.Mono
|
|||||||
|
|
||||||
var nativeApp = new NativeApp(options);
|
var nativeApp = new NativeApp(options);
|
||||||
|
|
||||||
_appHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "MBServer.Mono", nativeApp);
|
_appHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "emby.mono.zip", nativeApp);
|
||||||
|
|
||||||
if (options.ContainsOption("-v"))
|
if (options.ContainsOption("-v"))
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.7" targetFramework="net45" />
|
||||||
<package id="Mono.Posix" version="4.0.0.0" targetFramework="net45" />
|
<package id="Mono.Posix" version="4.0.0.0" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -91,14 +91,17 @@ using MediaBrowser.Server.Startup.Common.Migrations;
|
|||||||
using MediaBrowser.WebDashboard.Api;
|
using MediaBrowser.WebDashboard.Api;
|
||||||
using MediaBrowser.XbmcMetadata.Providers;
|
using MediaBrowser.XbmcMetadata.Providers;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Common.Implementations.Updates;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Startup.Common
|
namespace MediaBrowser.Server.Startup.Common
|
||||||
{
|
{
|
||||||
@ -204,9 +207,10 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
private IPlaylistManager PlaylistManager { get; set; }
|
private IPlaylistManager PlaylistManager { get; set; }
|
||||||
|
|
||||||
private readonly StartupOptions _startupOptions;
|
private readonly StartupOptions _startupOptions;
|
||||||
private readonly string _remotePackageName;
|
private readonly string _releaseAssetFilename;
|
||||||
|
|
||||||
internal INativeApp NativeApp { get; set; }
|
internal INativeApp NativeApp { get; set; }
|
||||||
|
private Timer _ipAddressCacheTimer;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ApplicationHost" /> class.
|
/// Initializes a new instance of the <see cref="ApplicationHost" /> class.
|
||||||
@ -215,21 +219,23 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
/// <param name="logManager">The log manager.</param>
|
/// <param name="logManager">The log manager.</param>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <param name="fileSystem">The file system.</param>
|
/// <param name="fileSystem">The file system.</param>
|
||||||
/// <param name="remotePackageName">Name of the remote package.</param>
|
/// <param name="releaseAssetFilename">The release asset filename.</param>
|
||||||
/// <param name="nativeApp">The native application.</param>
|
/// <param name="nativeApp">The native application.</param>
|
||||||
public ApplicationHost(ServerApplicationPaths applicationPaths,
|
public ApplicationHost(ServerApplicationPaths applicationPaths,
|
||||||
ILogManager logManager,
|
ILogManager logManager,
|
||||||
StartupOptions options,
|
StartupOptions options,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
string remotePackageName,
|
string releaseAssetFilename,
|
||||||
INativeApp nativeApp)
|
INativeApp nativeApp)
|
||||||
: base(applicationPaths, logManager, fileSystem)
|
: base(applicationPaths, logManager, fileSystem)
|
||||||
{
|
{
|
||||||
_startupOptions = options;
|
_startupOptions = options;
|
||||||
_remotePackageName = remotePackageName;
|
_releaseAssetFilename = releaseAssetFilename;
|
||||||
NativeApp = nativeApp;
|
NativeApp = nativeApp;
|
||||||
|
|
||||||
SetBaseExceptionMessage();
|
SetBaseExceptionMessage();
|
||||||
|
|
||||||
|
_ipAddressCacheTimer = new Timer(OnCacheClearTimerFired, null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Version _version;
|
private Version _version;
|
||||||
@ -316,6 +322,7 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
{
|
{
|
||||||
await base.RunStartupTasks().ConfigureAwait(false);
|
await base.RunStartupTasks().ConfigureAwait(false);
|
||||||
|
|
||||||
|
Logger.Info("ServerId: {0}", SystemId);
|
||||||
Logger.Info("Core startup complete");
|
Logger.Info("Core startup complete");
|
||||||
HttpServer.GlobalResponse = null;
|
HttpServer.GlobalResponse = null;
|
||||||
|
|
||||||
@ -436,7 +443,7 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
|
|
||||||
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
|
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");
|
HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
|
||||||
RegisterSingleInstance(HttpServer, false);
|
RegisterSingleInstance(HttpServer, false);
|
||||||
progress.Report(10);
|
progress.Report(10);
|
||||||
@ -515,7 +522,7 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager);
|
SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager);
|
||||||
RegisterSingleInstance(SubtitleManager);
|
RegisterSingleInstance(SubtitleManager);
|
||||||
|
|
||||||
RegisterSingleInstance<IDeviceDiscovery>(new DeviceDiscovery(LogManager.GetLogger("IDeviceDiscovery"), ServerConfigurationManager, this));
|
RegisterSingleInstance<IDeviceDiscovery>(new DeviceDiscovery(LogManager.GetLogger("IDeviceDiscovery"), ServerConfigurationManager, this, NetworkManager));
|
||||||
|
|
||||||
ChapterManager = new ChapterManager(LibraryManager, LogManager.GetLogger("ChapterManager"), ServerConfigurationManager, ItemRepository);
|
ChapterManager = new ChapterManager(LibraryManager, LogManager.GetLogger("ChapterManager"), ServerConfigurationManager, ItemRepository);
|
||||||
RegisterSingleInstance(ChapterManager);
|
RegisterSingleInstance(ChapterManager);
|
||||||
@ -963,6 +970,10 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (!ServerConfigurationManager.Configuration.EnableAutoUpdate)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
@ -1108,14 +1119,14 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Return the first matched address, if found, or the first known local address
|
// 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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -1133,40 +1144,71 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
HttpPort.ToString(CultureInfo.InvariantCulture));
|
HttpPort.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string LocalIpAddress
|
public List<IPAddress> LocalIpAddresses
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return HttpServerIpAddresses.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<string> HttpServerIpAddresses
|
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var localAddresses = NetworkManager.GetLocalIpAddresses()
|
var localAddresses = NetworkManager.GetLocalIpAddresses()
|
||||||
|
.Where(IsIpAddressValid)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var httpServerAddresses = HttpServer.LocalEndPoints
|
return localAddresses;
|
||||||
.Select(i => i.Split(':').FirstOrDefault())
|
|
||||||
.Where(i => !string.IsNullOrEmpty(i))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
if (matchedAddresses.Count == 0)
|
|
||||||
{
|
|
||||||
return localAddresses;
|
|
||||||
}
|
|
||||||
|
|
||||||
return matchedAddresses;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private bool IsIpAddressValid(IPAddress address)
|
||||||
|
{
|
||||||
|
if (IPAddress.IsLoopback(address))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiUrl = GetLocalApiUrl(address.ToString());
|
||||||
|
apiUrl += "/system/ping";
|
||||||
|
|
||||||
|
bool cachedResult;
|
||||||
|
if (_validAddressResults.TryGetValue(apiUrl, out cachedResult))
|
||||||
|
{
|
||||||
|
return cachedResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var response = HttpClient.SendAsync(new HttpRequestOptions
|
||||||
|
{
|
||||||
|
Url = apiUrl,
|
||||||
|
LogErrorResponseBody = false,
|
||||||
|
LogErrors = false,
|
||||||
|
LogRequest = false
|
||||||
|
|
||||||
|
}, "POST").Result)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
_validAddressResults.AddOrUpdate(apiUrl, false, (k, v) => false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCacheClearTimerFired(object state)
|
||||||
|
{
|
||||||
|
_validAddressResults.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public string FriendlyName
|
public string FriendlyName
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -1263,25 +1305,23 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
/// <returns>Task{CheckForUpdateResult}.</returns>
|
/// <returns>Task{CheckForUpdateResult}.</returns>
|
||||||
public override async Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress)
|
public override async Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
{
|
{
|
||||||
var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
|
var cacheLength = TimeSpan.FromHours(3);
|
||||||
|
var updateLevel = ConfigurationManager.CommonConfiguration.SystemUpdateLevel;
|
||||||
|
|
||||||
var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, _remotePackageName, null, ApplicationVersion, ConfigurationManager.CommonConfiguration.SystemUpdateLevel);
|
if (updateLevel == PackageVersionClass.Beta)
|
||||||
|
{
|
||||||
|
cacheLength = TimeSpan.FromHours(1);
|
||||||
|
}
|
||||||
|
else if (updateLevel == PackageVersionClass.Dev)
|
||||||
|
{
|
||||||
|
cacheLength = TimeSpan.FromMinutes(5);
|
||||||
|
}
|
||||||
|
|
||||||
var versionObject = version == null || string.IsNullOrWhiteSpace(version.versionStr) ? null : new Version(version.versionStr);
|
var result = await new GithubUpdater(HttpClient, JsonSerializer, cacheLength).CheckForUpdateResult("MediaBrowser", "Emby", ApplicationVersion, updateLevel, _releaseAssetFilename,
|
||||||
|
"MBServer", "Mbserver.zip", cancellationToken).ConfigureAwait(false);
|
||||||
var isUpdateAvailable = versionObject != null && versionObject > ApplicationVersion;
|
|
||||||
|
|
||||||
var result = versionObject != null ?
|
|
||||||
new CheckForUpdateResult { AvailableVersion = versionObject.ToString(), IsUpdateAvailable = isUpdateAvailable, Package = version } :
|
|
||||||
new CheckForUpdateResult { AvailableVersion = ApplicationVersion.ToString(), IsUpdateAvailable = false };
|
|
||||||
|
|
||||||
HasUpdateAvailable = result.IsUpdateAvailable;
|
HasUpdateAvailable = result.IsUpdateAvailable;
|
||||||
|
|
||||||
if (result.IsUpdateAvailable)
|
|
||||||
{
|
|
||||||
Logger.Info("New application version is available: {0}", result.AvailableVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1294,7 +1334,7 @@ namespace MediaBrowser.Server.Startup.Common
|
|||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public override async Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress<double> progress)
|
public override async Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
{
|
{
|
||||||
await InstallationManager.InstallPackage(package, progress, cancellationToken).ConfigureAwait(false);
|
await InstallationManager.InstallPackage(package, false, progress, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
HasUpdateAvailable = false;
|
HasUpdateAvailable = false;
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Mono.Posix, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
<Reference Include="Mono.Posix, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user