diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj
index e9911a12d9..6cda8b5d05 100644
--- a/Emby.Drawing/Emby.Drawing.csproj
+++ b/Emby.Drawing/Emby.Drawing.csproj
@@ -37,7 +37,7 @@
False
- ..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll
+ ..\packages\ImageMagickSharp.1.0.0.17\lib\net45\ImageMagickSharp.dll
..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll
diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
index 64ddf7e884..12a98edffa 100644
--- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
+++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
@@ -72,11 +72,16 @@ namespace Emby.Drawing.ImageMagick
private void LogVersion()
{
- _logger.Info("ImageMagick version: " + Wand.VersionString);
+ _logger.Info("ImageMagick version: " + GetVersion());
TestWebp();
Wand.SetMagickThreadCount(1);
}
+ public static string GetVersion()
+ {
+ return Wand.VersionString;
+ }
+
private bool _webpAvailable = true;
private void TestWebp()
{
@@ -148,7 +153,7 @@ namespace Emby.Drawing.ImageMagick
DrawIndicator(originalImage, width, height, options);
originalImage.CurrentImage.CompressionQuality = quality;
- //originalImage.CurrentImage.StripImage();
+ originalImage.CurrentImage.StripImage();
originalImage.SaveImage(outputPath);
}
@@ -165,7 +170,7 @@ namespace Emby.Drawing.ImageMagick
DrawIndicator(wand, width, height, options);
wand.CurrentImage.CompressionQuality = quality;
- //wand.CurrentImage.StripImage();
+ wand.CurrentImage.StripImage();
wand.SaveImage(outputPath);
}
@@ -176,15 +181,14 @@ namespace Emby.Drawing.ImageMagick
private void ScaleImage(MagickWand wand, int width, int height)
{
- wand.CurrentImage.ResizeImage(width, height);
- //if (_config.Configuration.EnableHighQualityImageScaling)
- //{
- // wand.CurrentImage.ResizeImage(width, height);
- //}
- //else
- //{
- // wand.CurrentImage.ScaleImage(width, height);
- //}
+ if (_config.Configuration.EnableHighQualityImageScaling)
+ {
+ wand.CurrentImage.ResizeImage(width, height);
+ }
+ else
+ {
+ wand.CurrentImage.ScaleImage(width, height);
+ }
}
///
diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config
index 0fcdc278e3..3b8dbcab7c 100644
--- a/Emby.Drawing/packages.config
+++ b/Emby.Drawing/packages.config
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index 7a14ace777..ecab943491 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -198,50 +198,6 @@ namespace MediaBrowser.Api
return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
}
- protected IList GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func filter)
- {
- if (!string.IsNullOrEmpty(parentId))
- {
- var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
-
- if (!string.IsNullOrWhiteSpace(userId))
- {
- var user = userManager.GetUserById(userId);
-
- if (user == null)
- {
- throw new ArgumentException("User not found");
- }
-
- return folder
- .GetRecursiveChildren(user, filter)
- .ToList();
- }
-
- return folder
- .GetRecursiveChildren(filter);
- }
- if (!string.IsNullOrWhiteSpace(userId))
- {
- var user = userManager.GetUserById(userId);
-
- if (user == null)
- {
- throw new ArgumentException("User not found");
- }
-
- return userManager
- .GetUserById(userId)
- .RootFolder
- .GetRecursiveChildren(user, filter)
- .ToList();
- }
-
- return libraryManager
- .RootFolder
- .GetRecursiveChildren(filter);
- }
-
///
/// Deslugs an artist name by finding the correct entry in the library
///
diff --git a/MediaBrowser.Api/GamesService.cs b/MediaBrowser.Api/GamesService.cs
index 93cc010793..a27c872f15 100644
--- a/MediaBrowser.Api/GamesService.cs
+++ b/MediaBrowser.Api/GamesService.cs
@@ -102,12 +102,16 @@ namespace MediaBrowser.Api
/// System.Object.
public object Get(GetGameSystemSummaries request)
{
- var gameSystems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is GameSystem)
+ var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
+ var query = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(GameSystem).Name }
+ };
+ var parentIds = new string[] { } ;
+ var gameSystems = _libraryManager.GetItems(query, parentIds)
.Cast()
.ToList();
- var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
-
var result = gameSystems
.Select(i => GetSummary(i, user))
.ToList();
@@ -119,8 +123,15 @@ namespace MediaBrowser.Api
public object Get(GetPlayerIndex request)
{
- var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is Game)
- .Cast();
+ var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
+ var query = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Game).Name }
+ };
+ var parentIds = new string[] { };
+ var games = _libraryManager.GetItems(query, parentIds)
+ .Cast()
+ .ToList();
var lookup = games
.ToLookup(i => i.PlayersSupported ?? -1)
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 319bc13fd2..80076d0736 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -416,7 +416,7 @@ namespace MediaBrowser.Api.Library
public object Get(GetMediaFolders request)
{
- var items = _libraryManager.GetUserRootFolder().Children.OrderBy(i => i.SortName).ToList();
+ var items = _libraryManager.GetUserRootFolder().Children.Concat(_libraryManager.RootFolder.VirtualChildren).OrderBy(i => i.SortName).ToList();
if (request.IsHidden.HasValue)
{
@@ -610,7 +610,7 @@ namespace MediaBrowser.Api.Library
var dtoOptions = GetDtoOptions(request);
- BaseItem parent = item.Parent;
+ BaseItem parent = item.GetParent();
while (parent != null)
{
@@ -621,7 +621,7 @@ namespace MediaBrowser.Api.Library
baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
- parent = parent.Parent;
+ parent = parent.GetParent();
}
return baseItemDtos.ToList();
@@ -629,7 +629,7 @@ namespace MediaBrowser.Api.Library
private BaseItem TranslateParentItem(BaseItem item, User user)
{
- if (item.Parent is AggregateFolder)
+ if (item.GetParent() is AggregateFolder)
{
return user.RootFolder.GetChildren(user, true).FirstOrDefault(i => i.PhysicalLocations.Contains(item.Path));
}
@@ -677,6 +677,50 @@ namespace MediaBrowser.Api.Library
return ToOptimizedSerializedResultUsingCache(counts);
}
+ private IList GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func filter)
+ {
+ if (!string.IsNullOrEmpty(parentId))
+ {
+ var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
+
+ if (!string.IsNullOrWhiteSpace(userId))
+ {
+ var user = userManager.GetUserById(userId);
+
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ return folder
+ .GetRecursiveChildren(user, filter)
+ .ToList();
+ }
+
+ return folder
+ .GetRecursiveChildren(filter);
+ }
+ if (!string.IsNullOrWhiteSpace(userId))
+ {
+ var user = userManager.GetUserById(userId);
+
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ return userManager
+ .GetUserById(userId)
+ .RootFolder
+ .GetRecursiveChildren(user, filter)
+ .ToList();
+ }
+
+ return libraryManager
+ .RootFolder
+ .GetRecursiveChildren(filter);
+ }
+
private bool FilterItem(BaseItem item, GetItemCounts request, string userId)
{
if (!string.IsNullOrWhiteSpace(userId))
@@ -817,9 +861,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id);
- while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.Parent != null)
+ while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
{
- item = item.Parent;
+ item = item.GetParent();
}
var dtoOptions = GetDtoOptions(request);
@@ -860,9 +904,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id);
- while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.Parent != null)
+ while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
{
- item = item.Parent;
+ item = item.GetParent();
}
var dtoOptions = GetDtoOptions(request);
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 7be644bc80..08b99d5a4a 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -49,6 +49,9 @@
False
..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll
+
+ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll
+
..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll
@@ -63,9 +66,6 @@
..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll
-
- ..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll
-
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index fe8bae1a51..36cbc6ffa6 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -117,10 +117,7 @@ namespace MediaBrowser.Api.Movies
public async Task
diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
index c27dfd68d4..bc3dc360f7 100644
--- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
+++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
@@ -7,6 +7,7 @@ using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
+using MoreLinq;
namespace MediaBrowser.Common.Implementations.Networking
{
@@ -31,14 +32,14 @@ namespace MediaBrowser.Common.Implementations.Networking
}
}
- private volatile List _localIpAddresses;
+ private volatile List _localIpAddresses;
private readonly object _localIpAddressSyncLock = new object();
///
/// Gets the machine's local ip address
///
/// IPAddress.
- public IEnumerable GetLocalIpAddresses()
+ public IEnumerable GetLocalIpAddresses()
{
if (_localIpAddresses == null)
{
@@ -58,25 +59,24 @@ namespace MediaBrowser.Common.Implementations.Networking
return _localIpAddresses;
}
- private IEnumerable GetLocalIpAddressesInternal()
+ private IEnumerable GetLocalIpAddressesInternal()
{
var list = GetIPsDefault()
- .Where(i => !IPAddress.IsLoopback(i))
- .Select(i => i.ToString())
- .Where(FilterIpAddress)
.ToList();
- if (list.Count > 0)
+ if (list.Count == 0)
{
- return list;
+ list.AddRange(GetLocalIpAddressesFallback());
}
- return GetLocalIpAddressesFallback().Where(FilterIpAddress);
+ return list.Where(FilterIpAddress).DistinctBy(i => i.ToString());
}
- private bool FilterIpAddress(string address)
+ private bool FilterIpAddress(IPAddress address)
{
- if (address.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
+ var addressString = address.ToString ();
+
+ if (addressString.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
{
return false;
}
@@ -84,8 +84,16 @@ namespace MediaBrowser.Common.Implementations.Networking
return true;
}
- private bool IsInPrivateAddressSpace(string endpoint)
+ public bool IsInPrivateAddressSpace(string endpoint)
{
+ if (string.Equals(endpoint, "::1", StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+
+ // Handle ipv4 mapped to ipv6
+ endpoint = endpoint.Replace("::ffff:", string.Empty);
+
// Private address space:
// http://en.wikipedia.org/wiki/Private_network
@@ -96,9 +104,6 @@ namespace MediaBrowser.Common.Implementations.Networking
return
- // If url was requested with computer name, we may see this
- endpoint.IndexOf("::", StringComparison.OrdinalIgnoreCase) != -1 ||
-
endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
@@ -131,26 +136,41 @@ namespace MediaBrowser.Common.Implementations.Networking
throw new ArgumentNullException("endpoint");
}
- if (IsInPrivateAddressSpace(endpoint))
- {
- return true;
- }
-
- const int lengthMatch = 4;
-
- if (endpoint.Length >= lengthMatch)
+ IPAddress address;
+ if (IPAddress.TryParse(endpoint, out address))
{
- var prefix = endpoint.Substring(0, lengthMatch);
+ var addressString = address.ToString();
- if (GetLocalIpAddresses()
- .Any(i => i.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
+ int lengthMatch = 100;
+ if (address.AddressFamily == AddressFamily.InterNetwork)
{
- return true;
+ lengthMatch = 4;
+ if (IsInPrivateAddressSpace(addressString))
+ {
+ return true;
+ }
+ }
+ else if (address.AddressFamily == AddressFamily.InterNetworkV6)
+ {
+ lengthMatch = 10;
+ if (IsInPrivateAddressSpace(endpoint))
+ {
+ return true;
+ }
}
- }
- IPAddress address;
- if (resolveHost && !IPAddress.TryParse(endpoint, out address))
+ // Should be even be doing this with ipv6?
+ if (addressString.Length >= lengthMatch)
+ {
+ var prefix = addressString.Substring(0, lengthMatch);
+
+ if (GetLocalIpAddresses().Any(i => i.ToString().StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
+ {
+ return true;
+ }
+ }
+ }
+ else if (resolveHost)
{
Uri uri;
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
@@ -188,33 +208,45 @@ namespace MediaBrowser.Common.Implementations.Networking
return Dns.GetHostAddresses(hostName);
}
- private IEnumerable GetIPsDefault()
- {
- foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
- {
- var props = adapter.GetIPProperties();
- var gateways = from ga in props.GatewayAddresses
- where !ga.Address.Equals(IPAddress.Any)
- select true;
-
- if (!gateways.Any())
- {
- continue;
- }
-
- foreach (var uni in props.UnicastAddresses)
- {
- var address = uni.Address;
- if (address.AddressFamily != AddressFamily.InterNetwork)
- {
- continue;
- }
- yield return address;
- }
- }
- }
-
- private IEnumerable GetLocalIpAddressesFallback()
+ private List GetIPsDefault()
+ {
+ NetworkInterface[] interfaces;
+
+ try
+ {
+ interfaces = NetworkInterface.GetAllNetworkInterfaces();
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
+ return new List();
+ }
+
+ return interfaces.SelectMany(network => {
+
+ try
+ {
+ Logger.Debug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
+
+ var properties = network.GetIPProperties();
+
+ return properties.UnicastAddresses
+ .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();
+ }
+
+ }).DistinctBy(i => i.ToString())
+ .ToList();
+ }
+
+ private IEnumerable GetLocalIpAddressesFallback()
{
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
return host.AddressList
.Where(i => i.AddressFamily == AddressFamily.InterNetwork)
- .Select(i => i.ToString())
.Reverse();
}
diff --git a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs
new file mode 100644
index 0000000000..3604280729
--- /dev/null
+++ b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs
@@ -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(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(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()).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 assets { get; set; }
+ public string tarball_url { get; set; }
+ public string zipball_url { get; set; }
+ public string body { get; set; }
+ }
+ }
+}
diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
index 0142753314..d155f11c73 100644
--- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
+++ b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
@@ -438,11 +438,12 @@ namespace MediaBrowser.Common.Implementations.Updates
/// Installs the package.
///
/// The package.
+ /// if set to true [is plugin].
/// The progress.
/// The cancellation token.
/// Task.
/// package
- public async Task InstallPackage(PackageVersionInfo package, IProgress progress, CancellationToken cancellationToken)
+ public async Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress progress, CancellationToken cancellationToken)
{
if (package == null)
{
@@ -495,7 +496,7 @@ namespace MediaBrowser.Common.Implementations.Updates
try
{
- await InstallPackageInternal(package, innerProgress, linkedToken).ConfigureAwait(false);
+ await InstallPackageInternal(package, isPlugin, innerProgress, linkedToken).ConfigureAwait(false);
lock (CurrentInstallations)
{
@@ -551,18 +552,17 @@ namespace MediaBrowser.Common.Implementations.Updates
/// Installs the package internal.
///
/// The package.
+ /// if set to true [is plugin].
/// The progress.
/// The cancellation token.
/// Task.
- private async Task InstallPackageInternal(PackageVersionInfo package, IProgress progress, CancellationToken cancellationToken)
+ private async Task InstallPackageInternal(PackageVersionInfo package, bool isPlugin, IProgress progress, CancellationToken cancellationToken)
{
// Do the install
await PerformPackageInstallation(progress, package, cancellationToken).ConfigureAwait(false);
- var extension = Path.GetExtension(package.targetFilename) ?? "";
-
// 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
var plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config
index a0711a9c75..84f6632681 100644
--- a/MediaBrowser.Common.Implementations/packages.config
+++ b/MediaBrowser.Common.Implementations/packages.config
@@ -1,7 +1,8 @@
-
+
+
-
+
diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs
index 8fc947e8fe..de63ddd513 100644
--- a/MediaBrowser.Common/Net/INetworkManager.cs
+++ b/MediaBrowser.Common/Net/INetworkManager.cs
@@ -11,7 +11,7 @@ namespace MediaBrowser.Common.Net
/// Gets the machine's local ip address
///
/// IPAddress.
- IEnumerable GetLocalIpAddresses();
+ IEnumerable GetLocalIpAddresses();
///
/// Gets a random port number that is currently available
@@ -25,6 +25,13 @@ namespace MediaBrowser.Common.Net
/// [string] MAC Address
string GetMacAddress();
+ ///
+ /// Determines whether [is in private address space] [the specified endpoint].
+ ///
+ /// The endpoint.
+ /// true if [is in private address space] [the specified endpoint]; otherwise, false.
+ bool IsInPrivateAddressSpace(string endpoint);
+
///
/// Gets the network shares.
///
diff --git a/MediaBrowser.Common/Updates/IInstallationManager.cs b/MediaBrowser.Common/Updates/IInstallationManager.cs
index 7d721da6f0..68853f05e7 100644
--- a/MediaBrowser.Common/Updates/IInstallationManager.cs
+++ b/MediaBrowser.Common/Updates/IInstallationManager.cs
@@ -105,11 +105,12 @@ namespace MediaBrowser.Common.Updates
/// Installs the package.
///
/// The package.
+ /// if set to true [is plugin].
/// The progress.
/// The cancellation token.
/// Task.
/// package
- Task InstallPackage(PackageVersionInfo package, IProgress progress, CancellationToken cancellationToken);
+ Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress progress, CancellationToken cancellationToken);
///
/// Uninstalls a plugin
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
index 653cec9016..17dcf138bf 100644
--- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
@@ -18,9 +18,9 @@ namespace MediaBrowser.Controller.Channels
public List ChannelMediaSources { get; set; }
- protected override bool GetBlockUnratedValue(UserPolicy config)
+ public override UnratedItem GetBlockUnratedType()
{
- return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
+ return UnratedItem.ChannelContent;
}
protected override string CreateUserDataKey()
diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
index 9010470f8f..f662020bbf 100644
--- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
@@ -6,6 +6,7 @@ using System;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Channels
@@ -20,6 +21,11 @@ namespace MediaBrowser.Controller.Channels
return false;
}
+ public override UnratedItem GetBlockUnratedType()
+ {
+ return UnratedItem.ChannelContent;
+ }
+
[IgnoreDataMember]
public override bool SupportsLocalMetadata
{
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
index fb545e57aa..79ad4b36b1 100644
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
@@ -42,9 +42,9 @@ namespace MediaBrowser.Controller.Channels
return ExternalId;
}
- protected override bool GetBlockUnratedValue(UserPolicy config)
+ public override UnratedItem GetBlockUnratedType()
{
- return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
+ return UnratedItem.ChannelContent;
}
[IgnoreDataMember]
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 43b980c20d..766f1e5ed8 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -27,9 +27,22 @@ namespace MediaBrowser.Controller.Entities.Audio
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
- public List Tags { get; set; }
public ExtraType? ExtraType { get; set; }
+ ///
+ /// Gets or sets the artist.
+ ///
+ /// The artist.
+ public List Artists { get; set; }
+
+ public List AlbumArtists { get; set; }
+
+ ///
+ /// Gets or sets the album.
+ ///
+ /// The album.
+ public string Album { get; set; }
+
[IgnoreDataMember]
public bool IsThemeMedia
{
@@ -43,7 +56,6 @@ namespace MediaBrowser.Controller.Entities.Audio
{
Artists = new List();
AlbumArtists = new List();
- Tags = new List();
}
[IgnoreDataMember]
@@ -92,14 +104,6 @@ namespace MediaBrowser.Controller.Entities.Audio
locationType != LocationType.Virtual;
}
- ///
- /// Gets or sets the artist.
- ///
- /// The artist.
- public List Artists { get; set; }
-
- public List AlbumArtists { get; set; }
-
[IgnoreDataMember]
public List AllArtists
{
@@ -114,12 +118,6 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
- ///
- /// Gets or sets the album.
- ///
- /// The album.
- public string Album { get; set; }
-
[IgnoreDataMember]
public MusicAlbum AlbumEntity
{
@@ -173,9 +171,9 @@ namespace MediaBrowser.Controller.Entities.Audio
return base.CreateUserDataKey();
}
- protected override bool GetBlockUnratedValue(UserPolicy config)
+ public override UnratedItem GetBlockUnratedType()
{
- return config.BlockUnratedItems.Contains(UnratedItem.Music);
+ return UnratedItem.Music;
}
public SongInfo GetLookupInfo()
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 98d1eb4ce2..9a38912ea0 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -30,7 +30,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
get
{
- return Parents.OfType().FirstOrDefault();
+ return GetParents().OfType().FirstOrDefault();
}
}
@@ -110,13 +110,18 @@ namespace MediaBrowser.Controller.Entities.Audio
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
+ public override UnratedItem GetBlockUnratedType()
+ {
+ return UnratedItem.Music;
+ }
+
public AlbumInfo GetLookupInfo()
{
var id = GetItemLookupInfo();
id.AlbumArtists = AlbumArtists;
- var artist = Parents.OfType().FirstOrDefault();
+ var artist = GetParents().OfType().FirstOrDefault();
if (artist != null)
{
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index f6d1d32a4c..02bcceada4 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -138,6 +138,11 @@ namespace MediaBrowser.Controller.Entities.Audio
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
+ public override UnratedItem GetBlockUnratedType()
+ {
+ return UnratedItem.Music;
+ }
+
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress progress, CancellationToken cancellationToken)
{
var items = GetRecursiveChildren().ToList();
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 59e2b87e3a..379697b816 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration;
@@ -24,6 +23,7 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Controller.Entities
{
@@ -34,6 +34,7 @@ namespace MediaBrowser.Controller.Entities
{
protected BaseItem()
{
+ Tags = new List();
Genres = new List();
Studios = new List();
ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase);
@@ -44,7 +45,7 @@ namespace MediaBrowser.Controller.Entities
///
/// The supported image extensions
///
- public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg" };
+ public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn", ".gif" };
public static readonly List SupportedImageExtensionsList = SupportedImageExtensions.ToList();
@@ -103,7 +104,8 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the name.
///
/// The name.
- public string Name
+ [IgnoreDataMember]
+ public virtual string Name
{
get
{
@@ -122,14 +124,23 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the id.
///
/// The id.
+ [IgnoreDataMember]
public Guid Id { get; set; }
///
/// Gets or sets a value indicating whether this instance is hd.
///
/// true if this instance is hd; otherwise, false.
+ [IgnoreDataMember]
public bool? IsHD { get; set; }
+ ///
+ /// Gets or sets the audio.
+ ///
+ /// The audio.
+ [IgnoreDataMember]
+ public ProgramAudio? Audio { get; set; }
+
///
/// Return the id that should be used to key display prefs for this item.
/// Default is based on the type for everything except actual generic folders.
@@ -149,6 +160,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the path.
///
/// The path.
+ [IgnoreDataMember]
public virtual string Path { get; set; }
[IgnoreDataMember]
@@ -173,7 +185,7 @@ namespace MediaBrowser.Controller.Entities
}
///
- /// Id of the program.
+ /// If this content came from an external service, the id of the content on that service
///
[IgnoreDataMember]
public string ExternalId
@@ -201,11 +213,6 @@ namespace MediaBrowser.Controller.Entities
}
}
- public virtual bool IsHiddenFromUser(User user)
- {
- return false;
- }
-
[IgnoreDataMember]
public virtual bool IsOwnedItem
{
@@ -325,12 +332,14 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the date created.
///
/// The date created.
+ [IgnoreDataMember]
public DateTime DateCreated { get; set; }
///
/// Gets or sets the date modified.
///
/// The date modified.
+ [IgnoreDataMember]
public DateTime DateModified { get; set; }
public DateTime DateLastSaved { get; set; }
@@ -407,6 +416,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the name of the forced sort.
///
/// The name of the forced sort.
+ [IgnoreDataMember]
public string ForcedSortName
{
get { return _forcedSortName; }
@@ -447,10 +457,7 @@ namespace MediaBrowser.Controller.Entities
{
var idString = Id.ToString("N");
- if (ConfigurationManager.Configuration.EnableLibraryMetadataSubFolder)
- {
- basePath = System.IO.Path.Combine(basePath, "library");
- }
+ basePath = System.IO.Path.Combine(basePath, "library");
return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString);
}
@@ -493,6 +500,7 @@ namespace MediaBrowser.Controller.Entities
return sortable;
}
+ [IgnoreDataMember]
public Guid ParentId { get; set; }
///
@@ -502,15 +510,7 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public Folder Parent
{
- get
- {
- if (ParentId != Guid.Empty)
- {
- return LibraryManager.GetItemById(ParentId) as Folder;
- }
-
- return null;
- }
+ get { return GetParent() as Folder; }
set
{
@@ -525,16 +525,28 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public IEnumerable Parents
{
- get
+ get { return GetParents().OfType(); }
+ }
+
+ public BaseItem GetParent()
+ {
+ if (ParentId != Guid.Empty)
{
- var parent = Parent;
+ return LibraryManager.GetItemById(ParentId);
+ }
- while (parent != null)
- {
- yield return parent;
+ return null;
+ }
- parent = parent.Parent;
- }
+ public IEnumerable GetParents()
+ {
+ var parent = GetParent();
+
+ while (parent != null)
+ {
+ yield return parent;
+
+ parent = parent.GetParent();
}
}
@@ -546,19 +558,20 @@ namespace MediaBrowser.Controller.Entities
public T FindParent()
where T : Folder
{
- return Parents.OfType().FirstOrDefault();
+ return GetParents().OfType().FirstOrDefault();
}
[IgnoreDataMember]
public virtual BaseItem DisplayParent
{
- get { return Parent; }
+ get { return GetParent(); }
}
///
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
///
/// The premiere date.
+ [IgnoreDataMember]
public DateTime? PremiereDate { get; set; }
///
@@ -572,31 +585,35 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the display type of the media.
///
/// The display type of the media.
+ [IgnoreDataMember]
public string DisplayMediaType { get; set; }
///
/// Gets or sets the official rating.
///
/// The official rating.
+ [IgnoreDataMember]
public string OfficialRating { get; set; }
///
/// Gets or sets the official rating description.
///
/// The official rating description.
+ [IgnoreDataMember]
public string OfficialRatingDescription { get; set; }
///
/// Gets or sets the custom rating.
///
/// The custom rating.
- //[IgnoreDataMember]
+ [IgnoreDataMember]
public string CustomRating { get; set; }
///
/// Gets or sets the overview.
///
/// The overview.
+ [IgnoreDataMember]
public string Overview { get; set; }
///
@@ -609,37 +626,48 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the genres.
///
/// The genres.
+ [IgnoreDataMember]
public List Genres { get; set; }
+ ///
+ /// Gets or sets the tags.
+ ///
+ /// The tags.
+ public List Tags { get; set; }
+
///
/// Gets or sets the home page URL.
///
/// The home page URL.
+ [IgnoreDataMember]
public string HomePageUrl { get; set; }
///
/// Gets or sets the community rating.
///
/// The community rating.
- //[IgnoreDataMember]
+ [IgnoreDataMember]
public float? CommunityRating { get; set; }
///
/// Gets or sets the community rating vote count.
///
/// The community rating vote count.
+ [IgnoreDataMember]
public int? VoteCount { get; set; }
///
/// Gets or sets the run time ticks.
///
/// The run time ticks.
+ [IgnoreDataMember]
public long? RunTimeTicks { get; set; }
///
/// Gets or sets the production year.
///
/// The production year.
+ [IgnoreDataMember]
public int? ProductionYear { get; set; }
///
@@ -647,19 +675,34 @@ namespace MediaBrowser.Controller.Entities
/// This could be episode number, album track number, etc.
///
/// The index number.
- //[IgnoreDataMember]
+ [IgnoreDataMember]
public int? IndexNumber { get; set; }
///
/// For an episode this could be the season number, or for a song this could be the disc number.
///
/// The parent index number.
+ [IgnoreDataMember]
public int? ParentIndexNumber { get; set; }
[IgnoreDataMember]
- public virtual string OfficialRatingForComparison
+ public string OfficialRatingForComparison
{
- get { return OfficialRating; }
+ get
+ {
+ if (!string.IsNullOrWhiteSpace(OfficialRating))
+ {
+ return OfficialRating;
+ }
+
+ var parent = DisplayParent;
+ if (parent != null)
+ {
+ return parent.OfficialRatingForComparison;
+ }
+
+ return null;
+ }
}
[IgnoreDataMember]
@@ -721,21 +764,21 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.ResolvePaths(files, directoryService, null)
.OfType()
.Select(audio =>
- {
- // Try to retrieve it from the db. If we don't find it, use the resolved version
- var dbItem = LibraryManager.GetItemById(audio.Id) as Audio.Audio;
-
- if (dbItem != null)
{
- audio = dbItem;
- }
+ // Try to retrieve it from the db. If we don't find it, use the resolved version
+ var dbItem = LibraryManager.GetItemById(audio.Id) as Audio.Audio;
- audio.ExtraType = ExtraType.ThemeSong;
+ if (dbItem != null)
+ {
+ audio = dbItem;
+ }
- return audio;
+ audio.ExtraType = ExtraType.ThemeSong;
- // Sort them so that the list can be easily compared for changes
- }).OrderBy(i => i.Path).ToList();
+ return audio;
+
+ // Sort them so that the list can be easily compared for changes
+ }).OrderBy(i => i.Path).ToList();
}
///
@@ -751,21 +794,21 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.ResolvePaths(files, directoryService, null)
.OfType
@@ -162,6 +162,7 @@
+
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index 427af6f6d7..76ef054de0 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -35,9 +35,10 @@ namespace MediaBrowser.Controller.MediaEncoding
/// Extracts the audio image.
///
/// The path.
+ /// Index of the image stream.
/// The cancellation token.
/// Task{Stream}.
- Task ExtractAudioImage(string path, CancellationToken cancellationToken);
+ Task ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken);
///
/// Extracts the video image.
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs
index 24df7b8854..ca0c2fdbb4 100644
--- a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs
+++ b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs
@@ -15,7 +15,6 @@ namespace MediaBrowser.Controller.MediaEncoding
public IIsoMount MountedIso { get; set; }
public VideoType VideoType { get; set; }
public List PlayableStreamFileNames { get; set; }
- public bool ExtractKeyFrameInterval { get; set; }
public MediaInfoRequest()
{
diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs
index 91da5fab20..97c5dd31b6 100644
--- a/MediaBrowser.Controller/Net/IHttpServer.cs
+++ b/MediaBrowser.Controller/Net/IHttpServer.cs
@@ -28,12 +28,6 @@ namespace MediaBrowser.Controller.Net
/// the ssl certificate localtion on the file system.
void StartServer(IEnumerable urlPrefixes, string certificatePath);
- ///
- /// Gets the local end points.
- ///
- /// The local end points.
- IEnumerable LocalEndPoints { get; }
-
///
/// Stops this instance.
///
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index 8fc0aedd3f..533d66b950 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -176,6 +176,20 @@ namespace MediaBrowser.Controller.Persistence
/// The query.
/// QueryResult<Tuple<Guid, System.String>>.
QueryResult> GetItemIdsWithPath(InternalItemsQuery query);
+
+ ///
+ /// Gets the item list.
+ ///
+ /// The query.
+ /// List<BaseItem>.
+ IEnumerable GetItemList(InternalItemsQuery query);
+
+ ///
+ /// Updates the inherited values.
+ ///
+ /// The cancellation token.
+ /// Task.
+ Task UpdateInheritedValues(CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs
index fdc36db354..0f9af6550b 100644
--- a/MediaBrowser.Controller/Playlists/Playlist.cs
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -144,6 +144,7 @@ namespace MediaBrowser.Controller.Playlists
public string PlaylistMediaType { get; set; }
+ [IgnoreDataMember]
public override string MediaType
{
get
diff --git a/MediaBrowser.Controller/Providers/MetadataStatus.cs b/MediaBrowser.Controller/Providers/MetadataStatus.cs
index 9b946aee27..b19377a680 100644
--- a/MediaBrowser.Controller/Providers/MetadataStatus.cs
+++ b/MediaBrowser.Controller/Providers/MetadataStatus.cs
@@ -10,24 +10,6 @@ namespace MediaBrowser.Controller.Providers
/// The item identifier.
public Guid ItemId { get; set; }
- ///
- /// Gets or sets the name of the item.
- ///
- /// The name of the item.
- public string ItemName { get; set; }
-
- ///
- /// Gets or sets the type of the item.
- ///
- /// The type of the item.
- public string ItemType { get; set; }
-
- ///
- /// Gets or sets the name of the series.
- ///
- /// The name of the series.
- public string SeriesName { get; set; }
-
///
/// Gets or sets the date last metadata refresh.
///
@@ -40,22 +22,8 @@ namespace MediaBrowser.Controller.Providers
/// The date last images refresh.
public DateTime? DateLastImagesRefresh { get; set; }
- ///
- /// Gets or sets the last result error message.
- ///
- /// The last result error message.
- public string LastErrorMessage { get; set; }
-
public DateTime? ItemDateModified { get; set; }
- public void AddStatus(string errorMessage)
- {
- if (string.IsNullOrEmpty(LastErrorMessage))
- {
- LastErrorMessage = errorMessage;
- }
- }
-
public bool IsDirty { get; private set; }
public void SetDateLastMetadataRefresh(DateTime? date)
diff --git a/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs b/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs
index e855355488..2c82882c68 100644
--- a/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs
+++ b/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Library;
+using CommonIO;
+using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Resolvers
{
@@ -7,6 +8,6 @@ namespace MediaBrowser.Controller.Resolvers
///
public interface IResolverIgnoreRule
{
- bool ShouldIgnore(ItemResolveArgs args);
+ bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent);
}
}
diff --git a/MediaBrowser.Controller/packages.config b/MediaBrowser.Controller/packages.config
index a0aacbc958..90b347929f 100644
--- a/MediaBrowser.Controller/packages.config
+++ b/MediaBrowser.Controller/packages.config
@@ -2,6 +2,6 @@
-
+
\ No newline at end of file
diff --git a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
index 2ab27fde50..21289970e2 100644
--- a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
+++ b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
@@ -26,6 +26,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly ILocalizationManager _localization;
private readonly IChannelManager _channelManager;
private readonly IMediaSourceManager _mediaSourceManager;
+ private readonly IUserViewManager _userViewManager;
public ContentDirectory(IDlnaManager dlna,
IUserDataManager userDataManager,
@@ -34,7 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
IServerConfigurationManager config,
IUserManager userManager,
ILogger logger,
- IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager)
+ IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager)
: base(logger, httpClient)
{
_dlna = dlna;
@@ -46,6 +47,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
_localization = localization;
_channelManager = channelManager;
_mediaSourceManager = mediaSourceManager;
+ _userViewManager = userViewManager;
}
private int SystemUpdateId
@@ -86,7 +88,8 @@ namespace MediaBrowser.Dlna.ContentDirectory
_config,
_localization,
_channelManager,
- _mediaSourceManager)
+ _mediaSourceManager,
+ _userViewManager)
.ProcessControlRequest(request);
}
diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
index a9ce5587d7..fb7596387d 100644
--- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
+++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
@@ -24,6 +24,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
+using MediaBrowser.Model.Library;
namespace MediaBrowser.Dlna.ContentDirectory
{
@@ -34,6 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly IUserDataManager _userDataManager;
private readonly IServerConfigurationManager _config;
private readonly User _user;
+ private readonly IUserViewManager _userViewManager;
private const string NS_DC = "http://purl.org/dc/elements/1.1/";
private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
@@ -47,7 +49,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly DeviceProfile _profile;
- public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager)
+ public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager)
: base(config, logger)
{
_libraryManager = libraryManager;
@@ -55,6 +57,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
_user = user;
_systemUpdateId = systemUpdateId;
_channelManager = channelManager;
+ _userViewManager = userViewManager;
_profile = profile;
_config = config;
@@ -450,16 +453,32 @@ namespace MediaBrowser.Dlna.ContentDirectory
sortOrders.Add(ItemSortBy.SortName);
}
- var queryResult = await folder.GetItems(new InternalItemsQuery
+ QueryResult queryResult;
+
+ if (folder is UserRootFolder)
{
- Limit = limit,
- StartIndex = startIndex,
- SortBy = sortOrders.ToArray(),
- SortOrder = sort.SortOrder,
- User = user,
- Filter = FilterUnsupportedContent
+ var views = await _userViewManager.GetUserViews(new UserViewQuery { UserId = user.Id.ToString("N"), PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music } }, CancellationToken.None)
+ .ConfigureAwait(false);
+
+ queryResult = new QueryResult
+ {
+ Items = views.Cast().ToArray()
+ };
+ queryResult.TotalRecordCount = queryResult.Items.Length;
+ }
+ else
+ {
+ queryResult = await folder.GetItems(new InternalItemsQuery
+ {
+ Limit = limit,
+ StartIndex = startIndex,
+ SortBy = sortOrders.ToArray(),
+ SortOrder = sort.SortOrder,
+ User = user,
+ Filter = FilterUnsupportedContent
- }).ConfigureAwait(false);
+ }).ConfigureAwait(false);
+ }
var options = _config.GetDlnaConfiguration();
@@ -481,23 +500,17 @@ namespace MediaBrowser.Dlna.ContentDirectory
private QueryResult GetItemsFromPerson(Person person, User user, int? startIndex, int? limit)
{
- var itemsWithPerson = _libraryManager.GetItems(new InternalItemsQuery
+ var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{
- Person = person.Name
-
- }).Items;
-
- var items = itemsWithPerson
- .Where(i => i is Movie || i is Series || i is IChannelItem)
- .Where(i => i.IsVisibleStandalone(user))
- .ToList();
+ Person = person.Name,
+ IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(ChannelVideoItem).Name },
+ SortBy = new[] { ItemSortBy.SortName },
+ Limit = limit,
+ StartIndex = startIndex
- items = _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
- .Skip(startIndex ?? 0)
- .Take(limit ?? int.MaxValue)
- .ToList();
+ }, new string[] { });
- var serverItems = items.Select(i => new ServerItem
+ var serverItems = itemsResult.Items.Select(i => new ServerItem
{
Item = i,
StubType = null
@@ -506,7 +519,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
return new QueryResult
{
- TotalRecordCount = serverItems.Length,
+ TotalRecordCount = itemsResult.TotalRecordCount,
Items = serverItems
};
}
diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
index 0a5b591ec5..40507db0c3 100644
--- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs
+++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
@@ -966,7 +966,7 @@ namespace MediaBrowser.Dlna.Didl
}
}
- item = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
+ item = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Primary));
if (item != null)
{
diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
index 8c45757e76..d79ef9eafa 100644
--- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
+++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
@@ -43,19 +43,19 @@ namespace MediaBrowser.Dlna.Main
private readonly List _registeredServerIds = new List();
private bool _dlnaServerStarted;
- public DlnaEntryPoint(IServerConfigurationManager config,
- ILogManager logManager,
- IServerApplicationHost appHost,
- INetworkManager network,
- ISessionManager sessionManager,
- IHttpClient httpClient,
- ILibraryManager libraryManager,
- IUserManager userManager,
- IDlnaManager dlnaManager,
- IImageProcessor imageProcessor,
- IUserDataManager userDataManager,
- ILocalizationManager localization,
- IMediaSourceManager mediaSourceManager,
+ public DlnaEntryPoint(IServerConfigurationManager config,
+ ILogManager logManager,
+ IServerApplicationHost appHost,
+ INetworkManager network,
+ ISessionManager sessionManager,
+ IHttpClient httpClient,
+ ILibraryManager libraryManager,
+ IUserManager userManager,
+ IDlnaManager dlnaManager,
+ IImageProcessor imageProcessor,
+ IUserDataManager userDataManager,
+ ILocalizationManager localization,
+ IMediaSourceManager mediaSourceManager,
ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery)
{
_config = config;
@@ -148,13 +148,20 @@ namespace MediaBrowser.Dlna.Main
private void RegisterServerEndpoints()
{
- foreach (var address in _network.GetLocalIpAddresses())
+ foreach (var address in _appHost.LocalIpAddresses)
{
- var guid = address.GetMD5();
+ //if (IPAddress.IsLoopback(address))
+ //{
+ // // Should we allow this?
+ // continue;
+ //}
+
+ var addressString = address.ToString();
+ var guid = addressString.GetMD5();
var descriptorURI = "/dlna/" + guid.ToString("N") + "/description.xml";
- var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorURI);
+ var uri = new Uri(_appHost.GetLocalApiUrl(addressString) + descriptorURI);
var services = new List
{
@@ -165,8 +172,8 @@ namespace MediaBrowser.Dlna.Main
"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1",
"uuid:" + guid.ToString("N")
};
-
- _ssdpHandler.RegisterNotification(guid, uri, IPAddress.Parse(address), services);
+
+ _ssdpHandler.RegisterNotification(guid, uri, address, services);
_registeredServerIds.Add(guid.ToString("N"));
}
diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
index b8ac60ef65..db69a45c88 100644
--- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
+++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
@@ -44,6 +44,9 @@
False
..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll
+
+ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll
+
..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll
diff --git a/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs b/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs
index a99d7775aa..6ad2b3fca2 100644
--- a/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs
+++ b/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs
@@ -92,7 +92,7 @@ namespace MediaBrowser.Dlna.Profiles
{
Container = "ts",
VideoCodec = "h264",
- AudioCodec = "mp3",
+ AudioCodec = "ac3,aac,mp3",
Type = DlnaProfileType.Video
},
new TranscodingProfile
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
index 5d6e720000..ce34dd5f29 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
@@ -48,7 +48,7 @@
-
+
diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs
index c9b983baef..ed3698e437 100644
--- a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs
+++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs
@@ -11,6 +11,8 @@ using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
+using MoreLinq;
namespace MediaBrowser.Dlna.Ssdp
{
@@ -26,50 +28,39 @@ namespace MediaBrowser.Dlna.Ssdp
public event EventHandler DeviceDiscovered;
public event EventHandler 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();
_logger = logger;
_config = config;
_appHost = appHost;
+ _networkManager = networkManager;
}
+ private List GetLocalIpAddresses()
+ {
+ return _networkManager.GetLocalIpAddresses().ToList();
+ }
+
public void Start(SsdpHandler ssdpHandler)
{
_ssdpHandler = ssdpHandler;
_ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived;
- foreach (var network in GetNetworkInterfaces())
- {
- _logger.Debug("Found interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
-
- if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any())
- continue;
-
- var properties = network.GetIPProperties();
- var ipV4 = properties.GetIPv4Properties();
- if (null == ipV4)
- continue;
-
- var localIps = properties.UnicastAddresses
- .Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork)
- .Select(i => i.Address)
- .ToList();
-
- foreach (var localIp in localIps)
- {
- try
- {
- CreateListener(localIp);
- }
- catch (Exception e)
- {
- _logger.ErrorException("Failed to Initilize Socket", e);
- }
- }
- }
+ foreach (var localIp in GetLocalIpAddresses())
+ {
+ try
+ {
+ CreateListener(localIp);
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to Initilize Socket", e);
+ }
+ }
}
void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
@@ -89,8 +80,11 @@ namespace MediaBrowser.Dlna.Ssdp
{
if (e.LocalEndPoint == null)
{
- var ip = _appHost.LocalIpAddress;
- e.LocalEndPoint = new IPEndPoint(IPAddress.Parse(ip), 0);
+ var ip = _appHost.LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i));
+ if (ip != null)
+ {
+ e.LocalEndPoint = new IPEndPoint(ip, 0);
+ }
}
if (e.LocalEndPoint != null)
@@ -107,29 +101,17 @@ namespace MediaBrowser.Dlna.Ssdp
}
}
- private IEnumerable GetNetworkInterfaces()
- {
- try
- {
- return NetworkInterface.GetAllNetworkInterfaces();
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
- return new List();
- }
- }
private void CreateListener(IPAddress localIp)
{
Task.Factory.StartNew(async (o) =>
{
try
{
- var endPoint = new IPEndPoint(localIp, 1900);
+ _logger.Info("Creating SSDP listener on {0}", localIp);
- var socket = GetMulticastSocket(localIp, endPoint);
+ var endPoint = new IPEndPoint(localIp, 1900);
- _logger.Info("Creating SSDP listener on {0}", localIp);
+ var socket = GetMulticastSocket(localIp, endPoint);
var receiveBuffer = new byte[64000];
diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
index 5dd05fd64c..32c369a8ff 100644
--- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
+++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
@@ -15,6 +15,7 @@ using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.Win32;
namespace MediaBrowser.Dlna.Ssdp
{
@@ -112,7 +113,9 @@ namespace MediaBrowser.Dlna.Ssdp
{
get
{
- return _devices.Values.SelectMany(i => i).ToList();
+ var devices = _devices.Values.ToList();
+
+ return devices.SelectMany(i => i).ToList();
}
}
@@ -121,6 +124,15 @@ namespace MediaBrowser.Dlna.Ssdp
RestartSocketListener();
ReloadAliveNotifier();
+ SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
+ }
+
+ void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
+ {
+ if (e.Mode == PowerModes.Resume)
+ {
+ NotifyAll();
+ }
}
public void SendSearchMessage(EndPoint localIp)
@@ -433,6 +445,7 @@ namespace MediaBrowser.Dlna.Ssdp
public void Dispose()
{
_config.NamedConfigurationUpdated -= _config_ConfigurationUpdated;
+ SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
_isDisposed = true;
while (_messageQueue.Count != 0)
diff --git a/MediaBrowser.Dlna/packages.config b/MediaBrowser.Dlna/packages.config
index fad6af08eb..258a097cd2 100644
--- a/MediaBrowser.Dlna/packages.config
+++ b/MediaBrowser.Dlna/packages.config
@@ -1,5 +1,6 @@
+
\ No newline at end of file
diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
index a74fe7e981..5ef8eaaa3d 100644
--- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
+++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
@@ -79,14 +79,11 @@
-
-
-
diff --git a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs
deleted file mode 100644
index dc8a16cd8b..0000000000
--- a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs
+++ /dev/null
@@ -1,166 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
-using MediaBrowser.Common.IO;
-
-namespace MediaBrowser.LocalMetadata.Savers
-{
- public class EpisodeXmlProvider : IMetadataFileSaver, IConfigurableProvider
- {
- private readonly IItemRepository _itemRepository;
-
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private IFileSystem _fileSystem;
-
- public EpisodeXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _itemRepository = itemRepository;
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- ///
- /// Determines whether [is enabled for] [the specified item].
- ///
- /// The item.
- /// Type of the update.
- /// true if [is enabled for] [the specified item]; otherwise, false.
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
- {
- if (!item.SupportsLocalMetadata)
- {
- return false;
- }
-
- return item is Episode && updateType >= ItemUpdateType.MetadataDownload;
- }
-
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- public bool IsEnabled
- {
- get { return !_config.Configuration.DisableXmlSavers; }
- }
-
- ///
- /// Saves the specified item.
- ///
- /// The item.
- /// The cancellation token.
- /// Task.
- public void Save(IHasMetadata item, CancellationToken cancellationToken)
- {
- var episode = (Episode)item;
-
- var builder = new StringBuilder();
-
- builder.Append("- ");
-
- if (!string.IsNullOrEmpty(item.Name))
- {
- builder.Append("" + SecurityElement.Escape(episode.Name) + "");
- }
-
- if (episode.IndexNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.IndexNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.IndexNumberEnd.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.AirsAfterSeasonNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)) + "");
- }
- if (episode.AirsBeforeEpisodeNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)) + "");
- }
- if (episode.AirsBeforeSeasonNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.ParentIndexNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.AbsoluteEpisodeNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.AbsoluteEpisodeNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.DvdEpisodeNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.DvdSeasonNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.DvdSeasonNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.PremiereDate.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "");
- }
-
- XmlSaverHelpers.AddCommonNodes(episode, _libraryManager, builder);
- XmlSaverHelpers.AddMediaInfo(episode, builder, _itemRepository);
-
- builder.Append("
");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List
- {
- "FirstAired",
- "SeasonNumber",
- "EpisodeNumber",
- "EpisodeName",
- "EpisodeNumberEnd",
- "airsafter_season",
- "airsbefore_episode",
- "airsbefore_season",
- "DVD_episodenumber",
- "DVD_season",
- "absolute_number"
-
- }, _config, _fileSystem);
- }
-
- ///
- /// Gets the save path.
- ///
- /// The item.
- /// System.String.
- public string GetSavePath(IHasMetadata item)
- {
- var filename = Path.ChangeExtension(Path.GetFileName(item.Path), ".xml");
-
- return Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename);
- }
- }
-}
diff --git a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
deleted file mode 100644
index 2e3e7aaa1e..0000000000
--- a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-using System.Collections.Generic;
-using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
-using MediaBrowser.Common.IO;
-
-namespace MediaBrowser.LocalMetadata.Savers
-{
- ///
- /// Saves movie.xml for movies, trailers and music videos
- ///
- public class MovieXmlProvider : IMetadataFileSaver, IConfigurableProvider
- {
- private readonly IItemRepository _itemRepository;
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private IFileSystem _fileSystem;
-
- public MovieXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _itemRepository = itemRepository;
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- public bool IsEnabled
- {
- get { return !_config.Configuration.DisableXmlSavers; }
- }
-
- ///
- /// Determines whether [is enabled for] [the specified item].
- ///
- /// The item.
- /// Type of the update.
- /// true if [is enabled for] [the specified item]; otherwise, false.
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
- {
- if (!item.SupportsLocalMetadata)
- {
- return false;
- }
-
- var video = item as Video;
-
- // Check parent for null to avoid running this against things like video backdrops
- if (video != null && !(item is Episode) && !video.IsOwnedItem)
- {
- return updateType >= ItemUpdateType.MetadataDownload;
- }
-
- return false;
- }
-
- ///
- /// Saves the specified item.
- ///
- /// The item.
- /// The cancellation token.
- /// Task.
- public void Save(IHasMetadata item, CancellationToken cancellationToken)
- {
- var video = (Video)item;
-
- var builder = new StringBuilder();
-
- builder.Append("");
-
- XmlSaverHelpers.AddCommonNodes(video, _libraryManager, builder);
-
- var musicVideo = item as MusicVideo;
-
- if (musicVideo != null)
- {
- if (musicVideo.Artists.Count > 0)
- {
- builder.Append("" + SecurityElement.Escape(string.Join(";", musicVideo.Artists.ToArray())) + "");
- }
- if (!string.IsNullOrEmpty(musicVideo.Album))
- {
- builder.Append("" + SecurityElement.Escape(musicVideo.Album) + "");
- }
- }
-
- var movie = item as Movie;
-
- if (movie != null)
- {
- if (!string.IsNullOrEmpty(movie.TmdbCollectionName))
- {
- builder.Append("" + SecurityElement.Escape(movie.TmdbCollectionName) + "");
- }
- }
-
- XmlSaverHelpers.AddMediaInfo(video, builder, _itemRepository);
-
- builder.Append("");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List
- {
- // Deprecated. No longer saving in this field.
- "IMDBrating",
-
- // Deprecated. No longer saving in this field.
- "Description",
-
- "Artist",
- "Album",
- "TmdbCollectionName"
- }, _config, _fileSystem);
- }
-
- public string GetSavePath(IHasMetadata item)
- {
- return GetMovieSavePath((Video)item);
- }
-
- public static string GetMovieSavePath(Video item)
- {
- if (item.IsInMixedFolder)
- {
- return Path.ChangeExtension(item.Path, ".xml");
- }
-
- return Path.Combine(item.ContainingFolderPath, "movie.xml");
- }
- }
-}
diff --git a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs
deleted file mode 100644
index 9806c4216e..0000000000
--- a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
-using MediaBrowser.Common.IO;
-
-namespace MediaBrowser.LocalMetadata.Savers
-{
- public class SeriesXmlProvider : IMetadataFileSaver, IConfigurableProvider
- {
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private IFileSystem _fileSystem;
-
- public SeriesXmlProvider(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- ///
- /// Determines whether [is enabled for] [the specified item].
- ///
- /// The item.
- /// Type of the update.
- /// true if [is enabled for] [the specified item]; otherwise, false.
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
- {
- if (!item.SupportsLocalMetadata)
- {
- return false;
- }
-
- return item is Series && updateType >= ItemUpdateType.MetadataDownload;
- }
-
- public bool IsEnabled
- {
- get { return !_config.Configuration.DisableXmlSavers; }
- }
-
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
- ///
- /// Saves the specified item.
- ///
- /// The item.
- /// The cancellation token.
- /// Task.
- public void Save(IHasMetadata item, CancellationToken cancellationToken)
- {
- var series = (Series)item;
-
- var builder = new StringBuilder();
-
- builder.Append("");
-
- var tvdb = item.GetProviderId(MetadataProviders.Tvdb);
-
- if (!string.IsNullOrEmpty(tvdb))
- {
- builder.Append("" + SecurityElement.Escape(tvdb) + "");
- }
-
- if (series.Status.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(series.Status.Value.ToString()) + "");
- }
-
- if (series.Studios.Count > 0)
- {
- builder.Append("" + SecurityElement.Escape(series.Studios[0]) + "");
- }
-
- if (!string.IsNullOrEmpty(series.AirTime))
- {
- builder.Append("" + SecurityElement.Escape(series.AirTime) + "");
- }
-
- if (series.AirDays != null)
- {
- if (series.AirDays.Count == 7)
- {
- builder.Append("" + SecurityElement.Escape("Daily") + "");
- }
- else if (series.AirDays.Count > 0)
- {
- builder.Append("" + SecurityElement.Escape(series.AirDays[0].ToString()) + "");
- }
- }
-
- if (series.PremiereDate.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(series.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "");
- }
-
- if (series.AnimeSeriesIndex.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(series.AnimeSeriesIndex.Value.ToString(UsCulture)) + "");
- }
-
- XmlSaverHelpers.AddCommonNodes(series, _libraryManager, builder);
-
- builder.Append("");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List
- {
- "id",
- "Status",
- "Network",
- "Airs_Time",
- "Airs_DayOfWeek",
- "FirstAired",
-
- // Don't preserve old series node
- "Series",
-
- "SeriesName",
-
- // Deprecated. No longer saving in this field.
- "AnimeSeriesIndex"
- }, _config, _fileSystem);
- }
-
- ///
- /// Gets the save path.
- ///
- /// The item.
- /// System.String.
- public string GetSavePath(IHasMetadata item)
- {
- return Path.Combine(item.Path, "series.xml");
- }
- }
-}
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
index afbd29578e..9cdc4a7bf1 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
@@ -505,7 +505,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
return "libx264";
}
- if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
{
return "libx265";
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index f44d922d57..3c6a99c65f 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -258,17 +258,17 @@ namespace MediaBrowser.MediaEncoding.Encoder
var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol);
- //var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
+ var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
- //if (videoStream != null)
- //{
- // var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false);
+ if (videoStream != null)
+ {
+ var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false);
- // if (isInterlaced)
- // {
- // videoStream.IsInterlaced = true;
- // }
- //}
+ if (isInterlaced)
+ {
+ videoStream.IsInterlaced = true;
+ }
+ }
return mediaInfo;
}
@@ -292,16 +292,19 @@ namespace MediaBrowser.MediaEncoding.Encoder
return false;
}
- var formats = (video.Container ?? string.Empty).Split(',').ToList();
-
- // Take a shortcut and limit this to containers that are likely to have interlaced content
- if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) &&
- !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) &&
- !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) &&
- !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) &&
- !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase))
+ // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content
+ if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) == -1)
{
- return false;
+ var formats = (video.Container ?? string.Empty).Split(',').ToList();
+
+ if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) &&
+ !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) &&
+ !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) &&
+ !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) &&
+ !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase))
+ {
+ return false;
+ }
}
var args = "{0} -i {1} -map 0:v:{2} -filter:v idet -frames:v 500 -an -f null /dev/null";
@@ -469,18 +472,18 @@ namespace MediaBrowser.MediaEncoding.Encoder
///
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
- public Task ExtractAudioImage(string path, CancellationToken cancellationToken)
+ public Task ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken)
{
- return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, cancellationToken);
+ return ExtractImage(new[] { path }, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken);
}
public Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat,
TimeSpan? offset, CancellationToken cancellationToken)
{
- return ExtractImage(inputFiles, protocol, false, threedFormat, offset, cancellationToken);
+ return ExtractImage(inputFiles, null, protocol, false, threedFormat, offset, cancellationToken);
}
- private async Task ExtractImage(string[] inputFiles, MediaProtocol protocol, bool isAudio,
+ private async Task ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio,
Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
{
var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool;
@@ -491,7 +494,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
try
{
- return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
+ return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
}
catch (ArgumentException)
{
@@ -503,10 +506,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
}
- return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
+ return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
}
- private async Task ExtractImageInternal(string inputPath, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
+ private async Task ExtractImageInternal(string inputPath, int? imageStreamIndex, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(inputPath))
{
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index 6bd754865d..1df8896d5d 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -141,6 +141,7 @@ namespace MediaBrowser.MediaEncoding.Probing
if (streamInfo.tags != null)
{
stream.Language = GetDictionaryValue(streamInfo.tags, "language");
+ stream.Comment = GetDictionaryValue(streamInfo.tags, "comment");
}
if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase))
@@ -864,7 +865,7 @@ namespace MediaBrowser.MediaEncoding.Probing
}
}
- private void ExtractTimestamp(Model.MediaInfo.MediaInfo video)
+ private void ExtractTimestamp(MediaInfo video)
{
if (video.VideoType == VideoType.VideoFile)
{
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index ba44ed7dd4..882b2e1c24 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -122,10 +122,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
.ConfigureAwait(false);
- using (var stream = subtitle.Item1)
+ var inputFormat = subtitle.Item2;
+
+ if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && TryGetWriter(outputFormat) == null)
{
- var inputFormat = subtitle.Item2;
+ return subtitle.Item1;
+ }
+ using (var stream = subtitle.Item1)
+ {
return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, cancellationToken).ConfigureAwait(false);
}
}
@@ -288,7 +293,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
return null;
}
- private ISubtitleWriter GetWriter(string format)
+ private ISubtitleWriter TryGetWriter(string format)
{
if (string.IsNullOrEmpty(format))
{
@@ -312,6 +317,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles
return new TtmlWriter();
}
+ return null;
+ }
+
+ private ISubtitleWriter GetWriter(string format)
+ {
+ var writer = TryGetWriter(format);
+
+ if (writer != null)
+ {
+ return writer;
+ }
+
throw new ArgumentException("Unsupported format: " + format);
}
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index 6145983e26..b8c64b6431 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -827,6 +827,9 @@
MediaInfo\VideoCodec.cs
+
+ Net\EndPointInfo.cs
+
Net\HttpException.cs
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index 435c4f50b4..e74468effd 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -783,6 +783,9 @@
MediaInfo\VideoCodec.cs
+
+ Net\EndPointInfo.cs
+
Net\HttpException.cs
diff --git a/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs b/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs
index 764a7222f6..dd6c77e66d 100644
--- a/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs
@@ -11,16 +11,19 @@ namespace MediaBrowser.Model.Configuration
public bool EnableIntrosParentalControl { get; set; }
public bool EnableIntrosFromSimilarMovies { get; set; }
public string CustomIntroPath { get; set; }
+ public string MediaInfoIntroPath { get; set; }
public bool EnableIntrosFromUpcomingDvdMovies { get; set; }
public bool EnableIntrosFromUpcomingStreamingMovies { get; set; }
public int TrailerLimit { get; set; }
+ public string[] Tags { get; set; }
public CinemaModeConfiguration()
{
EnableIntrosParentalControl = true;
EnableIntrosFromSimilarMovies = true;
TrailerLimit = 2;
+ Tags = new[] { "thx" };
}
}
}
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 7208ccb1d9..08f7f89e30 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -62,6 +62,12 @@ namespace MediaBrowser.Model.Configuration
/// true if this instance is port authorized; otherwise, false.
public bool IsPortAuthorized { get; set; }
+ ///
+ /// Gets or sets a value indicating whether [enable high quality image scaling].
+ ///
+ /// true if [enable high quality image scaling]; otherwise, false.
+ public bool EnableHighQualityImageScaling { get; set; }
+
///
/// Gets or sets the item by name path.
///
@@ -92,24 +98,6 @@ namespace MediaBrowser.Model.Configuration
/// true if [enable localized guids]; otherwise, false.
public bool EnableLocalizedGuids { get; set; }
- ///
- /// Gets or sets a value indicating whether [disable startup scan].
- ///
- /// true if [disable startup scan]; otherwise, false.
- public bool DisableStartupScan { get; set; }
-
- ///
- /// Gets or sets a value indicating whether [enable user views].
- ///
- /// true if [enable user views]; otherwise, false.
- public bool EnableUserViews { get; set; }
-
- ///
- /// Gets or sets a value indicating whether [enable library metadata sub folder].
- ///
- /// true if [enable library metadata sub folder]; otherwise, false.
- public bool EnableLibraryMetadataSubFolder { get; set; }
-
///
/// Gets or sets the preferred metadata language.
///
@@ -219,21 +207,20 @@ namespace MediaBrowser.Model.Configuration
public int SharingExpirationDays { get; set; }
- public bool DisableXmlSavers { get; set; }
public bool EnableWindowsShortcuts { get; set; }
- public bool EnableVideoFrameByFrameAnalysis { get; set; }
-
public bool EnableDateLastRefresh { get; set; }
public string[] Migrations { get; set; }
+ public int MigrationVersion { get; set; }
+
///
/// Initializes a new instance of the class.
///
public ServerConfiguration()
{
- Migrations = new string[] {};
+ Migrations = new string[] { };
ImageSavingConvention = ImageSavingConvention.Compatible;
PublicPort = 8096;
diff --git a/MediaBrowser.Model/Connect/ConnectUser.cs b/MediaBrowser.Model/Connect/ConnectUser.cs
index da290da120..383261a6b7 100644
--- a/MediaBrowser.Model/Connect/ConnectUser.cs
+++ b/MediaBrowser.Model/Connect/ConnectUser.cs
@@ -8,5 +8,6 @@ namespace MediaBrowser.Model.Connect
public string Email { get; set; }
public bool IsActive { get; set; }
public string ImageUrl { get; set; }
+ public bool IsSupporter { get; set; }
}
}
diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs
index d089f0aa94..7f4cc2f84d 100644
--- a/MediaBrowser.Model/Entities/MediaStream.cs
+++ b/MediaBrowser.Model/Entities/MediaStream.cs
@@ -30,6 +30,12 @@ namespace MediaBrowser.Model.Entities
/// The language.
public string Language { get; set; }
+ ///
+ /// Gets or sets the comment.
+ ///
+ /// The comment.
+ public string Comment { get; set; }
+
///
/// Gets or sets a value indicating whether this instance is interlaced.
///
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 3664175d8e..db278baa14 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -162,6 +162,7 @@
+
diff --git a/MediaBrowser.Model/Net/EndPointInfo.cs b/MediaBrowser.Model/Net/EndPointInfo.cs
new file mode 100644
index 0000000000..5a158e7859
--- /dev/null
+++ b/MediaBrowser.Model/Net/EndPointInfo.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Net
+{
+ public class EndPointInfo
+ {
+ public bool IsLocal { get; set; }
+ public bool IsInNetwork { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 580e9c4ac3..477ff167ce 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -1038,7 +1038,7 @@ namespace MediaBrowser.Providers.Manager
.ToList();
var musicArtists = albums
- .Select(i => i.Parent)
+ .Select(i => i.GetParent())
.OfType()
.ToList();
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 731d30d845..7478b27388 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -56,9 +56,8 @@
False
..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll
-
- False
- ..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll
+
+ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll
..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index 8884412d27..c98a67bbdb 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using System;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -43,20 +44,27 @@ namespace MediaBrowser.Providers.MediaInfo
{
var audio = (Audio)item;
+ var imageStreams =
+ audio.GetMediaSources(false)
+ .Take(1)
+ .SelectMany(i => i.MediaStreams)
+ .Where(i => i.Type == MediaStreamType.EmbeddedImage)
+ .ToList();
+
// Can't extract if we didn't find a video stream in the file
- if (!audio.GetMediaSources(false).Take(1).SelectMany(i => i.MediaStreams).Any(i => i.Type == MediaStreamType.EmbeddedImage))
+ if (imageStreams.Count == 0)
{
return Task.FromResult(new DynamicImageResponse { HasImage = false });
}
- return GetImage((Audio)item, cancellationToken);
+ return GetImage((Audio)item, imageStreams, cancellationToken);
}
- public async Task GetImage(Audio item, CancellationToken cancellationToken)
+ public async Task GetImage(Audio item, List imageStreams, CancellationToken cancellationToken)
{
var path = GetAudioImagePath(item);
- if (!_fileSystem.FileExists(path))
+ if (!_fileSystem.FileExists(path))
{
var semaphore = GetLock(path);
@@ -66,11 +74,16 @@ namespace MediaBrowser.Providers.MediaInfo
try
{
// Check again in case it was saved while waiting for the lock
- if (!_fileSystem.FileExists(path))
+ if (!_fileSystem.FileExists(path))
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+
+ var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ??
+ imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1);
+
+ var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index;
- using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, cancellationToken).ConfigureAwait(false))
+ using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false))
{
using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config
index 9ff08e4f4c..9002f1a400 100644
--- a/MediaBrowser.Providers/packages.config
+++ b/MediaBrowser.Providers/packages.config
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index b115c3bfdc..fe13d8cef0 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -104,6 +104,11 @@ namespace MediaBrowser.Server.Implementations.Channels
.OrderBy(i => i.Name);
}
+ public IEnumerable GetInstalledChannelIds()
+ {
+ return GetAllChannels().Select(i => GetInternalChannelId(i.Name));
+ }
+
public Task> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken)
{
var user = string.IsNullOrWhiteSpace(query.UserId)
@@ -408,25 +413,15 @@ namespace MediaBrowser.Server.Implementations.Channels
private async Task GetChannel(IChannel channelInfo, CancellationToken cancellationToken)
{
+ var parentFolder = await GetInternalChannelFolder(cancellationToken).ConfigureAwait(false);
+ var parentFolderId = parentFolder.Id;
+
var id = GetInternalChannelId(channelInfo.Name);
var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id);
var isNew = false;
-
- if (!_fileSystem.DirectoryExists(path))
- {
- _logger.Debug("Creating directory {0}", path);
-
- _fileSystem.CreateDirectory(path);
-
- if (!_fileSystem.DirectoryExists(path))
- {
- throw new IOException("Path not created: " + path);
- }
-
- isNew = true;
- }
+ var forceUpdate = false;
var item = _libraryManager.GetItemById(id) as Channel;
var channelId = channelInfo.Name.GetMD5().ToString("N");
@@ -438,18 +433,29 @@ namespace MediaBrowser.Server.Implementations.Channels
Name = channelInfo.Name,
Id = id,
DateCreated = _fileSystem.GetCreationTimeUtc(path),
- DateModified = _fileSystem.GetLastWriteTimeUtc(path),
- Path = path,
- ChannelId = channelId
+ DateModified = _fileSystem.GetLastWriteTimeUtc(path)
};
isNew = true;
}
- if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase))
+ if (!string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
{
isNew = true;
}
+ item.Path = path;
+
+ if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase))
+ {
+ forceUpdate = true;
+ }
+ item.ChannelId = channelId;
+
+ if (item.ParentId != parentFolderId)
+ {
+ forceUpdate = true;
+ }
+ item.ParentId = parentFolderId;
item.OfficialRating = GetOfficialRating(channelInfo.ParentalRating);
item.Overview = channelInfo.Description;
@@ -459,13 +465,17 @@ namespace MediaBrowser.Server.Implementations.Channels
{
item.Name = channelInfo.Name;
}
-
- await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
- {
- ForceSave = isNew
- }, cancellationToken);
+ if (isNew)
+ {
+ await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
+ }
+ else if (forceUpdate)
+ {
+ await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
+ }
+ await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken);
return item;
}
@@ -1225,6 +1235,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
BaseItem item;
bool isNew;
+ bool forceUpdate = false;
if (info.Type == ChannelItemType.Folder)
{
@@ -1254,24 +1265,25 @@ namespace MediaBrowser.Server.Implementations.Channels
item.ProductionYear = info.ProductionYear;
item.ProviderIds = info.ProviderIds;
item.OfficialRating = info.OfficialRating;
-
item.DateCreated = info.DateCreated ?? DateTime.UtcNow;
+ item.Tags = info.Tags;
}
var channelItem = (IChannelItem)item;
channelItem.ChannelId = internalChannelId.ToString("N");
- if (!string.Equals(channelItem.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase))
+ if (item.ParentId != internalChannelId)
{
- isNew = true;
+ forceUpdate = true;
}
- channelItem.ExternalId = info.Id;
+ item.ParentId = internalChannelId;
- if (isNew)
+ if (!string.Equals(channelItem.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase))
{
- channelItem.Tags = info.Tags;
+ forceUpdate = true;
}
+ channelItem.ExternalId = info.Id;
var channelMediaItem = item as IChannelMediaItem;
@@ -1300,6 +1312,10 @@ namespace MediaBrowser.Server.Implementations.Channels
await _libraryManager.UpdatePeople(item, info.People ?? new List()).ConfigureAwait(false);
}
}
+ else if (forceUpdate)
+ {
+ await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
+ }
return item;
}
@@ -1573,4 +1589,4 @@ namespace MediaBrowser.Server.Implementations.Channels
}
}
}
-}
+}
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs
index 2e9d42f49e..da4a72cd49 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs
@@ -123,15 +123,15 @@ namespace MediaBrowser.Server.Implementations.Channels
private async Task CleanDatabase(CancellationToken cancellationToken)
{
- var allChannels = await _channelManager.GetChannelsInternal(new ChannelQuery { }, cancellationToken);
+ var installedChannelIds = ((ChannelManager)_channelManager).GetInstalledChannelIds();
- var allIds = _libraryManager.GetItemIds(new InternalItemsQuery
+ var databaseIds = _libraryManager.GetItemIds(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Channel).Name }
});
- var invalidIds = allIds
- .Except(allChannels.Items.Select(i => i.Id).ToList())
+ var invalidIds = databaseIds
+ .Except(installedChannelIds)
.ToList();
foreach (var id in invalidIds)
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
index 9ea4572847..7ed0d43b14 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
@@ -59,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.Collections
return subItem;
}
- var parent = subItem.Parent;
+ var parent = subItem.GetParent();
if (parent != null && parent.HasImage(ImageType.Primary))
{
@@ -78,24 +78,9 @@ namespace MediaBrowser.Server.Implementations.Collections
return Task.FromResult(GetFinalItems(items, 2));
}
- protected override async Task CreateImage(IHasImages item, List itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex)
+ protected override Task CreateImage(IHasImages item, List itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex)
{
- var image = itemsWithImages
- .Where(i => i.HasImage(ImageType.Primary) && i.GetImageInfo(ImageType.Primary, 0).IsLocalFile && Path.HasExtension(i.GetImagePath(ImageType.Primary)))
- .Select(i => i.GetImagePath(ImageType.Primary))
- .FirstOrDefault();
-
- if (string.IsNullOrWhiteSpace(image))
- {
- return null;
- }
-
- var ext = Path.GetExtension(image);
-
- var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ext);
- File.Copy(image, outputPath);
-
- return outputPath;
+ return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
index 5c98e401f4..4e742ca7a2 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
@@ -40,6 +40,7 @@ namespace MediaBrowser.Server.Implementations.Collections
public Folder GetCollectionsFolder(string userId)
{
return _libraryManager.RootFolder.Children.OfType()
+ .FirstOrDefault() ?? _libraryManager.GetUserRootFolder().Children.OfType()
.FirstOrDefault();
}
diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
index d62918d567..7a1d860475 100644
--- a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
@@ -3,7 +3,7 @@ using System.Linq;
namespace MediaBrowser.Server.Implementations.Collections
{
- public class ManualCollectionsFolder : BasePluginFolder
+ public class ManualCollectionsFolder : BasePluginFolder, IHiddenFromDisplay
{
public ManualCollectionsFolder()
{
@@ -11,11 +11,6 @@ namespace MediaBrowser.Server.Implementations.Collections
DisplayMediaType = "CollectionFolder";
}
- public override bool IsVisible(User user)
- {
- return base.IsVisible(user) && GetChildren(user, false).Any();
- }
-
public override bool IsHidden
{
get
@@ -24,7 +19,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
}
- public override bool IsHiddenFromUser(User user)
+ public bool IsHiddenFromUser(User user)
{
return !user.Configuration.DisplayCollectionsView;
}
@@ -36,7 +31,7 @@ namespace MediaBrowser.Server.Implementations.Collections
public override string GetClientTypeName()
{
- return typeof (CollectionFolder).Name;
+ return typeof(CollectionFolder).Name;
}
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
index a7d3854e71..2f4c3f5eed 100644
--- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -171,12 +171,36 @@ namespace MediaBrowser.Server.Implementations.Configuration
ValidateItemByNamePath(newConfig);
ValidatePathSubstitutions(newConfig);
ValidateMetadataPath(newConfig);
+ ValidateSslCertificate(newConfig);
EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs { Argument = newConfig }, Logger);
base.ReplaceConfiguration(newConfiguration);
}
+
+ ///
+ /// Validates the SSL certificate.
+ ///
+ /// The new configuration.
+ ///
+ private void ValidateSslCertificate(BaseApplicationConfiguration newConfig)
+ {
+ var serverConfig = (ServerConfiguration)newConfig;
+
+ var newPath = serverConfig.CertificatePath;
+
+ if (!string.IsNullOrWhiteSpace(newPath)
+ && !string.Equals(Configuration.CertificatePath ?? string.Empty, newPath))
+ {
+ // Validate
+ if (!FileSystem.FileExists(newPath))
+ {
+ throw new FileNotFoundException(string.Format("Certificate file '{0}' does not exist.", newPath));
+ }
+ }
+ }
+
private void ValidatePathSubstitutions(ServerConfiguration newConfig)
{
foreach (var map in newConfig.PathSubstitutions)
diff --git a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs
index 6d7265972f..9479335614 100644
--- a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs
@@ -3,12 +3,15 @@ using MediaBrowser.Controller.Entities;
using System;
using System.IO;
using System.Linq;
+using System.Runtime.Serialization;
+using System.Threading;
+using System.Threading.Tasks;
using CommonIO;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Providers;
namespace MediaBrowser.Server.Implementations.Devices
{
- public class CameraUploadsFolder : BasePluginFolder
+ public class CameraUploadsFolder : BasePluginFolder, ISupportsUserSpecificView
{
public CameraUploadsFolder()
{
@@ -21,32 +24,41 @@ namespace MediaBrowser.Server.Implementations.Devices
{
return false;
}
-
- return GetChildren(user, true).Any() &&
- base.IsVisible(user);
+
+ return base.IsVisible(user) && HasChildren();
}
- public override bool IsHidden
+ public override string CollectionType
{
- get
- {
- return base.IsHidden || !Children.Any();
- }
+ get { return Model.Entities.CollectionType.Photos; }
}
- public override bool IsHiddenFromUser(User user)
+ public override string GetClientTypeName()
{
- return false;
+ return typeof(CollectionFolder).Name;
}
- public override string CollectionType
+ private bool? _hasChildren;
+ private bool HasChildren()
{
- get { return Model.Entities.CollectionType.Photos; }
+ if (!_hasChildren.HasValue)
+ {
+ _hasChildren = LibraryManager.GetItemIds(new InternalItemsQuery { ParentId = Id }).Count > 0;
+ }
+
+ return _hasChildren.Value;
}
- public override string GetClientTypeName()
+ protected override Task ValidateChildrenInternal(IProgress progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
{
- return typeof(CollectionFolder).Name;
+ _hasChildren = null;
+ return base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService);
+ }
+
+ [IgnoreDataMember]
+ public bool EnableUserSpecificView
+ {
+ get { return true; }
}
}
@@ -65,7 +77,7 @@ namespace MediaBrowser.Server.Implementations.Devices
{
var path = Path.Combine(_appPaths.DataPath, "camerauploads");
- _fileSystem.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
return new CameraUploadsFolder
{
diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs
index 0b2c082a85..6b1af8d2d9 100644
--- a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs
+++ b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
-using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library;
@@ -18,6 +17,7 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Controller.Configuration;
namespace MediaBrowser.Server.Implementations.Devices
{
@@ -27,7 +27,7 @@ namespace MediaBrowser.Server.Implementations.Devices
private readonly IUserManager _userManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _libraryMonitor;
- private readonly IConfigurationManager _config;
+ private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
private readonly INetworkManager _network;
@@ -38,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.Devices
///
public event EventHandler> DeviceOptionsUpdated;
- public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IConfigurationManager config, ILogger logger, INetworkManager network)
+ public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IServerConfigurationManager config, ILogger logger, INetworkManager network)
{
_repo = repo;
_userManager = userManager;
@@ -187,11 +187,6 @@ namespace MediaBrowser.Server.Implementations.Devices
}
}
- private string GetUploadPath(string deviceId)
- {
- return GetUploadPath(GetDevice(deviceId));
- }
-
private string GetUploadPath(DeviceInfo device)
{
if (!string.IsNullOrWhiteSpace(device.CameraUploadPath))
@@ -205,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.Devices
return config.CameraUploadPath;
}
- var path = Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads");
+ var path = DefaultCameraUploadsPath;
if (config.EnableCameraUploadSubfolders)
{
@@ -215,6 +210,11 @@ namespace MediaBrowser.Server.Implementations.Devices
return path;
}
+ private string DefaultCameraUploadsPath
+ {
+ get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads"); }
+ }
+
public async Task UpdateDeviceInfo(string id, DeviceOptions options)
{
var device = GetDevice(id);
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index bb7f818bad..ccca6414a7 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -163,16 +163,11 @@ namespace MediaBrowser.Server.Implementations.Dto
if (person != null)
{
- var items = _libraryManager.GetItems(new InternalItemsQuery
+ var items = _libraryManager.GetItems(new InternalItemsQuery(user)
{
Person = byName.Name
- }).Items;
-
- if (user != null)
- {
- return items.Where(i => i.IsVisibleStandalone(user)).ToList();
- }
+ }, new string[] { });
return items.ToList();
}
@@ -361,6 +356,8 @@ namespace MediaBrowser.Server.Implementations.Dto
var collectionFolder = item as ICollectionFolder;
if (collectionFolder != null)
{
+ dto.OriginalCollectionType = collectionFolder.CollectionType;
+
dto.CollectionType = user == null ?
collectionFolder.CollectionType :
collectionFolder.GetViewType(user);
@@ -468,13 +465,15 @@ namespace MediaBrowser.Server.Implementations.Dto
var folder = (Folder)item;
- dto.ChildCount = GetChildCount(folder, user);
-
- // These are just far too slow.
- // TODO: Disable for CollectionFolder
- if (!(folder is UserRootFolder) && !(folder is UserView))
+ if (!(folder is IChannelItem) && !(folder is Channel))
{
- SetSpecialCounts(folder, user, dto, fields, syncProgress);
+ dto.ChildCount = GetChildCount(folder, user);
+
+ // These are just far too slow.
+ if (!(folder is UserRootFolder) && !(folder is UserView) && !(folder is ICollectionFolder))
+ {
+ SetSpecialCounts(folder, user, dto, fields, syncProgress);
+ }
}
dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100;
@@ -815,7 +814,7 @@ namespace MediaBrowser.Server.Implementations.Dto
/// BaseItem.
private BaseItem GetParentBackdropItem(BaseItem item, BaseItem owner)
{
- var parent = item.Parent ?? owner;
+ var parent = item.GetParent() ?? owner;
while (parent != null)
{
@@ -824,7 +823,7 @@ namespace MediaBrowser.Server.Implementations.Dto
return parent;
}
- parent = parent.Parent;
+ parent = parent.GetParent();
}
return null;
@@ -839,7 +838,7 @@ namespace MediaBrowser.Server.Implementations.Dto
/// BaseItem.
private BaseItem GetParentImageItem(BaseItem item, ImageType type, BaseItem owner)
{
- var parent = item.Parent ?? owner;
+ var parent = item.GetParent() ?? owner;
while (parent != null)
{
@@ -848,7 +847,7 @@ namespace MediaBrowser.Server.Implementations.Dto
return parent;
}
- parent = parent.Parent;
+ parent = parent.GetParent();
}
return null;
@@ -1042,7 +1041,11 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.IsFolder = item.IsFolder;
dto.MediaType = item.MediaType;
dto.LocationType = item.LocationType;
- dto.IsHD = item.IsHD;
+ if (item.IsHD.HasValue && item.IsHD.Value)
+ {
+ dto.IsHD = item.IsHD;
+ }
+ dto.Audio = item.Audio;
dto.PreferredMetadataCountryCode = item.PreferredMetadataCountryCode;
dto.PreferredMetadataLanguage = item.PreferredMetadataLanguage;
@@ -1209,15 +1212,15 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.VoteCount = item.VoteCount;
}
- if (item.IsFolder)
- {
- var folder = (Folder)item;
+ //if (item.IsFolder)
+ //{
+ // var folder = (Folder)item;
- if (fields.Contains(ItemFields.IndexOptions))
- {
- dto.IndexOptions = folder.IndexByOptionStrings.ToArray();
- }
- }
+ // if (fields.Contains(ItemFields.IndexOptions))
+ // {
+ // dto.IndexOptions = folder.IndexByOptionStrings.ToArray();
+ // }
+ //}
var supportsPlaceHolders = item as ISupportsPlaceHolders;
if (supportsPlaceHolders != null)
@@ -1520,7 +1523,7 @@ namespace MediaBrowser.Server.Implementations.Dto
}
dto.ChannelId = item.ChannelId;
-
+
var channelItem = item as IChannelItem;
if (channelItem != null)
{
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
index 008363ca4e..b059e41440 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
@@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
// Go up one level for indicators
if (baseItem != null)
{
- var parent = baseItem.Parent;
+ var parent = baseItem.GetParent();
if (parent != null)
{
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index 6ade9a8f6d..0283c1f7a5 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -19,6 +19,7 @@ using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
using MediaBrowser.Common.Security;
namespace MediaBrowser.Server.Implementations.HttpServer
@@ -39,40 +40,20 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public event EventHandler WebSocketConnected;
public event EventHandler WebSocketConnecting;
- private readonly List _localEndpoints = new List();
-
- private readonly ReaderWriterLockSlim _localEndpointLock = new ReaderWriterLockSlim();
-
public string CertificatePath { get; private set; }
private readonly IServerConfigurationManager _config;
-
- ///
- /// Gets the local end points.
- ///
- /// The local end points.
- public IEnumerable LocalEndPoints
- {
- get
- {
- _localEndpointLock.EnterReadLock();
-
- var list = _localEndpoints.ToList();
-
- _localEndpointLock.ExitReadLock();
-
- return list;
- }
- }
+ private readonly INetworkManager _networkManager;
public HttpListenerHost(IApplicationHost applicationHost,
ILogManager logManager,
IServerConfigurationManager config,
string serviceName,
- string defaultRedirectPath, params Assembly[] assembliesWithServices)
+ string defaultRedirectPath, INetworkManager networkManager, params Assembly[] assembliesWithServices)
: base(serviceName, assembliesWithServices)
{
DefaultRedirectPath = defaultRedirectPath;
+ _networkManager = networkManager;
_config = config;
_logger = logManager.GetLogger("HttpServer");
@@ -175,26 +156,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private void OnRequestReceived(string localEndPoint)
{
- var ignore = localEndPoint.IndexOf("::", StringComparison.OrdinalIgnoreCase) != -1 ||
-
- localEndPoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
- localEndPoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
- localEndPoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase);
-
- if (ignore)
- {
- return;
- }
-
- if (_localEndpointLock.TryEnterWriteLock(100))
- {
- var list = _localEndpoints.ToList();
-
- list.Remove(localEndPoint);
- list.Insert(0, localEndPoint);
-
- _localEndpointLock.ExitWriteLock();
- }
}
///
diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs
index 4d81ec157e..cc351f6b3e 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
@@ -17,18 +18,20 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// The application host.
/// The log manager.
/// The configuration.
+ /// The _networkmanager.
/// Name of the server.
/// The default redirectpath.
/// IHttpServer.
public static IHttpServer CreateServer(IApplicationHost applicationHost,
ILogManager logManager,
IServerConfigurationManager config,
+ INetworkManager _networkmanager,
string serverName,
string defaultRedirectpath)
{
LogManager.LogFactory = new ServerLogFactory(logManager);
- return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath);
+ return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs
new file mode 100644
index 0000000000..3ef48d13a0
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs
@@ -0,0 +1,941 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
+{
+ public static class MyHttpUtility
+ {
+ sealed class HttpQSCollection : NameValueCollection
+ {
+ public override string ToString()
+ {
+ int count = Count;
+ if (count == 0)
+ return "";
+ StringBuilder sb = new StringBuilder();
+ string[] keys = AllKeys;
+ for (int i = 0; i < count; i++)
+ {
+ sb.AppendFormat("{0}={1}&", keys[i], this[keys[i]]);
+ }
+ if (sb.Length > 0)
+ sb.Length--;
+ return sb.ToString();
+ }
+ }
+
+ // Must be sorted
+ static readonly long[] entities = new long[] {
+ (long)'A' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'A' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'A' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'A' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'A' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24,
+ (long)'A' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24,
+ (long)'A' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'A' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'B' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'C' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16,
+ (long)'C' << 56 | (long)'h' << 48 | (long)'i' << 40,
+ (long)'D' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16,
+ (long)'D' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24,
+ (long)'E' << 56 | (long)'T' << 48 | (long)'H' << 40,
+ (long)'E' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'E' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'E' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'E' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'E' << 56 | (long)'t' << 48 | (long)'a' << 40,
+ (long)'E' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'G' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24,
+ (long)'I' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'I' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'I' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'I' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'I' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'K' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24,
+ (long)'L' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16,
+ (long)'M' << 56 | (long)'u' << 48,
+ (long)'N' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'N' << 56 | (long)'u' << 48,
+ (long)'O' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'O' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'O' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'O' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'O' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24,
+ (long)'O' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'O' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16,
+ (long)'O' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'O' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'P' << 56 | (long)'h' << 48 | (long)'i' << 40,
+ (long)'P' << 56 | (long)'i' << 48,
+ (long)'P' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24,
+ (long)'P' << 56 | (long)'s' << 48 | (long)'i' << 40,
+ (long)'R' << 56 | (long)'h' << 48 | (long)'o' << 40,
+ (long)'S' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16,
+ (long)'S' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24,
+ (long)'T' << 56 | (long)'H' << 48 | (long)'O' << 40 | (long)'R' << 32 | (long)'N' << 24,
+ (long)'T' << 56 | (long)'a' << 48 | (long)'u' << 40,
+ (long)'T' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24,
+ (long)'U' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'U' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'U' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'U' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'U' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'X' << 56 | (long)'i' << 48,
+ (long)'Y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'Y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'Z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'a' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'a' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'a' << 56 | (long)'c' << 48 | (long)'u' << 40 | (long)'t' << 32 | (long)'e' << 24,
+ (long)'a' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'a' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'a' << 56 | (long)'l' << 48 | (long)'e' << 40 | (long)'f' << 32 | (long)'s' << 24 | (long)'y' << 16 | (long)'m' << 8,
+ (long)'a' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24,
+ (long)'a' << 56 | (long)'m' << 48 | (long)'p' << 40,
+ (long)'a' << 56 | (long)'n' << 48 | (long)'d' << 40,
+ (long)'a' << 56 | (long)'n' << 48 | (long)'g' << 40,
+ (long)'a' << 56 | (long)'p' << 48 | (long)'o' << 40 | (long)'s' << 32,
+ (long)'a' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24,
+ (long)'a' << 56 | (long)'s' << 48 | (long)'y' << 40 | (long)'m' << 32 | (long)'p' << 24,
+ (long)'a' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'a' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'b' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'b' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'b' << 56 | (long)'r' << 48 | (long)'v' << 40 | (long)'b' << 32 | (long)'a' << 24 | (long)'r' << 16,
+ (long)'b' << 56 | (long)'u' << 48 | (long)'l' << 40 | (long)'l' << 32,
+ (long)'c' << 56 | (long)'a' << 48 | (long)'p' << 40,
+ (long)'c' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16,
+ (long)'c' << 56 | (long)'e' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'l' << 24,
+ (long)'c' << 56 | (long)'e' << 48 | (long)'n' << 40 | (long)'t' << 32,
+ (long)'c' << 56 | (long)'h' << 48 | (long)'i' << 40,
+ (long)'c' << 56 | (long)'i' << 48 | (long)'r' << 40 | (long)'c' << 32,
+ (long)'c' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'b' << 32 | (long)'s' << 24,
+ (long)'c' << 56 | (long)'o' << 48 | (long)'n' << 40 | (long)'g' << 32,
+ (long)'c' << 56 | (long)'o' << 48 | (long)'p' << 40 | (long)'y' << 32,
+ (long)'c' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'r' << 24,
+ (long)'c' << 56 | (long)'u' << 48 | (long)'p' << 40,
+ (long)'c' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'n' << 16,
+ (long)'d' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'d' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16,
+ (long)'d' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'d' << 56 | (long)'e' << 48 | (long)'g' << 40,
+ (long)'d' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24,
+ (long)'d' << 56 | (long)'i' << 48 | (long)'a' << 40 | (long)'m' << 32 | (long)'s' << 24,
+ (long)'d' << 56 | (long)'i' << 48 | (long)'v' << 40 | (long)'i' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'e' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'e' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'e' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'e' << 56 | (long)'m' << 48 | (long)'p' << 40 | (long)'t' << 32 | (long)'y' << 24,
+ (long)'e' << 56 | (long)'m' << 48 | (long)'s' << 40 | (long)'p' << 32,
+ (long)'e' << 56 | (long)'n' << 48 | (long)'s' << 40 | (long)'p' << 32,
+ (long)'e' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'e' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'i' << 32 | (long)'v' << 24,
+ (long)'e' << 56 | (long)'t' << 48 | (long)'a' << 40,
+ (long)'e' << 56 | (long)'t' << 48 | (long)'h' << 40,
+ (long)'e' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'e' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'o' << 32,
+ (long)'e' << 56 | (long)'x' << 48 | (long)'i' << 40 | (long)'s' << 32 | (long)'t' << 24,
+ (long)'f' << 56 | (long)'n' << 48 | (long)'o' << 40 | (long)'f' << 32,
+ (long)'f' << 56 | (long)'o' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'l' << 24 | (long)'l' << 16,
+ (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'2' << 16,
+ (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'4' << 16,
+ (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'3' << 24 | (long)'4' << 16,
+ (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'l' << 24,
+ (long)'g' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24,
+ (long)'g' << 56 | (long)'e' << 48,
+ (long)'g' << 56 | (long)'t' << 48,
+ (long)'h' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'h' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'h' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'t' << 24 | (long)'s' << 16,
+ (long)'h' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'l' << 32 | (long)'i' << 24 | (long)'p' << 16,
+ (long)'i' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'i' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'i' << 56 | (long)'e' << 48 | (long)'x' << 40 | (long)'c' << 32 | (long)'l' << 24,
+ (long)'i' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'i' << 56 | (long)'m' << 48 | (long)'a' << 40 | (long)'g' << 32 | (long)'e' << 24,
+ (long)'i' << 56 | (long)'n' << 48 | (long)'f' << 40 | (long)'i' << 32 | (long)'n' << 24,
+ (long)'i' << 56 | (long)'n' << 48 | (long)'t' << 40,
+ (long)'i' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'i' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'e' << 32 | (long)'s' << 24 | (long)'t' << 16,
+ (long)'i' << 56 | (long)'s' << 48 | (long)'i' << 40 | (long)'n' << 32,
+ (long)'i' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'k' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24,
+ (long)'l' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'l' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16,
+ (long)'l' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32,
+ (long)'l' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'l' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'l' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24,
+ (long)'l' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'l' << 56 | (long)'e' << 48,
+ (long)'l' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16,
+ (long)'l' << 56 | (long)'o' << 48 | (long)'w' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'t' << 16,
+ (long)'l' << 56 | (long)'o' << 48 | (long)'z' << 40,
+ (long)'l' << 56 | (long)'r' << 48 | (long)'m' << 40,
+ (long)'l' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16,
+ (long)'l' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'l' << 56 | (long)'t' << 48,
+ (long)'m' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'r' << 32,
+ (long)'m' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24,
+ (long)'m' << 56 | (long)'i' << 48 | (long)'c' << 40 | (long)'r' << 32 | (long)'o' << 24,
+ (long)'m' << 56 | (long)'i' << 48 | (long)'d' << 40 | (long)'d' << 32 | (long)'o' << 24 | (long)'t' << 16,
+ (long)'m' << 56 | (long)'i' << 48 | (long)'n' << 40 | (long)'u' << 32 | (long)'s' << 24,
+ (long)'m' << 56 | (long)'u' << 48,
+ (long)'n' << 56 | (long)'a' << 48 | (long)'b' << 40 | (long)'l' << 32 | (long)'a' << 24,
+ (long)'n' << 56 | (long)'b' << 48 | (long)'s' << 40 | (long)'p' << 32,
+ (long)'n' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24,
+ (long)'n' << 56 | (long)'e' << 48,
+ (long)'n' << 56 | (long)'i' << 48,
+ (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40,
+ (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'i' << 32 | (long)'n' << 24,
+ (long)'n' << 56 | (long)'s' << 48 | (long)'u' << 40 | (long)'b' << 32,
+ (long)'n' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'n' << 56 | (long)'u' << 48,
+ (long)'o' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'o' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'o' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'o' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'o' << 56 | (long)'l' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'e' << 24,
+ (long)'o' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24,
+ (long)'o' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'o' << 56 | (long)'p' << 48 | (long)'l' << 40 | (long)'u' << 32 | (long)'s' << 24,
+ (long)'o' << 56 | (long)'r' << 48,
+ (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'f' << 32,
+ (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'m' << 32,
+ (long)'o' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16,
+ (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16,
+ (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24 | (long)'s' << 16,
+ (long)'o' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'a' << 32,
+ (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'t' << 32,
+ (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'m' << 32 | (long)'i' << 24 | (long)'l' << 16,
+ (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'p' << 32,
+ (long)'p' << 56 | (long)'h' << 48 | (long)'i' << 40,
+ (long)'p' << 56 | (long)'i' << 48,
+ (long)'p' << 56 | (long)'i' << 48 | (long)'v' << 40,
+ (long)'p' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'s' << 32 | (long)'m' << 24 | (long)'n' << 16,
+ (long)'p' << 56 | (long)'o' << 48 | (long)'u' << 40 | (long)'n' << 32 | (long)'d' << 24,
+ (long)'p' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24,
+ (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'d' << 32,
+ (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'p' << 32,
+ (long)'p' << 56 | (long)'s' << 48 | (long)'i' << 40,
+ (long)'q' << 56 | (long)'u' << 48 | (long)'o' << 40 | (long)'t' << 32,
+ (long)'r' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'r' << 56 | (long)'a' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'c' << 24,
+ (long)'r' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32,
+ (long)'r' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'r' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'r' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24,
+ (long)'r' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'r' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'l' << 32,
+ (long)'r' << 56 | (long)'e' << 48 | (long)'g' << 40,
+ (long)'r' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16,
+ (long)'r' << 56 | (long)'h' << 48 | (long)'o' << 40,
+ (long)'r' << 56 | (long)'l' << 48 | (long)'m' << 40,
+ (long)'r' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16,
+ (long)'r' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'s' << 56 | (long)'b' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24,
+ (long)'s' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16,
+ (long)'s' << 56 | (long)'d' << 48 | (long)'o' << 40 | (long)'t' << 32,
+ (long)'s' << 56 | (long)'e' << 48 | (long)'c' << 40 | (long)'t' << 32,
+ (long)'s' << 56 | (long)'h' << 48 | (long)'y' << 40,
+ (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24,
+ (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24 | (long)'f' << 16,
+ (long)'s' << 56 | (long)'i' << 48 | (long)'m' << 40,
+ (long)'s' << 56 | (long)'p' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24 | (long)'s' << 16,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40 | (long)'e' << 32,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'m' << 40,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'1' << 32,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'2' << 32,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'3' << 32,
+ (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'e' << 32,
+ (long)'s' << 56 | (long)'z' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24,
+ (long)'t' << 56 | (long)'a' << 48 | (long)'u' << 40,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'4' << 16,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24 | (long)'s' << 16 | (long)'y' << 8 | (long)'m' << 0,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'s' << 24 | (long)'p' << 16,
+ (long)'t' << 56 | (long)'h' << 48 | (long)'o' << 40 | (long)'r' << 32 | (long)'n' << 24,
+ (long)'t' << 56 | (long)'i' << 48 | (long)'l' << 40 | (long)'d' << 32 | (long)'e' << 24,
+ (long)'t' << 56 | (long)'i' << 48 | (long)'m' << 40 | (long)'e' << 32 | (long)'s' << 24,
+ (long)'t' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24,
+ (long)'u' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'u' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'u' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32,
+ (long)'u' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24,
+ (long)'u' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16,
+ (long)'u' << 56 | (long)'m' << 48 | (long)'l' << 40,
+ (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'h' << 24,
+ (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8,
+ (long)'u' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'w' << 56 | (long)'e' << 48 | (long)'i' << 40 | (long)'e' << 32 | (long)'r' << 24 | (long)'p' << 16,
+ (long)'x' << 56 | (long)'i' << 48,
+ (long)'y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16,
+ (long)'y' << 56 | (long)'e' << 48 | (long)'n' << 40,
+ (long)'y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32,
+ (long)'z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32,
+ (long)'z' << 56 | (long)'w' << 48 | (long)'j' << 40,
+ (long)'z' << 56 | (long)'w' << 48 | (long)'n' << 40 | (long)'j' << 32
+ };
+
+ static readonly char[] entities_values = new char[] {
+ '\u00C6',
+ '\u00C1',
+ '\u00C2',
+ '\u00C0',
+ '\u0391',
+ '\u00C5',
+ '\u00C3',
+ '\u00C4',
+ '\u0392',
+ '\u00C7',
+ '\u03A7',
+ '\u2021',
+ '\u0394',
+ '\u00D0',
+ '\u00C9',
+ '\u00CA',
+ '\u00C8',
+ '\u0395',
+ '\u0397',
+ '\u00CB',
+ '\u0393',
+ '\u00CD',
+ '\u00CE',
+ '\u00CC',
+ '\u0399',
+ '\u00CF',
+ '\u039A',
+ '\u039B',
+ '\u039C',
+ '\u00D1',
+ '\u039D',
+ '\u0152',
+ '\u00D3',
+ '\u00D4',
+ '\u00D2',
+ '\u03A9',
+ '\u039F',
+ '\u00D8',
+ '\u00D5',
+ '\u00D6',
+ '\u03A6',
+ '\u03A0',
+ '\u2033',
+ '\u03A8',
+ '\u03A1',
+ '\u0160',
+ '\u03A3',
+ '\u00DE',
+ '\u03A4',
+ '\u0398',
+ '\u00DA',
+ '\u00DB',
+ '\u00D9',
+ '\u03A5',
+ '\u00DC',
+ '\u039E',
+ '\u00DD',
+ '\u0178',
+ '\u0396',
+ '\u00E1',
+ '\u00E2',
+ '\u00B4',
+ '\u00E6',
+ '\u00E0',
+ '\u2135',
+ '\u03B1',
+ '\u0026',
+ '\u2227',
+ '\u2220',
+ '\u0027',
+ '\u00E5',
+ '\u2248',
+ '\u00E3',
+ '\u00E4',
+ '\u201E',
+ '\u03B2',
+ '\u00A6',
+ '\u2022',
+ '\u2229',
+ '\u00E7',
+ '\u00B8',
+ '\u00A2',
+ '\u03C7',
+ '\u02C6',
+ '\u2663',
+ '\u2245',
+ '\u00A9',
+ '\u21B5',
+ '\u222A',
+ '\u00A4',
+ '\u21D3',
+ '\u2020',
+ '\u2193',
+ '\u00B0',
+ '\u03B4',
+ '\u2666',
+ '\u00F7',
+ '\u00E9',
+ '\u00EA',
+ '\u00E8',
+ '\u2205',
+ '\u2003',
+ '\u2002',
+ '\u03B5',
+ '\u2261',
+ '\u03B7',
+ '\u00F0',
+ '\u00EB',
+ '\u20AC',
+ '\u2203',
+ '\u0192',
+ '\u2200',
+ '\u00BD',
+ '\u00BC',
+ '\u00BE',
+ '\u2044',
+ '\u03B3',
+ '\u2265',
+ '\u003E',
+ '\u21D4',
+ '\u2194',
+ '\u2665',
+ '\u2026',
+ '\u00ED',
+ '\u00EE',
+ '\u00A1',
+ '\u00EC',
+ '\u2111',
+ '\u221E',
+ '\u222B',
+ '\u03B9',
+ '\u00BF',
+ '\u2208',
+ '\u00EF',
+ '\u03BA',
+ '\u21D0',
+ '\u03BB',
+ '\u2329',
+ '\u00AB',
+ '\u2190',
+ '\u2308',
+ '\u201C',
+ '\u2264',
+ '\u230A',
+ '\u2217',
+ '\u25CA',
+ '\u200E',
+ '\u2039',
+ '\u2018',
+ '\u003C',
+ '\u00AF',
+ '\u2014',
+ '\u00B5',
+ '\u00B7',
+ '\u2212',
+ '\u03BC',
+ '\u2207',
+ '\u00A0',
+ '\u2013',
+ '\u2260',
+ '\u220B',
+ '\u00AC',
+ '\u2209',
+ '\u2284',
+ '\u00F1',
+ '\u03BD',
+ '\u00F3',
+ '\u00F4',
+ '\u0153',
+ '\u00F2',
+ '\u203E',
+ '\u03C9',
+ '\u03BF',
+ '\u2295',
+ '\u2228',
+ '\u00AA',
+ '\u00BA',
+ '\u00F8',
+ '\u00F5',
+ '\u2297',
+ '\u00F6',
+ '\u00B6',
+ '\u2202',
+ '\u2030',
+ '\u22A5',
+ '\u03C6',
+ '\u03C0',
+ '\u03D6',
+ '\u00B1',
+ '\u00A3',
+ '\u2032',
+ '\u220F',
+ '\u221D',
+ '\u03C8',
+ '\u0022',
+ '\u21D2',
+ '\u221A',
+ '\u232A',
+ '\u00BB',
+ '\u2192',
+ '\u2309',
+ '\u201D',
+ '\u211C',
+ '\u00AE',
+ '\u230B',
+ '\u03C1',
+ '\u200F',
+ '\u203A',
+ '\u2019',
+ '\u201A',
+ '\u0161',
+ '\u22C5',
+ '\u00A7',
+ '\u00AD',
+ '\u03C3',
+ '\u03C2',
+ '\u223C',
+ '\u2660',
+ '\u2282',
+ '\u2286',
+ '\u2211',
+ '\u2283',
+ '\u00B9',
+ '\u00B2',
+ '\u00B3',
+ '\u2287',
+ '\u00DF',
+ '\u03C4',
+ '\u2234',
+ '\u03B8',
+ '\u03D1',
+ '\u2009',
+ '\u00FE',
+ '\u02DC',
+ '\u00D7',
+ '\u2122',
+ '\u21D1',
+ '\u00FA',
+ '\u2191',
+ '\u00FB',
+ '\u00F9',
+ '\u00A8',
+ '\u03D2',
+ '\u03C5',
+ '\u00FC',
+ '\u2118',
+ '\u03BE',
+ '\u00FD',
+ '\u00A5',
+ '\u00FF',
+ '\u03B6',
+ '\u200D',
+ '\u200C'
+ };
+
+ #region Methods
+
+ static void WriteCharBytes(IList buf, char ch, Encoding e)
+ {
+ if (ch > 255)
+ {
+ foreach (byte b in e.GetBytes(new char[] { ch }))
+ buf.Add(b);
+ }
+ else
+ buf.Add((byte)ch);
+ }
+
+ public static string UrlDecode(string s, Encoding e)
+ {
+ if (null == s)
+ return null;
+
+ if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1)
+ return s;
+
+ if (e == null)
+ e = Encoding.UTF8;
+
+ long len = s.Length;
+ var bytes = new List();
+ 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;
+ }
+
+ ///
+ /// Decodes an HTML-encoded string and returns the decoded string.
+ ///
+ /// The HTML string to decode.
+ /// The decoded text.
+ public static string HtmlDecode(string s)
+ {
+ if (s == null)
+ throw new ArgumentNullException("s");
+
+ if (s.IndexOf('&') == -1)
+ return s;
+
+ StringBuilder entity = new StringBuilder();
+ StringBuilder output = new StringBuilder();
+ int len = s.Length;
+ // 0 -> nothing,
+ // 1 -> right after '&'
+ // 2 -> between '&' and ';' but no '#'
+ // 3 -> '#' found after '&' and getting numbers
+ int state = 0;
+ int number = 0;
+ int digit_start = 0;
+ bool hex_number = false;
+
+ for (int i = 0; i < len; i++)
+ {
+ char c = s[i];
+ if (state == 0)
+ {
+ if (c == '&')
+ {
+ entity.Append(c);
+ state = 1;
+ }
+ else
+ {
+ output.Append(c);
+ }
+ continue;
+ }
+
+ if (c == '&')
+ {
+ state = 1;
+ if (digit_start > 0)
+ {
+ entity.Append(s, digit_start, i - digit_start);
+ digit_start = 0;
+ }
+
+ output.Append(entity.ToString());
+ entity.Length = 0;
+ entity.Append('&');
+ continue;
+ }
+
+ switch (state)
+ {
+ case 1:
+ if (c == ';')
+ {
+ state = 0;
+ output.Append(entity.ToString());
+ output.Append(c);
+ entity.Length = 0;
+ break;
+ }
+
+ number = 0;
+ hex_number = false;
+ if (c != '#')
+ {
+ state = 2;
+ }
+ else
+ {
+ state = 3;
+ }
+ entity.Append(c);
+
+ break;
+ case 2:
+ entity.Append(c);
+ if (c == ';')
+ {
+ string key = entity.ToString();
+ state = 0;
+ entity.Length = 0;
+
+ if (key.Length > 1)
+ {
+ var skey = key.Substring(1, key.Length - 2);
+ if (TryConvertKeyToEntity(skey, out c))
+ {
+ output.Append(c);
+ break;
+ }
+ }
+
+ output.Append(key);
+ }
+
+ break;
+ case 3:
+ if (c == ';')
+ {
+ if (number < 0x10000)
+ {
+ output.Append((char)number);
+ }
+ else
+ {
+ output.Append((char)(0xd800 + ((number - 0x10000) >> 10)));
+ output.Append((char)(0xdc00 + ((number - 0x10000) & 0x3ff)));
+ }
+ state = 0;
+ entity.Length = 0;
+ digit_start = 0;
+ break;
+ }
+
+ if (c == 'x' || c == 'X' && !hex_number)
+ {
+ digit_start = i;
+ hex_number = true;
+ break;
+ }
+
+ if (Char.IsDigit(c))
+ {
+ if (digit_start == 0)
+ digit_start = i;
+
+ number = number * (hex_number ? 16 : 10) + ((int)c - '0');
+ break;
+ }
+
+ if (hex_number)
+ {
+ if (c >= 'a' && c <= 'f')
+ {
+ number = number * 16 + 10 + ((int)c - 'a');
+ break;
+ }
+ if (c >= 'A' && c <= 'F')
+ {
+ number = number * 16 + 10 + ((int)c - 'A');
+ break;
+ }
+ }
+
+ state = 2;
+ if (digit_start > 0)
+ {
+ entity.Append(s, digit_start, i - digit_start);
+ digit_start = 0;
+ }
+
+ entity.Append(c);
+ break;
+ }
+ }
+
+ if (entity.Length > 0)
+ {
+ output.Append(entity);
+ }
+ else if (digit_start > 0)
+ {
+ output.Append(s, digit_start, s.Length - digit_start);
+ }
+ return output.ToString();
+ }
+
+ public static NameValueCollection ParseQueryString(string query)
+ {
+ return ParseQueryString(query, Encoding.UTF8);
+ }
+
+ public static NameValueCollection ParseQueryString(string query, Encoding encoding)
+ {
+ if (query == null)
+ throw new ArgumentNullException("query");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (query.Length == 0 || (query.Length == 1 && query[0] == '?'))
+ return new NameValueCollection();
+ if (query[0] == '?')
+ query = query.Substring(1);
+
+ NameValueCollection result = new HttpQSCollection();
+ ParseQueryString(query, encoding, result);
+ return result;
+ }
+
+ internal static void ParseQueryString(string query, Encoding encoding, NameValueCollection result)
+ {
+ if (query.Length == 0)
+ return;
+
+ string decoded = HtmlDecode(query);
+ int decodedLength = decoded.Length;
+ int namePos = 0;
+ bool first = true;
+ while (namePos <= decodedLength)
+ {
+ int valuePos = -1, valueEnd = -1;
+ for (int q = namePos; q < decodedLength; q++)
+ {
+ if (valuePos == -1 && decoded[q] == '=')
+ {
+ valuePos = q + 1;
+ }
+ else if (decoded[q] == '&')
+ {
+ valueEnd = q;
+ break;
+ }
+ }
+
+ if (first)
+ {
+ first = false;
+ if (decoded[namePos] == '?')
+ namePos++;
+ }
+
+ string name, value;
+ if (valuePos == -1)
+ {
+ name = null;
+ valuePos = namePos;
+ }
+ else
+ {
+ name = UrlDecode(decoded.Substring(namePos, valuePos - namePos - 1), encoding);
+ }
+ if (valueEnd < 0)
+ {
+ namePos = -1;
+ valueEnd = decoded.Length;
+ }
+ else
+ {
+ namePos = valueEnd + 1;
+ }
+ value = UrlDecode(decoded.Substring(valuePos, valueEnd - valuePos), encoding);
+
+ result.Add(name, value);
+ if (namePos == -1)
+ break;
+ }
+ }
+ #endregion // Methods
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
index 54c27cf0a2..b3fbd2d1d4 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
+using System.Web;
using Funq;
using MediaBrowser.Model.Logging;
using ServiceStack;
@@ -236,7 +237,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
private NameValueCollectionWrapper queryString;
public INameValueCollection QueryString
{
- get { return queryString ?? (queryString = new NameValueCollectionWrapper(HttpUtility.ParseQueryString(request.Url.Query))); }
+ get { return queryString ?? (queryString = new NameValueCollectionWrapper(MyHttpUtility.ParseQueryString(request.Url.Query))); }
}
private NameValueCollectionWrapper formData;
diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
index 97f082295e..49cf4c1620 100644
--- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
+++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
@@ -217,7 +217,7 @@ namespace MediaBrowser.Server.Implementations.IO
/// The instance containing the event data.
void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
{
- if (e.Item.Parent is AggregateFolder)
+ if (e.Item.GetParent() is AggregateFolder)
{
StopWatchingPath(e.Item.Path);
}
@@ -230,7 +230,7 @@ namespace MediaBrowser.Server.Implementations.IO
/// The instance containing the event data.
void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{
- if (e.Item.Parent is AggregateFolder)
+ if (e.Item.GetParent() is AggregateFolder)
{
StartWatchingPath(e.Item.Path);
}
@@ -536,9 +536,16 @@ namespace MediaBrowser.Server.Implementations.IO
return false;
}
+ // In order to determine if the file is being written to, we have to request write access
+ // But if the server only has readonly access, this is going to cause this entire algorithm to fail
+ // So we'll take a best guess about our access level
+ var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta
+ ? FileAccess.ReadWrite
+ : FileAccess.Read;
+
try
{
- using (_fileSystem.GetFileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
+ using (_fileSystem.GetFileStream(path, FileMode.Open, requestedFileAccess, FileShare.ReadWrite))
{
if (_updateTimer != null)
{
@@ -655,7 +662,7 @@ namespace MediaBrowser.Server.Implementations.IO
// If the item has been deleted find the first valid parent that still exists
while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
{
- item = item.Parent;
+ item = item.GetParent();
if (item == null)
{
diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs
index 37131ad2c7..edc329ec42 100644
--- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs
+++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs
@@ -78,13 +78,11 @@ namespace MediaBrowser.Server.Implementations.Intros
if (config.EnableIntrosFromMoviesInLibrary)
{
- var inputItems = _libraryManager.GetItems(new InternalItemsQuery
+ var inputItems = _libraryManager.GetItems(new InternalItemsQuery(user)
{
- IncludeItemTypes = new[] { typeof(Movie).Name },
+ IncludeItemTypes = new[] { typeof(Movie).Name }
- User = user
-
- }).Items;
+ }, new string[]{});
var itemsWithTrailers = inputItems
.Where(i =>
@@ -163,7 +161,7 @@ namespace MediaBrowser.Server.Implementations.Intros
private IEnumerable GetResult(BaseItem item, IEnumerable candidates, CinemaModeConfiguration config, int? ratingLevel)
{
var customIntros = !string.IsNullOrWhiteSpace(config.CustomIntroPath) ?
- GetCustomIntros(item) :
+ GetCustomIntros(config) :
new List();
var trailerLimit = config.TrailerLimit;
@@ -212,11 +210,11 @@ namespace MediaBrowser.Server.Implementations.Intros
return _serverConfig.GetConfiguration("cinemamode");
}
- private List GetCustomIntros(BaseItem item)
+ private List GetCustomIntros(CinemaModeConfiguration options)
{
try
{
- return GetCustomIntroFiles()
+ return GetCustomIntroFiles(options, true, false)
.OrderBy(i => Guid.NewGuid())
.Select(i => new IntroInfo
{
@@ -230,17 +228,23 @@ namespace MediaBrowser.Server.Implementations.Intros
}
}
- private IEnumerable GetCustomIntroFiles(CinemaModeConfiguration options = null)
+ private IEnumerable GetCustomIntroFiles(CinemaModeConfiguration options, bool enableCustomIntros, bool enableMediaInfoIntros)
{
- options = options ?? GetOptions();
+ var list = new List();
+
+ if (enableCustomIntros && !string.IsNullOrWhiteSpace(options.CustomIntroPath))
+ {
+ list.AddRange(_fileSystem.GetFilePaths(options.CustomIntroPath, true)
+ .Where(_libraryManager.IsVideoFile));
+ }
- if (string.IsNullOrWhiteSpace(options.CustomIntroPath))
+ if (enableMediaInfoIntros && !string.IsNullOrWhiteSpace(options.MediaInfoIntroPath))
{
- return new List();
+ list.AddRange(_fileSystem.GetFilePaths(options.MediaInfoIntroPath, true)
+ .Where(_libraryManager.IsVideoFile));
}
- return _fileSystem.GetFilePaths(options.CustomIntroPath, true)
- .Where(_libraryManager.IsVideoFile);
+ return list.Distinct(StringComparer.OrdinalIgnoreCase);
}
private bool FilterByParentalRating(int? ratingLevel, BaseItem item)
@@ -341,7 +345,7 @@ namespace MediaBrowser.Server.Implementations.Intros
public IEnumerable GetAllIntroFiles()
{
- return GetCustomIntroFiles();
+ return GetCustomIntroFiles(GetOptions(), true, true);
}
private bool IsSupporter
diff --git a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
index 9035d6479f..402fa439da 100644
--- a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
+++ b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
@@ -47,11 +47,14 @@ namespace MediaBrowser.Server.Implementations.Library
///
/// Shoulds the ignore.
///
- /// The args.
+ /// The file information.
+ /// The parent.
/// true if XXXX, false otherwise
- public bool ShouldIgnore(ItemResolveArgs args)
+ public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent)
{
- var filename = args.FileInfo.Name;
+ var filename = fileInfo.Name;
+ var isHidden = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
+ var path = fileInfo.FullName;
// Handle mac .DS_Store
// https://github.com/MediaBrowser/MediaBrowser/issues/427
@@ -61,21 +64,24 @@ namespace MediaBrowser.Server.Implementations.Library
}
// Ignore hidden files and folders
- if (args.IsHidden)
+ if (isHidden)
{
- var parentFolderName = Path.GetFileName(Path.GetDirectoryName(args.Path));
-
- if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
- if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
+ if (parent == null)
{
- return false;
+ var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path));
+
+ if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+ if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
}
// Sometimes these are marked hidden
- if (_fileSystem.IsRootPath(args.Path))
+ if (_fileSystem.IsRootPath(path))
{
return false;
}
@@ -83,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.Library
return true;
}
- if (args.IsDirectory)
+ if (fileInfo.IsDirectory)
{
// Ignore any folders in our list
if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))
@@ -91,26 +97,29 @@ namespace MediaBrowser.Server.Implementations.Library
return true;
}
- // Ignore trailer folders but allow it at the collection level
- if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
- !(args.Parent is AggregateFolder) && !(args.Parent is UserRootFolder))
+ if (parent != null)
{
- return true;
- }
+ // Ignore trailer folders but allow it at the collection level
+ if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
+ !(parent is AggregateFolder) && !(parent is UserRootFolder))
+ {
+ return true;
+ }
- if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
+ if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
- if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
- {
- return true;
+ if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
}
}
else
{
- if (args.Parent != null)
+ if (parent != null)
{
// Don't resolve these into audio files
if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename))
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index f27f35c486..9e19ffbe0c 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -27,6 +27,7 @@ using MediaBrowser.Server.Implementations.Library.Validators;
using MediaBrowser.Server.Implementations.Logging;
using MediaBrowser.Server.Implementations.ScheduledTasks;
using System;
+using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
@@ -36,6 +37,7 @@ using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Model.Extensions;
+using MediaBrowser.Model.Library;
using MoreLinq;
using SortOrder = MediaBrowser.Model.Entities.SortOrder;
@@ -140,6 +142,7 @@ namespace MediaBrowser.Server.Implementations.Library
private readonly Func _libraryMonitorFactory;
private readonly Func _providerManagerFactory;
+ private readonly Func _userviewManager;
///
/// The _library items cache
@@ -167,7 +170,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// The user manager.
/// The configuration manager.
/// The user data repository.
- public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func libraryMonitorFactory, IFileSystem fileSystem, Func providerManagerFactory)
+ public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func libraryMonitorFactory, IFileSystem fileSystem, Func providerManagerFactory, Func userviewManager)
{
_logger = logger;
_taskManager = taskManager;
@@ -177,6 +180,7 @@ namespace MediaBrowser.Server.Implementations.Library
_libraryMonitorFactory = libraryMonitorFactory;
_fileSystem = fileSystem;
_providerManagerFactory = providerManagerFactory;
+ _userviewManager = userviewManager;
ByReferenceItems = new ConcurrentDictionary();
_libraryItemsCache = new ConcurrentDictionary();
@@ -401,12 +405,12 @@ namespace MediaBrowser.Server.Implementations.Library
{
foreach (var path in item.GetDeletePaths().ToList())
{
- if (_fileSystem.DirectoryExists(path))
+ if (_fileSystem.DirectoryExists(path))
{
_logger.Debug("Deleting path {0}", path);
_fileSystem.DeleteDirectory(path, true);
}
- else if (_fileSystem.FileExists(path))
+ else if (_fileSystem.FileExists(path))
{
_logger.Debug("Deleting path {0}", path);
_fileSystem.DeleteFile(path);
@@ -580,7 +584,7 @@ namespace MediaBrowser.Server.Implementations.Library
};
// Return null if ignore rules deem that we should do so
- if (EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(args)))
+ if (IgnoreFile(args.FileInfo, args.Parent))
{
return null;
}
@@ -616,6 +620,11 @@ namespace MediaBrowser.Server.Implementations.Library
return ResolveItem(args);
}
+ public bool IgnoreFile(FileSystemMetadata file, BaseItem parent)
+ {
+ return EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent));
+ }
+
public IEnumerable NormalizeRootPathList(IEnumerable paths)
{
var originalList = paths.ToList();
@@ -651,7 +660,7 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable ResolvePaths(IEnumerable files, IDirectoryService directoryService, Folder parent, string collectionType)
{
- var fileList = files.ToList();
+ var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList();
if (parent != null)
{
@@ -702,7 +711,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath;
- _fileSystem.CreateDirectory(rootFolderPath);
+ _fileSystem.CreateDirectory(rootFolderPath);
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath));
@@ -732,6 +741,13 @@ namespace MediaBrowser.Server.Implementations.Library
folder = dbItem;
}
+ if (folder.ParentId != rootFolder.Id)
+ {
+ folder.ParentId = rootFolder.Id;
+ var task = folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
+ Task.WaitAll(task);
+ }
+
rootFolder.AddVirtualChild(folder);
RegisterItem(folder);
@@ -753,7 +769,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
- _fileSystem.CreateDirectory(userRootPath);
+ _fileSystem.CreateDirectory(userRootPath);
var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder;
@@ -1005,9 +1021,9 @@ namespace MediaBrowser.Server.Implementations.Library
private void SetPropertiesFromSongs(MusicArtist artist, IEnumerable items)
{
-
+
}
-
+
///
/// Validate and refresh the People sub-set of the IBN.
/// The items are stored in the db but not loaded into memory until actually requested by an operation.
@@ -1018,7 +1034,7 @@ namespace MediaBrowser.Server.Implementations.Library
public Task ValidatePeople(CancellationToken cancellationToken, IProgress progress)
{
// Ensure the location is available.
- _fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
+ _fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress);
}
@@ -1265,6 +1281,11 @@ namespace MediaBrowser.Server.Implementations.Library
public QueryResult GetItems(InternalItemsQuery query)
{
+ if (query.User != null)
+ {
+ AddUserToQuery(query, query.User);
+ }
+
var result = ItemRepository.GetItemIdsList(query);
var items = result.Select(GetItemById).Where(i => i != null).ToArray();
@@ -1277,14 +1298,140 @@ namespace MediaBrowser.Server.Implementations.Library
public QueryResult QueryItems(InternalItemsQuery query)
{
+ if (query.User != null)
+ {
+ AddUserToQuery(query, query.User);
+ }
+
return ItemRepository.GetItems(query);
}
public List GetItemIds(InternalItemsQuery query)
{
+ if (query.User != null)
+ {
+ AddUserToQuery(query, query.User);
+ }
+
return ItemRepository.GetItemIdsList(query);
}
+ public IEnumerable GetItems(InternalItemsQuery query, IEnumerable parentIds)
+ {
+ var parents = parentIds.Select(i => GetItemById(new Guid(i))).ToList();
+
+ SetTopParentIdsOrAncestors(query, parents);
+
+ return GetItemIds(query).Select(GetItemById);
+ }
+
+ public QueryResult GetItemsResult(InternalItemsQuery query, IEnumerable parentIds)
+ {
+ var parents = parentIds.Select(i => GetItemById(new Guid(i))).ToList();
+
+ SetTopParentIdsOrAncestors(query, parents);
+
+ return GetItems(query);
+ }
+
+ private void SetTopParentIdsOrAncestors(InternalItemsQuery query, List parents)
+ {
+ if (parents.All(i =>
+ {
+ if ((i is ICollectionFolder) || (i is UserView))
+ {
+ return true;
+ }
+
+ _logger.Debug("Query requires ancestor query due to type: " + i.GetType().Name);
+ return false;
+
+ }))
+ {
+ // Optimize by querying against top level views
+ query.TopParentIds = parents.SelectMany(i => GetTopParentsForQuery(i, query.User)).Select(i => i.Id.ToString("N")).ToArray();
+ }
+ else
+ {
+ // We need to be able to query from any arbitrary ancestor up the tree
+ query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).Select(i => i.ToString("N")).ToArray();
+ }
+ }
+
+ private void AddUserToQuery(InternalItemsQuery query, User user)
+ {
+ if (query.AncestorIds.Length == 0 && !query.ParentId.HasValue && query.ChannelIds.Length == 0 && query.TopParentIds.Length == 0)
+ {
+ var userViews = _userviewManager().GetUserViews(new UserViewQuery
+ {
+ UserId = user.Id.ToString("N"),
+ IncludeHidden = true
+
+ }, CancellationToken.None).Result.ToList();
+
+ query.TopParentIds = userViews.SelectMany(i => GetTopParentsForQuery(i, user)).Select(i => i.Id.ToString("N")).ToArray();
+ }
+ }
+
+ private IEnumerable GetTopParentsForQuery(BaseItem item, User user)
+ {
+ var view = item as UserView;
+
+ if (view != null)
+ {
+ if (string.Equals(view.ViewType, CollectionType.LiveTv))
+ {
+ return new[] { view };
+ }
+ if (string.Equals(view.ViewType, CollectionType.Channels))
+ {
+ // TODO: Return channels
+ return new[] { view };
+ }
+
+ // Translate view into folders
+ if (view.DisplayParentId != Guid.Empty)
+ {
+ var displayParent = GetItemById(view.DisplayParentId);
+ if (displayParent != null)
+ {
+ return GetTopParentsForQuery(displayParent, user);
+ }
+ return new BaseItem[] { };
+ }
+ if (view.ParentId != Guid.Empty)
+ {
+ var displayParent = GetItemById(view.ParentId);
+ if (displayParent != null)
+ {
+ return GetTopParentsForQuery(displayParent, user);
+ }
+ return new BaseItem[] { };
+ }
+
+ // Handle grouping
+ if (user != null && !string.IsNullOrWhiteSpace(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType))
+ {
+ var collectionFolders = user.RootFolder.GetChildren(user, true).OfType().Where(i => string.IsNullOrWhiteSpace(i.CollectionType) || string.Equals(i.CollectionType, view.ViewType, StringComparison.OrdinalIgnoreCase));
+ return collectionFolders.SelectMany(i => GetTopParentsForQuery(i, user));
+ }
+ return new BaseItem[] { };
+ }
+
+ var collectionFolder = item as CollectionFolder;
+ if (collectionFolder != null)
+ {
+ return collectionFolder.GetPhysicalParents();
+ }
+
+ var topParent = item.GetTopParent();
+ if (topParent != null)
+ {
+ return new[] { topParent };
+ }
+ return new BaseItem[] { };
+ }
+
///
/// Gets the intros.
///
@@ -1577,9 +1724,9 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable GetCollectionFolders(BaseItem item)
{
- while (!(item.Parent is AggregateFolder) && item.Parent != null)
+ while (!(item.GetParent() is AggregateFolder) && item.GetParent() != null)
{
- item = item.Parent;
+ item = item.GetParent();
}
if (item == null)
@@ -1616,7 +1763,7 @@ namespace MediaBrowser.Server.Implementations.Library
return type;
}
- return item.Parents
+ return item.GetParents()
.Select(GetConfiguredContentType)
.LastOrDefault(i => !string.IsNullOrWhiteSpace(i));
}
@@ -1653,14 +1800,14 @@ namespace MediaBrowser.Server.Implementations.Library
private string GetTopFolderContentType(BaseItem item)
{
- while (!(item.Parent is AggregateFolder) && item.Parent != null)
+ if (item == null)
{
- item = item.Parent;
+ return null;
}
- if (item == null)
+ while (!(item.GetParent() is AggregateFolder) && item.GetParent() != null)
{
- return null;
+ item = item.GetParent();
}
return GetUserRootFolder().Children
@@ -1679,7 +1826,7 @@ namespace MediaBrowser.Server.Implementations.Library
string sortName,
CancellationToken cancellationToken)
{
- return GetNamedViewInternal(user, name, null, viewType, sortName, null, cancellationToken);
+ return GetNamedView(user, name, null, viewType, sortName, cancellationToken);
}
public async Task GetNamedView(string name,
@@ -1697,10 +1844,9 @@ namespace MediaBrowser.Server.Implementations.Library
var refresh = false;
- if (item == null ||
- !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
+ if (item == null || !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
{
- _fileSystem.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
item = new UserView
{
@@ -1717,12 +1863,6 @@ namespace MediaBrowser.Server.Implementations.Library
refresh = true;
}
- if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
- {
- item.ViewType = viewType;
- await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
- }
-
if (!refresh)
{
refresh = (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
@@ -1748,40 +1888,14 @@ namespace MediaBrowser.Server.Implementations.Library
return item;
}
- public Task GetNamedView(User user,
+ public async Task GetNamedView(User user,
string name,
string parentId,
string viewType,
string sortName,
- string uniqueId,
CancellationToken cancellationToken)
{
- if (string.IsNullOrWhiteSpace(parentId))
- {
- throw new ArgumentNullException("parentId");
- }
-
- return GetNamedViewInternal(user, name, parentId, viewType, sortName, uniqueId, cancellationToken);
- }
-
- private async Task GetNamedViewInternal(User user,
- string name,
- string parentId,
- string viewType,
- string sortName,
- string uniqueId,
- CancellationToken cancellationToken)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- throw new ArgumentNullException("name");
- }
-
- var idValues = "37_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty);
- if (!string.IsNullOrWhiteSpace(uniqueId))
- {
- idValues += uniqueId;
- }
+ var idValues = "38_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty) + (viewType ?? string.Empty);
var id = GetNewItemId(idValues, typeof(UserView));
@@ -1793,7 +1907,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item == null)
{
- _fileSystem.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
item = new UserView
{
@@ -1816,18 +1930,6 @@ namespace MediaBrowser.Server.Implementations.Library
isNew = true;
}
- if (!item.UserId.HasValue)
- {
- item.UserId = user.Id;
- await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
- }
-
- if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
- {
- item.ViewType = viewType;
- await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
- }
-
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
if (!refresh && item.DisplayParentId != Guid.Empty)
@@ -1851,7 +1953,6 @@ namespace MediaBrowser.Server.Implementations.Library
public async Task GetShadowView(BaseItem parent,
string viewType,
string sortName,
- string uniqueId,
CancellationToken cancellationToken)
{
if (parent == null)
@@ -1862,11 +1963,7 @@ namespace MediaBrowser.Server.Implementations.Library
var name = parent.Name;
var parentId = parent.Id;
- var idValues = "37_namedview_" + name + parentId + (viewType ?? string.Empty);
- if (!string.IsNullOrWhiteSpace(uniqueId))
- {
- idValues += uniqueId;
- }
+ var idValues = "38_namedview_" + name + parentId + (viewType ?? string.Empty);
var id = GetNewItemId(idValues, typeof(UserView));
@@ -1897,12 +1994,6 @@ namespace MediaBrowser.Server.Implementations.Library
isNew = true;
}
- if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
- {
- item.ViewType = viewType;
- await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
- }
-
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
if (!refresh && item.DisplayParentId != Guid.Empty)
@@ -1922,7 +2013,7 @@ namespace MediaBrowser.Server.Implementations.Library
return item;
}
-
+
public async Task GetNamedView(string name,
string parentId,
string viewType,
@@ -1951,7 +2042,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item == null)
{
- _fileSystem.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
item = new UserView
{
@@ -2198,21 +2289,21 @@ namespace MediaBrowser.Server.Implementations.Library
return ResolvePaths(files, directoryService, null, null)
.OfType
+
+ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll
+
..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll
..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll
-
+
False
- ..\packages\SocketHttpListener.1.0.0.10\lib\net45\SocketHttpListener.dll
+ ..\packages\SocketHttpListener.1.0.0.25\lib\net45\SocketHttpListener.dll
@@ -70,6 +73,7 @@
+
@@ -94,9 +98,6 @@
..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll
-
- ..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll
-
@@ -160,6 +161,7 @@
+
@@ -216,9 +218,6 @@
-
-
-
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
index bd634ed739..ac0f2c69da 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -124,8 +124,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{
if (extractImages)
{
- if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso ||
- video.VideoType == VideoType.BluRay)
+ if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso || video.VideoType == VideoType.BluRay)
{
continue;
}
diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
index 070c5239ee..69ddb4d136 100644
--- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
@@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Entities.Audio;
namespace MediaBrowser.Server.Implementations.Persistence
@@ -24,6 +25,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
+ public const int MigrationVersion = 7;
+
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
@@ -64,16 +67,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
innerProgress.RegisterAction(p => progress.Report(45 + (.55 * p)));
await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false);
progress.Report(100);
+
+ await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false);
}
private async Task UpdateToLatestSchema(CancellationToken cancellationToken, IProgress progress)
{
var itemIds = _libraryManager.GetItemIds(new InternalItemsQuery
{
- IsCurrentSchema = false,
-
- // These are constantly getting regenerated so don't bother with them here
- ExcludeItemTypes = new[] { typeof(LiveTvProgram).Name }
+ IsCurrentSchema = false
});
var numComplete = 0;
@@ -115,9 +117,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
progress.Report(percent * 100);
}
- if (!_config.Configuration.DisableStartupScan)
+ if (_config.Configuration.MigrationVersion < MigrationVersion)
{
- _config.Configuration.DisableStartupScan = true;
+ _config.Configuration.MigrationVersion = MigrationVersion;
_config.SaveConfiguration();
}
@@ -165,12 +167,22 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var result = _itemRepo.GetItemIdsWithPath(new InternalItemsQuery
{
- IsOffline = false,
LocationType = LocationType.FileSystem,
//Limit = limit,
// These have their own cleanup routines
- ExcludeItemTypes = new[] { typeof(Person).Name, typeof(Genre).Name, typeof(MusicGenre).Name, typeof(GameGenre).Name, typeof(Studio).Name, typeof(Year).Name }
+ ExcludeItemTypes = new[]
+ {
+ typeof(Person).Name,
+ typeof(Genre).Name,
+ typeof(MusicGenre).Name,
+ typeof(GameGenre).Name,
+ typeof(Studio).Name,
+ typeof(Year).Name,
+ typeof(Channel).Name,
+ typeof(AggregateFolder).Name,
+ typeof(CollectionFolder).Name
+ }
});
var numComplete = 0;
@@ -191,6 +203,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
var libraryItem = _libraryManager.GetItemById(item.Item1);
+ if (libraryItem.IsTopParent)
+ {
+ continue;
+ }
+
if (Folder.IsPathOffline(path))
{
libraryItem.IsOffline = true;
@@ -229,4 +246,4 @@ namespace MediaBrowser.Server.Implementations.Persistence
};
}
}
-}
+}
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs
index f54e702d64..7e46db5a79 100644
--- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs
@@ -27,6 +27,70 @@ namespace MediaBrowser.Server.Implementations.Persistence
AddIsCabacColumn();
AddKeyFramesColumn();
AddRefFramesCommand();
+ AddCodecTagColumn();
+ AddCommentColumn();
+ }
+
+ private void AddCommentColumn()
+ {
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "PRAGMA table_info(mediastreams)";
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ {
+ while (reader.Read())
+ {
+ if (!reader.IsDBNull(1))
+ {
+ var name = reader.GetString(1);
+
+ if (string.Equals(name, "Comment", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ var builder = new StringBuilder();
+
+ builder.AppendLine("alter table mediastreams");
+ builder.AppendLine("add column Comment TEXT");
+
+ _connection.RunQueries(new[] { builder.ToString() }, _logger);
+ }
+
+ private void AddCodecTagColumn()
+ {
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "PRAGMA table_info(mediastreams)";
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ {
+ while (reader.Read())
+ {
+ if (!reader.IsDBNull(1))
+ {
+ var name = reader.GetString(1);
+
+ if (string.Equals(name, "CodecTag", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ var builder = new StringBuilder();
+
+ builder.AppendLine("alter table mediastreams");
+ builder.AppendLine("add column CodecTag TEXT");
+
+ _connection.RunQueries(new[] { builder.ToString() }, _logger);
}
private void AddPixelFormatColumnCommand()
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
index dc62413627..3d5ddcf495 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
@@ -19,6 +19,7 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Channels;
+using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Server.Implementations.Persistence
{
@@ -76,7 +77,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _deleteStreamsCommand;
private IDbCommand _saveStreamCommand;
- private const int LatestSchemaVersion = 13;
+ private IDbCommand _deleteAncestorsCommand;
+ private IDbCommand _saveAncestorCommand;
+
+ private IDbCommand _updateInheritedRatingCommand;
+
+ private const int LatestSchemaVersion = 40;
///
/// Initializes a new instance of the class.
@@ -121,17 +127,24 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
var createMediaStreamsTableCommand
- = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, KeyFrames TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
+ = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
string[] queries = {
- "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB)",
+ "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID)",
"create index if not exists idx_TypedBaseItems on TypedBaseItems(guid)",
+ "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)",
+ "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))",
+ "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)",
+ "create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)",
+
"create table if not exists ChildrenIds (ParentId GUID, ItemId GUID, PRIMARY KEY (ParentId, ItemId))",
"create index if not exists idx_ChildrenIds on ChildrenIds(ParentId,ItemId)",
"create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)",
+ "create index if not exists idxPeopleItemId on People(ItemId)",
+ "create index if not exists idxPeopleName on People(Name)",
"create table if not exists "+ChaptersTableName+" (ItemId GUID, ChapterIndex INT, StartPositionTicks BIGINT, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))",
"create index if not exists idx_"+ChaptersTableName+" on "+ChaptersTableName+"(ItemId, ChapterIndex)",
@@ -147,6 +160,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.RunQueries(queries, _logger);
+ _connection.AddColumn(_logger, "AncestorIds", "AncestorIdText", "Text");
+
_connection.AddColumn(_logger, "TypedBaseItems", "Path", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "StartDate", "DATETIME");
_connection.AddColumn(_logger, "TypedBaseItems", "EndDate", "DATETIME");
@@ -198,6 +213,18 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.AddColumn(_logger, "TypedBaseItems", "ExternalEtag", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "DateLastRefreshed", "DATETIME");
+ _connection.AddColumn(_logger, "TypedBaseItems", "DateLastSaved", "DATETIME");
+ _connection.AddColumn(_logger, "TypedBaseItems", "IsInMixedFolder", "BIT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "LockedFields", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "Studios", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "Audio", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "ExternalServiceId", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "Tags", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "IsFolder", "BIT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "InheritedParentalRatingValue", "INT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "UnratedType", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "TopParentId", "Text");
+
PrepareStatements();
new MediaStreamColumns(_connection, _logger).AddColumns();
@@ -307,7 +334,27 @@ namespace MediaBrowser.Server.Implementations.Persistence
"PreferredMetadataCountryCode",
"IsHD",
"ExternalEtag",
- "DateLastRefreshed"
+ "DateLastRefreshed",
+ "Name",
+ "Path",
+ "PremiereDate",
+ "Overview",
+ "ParentIndexNumber",
+ "ProductionYear",
+ "OfficialRating",
+ "OfficialRatingDescription",
+ "HomePageUrl",
+ "DisplayMediaType",
+ "ForcedSortName",
+ "RunTimeTicks",
+ "VoteCount",
+ "DateCreated",
+ "DateModified",
+ "guid",
+ "Genres",
+ "ParentId",
+ "Audio",
+ "ExternalServiceId"
};
private readonly string[] _mediaStreamSaveColumns =
@@ -338,7 +385,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"IsAnamorphic",
"RefFrames",
"IsCabac",
- "KeyFrames"
+ "CodecTag",
+ "Comment"
};
///
@@ -378,6 +426,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
"ParentId",
"Genres",
"ParentalRatingValue",
+ "InheritedParentalRatingValue",
"SchemaVersion",
"SortName",
"RunTimeTicks",
@@ -394,7 +443,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
"PreferredMetadataCountryCode",
"IsHD",
"ExternalEtag",
- "DateLastRefreshed"
+ "DateLastRefreshed",
+ "DateLastSaved",
+ "IsInMixedFolder",
+ "LockedFields",
+ "Studios",
+ "Audio",
+ "ExternalServiceId",
+ "Tags",
+ "IsFolder",
+ "UnratedType",
+ "TopParentId"
};
_saveItemCommand = _connection.CreateCommand();
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
@@ -438,6 +497,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
_savePersonCommand.Parameters.Add(_savePersonCommand, "@SortOrder");
_savePersonCommand.Parameters.Add(_savePersonCommand, "@ListOrder");
+ // Ancestors
+ _deleteAncestorsCommand = _connection.CreateCommand();
+ _deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id";
+ _deleteAncestorsCommand.Parameters.Add(_deleteAncestorsCommand, "@Id");
+
+ _saveAncestorCommand = _connection.CreateCommand();
+ _saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId, AncestorIdText) values (@ItemId, @AncestorId, @AncestorIdText)";
+ _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@ItemId");
+ _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorId");
+ _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorIdText");
+
// Chapters
_deleteChaptersCommand = _connection.CreateCommand();
_deleteChaptersCommand.CommandText = "delete from " + ChaptersTableName + " where ItemId=@ItemId";
@@ -467,6 +537,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
_saveStreamCommand.Parameters.Add(_saveStreamCommand, "@" + col);
}
+
+ _updateInheritedRatingCommand = _connection.CreateCommand();
+ _updateInheritedRatingCommand.CommandText = "Update TypedBaseItems set InheritedParentalRatingValue=@InheritedParentalRatingValue where Guid=@Guid";
+ _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@InheritedParentalRatingValue");
+ _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@Guid");
}
///
@@ -592,7 +667,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
_saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Genres.ToArray());
- _saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue();
+ _saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue() ?? 0;
+ _saveItemCommand.GetParameter(index++).Value = item.GetInheritedParentalRatingValue() ?? 0;
_saveItemCommand.GetParameter(index++).Value = LatestSchemaVersion;
_saveItemCommand.GetParameter(index++).Value = item.SortName;
@@ -623,9 +699,53 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed;
}
+ _saveItemCommand.GetParameter(index++).Value = item.DateLastSaved;
+ _saveItemCommand.GetParameter(index++).Value = item.IsInMixedFolder;
+ _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray());
+ _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.ToArray());
+
+ if (item.Audio.HasValue)
+ {
+ _saveItemCommand.GetParameter(index++).Value = item.Audio.Value.ToString();
+ }
+ else
+ {
+ _saveItemCommand.GetParameter(index++).Value = null;
+ }
+
+ var tvItem = item as ILiveTvItem;
+ if (tvItem != null)
+ {
+ _saveItemCommand.GetParameter(index++).Value = tvItem.ServiceName;
+ }
+ else
+ {
+ _saveItemCommand.GetParameter(index++).Value = null;
+ }
+
+ _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray());
+ _saveItemCommand.GetParameter(index++).Value = item.IsFolder;
+
+ _saveItemCommand.GetParameter(index++).Value = item.GetBlockUnratedType().ToString();
+
+ var topParent = item.GetTopParent();
+ if (topParent != null)
+ {
+ _saveItemCommand.GetParameter(index++).Value = topParent.Id.ToString("N");
+ }
+ else
+ {
+ _saveItemCommand.GetParameter(index++).Value = null;
+ }
+
_saveItemCommand.Transaction = transaction;
_saveItemCommand.ExecuteNonQuery();
+
+ if (item.SupportsAncestors)
+ {
+ UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), transaction);
+ }
}
transaction.Commit();
@@ -706,22 +826,32 @@ namespace MediaBrowser.Server.Implementations.Persistence
return null;
}
- BaseItem item;
+ BaseItem item = null;
using (var stream = reader.GetMemoryStream(1))
{
try
{
item = _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
+ }
+ catch (SerializationException ex)
+ {
+ _logger.ErrorException("Error deserializing item", ex);
+ }
- if (item == null)
+ if (item == null)
+ {
+ try
+ {
+ item = Activator.CreateInstance(type) as BaseItem;
+ }
+ catch
{
- return null;
}
}
- catch (SerializationException ex)
+
+ if (item == null)
{
- _logger.ErrorException("Error deserializing item", ex);
return null;
}
}
@@ -844,6 +974,107 @@ namespace MediaBrowser.Server.Implementations.Persistence
item.DateLastRefreshed = reader.GetDateTime(23).ToUniversalTime();
}
+ if (!reader.IsDBNull(24))
+ {
+ item.Name = reader.GetString(24);
+ }
+
+ if (!reader.IsDBNull(25))
+ {
+ item.Path = reader.GetString(25);
+ }
+
+ if (!reader.IsDBNull(26))
+ {
+ item.PremiereDate = reader.GetDateTime(26).ToUniversalTime();
+ }
+
+ if (!reader.IsDBNull(27))
+ {
+ item.Overview = reader.GetString(27);
+ }
+
+ if (!reader.IsDBNull(28))
+ {
+ item.ParentIndexNumber = reader.GetInt32(28);
+ }
+
+ if (!reader.IsDBNull(29))
+ {
+ item.ProductionYear = reader.GetInt32(29);
+ }
+
+ if (!reader.IsDBNull(30))
+ {
+ item.OfficialRating = reader.GetString(30);
+ }
+
+ if (!reader.IsDBNull(31))
+ {
+ item.OfficialRating = reader.GetString(31);
+ }
+
+ if (!reader.IsDBNull(32))
+ {
+ item.HomePageUrl = reader.GetString(32);
+ }
+
+ if (!reader.IsDBNull(33))
+ {
+ item.DisplayMediaType = reader.GetString(33);
+ }
+
+ if (!reader.IsDBNull(34))
+ {
+ item.ForcedSortName = reader.GetString(34);
+ }
+
+ if (!reader.IsDBNull(35))
+ {
+ item.RunTimeTicks = reader.GetInt64(35);
+ }
+
+ if (!reader.IsDBNull(36))
+ {
+ item.VoteCount = reader.GetInt32(36);
+ }
+
+ if (!reader.IsDBNull(37))
+ {
+ item.DateCreated = reader.GetDateTime(37).ToUniversalTime();
+ }
+
+ if (!reader.IsDBNull(38))
+ {
+ item.DateModified = reader.GetDateTime(38).ToUniversalTime();
+ }
+
+ item.Id = reader.GetGuid(39);
+
+ if (!reader.IsDBNull(40))
+ {
+ item.Genres = reader.GetString(40).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
+ }
+
+ if (!reader.IsDBNull(41))
+ {
+ item.ParentId = reader.GetGuid(41);
+ }
+
+ if (!reader.IsDBNull(42))
+ {
+ item.Audio = (ProgramAudio)Enum.Parse(typeof(ProgramAudio), reader.GetString(42), true);
+ }
+
+ if (!reader.IsDBNull(43))
+ {
+ var tvItem = item as ILiveTvItem;
+ if (tvItem != null)
+ {
+ tvItem.ServiceName = reader.GetString(43);
+ }
+ }
+
return item;
}
@@ -1168,6 +1399,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.Parameters.Add(cmd, "@ParentId", DbType.Guid).Value = parentId;
+ //_logger.Debug(cmd.CommandText);
+
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
@@ -1213,6 +1446,50 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
+ public IEnumerable GetItemList(InternalItemsQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ CheckDisposed();
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
+
+ var whereClauses = GetWhereClauses(query, cmd, true);
+
+ var whereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ cmd.CommandText += whereText;
+
+ cmd.CommandText += GetOrderByText(query);
+
+ if (query.Limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ //_logger.Debug(cmd.CommandText);
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ {
+ while (reader.Read())
+ {
+ var item = GetItem(reader);
+ if (item != null)
+ {
+ yield return item;
+ }
+ }
+ }
+ }
+ }
+
public QueryResult GetItems(InternalItemsQuery query)
{
if (query == null)
@@ -1293,6 +1570,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
private string MapOrderByField(string name)
{
+ if (string.Equals(name, "airtime", StringComparison.OrdinalIgnoreCase))
+ {
+ // TODO
+ return "SortName";
+ }
+
return name;
}
@@ -1328,7 +1611,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
_logger.Debug(cmd.CommandText);
- using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
@@ -1512,6 +1795,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
whereClauses.Add("IsSports=@IsSports");
cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports;
}
+ if (query.IsFolder.HasValue)
+ {
+ whereClauses.Add("IsFolder=@IsFolder");
+ cmd.Parameters.Add(cmd, "@IsFolder", DbType.Boolean).Value = query.IsFolder;
+ }
var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray();
if (includeTypes.Length == 1)
@@ -1572,6 +1860,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.Parameters.Add(cmd, "@MinStartDate", DbType.Date).Value = query.MinStartDate.Value;
}
+ if (query.MinPremiereDate.HasValue)
+ {
+ whereClauses.Add("PremiereDate>=@MinPremiereDate");
+ cmd.Parameters.Add(cmd, "@MinPremiereDate", DbType.Date).Value = query.MinPremiereDate.Value;
+ }
+
if (query.MaxStartDate.HasValue)
{
whereClauses.Add("StartDate<=@MaxStartDate");
@@ -1623,7 +1917,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
if (query.MaxParentalRating.HasValue)
{
- whereClauses.Add("(ParentalRatingValue is NULL OR ParentalRatingValue<=@MaxParentalRating)");
+ whereClauses.Add("InheritedParentalRatingValue<=@MaxParentalRating");
cmd.Parameters.Add(cmd, "@MaxParentalRating", DbType.Int32).Value = query.MaxParentalRating.Value;
}
@@ -1631,11 +1925,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
if (query.HasParentalRating.Value)
{
- whereClauses.Add("ParentalRatingValue NOT NULL");
+ whereClauses.Add("InheritedParentalRatingValue > 0");
}
else
{
- whereClauses.Add("ParentalRatingValue IS NULL");
+ whereClauses.Add("InheritedParentalRatingValue = 0");
}
}
@@ -1646,7 +1940,60 @@ namespace MediaBrowser.Server.Implementations.Persistence
whereClauses.Add("ParentId NOT NULL AND ParentId NOT IN (select guid from TypedBaseItems)");
}
}
+ if (query.ExcludeLocationTypes.Length == 1)
+ {
+ whereClauses.Add("LocationType<>@LocationType");
+ cmd.Parameters.Add(cmd, "@LocationType", DbType.String).Value = query.ExcludeLocationTypes[0].ToString();
+ }
+ if (query.ExcludeLocationTypes.Length > 1)
+ {
+ var val = string.Join(",", query.ExcludeLocationTypes.Select(i => "'" + i + "'").ToArray());
+
+ whereClauses.Add("LocationType not in (" + val + ")");
+ }
+
+ if (query.TopParentIds.Length == 1)
+ {
+ whereClauses.Add("(TopParentId=@TopParentId)");
+ cmd.Parameters.Add(cmd, "@TopParentId", DbType.String).Value = query.TopParentIds[0];
+ }
+ if (query.TopParentIds.Length > 1)
+ {
+ var val = string.Join(",", query.TopParentIds.Select(i => "'" + i + "'").ToArray());
+ whereClauses.Add("(TopParentId in (" + val + "))");
+ }
+
+ if (query.AncestorIds.Length == 1)
+ {
+ whereClauses.Add("Guid in (select itemId from AncestorIds where AncestorId=@AncestorId)");
+ cmd.Parameters.Add(cmd, "@AncestorId", DbType.Guid).Value = new Guid(query.AncestorIds[0]);
+ }
+ if (query.AncestorIds.Length > 1)
+ {
+ var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + new Guid(i).ToString("N") + "'").ToArray());
+ whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause));
+ }
+
+ if (query.BlockUnratedItems.Length == 1)
+ {
+ whereClauses.Add("(InheritedParentalRatingValue > 0 or UnratedType <> @UnratedType)");
+ cmd.Parameters.Add(cmd, "@UnratedType", DbType.String).Value = query.BlockUnratedItems[0].ToString();
+ }
+ if (query.BlockUnratedItems.Length > 1)
+ {
+ var inClause = string.Join(",", query.BlockUnratedItems.Select(i => "'" + i.ToString() + "'").ToArray());
+ whereClauses.Add(string.Format("(InheritedParentalRatingValue > 0 or UnratedType not in ({0}))", inClause));
+ }
+
+ //var excludeTagIndex = 0;
+ //foreach (var excludeTag in query.ExcludeTags)
+ //{
+ // whereClauses.Add("Tags not like @excludeTag" + excludeTagIndex);
+ // cmd.Parameters.Add(cmd, "@excludeTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%";
+ // excludeTagIndex++;
+ //}
+
if (addPaging)
{
if (query.StartIndex.HasValue && query.StartIndex.Value > 0)
@@ -1703,6 +2050,83 @@ namespace MediaBrowser.Server.Implementations.Persistence
typeof(AggregateFolder)
};
+ public async Task UpdateInheritedValues(CancellationToken cancellationToken)
+ {
+ var newValues = new List>();
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select Guid,InheritedParentalRatingValue,(select Max(ParentalRatingValue, (select COALESCE(MAX(ParentalRatingValue),0) from TypedBaseItems where guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid)))) as NewInheritedParentalRatingValue from typedbaseitems as Outer where InheritedParentalRatingValue <> NewInheritedParentalRatingValue";
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ {
+ while (reader.Read())
+ {
+ var id = reader.GetGuid(0);
+ var newValue = reader.GetInt32(2);
+
+ newValues.Add(new Tuple(id, newValue));
+ }
+ }
+ }
+
+ if (newValues.Count == 0)
+ {
+ return;
+ }
+
+ await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ IDbTransaction transaction = null;
+
+ try
+ {
+ transaction = _connection.BeginTransaction();
+
+ foreach (var item in newValues)
+ {
+ _updateInheritedRatingCommand.GetParameter(0).Value = item.Item1;
+ _updateInheritedRatingCommand.GetParameter(1).Value = item.Item2;
+
+ _updateInheritedRatingCommand.Transaction = transaction;
+ _updateInheritedRatingCommand.ExecuteNonQuery();
+
+ _updateInheritedRatingCommand.ExecuteNonQuery();
+ }
+
+ transaction.Commit();
+ }
+ catch (OperationCanceledException)
+ {
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Error running query:", e);
+
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ finally
+ {
+ if (transaction != null)
+ {
+ transaction.Dispose();
+ }
+
+ _writeLock.Release();
+ }
+ }
+
private static Dictionary GetTypeMapDictionary()
{
var dict = new Dictionary();
@@ -1712,6 +2136,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
dict[t.Name] = new[] { t.FullName };
}
+ dict["ChannelItem"] = new[] { typeof(ChannelVideoItem).FullName, typeof(ChannelAudioItem).FullName, typeof(ChannelFolderItem).FullName };
+ dict["LiveTvItem"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName, typeof(LiveTvChannel).FullName, typeof(LiveTvProgram).FullName };
dict["Recording"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName };
dict["Program"] = new[] { typeof(LiveTvProgram).FullName };
dict["TvChannel"] = new[] { typeof(LiveTvChannel).FullName };
@@ -1770,11 +2196,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
_deleteStreamsCommand.Transaction = transaction;
_deleteStreamsCommand.ExecuteNonQuery();
+ // Delete ancestors
+ _deleteAncestorsCommand.GetParameter(0).Value = id;
+ _deleteAncestorsCommand.Transaction = transaction;
+ _deleteAncestorsCommand.ExecuteNonQuery();
+
// Delete the item
_deleteItemCommand.GetParameter(0).Value = id;
_deleteItemCommand.Transaction = transaction;
_deleteItemCommand.ExecuteNonQuery();
-
+
transaction.Commit();
}
catch (OperationCanceledException)
@@ -2003,6 +2434,38 @@ namespace MediaBrowser.Server.Implementations.Persistence
return whereClauses;
}
+ private void UpdateAncestors(Guid itemId, List ancestorIds, IDbTransaction transaction)
+ {
+ if (itemId == Guid.Empty)
+ {
+ throw new ArgumentNullException("itemId");
+ }
+
+ if (ancestorIds == null)
+ {
+ throw new ArgumentNullException("ancestorIds");
+ }
+
+ CheckDisposed();
+
+ // First delete
+ _deleteAncestorsCommand.GetParameter(0).Value = itemId;
+ _deleteAncestorsCommand.Transaction = transaction;
+
+ _deleteAncestorsCommand.ExecuteNonQuery();
+
+ foreach (var ancestorId in ancestorIds)
+ {
+ _saveAncestorCommand.GetParameter(0).Value = itemId;
+ _saveAncestorCommand.GetParameter(1).Value = ancestorId;
+ _saveAncestorCommand.GetParameter(2).Value = ancestorId.ToString("N");
+
+ _saveAncestorCommand.Transaction = transaction;
+
+ _saveAncestorCommand.ExecuteNonQuery();
+ }
+ }
+
public async Task UpdatePeople(Guid itemId, List people)
{
if (itemId == Guid.Empty)
@@ -2220,7 +2683,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveStreamCommand.GetParameter(index++).Value = stream.RefFrames;
_saveStreamCommand.GetParameter(index++).Value = stream.IsCabac;
- _saveStreamCommand.GetParameter(index++).Value = null;
+ _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag;
+ _saveStreamCommand.GetParameter(index++).Value = stream.Comment;
_saveStreamCommand.Transaction = transaction;
_saveStreamCommand.ExecuteNonQuery();
@@ -2376,10 +2840,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
if (!reader.IsDBNull(26))
{
- var frames = reader.GetString(26);
- if (!string.IsNullOrWhiteSpace(frames))
- {
- }
+ item.CodecTag = reader.GetString(26);
+ }
+
+ if (!reader.IsDBNull(27))
+ {
+ item.Comment = reader.GetString(27);
}
return item;
diff --git a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
index 4d3e091b1d..fbf5144235 100644
--- a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
@@ -34,11 +34,6 @@ namespace MediaBrowser.Server.Implementations.Playlists
}
}
- public override bool IsHiddenFromUser(User user)
- {
- return false;
- }
-
public override string CollectionType
{
get { return Model.Entities.CollectionType.Playlists; }
diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs
index d9e9fac2a8..4413a7ddf8 100644
--- a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs
@@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
return subItem;
}
- var parent = subItem.Parent;
+ var parent = subItem.GetParent();
if (parent != null && parent.HasImage(ImageType.Primary))
{
diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs
index d9b3ed7551..048e2bf8d5 100644
--- a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs
+++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs
@@ -264,6 +264,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
public Folder GetPlaylistsFolder(string userId)
{
return _libraryManager.RootFolder.Children.OfType()
+ .FirstOrDefault() ?? _libraryManager.GetUserRootFolder().Children.OfType()
.FirstOrDefault();
}
}
diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs
index 96f469f696..457f5a33d3 100644
--- a/MediaBrowser.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs
+++ b/MediaBrowser.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs
@@ -72,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
try
{
- await _installationManager.InstallPackage(i, new Progress(), cancellationToken).ConfigureAwait(false);
+ await _installationManager.InstallPackage(i, true, new Progress(), cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs
index 2f219c299f..64ae249cd4 100644
--- a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs
+++ b/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs
@@ -43,11 +43,6 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
}.ToList();
- if (!_config.Configuration.DisableStartupScan)
- {
- list.Add(new StartupTrigger());
- }
-
return list;
}
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 8d32734217..a9ce5ba542 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -1621,17 +1621,17 @@ namespace MediaBrowser.Server.Implementations.Session
if (backropItem == null)
{
- backropItem = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Backdrop));
+ backropItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Backdrop));
}
if (thumbItem == null)
{
- thumbItem = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Thumb));
+ thumbItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Thumb));
}
if (logoItem == null)
{
- logoItem = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Logo));
+ logoItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Logo));
}
if (thumbItem != null)
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
index db6a753b76..21377da7ee 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
@@ -341,7 +341,7 @@ namespace MediaBrowser.Server.Implementations.Sync
if (primaryImage == null)
{
- var parentWithImage = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
+ var parentWithImage = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Primary));
if (parentWithImage != null)
{
@@ -380,7 +380,7 @@ namespace MediaBrowser.Server.Implementations.Sync
if (primaryImage == null)
{
- var parentWithImage = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
+ var parentWithImage = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Primary));
if (parentWithImage != null)
{
@@ -739,10 +739,10 @@ namespace MediaBrowser.Server.Implementations.Sync
var requiresSaving = false;
var removeFromDevice = false;
- var libraryItem = _libraryManager.GetItemById(jobItem.ItemId);
-
if (request.LocalItemIds.Contains(jobItem.ItemId, StringComparer.OrdinalIgnoreCase))
{
+ var libraryItem = _libraryManager.GetItemById(jobItem.ItemId);
+
var job = _repo.GetJob(jobItem.JobId);
var user = _userManager.GetUserById(job.UserId);
@@ -845,10 +845,10 @@ namespace MediaBrowser.Server.Implementations.Sync
var requiresSaving = false;
var removeFromDevice = false;
- var libraryItem = _libraryManager.GetItemById(jobItem.ItemId);
-
if (request.SyncJobItemIds.Contains(jobItem.Id, StringComparer.OrdinalIgnoreCase))
{
+ var libraryItem = _libraryManager.GetItemById(jobItem.ItemId);
+
var job = _repo.GetJob(jobItem.JobId);
var user = _userManager.GetUserById(job.UserId);
diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
index f34b43e433..69d1c89fe9 100644
--- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
+++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs
@@ -36,8 +36,12 @@ namespace MediaBrowser.Server.Implementations.TV
? new string[] { }
: new[] { request.ParentId };
- var items = GetAllLibraryItems(user, parentIds, i => i is Series)
- .Cast();
+ var items = _libraryManager.GetItems(new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Series).Name },
+ SortOrder = SortOrder.Ascending
+
+ }, parentIds).Cast();
// Avoid implicitly captured closure
var episodes = GetNextUpEpisodes(request, user, items);
@@ -54,9 +58,12 @@ namespace MediaBrowser.Server.Implementations.TV
throw new ArgumentException("User not found");
}
- var items = parentsFolders
- .SelectMany(i => i.GetRecursiveChildren(user, s => s is Series))
- .Cast();
+ var items = _libraryManager.GetItems(new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Series).Name },
+ SortOrder = SortOrder.Ascending
+
+ }, parentsFolders.Select(i => i.Id.ToString("N"))).Cast();
// Avoid implicitly captured closure
var episodes = GetNextUpEpisodes(request, user, items);
@@ -64,27 +71,6 @@ namespace MediaBrowser.Server.Implementations.TV
return GetResult(episodes, null, request);
}
- private IEnumerable GetAllLibraryItems(User user, string[] parentIds, Func filter)
- {
- if (parentIds.Length > 0)
- {
- return parentIds.SelectMany(i =>
- {
- var folder = (Folder)_libraryManager.GetItemById(new Guid(i));
-
- return folder.GetRecursiveChildren(user, filter);
-
- });
- }
-
- if (user == null)
- {
- throw new ArgumentException("User not found");
- }
-
- return user.RootFolder.GetRecursiveChildren(user, filter);
- }
-
public IEnumerable GetNextUpEpisodes(NextUpQuery request, User user, IEnumerable series)
{
// Avoid implicitly captured closure
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index 7d9453822e..aac5951b5e 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -4,7 +4,7 @@
-
+
-
+
\ No newline at end of file
diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
index ba6d7ad1fd..8f3006e116 100644
--- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
+++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
@@ -119,7 +119,7 @@ namespace MediaBrowser.Server.Mono.Native
{
get
{
- return false;
+ return Environment.OperatingSystem == Startup.Common.OperatingSystem.Linux;
}
}
diff --git a/MediaBrowser.Server.Mono/Native/NativeApp.cs b/MediaBrowser.Server.Mono/Native/NativeApp.cs
index 500555647f..c73a964970 100644
--- a/MediaBrowser.Server.Mono/Native/NativeApp.cs
+++ b/MediaBrowser.Server.Mono/Native/NativeApp.cs
@@ -28,7 +28,8 @@ namespace MediaBrowser.Server.Mono.Native
{
get
{
- return true;
+ // A restart script must be provided
+ return StartupOptions.ContainsOption("-restartpath");
}
}
diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs
index 69c8201af4..bccf6487a2 100644
--- a/MediaBrowser.Server.Mono/Program.cs
+++ b/MediaBrowser.Server.Mono/Program.cs
@@ -82,7 +82,7 @@ namespace MediaBrowser.Server.Mono
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"))
{
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index 99a7f0a152..d1c920f8a5 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -91,14 +91,17 @@ using MediaBrowser.Server.Startup.Common.Migrations;
using MediaBrowser.WebDashboard.Api;
using MediaBrowser.XbmcMetadata.Providers;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Net;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Common.Implementations.Updates;
namespace MediaBrowser.Server.Startup.Common
{
@@ -204,9 +207,10 @@ namespace MediaBrowser.Server.Startup.Common
private IPlaylistManager PlaylistManager { get; set; }
private readonly StartupOptions _startupOptions;
- private readonly string _remotePackageName;
+ private readonly string _releaseAssetFilename;
internal INativeApp NativeApp { get; set; }
+ private Timer _ipAddressCacheTimer;
///
/// Initializes a new instance of the class.
@@ -215,21 +219,23 @@ namespace MediaBrowser.Server.Startup.Common
/// The log manager.
/// The options.
/// The file system.
- /// Name of the remote package.
+ /// The release asset filename.
/// The native application.
public ApplicationHost(ServerApplicationPaths applicationPaths,
ILogManager logManager,
StartupOptions options,
IFileSystem fileSystem,
- string remotePackageName,
+ string releaseAssetFilename,
INativeApp nativeApp)
: base(applicationPaths, logManager, fileSystem)
{
_startupOptions = options;
- _remotePackageName = remotePackageName;
+ _releaseAssetFilename = releaseAssetFilename;
NativeApp = nativeApp;
SetBaseExceptionMessage();
+
+ _ipAddressCacheTimer = new Timer(OnCacheClearTimerFired, null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3));
}
private Version _version;
@@ -316,6 +322,7 @@ namespace MediaBrowser.Server.Startup.Common
{
await base.RunStartupTasks().ConfigureAwait(false);
+ Logger.Info("ServerId: {0}", SystemId);
Logger.Info("Core startup complete");
HttpServer.GlobalResponse = null;
@@ -363,7 +370,7 @@ namespace MediaBrowser.Server.Startup.Common
{
var migrations = new List
{
- new Release5767(ServerConfigurationManager, TaskManager)
+ new DbMigration(ServerConfigurationManager, TaskManager)
};
foreach (var task in migrations)
@@ -419,7 +426,7 @@ namespace MediaBrowser.Server.Startup.Common
UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, () => ConnectManager, this, JsonSerializer, FileSystemManager);
RegisterSingleInstance(UserManager);
- LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager);
+ LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager);
RegisterSingleInstance(LibraryManager);
var musicManager = new MusicManager(LibraryManager);
@@ -436,7 +443,7 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance(() => new SearchEngine(LogManager, LibraryManager, UserManager));
- HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, "Emby", "web/index.html");
+ HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, "Emby", "web/index.html");
HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
RegisterSingleInstance(HttpServer, false);
progress.Report(10);
@@ -465,7 +472,7 @@ namespace MediaBrowser.Server.Startup.Common
ConnectManager = new ConnectManager(LogManager.GetLogger("Connect"), ApplicationPaths, JsonSerializer, encryptionManager, HttpClient, this, ServerConfigurationManager, UserManager, ProviderManager, SecurityManager, FileSystemManager);
RegisterSingleInstance(ConnectManager);
- DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer, LogManager.GetLogger("DeviceManager"), FileSystemManager), UserManager, FileSystemManager, LibraryMonitor, ConfigurationManager, LogManager.GetLogger("DeviceManager"), NetworkManager);
+ DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer, LogManager.GetLogger("DeviceManager"), FileSystemManager), UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LogManager.GetLogger("DeviceManager"), NetworkManager);
RegisterSingleInstance(DeviceManager);
var newsService = new Implementations.News.NewsService(ApplicationPaths, JsonSerializer);
@@ -503,7 +510,7 @@ namespace MediaBrowser.Server.Startup.Common
UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager);
RegisterSingleInstance(UserViewManager);
- var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, LocalizationManager, ChannelManager, MediaSourceManager);
+ var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, LocalizationManager, ChannelManager, MediaSourceManager, UserViewManager);
RegisterSingleInstance(contentDirectory);
var mediaRegistrar = new MediaReceiverRegistrar(LogManager.GetLogger("MediaReceiverRegistrar"), HttpClient, ServerConfigurationManager);
@@ -515,7 +522,7 @@ namespace MediaBrowser.Server.Startup.Common
SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager);
RegisterSingleInstance(SubtitleManager);
- RegisterSingleInstance(new DeviceDiscovery(LogManager.GetLogger("IDeviceDiscovery"), ServerConfigurationManager, this));
+ RegisterSingleInstance(new DeviceDiscovery(LogManager.GetLogger("IDeviceDiscovery"), ServerConfigurationManager, this, NetworkManager));
ChapterManager = new ChapterManager(LibraryManager, LogManager.GetLogger("ChapterManager"), ServerConfigurationManager, ItemRepository);
RegisterSingleInstance(ChapterManager);
@@ -640,11 +647,19 @@ namespace MediaBrowser.Server.Startup.Common
/// Task{IUserRepository}.
private async Task GetUserRepository()
{
- var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer);
+ try
+ {
+ var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer);
- await repo.Initialize().ConfigureAwait(false);
+ await repo.Initialize().ConfigureAwait(false);
- return repo;
+ return repo;
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error opening user db", ex);
+ throw;
+ }
}
///
@@ -1108,14 +1123,14 @@ namespace MediaBrowser.Server.Startup.Common
try
{
// Return the first matched address, if found, or the first known local address
- var address = LocalIpAddress;
+ var address = LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i));
- if (!string.IsNullOrWhiteSpace(address))
+ if (address != null)
{
- address = GetLocalApiUrl(address);
+ return GetLocalApiUrl(address.ToString());
}
- return address;
+ return null;
}
catch (Exception ex)
{
@@ -1133,40 +1148,71 @@ namespace MediaBrowser.Server.Startup.Common
HttpPort.ToString(CultureInfo.InvariantCulture));
}
- public string LocalIpAddress
+ public List LocalIpAddresses
{
get
{
- return HttpServerIpAddresses.FirstOrDefault();
+ var localAddresses = NetworkManager.GetLocalIpAddresses()
+ .Where(IsIpAddressValid)
+ .ToList();
+
+ return localAddresses;
}
}
- private IEnumerable HttpServerIpAddresses
+ private readonly ConcurrentDictionary _validAddressResults = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase);
+ private bool IsIpAddressValid(IPAddress address)
{
- get
+ if (IPAddress.IsLoopback(address))
{
- var localAddresses = NetworkManager.GetLocalIpAddresses()
- .ToList();
+ return true;
+ }
- var httpServerAddresses = HttpServer.LocalEndPoints
- .Select(i => i.Split(':').FirstOrDefault())
- .Where(i => !string.IsNullOrEmpty(i))
- .ToList();
+ var apiUrl = GetLocalApiUrl(address.ToString());
+ apiUrl += "/system/ping";
- // Cross-check the local ip addresses with addresses that have been received on with the http server
- var matchedAddresses = httpServerAddresses
- .Where(i => localAddresses.Contains(i, StringComparer.OrdinalIgnoreCase))
- .ToList();
+ bool cachedResult;
+ if (_validAddressResults.TryGetValue(apiUrl, out cachedResult))
+ {
+ return cachedResult;
+ }
- if (matchedAddresses.Count == 0)
+ try
+ {
+ using (var response = HttpClient.SendAsync(new HttpRequestOptions
+ {
+ Url = apiUrl,
+ LogErrorResponseBody = false,
+ LogErrors = false,
+ LogRequest = false
+
+ }, "POST").Result)
{
- return localAddresses;
+ using (var reader = new StreamReader(response.Content))
+ {
+ var result = reader.ReadToEnd();
+ var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase);
+
+ _validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid);
+ Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, valid);
+ return valid;
+ }
}
+ }
+ catch
+ {
+ Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false);
- return matchedAddresses;
+ _validAddressResults.AddOrUpdate(apiUrl, false, (k, v) => false);
+ return false;
}
}
+ private void OnCacheClearTimerFired(object state)
+ {
+ _validAddressResults.Clear();
+ }
+
public string FriendlyName
{
get
@@ -1263,25 +1309,23 @@ namespace MediaBrowser.Server.Startup.Common
/// Task{CheckForUpdateResult}.
public override async Task CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress progress)
{
- var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
-
- var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, _remotePackageName, null, ApplicationVersion, ConfigurationManager.CommonConfiguration.SystemUpdateLevel);
-
- var versionObject = version == null || string.IsNullOrWhiteSpace(version.versionStr) ? null : new Version(version.versionStr);
+ var cacheLength = TimeSpan.FromHours(12);
+ var updateLevel = ConfigurationManager.CommonConfiguration.SystemUpdateLevel;
- var isUpdateAvailable = versionObject != null && versionObject > ApplicationVersion;
+ if (updateLevel == PackageVersionClass.Beta)
+ {
+ cacheLength = TimeSpan.FromHours(1);
+ }
+ else if (updateLevel == PackageVersionClass.Dev)
+ {
+ cacheLength = TimeSpan.FromMinutes(5);
+ }
- var result = versionObject != null ?
- new CheckForUpdateResult { AvailableVersion = versionObject.ToString(), IsUpdateAvailable = isUpdateAvailable, Package = version } :
- new CheckForUpdateResult { AvailableVersion = ApplicationVersion.ToString(), IsUpdateAvailable = false };
+ var result = await new GithubUpdater(HttpClient, JsonSerializer, cacheLength).CheckForUpdateResult("MediaBrowser", "Emby", ApplicationVersion, updateLevel, _releaseAssetFilename,
+ "MBServer", "Mbserver.zip", cancellationToken).ConfigureAwait(false);
HasUpdateAvailable = result.IsUpdateAvailable;
- if (result.IsUpdateAvailable)
- {
- Logger.Info("New application version is available: {0}", result.AvailableVersion);
- }
-
return result;
}
@@ -1294,7 +1338,7 @@ namespace MediaBrowser.Server.Startup.Common
/// Task.
public override async Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress progress)
{
- await InstallationManager.InstallPackage(package, progress, cancellationToken).ConfigureAwait(false);
+ await InstallationManager.InstallPackage(package, false, progress, cancellationToken).ConfigureAwait(false);
HasUpdateAvailable = false;
diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
index 13b782e406..b58646a2e6 100644
--- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
+++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
@@ -72,7 +72,7 @@
-
+
diff --git a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs
new file mode 100644
index 0000000000..cdb69025a1
--- /dev/null
+++ b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs
@@ -0,0 +1,32 @@
+using System.Threading.Tasks;
+using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Server.Implementations.Persistence;
+
+namespace MediaBrowser.Server.Startup.Common.Migrations
+{
+ public class DbMigration : IVersionMigration
+ {
+ private readonly IServerConfigurationManager _config;
+ private readonly ITaskManager _taskManager;
+
+ public DbMigration(IServerConfigurationManager config, ITaskManager taskManager)
+ {
+ _config = config;
+ _taskManager = taskManager;
+ }
+
+ public void Run()
+ {
+ if (_config.Configuration.MigrationVersion < CleanDatabaseScheduledTask.MigrationVersion)
+ {
+ Task.Run(async () =>
+ {
+ await Task.Delay(2000).ConfigureAwait(false);
+
+ _taskManager.QueueScheduledTask();
+ });
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Startup.Common/Migrations/Release5767.cs b/MediaBrowser.Server.Startup.Common/Migrations/Release5767.cs
deleted file mode 100644
index 168230b87b..0000000000
--- a/MediaBrowser.Server.Startup.Common/Migrations/Release5767.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using MediaBrowser.Common.ScheduledTasks;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Server.Implementations.LiveTv;
-using MediaBrowser.Server.Implementations.Persistence;
-using MediaBrowser.Server.Implementations.ScheduledTasks;
-
-namespace MediaBrowser.Server.Startup.Common.Migrations
-{
- public class Release5767 : IVersionMigration
- {
- private readonly IServerConfigurationManager _config;
- private readonly ITaskManager _taskManager;
-
- public Release5767(IServerConfigurationManager config, ITaskManager taskManager)
- {
- _config = config;
- _taskManager = taskManager;
- }
-
- public async void Run()
- {
- var name = "5767.1";
-
- if (_config.Configuration.Migrations.Contains(name, StringComparer.OrdinalIgnoreCase))
- {
- return;
- }
-
- Task.Run(async () =>
- {
- await Task.Delay(3000).ConfigureAwait(false);
-
- _taskManager.QueueScheduledTask();
- });
-
- // Wait a few minutes before marking this as done. Make sure the server doesn't get restarted.
- await Task.Delay(300000).ConfigureAwait(false);
-
- var list = _config.Configuration.Migrations.ToList();
- list.Add(name);
- _config.Configuration.Migrations = list.ToArray();
- _config.SaveConfiguration();
- }
- }
-}
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index b8af35fde1..ac6fd1bbea 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -18,6 +18,9 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using CommonIO.Windows;
+using Emby.Drawing.ImageMagick;
+using ImageMagickSharp;
+using MediaBrowser.Common.Net;
using MediaBrowser.Server.Implementations.Logging;
namespace MediaBrowser.ServerApplication
@@ -29,6 +32,10 @@ namespace MediaBrowser.ServerApplication
private static ILogger _logger;
private static bool _isRunningAsService = false;
+ private static bool _appHostDisposed;
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ static extern bool SetDllDirectory(string lpPathName);
///
/// Defines the entry point of the application.
@@ -41,6 +48,11 @@ namespace MediaBrowser.ServerApplication
var currentProcess = Process.GetCurrentProcess();
var applicationPath = currentProcess.MainModule.FileName;
+ var architecturePath = Path.Combine(Path.GetDirectoryName(applicationPath), Environment.Is64BitProcess ? "x64" : "x86");
+
+ Wand.SetMagickCoderModulePath(architecturePath);
+
+ var success = SetDllDirectory(architecturePath);
var appPaths = CreateApplicationPaths(applicationPath, _isRunningAsService);
@@ -215,7 +227,7 @@ namespace MediaBrowser.ServerApplication
logManager,
options,
fileSystem,
- "MBServer",
+ "emby.windows.zip",
nativeApp);
var initProgress = new Progress();
@@ -241,6 +253,9 @@ namespace MediaBrowser.ServerApplication
{
Task.WaitAll(task);
+ task = InstallVcredistIfNeeded(_appHost, _logger);
+ Task.WaitAll(task);
+
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
@@ -329,7 +344,7 @@ namespace MediaBrowser.ServerApplication
{
_logger.Info("Shutting down");
- _appHost.Dispose();
+ DisposeAppHost();
}
///
@@ -500,14 +515,15 @@ namespace MediaBrowser.ServerApplication
}
else
{
+ DisposeAppHost();
+
ShutdownWindowsApplication();
}
}
public static void Restart()
{
- _logger.Info("Disposing app host");
- _appHost.Dispose();
+ DisposeAppHost();
if (!_isRunningAsService)
{
@@ -522,11 +538,24 @@ namespace MediaBrowser.ServerApplication
}
}
+ private static void DisposeAppHost()
+ {
+ if (!_appHostDisposed)
+ {
+ _logger.Info("Disposing app host");
+
+ _appHostDisposed = true;
+ _appHost.Dispose();
+ }
+ }
+
private static void ShutdownWindowsApplication()
{
_logger.Info("Calling Application.Exit");
Application.Exit();
+ Environment.Exit(0);
+
_logger.Info("Calling ApplicationTaskCompletionSource.SetResult");
ApplicationTaskCompletionSource.SetResult(true);
}
@@ -544,6 +573,70 @@ namespace MediaBrowser.ServerApplication
}
}
+ private static async Task InstallVcredistIfNeeded(ApplicationHost appHost, ILogger logger)
+ {
+ try
+ {
+ var version = ImageMagickEncoder.GetVersion();
+ return;
+ }
+ catch (Exception ex)
+ {
+ logger.ErrorException("Error loading ImageMagick", ex);
+ }
+
+ try
+ {
+ await InstallVcredist().ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ logger.ErrorException("Error installing ImageMagick", ex);
+ }
+ }
+
+ private async static Task InstallVcredist()
+ {
+ var httpClient = _appHost.HttpClient;
+
+ var tmp = await httpClient.GetTempFile(new HttpRequestOptions
+ {
+ Url = GetVcredistUrl(),
+ Progress = new Progress()
+
+ }).ConfigureAwait(false);
+
+ var exePath = Path.ChangeExtension(tmp, ".exe");
+ File.Copy(tmp, exePath);
+
+ var startInfo = new ProcessStartInfo
+ {
+ FileName = exePath,
+
+ CreateNoWindow = true,
+ WindowStyle = ProcessWindowStyle.Hidden,
+ Verb = "runas",
+ ErrorDialog = false
+ };
+
+ using (var process = Process.Start(startInfo))
+ {
+ process.WaitForExit();
+ }
+ }
+
+ private static string GetVcredistUrl()
+ {
+ if (Environment.Is64BitProcess)
+ {
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x64.exe";
+ }
+
+ // TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_arm.exe
+
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x86.exe";
+ }
+
///
/// Sets the error mode.
///
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index 5813dcac58..e8d5b6d27e 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -22,7 +22,7 @@
DEBUG;TRACE
prompt
4
- true
+ false
AnyCPU
@@ -32,6 +32,7 @@
TRACE
prompt
4
+ false
MediaBrowser.ServerApplication.MainStartup
@@ -64,8 +65,9 @@
False
..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll
-
- ..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll
+
+ False
+ ..\packages\ImageMagickSharp.1.0.0.17\lib\net45\ImageMagickSharp.dll
..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll
@@ -156,255 +158,907 @@
-
+
+ x64\SQLite.Interop.dll
+ PreserveNewest
+
+
+ x86\SQLite.Interop.dll
+ PreserveNewest
+
+
MediaBrowser.InstallUtil.dll
PreserveNewest
-
+
MediaBrowser.Uninstaller.exe
PreserveNewest
-
+
MediaBrowser.Updater.exe
PreserveNewest
-
- x64\SQLite.Interop.dll
+
PreserveNewest
-
- x86\SQLite.Interop.dll
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
PreserveNewest
-
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
PreserveNewest
+
+ {08fff49b-f175-4807-a2b5-73b0ebd9f716}
+ Emby.Drawing
+
{4fd51ac5-2c16-4308-a993-c3a84f3b4582}
MediaBrowser.Api
diff --git a/MediaBrowser.ServerApplication/Native/Autorun.cs b/MediaBrowser.ServerApplication/Native/Autorun.cs
index 2cacaae8ed..c384d04602 100644
--- a/MediaBrowser.ServerApplication/Native/Autorun.cs
+++ b/MediaBrowser.ServerApplication/Native/Autorun.cs
@@ -17,25 +17,10 @@ namespace MediaBrowser.ServerApplication.Native
/// The file system.
public static void Configure(bool autorun, IFileSystem fileSystem)
{
- var shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Media Browser 3", "Media Browser Server.lnk");
-
- if (!Directory.Exists(Path.GetDirectoryName(shortcutPath)))
- {
- shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk");
- }
+ var shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk");
var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
- // Remove lnk from old name
- try
- {
- fileSystem.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Media Browser Server.lnk"));
- }
- catch
- {
-
- }
-
if (autorun)
{
//Copy our shortut into the startup folder for this user
diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs
index bff342d01f..ceab5379d5 100644
--- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs
+++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs
@@ -24,7 +24,7 @@ namespace MediaBrowser.ServerApplication.Native
if (!System.Environment.Is64BitProcess)
{
- list.Add(typeof(PismoIsoManager).Assembly);
+ //list.Add(typeof(PismoIsoManager).Assembly);
}
list.Add(GetType().Assembly);
diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config
index dec8199cc2..3ea97a30e6 100644
--- a/MediaBrowser.ServerApplication/packages.config
+++ b/MediaBrowser.ServerApplication/packages.config
@@ -1,7 +1,7 @@
-
+
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index 53dbaf4aaa..5ad40e4c75 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -345,6 +345,9 @@ namespace MediaBrowser.WebDashboard.Api
DeleteFoldersByName(bowerPath, "grunt");
DeleteFoldersByName(bowerPath, "rollups");
+ _fileSystem.DeleteDirectory(Path.Combine(bowerPath, "jquery", "external"), true);
+ _fileSystem.DeleteDirectory(Path.Combine(bowerPath, "jquery", "src"), true);
+
DeleteCryptoFiles(Path.Combine(bowerPath, "cryptojslib", "components"));
DeleteFoldersByName(Path.Combine(bowerPath, "jquery"), "src");
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index d0fbd743ee..a9b5020ec2 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Performance2.psess = Performance2.psess
Performance3.psess = Performance3.psess
Performance4.psess = Performance4.psess
+ Performance5.psess = Performance5.psess
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget (2)", ".nuget (2)", "{E60FB157-87E2-4A41-8B04-27EA49B63B4D}"
@@ -520,4 +521,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
EndGlobal
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index 8fa5b665d5..bec233b7dc 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common.Internal
- 3.0.638
+ 3.0.640
MediaBrowser.Common.Internal
Luke
ebr,Luke,scottisafool
@@ -12,9 +12,9 @@
Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.
Copyright © Emby 2013
-
-
-
+
+
+
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index cec3f63d50..76cf770908 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common
- 3.0.638
+ 3.0.640
MediaBrowser.Common
Emby Team
ebr,Luke,scottisafool
diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec
index 6f778882ad..4b207f1aa4 100644
--- a/Nuget/MediaBrowser.Model.Signed.nuspec
+++ b/Nuget/MediaBrowser.Model.Signed.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Model.Signed
- 3.0.638
+ 3.0.640
MediaBrowser.Model - Signed Edition
Emby Team
ebr,Luke,scottisafool
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index b6edd8719e..717019bfef 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Server.Core
- 3.0.638
+ 3.0.640
Media Browser.Server.Core
Emby Team
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains core components required to build plugins for Emby Server.
Copyright © Emby 2013
-
+
diff --git a/SharedVersion.cs b/SharedVersion.cs
index b4951f12dc..47d5397455 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,4 +1,4 @@
using System.Reflection;
-//[assembly: AssemblyVersion("3.0.*")]
-[assembly: AssemblyVersion("3.0.5785.0")]
+[assembly: AssemblyVersion("3.0.*")]
+//[assembly: AssemblyVersion("3.0.5802")]